Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwinmain.cGo to the documentation of this file.00001 #include "calc.h" 00002 00003 #define HTMLHELP_PATH(_pt) TEXT("%systemroot%\\Help\\calc.chm::") TEXT(_pt) 00004 00005 #define MAKE_BITMASK4(_show_b16, _show_b10, _show_b8, _show_b2) \ 00006 (((_show_b2) << 0) | \ 00007 ((_show_b8) << 1) | \ 00008 ((_show_b10) << 2) | \ 00009 ((_show_b16) << 3)) 00010 00011 #define MAKE_BITMASK5(_transl, _is_stats, _is_ctrl, _show_b16, _show_b10, _show_b8, _show_b2) \ 00012 (((_show_b2) << 0) | \ 00013 ((_show_b8) << 1) | \ 00014 ((_show_b10) << 2) | \ 00015 ((_show_b16) << 3) | \ 00016 ((_is_ctrl) << 5) | \ 00017 ((_is_stats) << 6) | \ 00018 ((_transl) << 7)) 00019 00020 #define KEY_IS_UP 0x80000000 00021 #define KEY_WAS_DOWN 0x40000000 00022 00023 #define BITMASK_IS_ASCII 0x80 00024 #define BITMASK_IS_STATS 0x40 00025 #define BITMASK_IS_CTRL 0x20 00026 #define BITMASK_HEX_MASK 0x08 00027 #define BITMASK_DEC_MASK 0x04 00028 #define BITMASK_OCT_MASK 0x02 00029 #define BITMASK_BIN_MASK 0x01 00030 00031 #define CALC_CLR_RED 0x000000FF 00032 #define CALC_CLR_BLUE 0x00FF0000 00033 #define CALC_CLR_PURP 0x00FF00FF 00034 00035 typedef struct { 00036 CHAR key; // Virtual key identifier 00037 WORD idc; // IDC for posting message 00038 } key2code_t; 00039 00040 typedef struct { 00041 WORD idc; // IDC for posting message 00042 CHAR key; // Virtual key identifier 00043 BYTE mask; // enable/disable into the various modes. 00044 COLORREF col; // color used for drawing the text 00045 } key3code_t; 00046 00047 #define CTRL_FLAG 0x100 00048 #define ALT_FLAG 0x200 00049 00050 #define CTRL_A (0x0001+'A'-'A') 00051 #define CTRL_C (0x0001+'C'-'A') 00052 #define CTRL_D (0x0001+'D'-'A') 00053 #define CTRL_L (0x0001+'L'-'A') 00054 #define CTRL_M (0x0001+'M'-'A') 00055 #define CTRL_P (0x0001+'P'-'A') 00056 #define CTRL_R (0x0001+'R'-'A') 00057 #define CTRL_S (0x0001+'S'-'A') 00058 #define CTRL_T (0x0001+'T'-'A') 00059 #define CTRL_V (0x0001+'V'-'A') 00060 #define CTRL_Z (0x0001+'Z'-'A') 00061 00062 static const key3code_t key2code[] = { 00063 /* CONTROL-ID Key asc sta ctl hex dec oct bin */ 00064 { IDC_BUTTON_STA, CTRL_S, MAKE_BITMASK5( 1, 0, 1, 1, 1, 1, 1), CALC_CLR_BLUE, }, 00065 { IDC_BUTTON_AVE, CTRL_A, MAKE_BITMASK5( 1, 1, 1, 1, 1, 1, 1), CALC_CLR_BLUE, }, 00066 { IDC_BUTTON_SUM, CTRL_T, MAKE_BITMASK5( 1, 1, 1, 1, 1, 1, 1), CALC_CLR_BLUE, }, 00067 { IDC_BUTTON_S, CTRL_D, MAKE_BITMASK5( 1, 1, 1, 1, 1, 1, 1), CALC_CLR_BLUE, }, 00068 { IDC_BUTTON_MS, CTRL_M, MAKE_BITMASK5( 1, 0, 1, 1, 1, 1, 1), CALC_CLR_RED, }, 00069 { IDC_BUTTON_MR, CTRL_R, MAKE_BITMASK5( 1, 0, 1, 1, 1, 1, 1), CALC_CLR_RED, }, 00070 { IDC_BUTTON_MP, CTRL_P, MAKE_BITMASK5( 1, 0, 1, 1, 1, 1, 1), CALC_CLR_RED, }, 00071 { IDC_BUTTON_MC, CTRL_L, MAKE_BITMASK5( 1, 0, 1, 1, 1, 1, 1), CALC_CLR_RED, }, 00072 { IDC_BUTTON_0, '0', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_BLUE, }, 00073 { IDC_BUTTON_1, '1', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_BLUE, }, 00074 { IDC_BUTTON_2, '2', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 0), CALC_CLR_BLUE, }, 00075 { IDC_BUTTON_3, '3', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 0), CALC_CLR_BLUE, }, 00076 { IDC_BUTTON_4, '4', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 0), CALC_CLR_BLUE, }, 00077 { IDC_BUTTON_5, '5', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 0), CALC_CLR_BLUE, }, 00078 { IDC_BUTTON_6, '6', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 0), CALC_CLR_BLUE, }, 00079 { IDC_BUTTON_7, '7', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 0), CALC_CLR_BLUE, }, 00080 { IDC_BUTTON_8, '8', MAKE_BITMASK5( 1, 0, 0, 1, 1, 0, 0), CALC_CLR_BLUE, }, 00081 { IDC_BUTTON_9, '9', MAKE_BITMASK5( 1, 0, 0, 1, 1, 0, 0), CALC_CLR_BLUE, }, 00082 { IDC_BUTTON_DOT, '.', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_BLUE, }, 00083 { IDC_BUTTON_DOT, ',', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), -1, }, 00084 { IDC_BUTTON_ADD, '+', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00085 { IDC_BUTTON_SUB, '-', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00086 { IDC_BUTTON_MULT, '*', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00087 { IDC_BUTTON_DIV, '/', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00088 { IDC_BUTTON_AND, '&', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00089 { IDC_BUTTON_OR, '|', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00090 { IDC_BUTTON_XOR, '^', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00091 { IDC_BUTTON_LSH, '<', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00092 { IDC_BUTTON_NOT, '~', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00093 { IDC_BUTTON_INT, ';', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_RED, }, 00094 { IDC_BUTTON_EQU, '=', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00095 { IDC_BUTTON_A, 'A', MAKE_BITMASK5( 1, 0, 0, 1, 0, 0, 0), CALC_CLR_BLUE, }, 00096 { IDC_BUTTON_B, 'B', MAKE_BITMASK5( 1, 0, 0, 1, 0, 0, 0), CALC_CLR_BLUE, }, 00097 { IDC_BUTTON_C, 'C', MAKE_BITMASK5( 1, 0, 0, 1, 0, 0, 0), CALC_CLR_BLUE, }, 00098 { IDC_BUTTON_D, 'D', MAKE_BITMASK5( 1, 0, 0, 1, 0, 0, 0), CALC_CLR_BLUE, }, 00099 { IDC_BUTTON_E, 'E', MAKE_BITMASK5( 1, 0, 0, 1, 0, 0, 0), CALC_CLR_BLUE, }, 00100 { IDC_BUTTON_F, 'F', MAKE_BITMASK5( 1, 0, 0, 1, 0, 0, 0), CALC_CLR_BLUE, }, 00101 { IDC_CHECK_HYP, 'H', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), -1, }, 00102 { IDC_CHECK_INV, 'I', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), -1, }, 00103 { IDC_BUTTON_LOG, 'L', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00104 { IDC_BUTTON_DMS, 'M', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00105 { IDC_BUTTON_LN, 'N', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00106 { IDC_BUTTON_PI, 'P', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_BLUE, }, 00107 { IDC_BUTTON_RX, 'R', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00108 { IDC_BUTTON_SIN, 'S', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00109 { IDC_BUTTON_COS, 'O', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00110 { IDC_BUTTON_TAN, 'T', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00111 { IDC_BUTTON_FE, 'V', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00112 { IDC_BUTTON_EXP, 'X', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_PURP, }, 00113 { IDC_BUTTON_XeY, 'Y', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_PURP, }, 00114 { IDC_BUTTON_SQRT, '@', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_BLUE, }, 00115 { IDC_BUTTON_Xe2, '@', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_PURP, }, 00116 { IDC_BUTTON_Xe3, '#', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_PURP, }, 00117 { IDC_BUTTON_NF, '!', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_PURP, }, 00118 { IDC_BUTTON_LEFTPAR, '(', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_PURP, }, 00119 { IDC_BUTTON_RIGHTPAR, ')', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_PURP, }, 00120 { IDC_BUTTON_MOD, '%', MAKE_BITMASK5( 1, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00121 { IDC_BUTTON_PERCENT, '%', MAKE_BITMASK5( 1, 0, 0, 0, 1, 0, 0), CALC_CLR_BLUE, }, 00122 /*----------------------------------------------------------------------*/ 00123 { IDC_BUTTON_DAT, VK_INSERT, MAKE_BITMASK5( 0, 1, 0, 1, 1, 1, 1), CALC_CLR_BLUE, }, 00124 { IDC_BUTTON_EQU, VK_RETURN, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00125 { IDC_BUTTON_CANC, VK_ESCAPE, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00126 { IDC_BUTTON_CE, VK_DELETE, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00127 { IDC_BUTTON_BACK, VK_BACK, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), CALC_CLR_RED, }, 00128 { IDC_RADIO_HEX, VK_F5, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), -1, }, 00129 { IDC_RADIO_DEC, VK_F6, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), -1, }, 00130 { IDC_RADIO_OCT, VK_F7, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), -1, }, 00131 { IDC_RADIO_BIN, VK_F8, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), -1, }, 00132 { IDC_BUTTON_SIGN, VK_F9, MAKE_BITMASK5( 0, 0, 0, 1, 1, 1, 1), CALC_CLR_BLUE, }, 00133 }; 00134 00135 static const key2code_t key2code_base16[] = { 00136 { VK_F2, IDC_RADIO_DWORD, }, 00137 { VK_F3, IDC_RADIO_WORD, }, 00138 { VK_F4, IDC_RADIO_BYTE, }, 00139 { VK_F12, IDC_RADIO_QWORD, }, 00140 }; 00141 00142 static const key2code_t key2code_base10[] = { 00143 { VK_F2, IDC_RADIO_DEG, }, 00144 { VK_F3, IDC_RADIO_RAD, }, 00145 { VK_F4, IDC_RADIO_GRAD, }, 00146 }; 00147 00148 static const WORD operator_codes[] = { 00149 /* CONTROL-ID operator */ 00150 (WORD)IDC_STATIC, // RPN_OPERATOR_PARENT 00151 IDC_BUTTON_PERCENT, // RPN_OPERATOR_PERCENT 00152 IDC_BUTTON_EQU, // RPN_OPERATOR_EQUAL 00153 IDC_BUTTON_OR, // RPN_OPERATOR_OR 00154 IDC_BUTTON_XOR, // RPN_OPERATOR_XOR 00155 IDC_BUTTON_AND, // RPN_OPERATOR_AND 00156 IDC_BUTTON_LSH, // RPN_OPERATOR_LSH 00157 IDC_BUTTON_RSH, // RPN_OPERATOR_RSH 00158 IDC_BUTTON_ADD, // RPN_OPERATOR_ADD 00159 IDC_BUTTON_SUB, // RPN_OPERATOR_SUB 00160 IDC_BUTTON_MULT, // RPN_OPERATOR_MULT 00161 IDC_BUTTON_DIV, // RPN_OPERATOR_DIV 00162 IDC_BUTTON_MOD, // RPN_OPERATOR_MOD 00163 }; 00164 00165 typedef void (*rpn_callback1)(calc_number_t *); 00166 00167 typedef struct { 00168 WORD idc; 00169 BYTE range; 00170 BYTE check_nan; 00171 rpn_callback1 direct; 00172 rpn_callback1 inverse; 00173 rpn_callback1 hyperb; 00174 rpn_callback1 inv_hyp; 00175 } function_table_t; 00176 00177 static void run_pow(calc_number_t *number); 00178 static void run_sqr(calc_number_t *number); 00179 static void run_fe(calc_number_t *number); 00180 static void run_dat_sta(calc_number_t *number); 00181 static void run_mp(calc_number_t *c); 00182 static void run_mm(calc_number_t *c); 00183 static void run_ms(calc_number_t *c); 00184 static void run_mw(calc_number_t *c); 00185 static void run_canc(calc_number_t *c); 00186 static void run_rpar(calc_number_t *c); 00187 static void run_lpar(calc_number_t *c); 00188 00189 static const function_table_t function_table[] = { 00190 { IDC_BUTTON_SIN, MODIFIER_INV|MODIFIER_HYP, 1, rpn_sin, rpn_asin, rpn_sinh, rpn_asinh }, 00191 { IDC_BUTTON_COS, MODIFIER_INV|MODIFIER_HYP, 1, rpn_cos, rpn_acos, rpn_cosh, rpn_acosh }, 00192 { IDC_BUTTON_TAN, MODIFIER_INV|MODIFIER_HYP, 1, rpn_tan, rpn_atan, rpn_tanh, rpn_atanh }, 00193 { IDC_BUTTON_INT, MODIFIER_INV, 1, rpn_int, rpn_frac, NULL, NULL }, 00194 { IDC_BUTTON_RX, 0, 1, rpn_reci, NULL, NULL, NULL }, 00195 { IDC_BUTTON_NOT, 0, 1, rpn_not, NULL, NULL, NULL }, 00196 { IDC_BUTTON_PI, MODIFIER_INV, 0, rpn_pi, rpn_2pi, NULL, NULL }, 00197 { IDC_BUTTON_Xe2, MODIFIER_INV, 1, rpn_exp2, rpn_sqrt, NULL, NULL }, 00198 { IDC_BUTTON_Xe3, MODIFIER_INV, 1, rpn_exp3, rpn_cbrt, NULL, NULL }, 00199 { IDC_BUTTON_LN, MODIFIER_INV, 1, rpn_ln, rpn_exp, NULL, NULL }, 00200 { IDC_BUTTON_LOG, MODIFIER_INV, 1, rpn_log, rpn_exp10, NULL, NULL }, 00201 { IDC_BUTTON_NF, 0, 1, rpn_fact, NULL, NULL, NULL }, 00202 { IDC_BUTTON_AVE, 0, 0, rpn_ave, NULL, NULL, NULL }, 00203 { IDC_BUTTON_SUM, 0, 0, rpn_sum, NULL, NULL, NULL }, 00204 { IDC_BUTTON_S, MODIFIER_INV, 0, rpn_s_m1, rpn_s, NULL, NULL }, 00205 { IDC_BUTTON_XeY, MODIFIER_INV, 1, run_pow, run_sqr, NULL, NULL }, 00206 { IDC_BUTTON_SQRT, MODIFIER_INV, 1, rpn_sqrt, NULL, NULL, NULL }, 00207 { IDC_BUTTON_DMS, MODIFIER_INV, 1, rpn_dec2dms, rpn_dms2dec, NULL, NULL }, 00208 { IDC_BUTTON_FE, 0, 1, run_fe, NULL, NULL, NULL }, 00209 { IDC_BUTTON_DAT, 0, 1, run_dat_sta, NULL, NULL, NULL, }, 00210 { IDC_BUTTON_MP, MODIFIER_INV, 1, run_mp, run_mm, NULL, NULL, }, 00211 { IDC_BUTTON_MS, MODIFIER_INV, 1, run_ms, run_mw, NULL, NULL, }, 00212 { IDC_BUTTON_CANC, NO_CHAIN, 0, run_canc, NULL, NULL, NULL, }, 00213 { IDC_BUTTON_RIGHTPAR, NO_CHAIN, 1, run_rpar, NULL, NULL, NULL, }, 00214 { IDC_BUTTON_LEFTPAR, NO_CHAIN, 0, run_lpar, NULL, NULL, NULL, }, 00215 }; 00216 00217 /* 00218 */ 00219 00220 calc_t calc; 00221 00222 static void load_config(void) 00223 { 00224 TCHAR buf[32]; 00225 DWORD tmp; 00226 #if _WIN32_WINNT >= 0x0500 00227 HKEY hKey; 00228 #endif 00229 00230 /* Try to load last selected layout */ 00231 GetProfileString(TEXT("SciCalc"), TEXT("layout"), TEXT("0"), buf, SIZEOF(buf)); 00232 if (_stscanf(buf, TEXT("%ld"), &calc.layout) != 1) 00233 calc.layout = CALC_LAYOUT_STANDARD; 00234 00235 /* Try to load last selected formatting option */ 00236 GetProfileString(TEXT("SciCalc"), TEXT("UseSep"), TEXT("0"), buf, SIZEOF(buf)); 00237 if (_stscanf(buf, TEXT("%ld"), &tmp) != 1) 00238 calc.usesep = FALSE; 00239 else 00240 calc.usesep = (tmp == 1) ? TRUE : FALSE; 00241 00242 /* memory is empty at startup */ 00243 calc.is_memory = FALSE; 00244 00245 #if _WIN32_WINNT >= 0x0500 00246 /* empty these values */ 00247 calc.sDecimal[0] = TEXT('\0'); 00248 calc.sThousand[0] = TEXT('\0'); 00249 00250 /* try to open the registry */ 00251 if (RegOpenKeyEx(HKEY_CURRENT_USER, 00252 TEXT("Control Panel\\International"), 00253 0, 00254 KEY_QUERY_VALUE, 00255 &hKey) == ERROR_SUCCESS) { 00256 /* get these values (ignore errors) */ 00257 tmp = sizeof(calc.sDecimal); 00258 RegQueryValueEx(hKey, TEXT("sDecimal"), NULL, NULL, (LPBYTE)calc.sDecimal, &tmp); 00259 00260 tmp = sizeof(calc.sThousand); 00261 RegQueryValueEx(hKey, TEXT("sThousand"), NULL, NULL, (LPBYTE)calc.sThousand, &tmp); 00262 00263 /* close the key */ 00264 RegCloseKey(hKey); 00265 } 00266 /* if something goes wrong, let's apply the defaults */ 00267 if (calc.sDecimal[0] == TEXT('\0')) 00268 _tcscpy(calc.sDecimal, TEXT(".")); 00269 00270 if (calc.sThousand[0] == TEXT('\0')) 00271 _tcscpy(calc.sThousand, TEXT(",")); 00272 00273 /* get the string lengths */ 00274 calc.sDecimal_len = _tcslen(calc.sDecimal); 00275 calc.sThousand_len = _tcslen(calc.sThousand); 00276 #else 00277 /* acquire regional settings */ 00278 calc.sDecimal_len = GetProfileString(TEXT("intl"), TEXT("sDecimal"), TEXT("."), calc.sDecimal, SIZEOF(calc.sDecimal)); 00279 calc.sThousand_len = GetProfileString(TEXT("intl"), TEXT("sThousand"), TEXT(","), calc.sThousand, SIZEOF(calc.sThousand)); 00280 #endif 00281 } 00282 00283 static void save_config(void) 00284 { 00285 TCHAR buf[32]; 00286 00287 _stprintf(buf, TEXT("%lu"), calc.layout); 00288 WriteProfileString(TEXT("SciCalc"), TEXT("layout"), buf); 00289 WriteProfileString(TEXT("SciCalc"), TEXT("UseSep"), (calc.usesep==TRUE) ? TEXT("1") : TEXT("0")); 00290 } 00291 00292 static LRESULT post_key_press(LPARAM lParam, WORD idc) 00293 { 00294 HWND hCtlWnd = GetDlgItem(calc.hWnd,idc); 00295 TCHAR ClassName[64]; 00296 00297 /* check if the key is enabled! */ 00298 if (!IsWindowEnabled(hCtlWnd)) 00299 return 1; 00300 00301 if (!GetClassName(hCtlWnd, ClassName, SIZEOF(ClassName))) 00302 return 1; 00303 00304 if (!_tcscmp(ClassName, TEXT("Button"))) { 00305 DWORD dwStyle = GetWindowLongPtr(hCtlWnd, GWL_STYLE) & 0xF; 00306 00307 /* Set states for press/release, but only for push buttons */ 00308 if (dwStyle == BS_PUSHBUTTON || dwStyle == BS_DEFPUSHBUTTON || dwStyle == BS_OWNERDRAW) { 00309 if (!(lParam & KEY_WAS_DOWN)) { 00310 PostMessage(hCtlWnd, BM_SETSTATE, 1, 0); 00311 } else 00312 if ((lParam & KEY_IS_UP)) { 00313 PostMessage(hCtlWnd, BM_SETSTATE, 0, 0); 00314 PostMessage(hCtlWnd, BM_CLICK, 0, 0); 00315 } 00316 return 1; 00317 } 00318 } 00319 /* default action: simple click event at key release */ 00320 if ((lParam & KEY_IS_UP)) { 00321 PostMessage(hCtlWnd, BM_CLICK, 0, 0); 00322 } 00323 return 1; 00324 } 00325 00326 static int vk2ascii(unsigned int vk) 00327 { 00328 unsigned short int s; 00329 int scan; 00330 BYTE state[256]; 00331 HKL layout=GetKeyboardLayout(0); 00332 00333 if(!GetKeyboardState(state)) 00334 return 0; 00335 00336 scan=MapVirtualKeyEx(vk, 0, layout); 00337 s = 0; 00338 if (ToAsciiEx(vk, scan, state, &s, 0, layout)>0) { 00339 /* convert to upper case */ 00340 if (s >= 'a' && s <= 'z') 00341 s = s - 'a' + 'A'; 00342 /* add check to CTRL key */ 00343 if (vk >= 'A' && vk <= 'Z' && 00344 s >= CTRL_A && s <= CTRL_Z) 00345 s |= CTRL_FLAG; 00346 else 00347 if (GetAsyncKeyState(VK_MENU) < 0) 00348 s |= ALT_FLAG; 00349 return s; 00350 } 00351 return 0; 00352 } 00353 00354 static int process_vk_key(WPARAM wParam, LPARAM lParam) 00355 { 00356 const key2code_t *k; 00357 unsigned int x; 00358 unsigned short int ch; 00359 00360 ch = vk2ascii(LOWORD(wParam)); 00361 if ((lParam & KEY_IS_UP)) { 00362 /* Test for "copy" to clipboard */ 00363 if (ch == (CTRL_C|CTRL_FLAG)) { 00364 SendMessage(calc.hWnd, WM_COMMAND, IDM_EDIT_COPY, 0); 00365 return 1; 00366 } 00367 /* Test for "paste" from clipboard */ 00368 if (ch == (CTRL_V|CTRL_FLAG)) { 00369 SendMessage(calc.hWnd, WM_COMMAND, IDM_EDIT_PASTE, 0); 00370 return 1; 00371 } 00372 /* Test of help menu */ 00373 if (LOWORD(wParam) == VK_F1) { 00374 SendMessage(calc.hWnd, WM_COMMAND, IDM_HELP_HELP, 0); 00375 return 1; 00376 } 00377 } 00378 00379 for (x=0; x<SIZEOF(key2code); x++) { 00380 int key = key2code[x].key; 00381 if (key2code[x].mask & BITMASK_IS_CTRL) 00382 key |= CTRL_FLAG; 00383 if ((key == ch && (key2code[x].mask & BITMASK_IS_ASCII)) || 00384 (key == LOWORD(wParam) && !(key2code[x].mask & BITMASK_IS_ASCII)) 00385 ) { 00386 if (GetDlgItem(calc.hWnd, key2code[x].idc) == NULL) 00387 continue; 00388 return post_key_press(lParam, key2code[x].idc); 00389 } 00390 } 00391 if (calc.layout == CALC_LAYOUT_SCIENTIFIC) { 00392 if (calc.base == IDC_RADIO_DEC) { 00393 k = key2code_base10; 00394 x = SIZEOF(key2code_base10); 00395 } else { 00396 k = key2code_base16; 00397 x = SIZEOF(key2code_base16); 00398 } 00399 do { 00400 if (k->key == LOWORD(wParam)) { 00401 return post_key_press(lParam, k->idc); 00402 } 00403 k++; 00404 } while (--x); 00405 } 00406 return 0; 00407 } 00408 00409 #ifdef USE_KEYBOARD_HOOK 00410 static LRESULT CALLBACK 00411 KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) 00412 { 00413 if(nCode<0 || calc.is_menu_on) 00414 return CallNextHookEx(calc.hKeyboardHook,nCode,wParam,lParam); 00415 00416 if(nCode==HC_ACTION) 00417 if (process_vk_key(wParam, lParam)) 00418 return; 00419 00420 return CallNextHookEx(calc.hKeyboardHook,nCode,wParam,lParam); 00421 } 00422 #endif 00423 00424 static void update_lcd_display(HWND hwnd) 00425 { 00426 /* 00427 * muliply size of calc.buffer by 2 because it may 00428 * happen that separator is used between each digit. 00429 * Also added little additional space for dot and '\0'. 00430 */ 00431 TCHAR *tmp = (TCHAR *)alloca(sizeof(calc.buffer)*2+2*sizeof(TCHAR)); 00432 00433 if (calc.buffer[0] == TEXT('\0')) 00434 _tcscpy(tmp, TEXT("0")); 00435 else 00436 _tcscpy(tmp, calc.buffer); 00437 /* add final '.' in decimal mode (if it's missing) */ 00438 if (calc.base == IDC_RADIO_DEC) { 00439 if (_tcschr(tmp, TEXT('.')) == NULL) 00440 _tcscat(tmp, TEXT(".")); 00441 } 00442 /* if separator mode is on, let's add an additional space */ 00443 if (calc.usesep && !calc.sci_in && !calc.sci_out && !calc.is_nan) { 00444 /* go to the integer part of the string */ 00445 TCHAR *p = _tcschr(tmp, TEXT('.')); 00446 TCHAR *e = _tcschr(tmp, TEXT('\0')); 00447 int n=0, t; 00448 00449 if (p == NULL) p = e; 00450 switch (calc.base) { 00451 case IDC_RADIO_HEX: 00452 case IDC_RADIO_BIN: 00453 t = 4; 00454 break; 00455 default: 00456 /* fall here for: 00457 IDC_RADIO_DEC: 00458 IDC_RADIO_OCT: */ 00459 t = 3; 00460 break; 00461 } 00462 while (--p > tmp) { 00463 if (++n == t && *(p-1) != TEXT('-')) { 00464 memmove(p+1, p, (e-p+1)*sizeof(TCHAR)); 00465 e++; 00466 *p = TEXT(' '); 00467 n = 0; 00468 } 00469 } 00470 /* if decimal mode, apply regional settings */ 00471 if (calc.base == IDC_RADIO_DEC) { 00472 TCHAR *p = tmp; 00473 TCHAR *e = _tcschr(tmp, TEXT('.')); 00474 00475 /* searching for thousands default separator */ 00476 while (p < e) { 00477 if (*p == TEXT(' ')) { 00478 memmove(p+calc.sThousand_len, p+1, _tcslen(p)*sizeof(TCHAR)); 00479 memcpy(p, calc.sThousand, calc.sThousand_len*sizeof(TCHAR)); 00480 p += calc.sThousand_len; 00481 } else 00482 p++; 00483 } 00484 /* update decimal point too. */ 00485 memmove(p+calc.sDecimal_len, p+1, _tcslen(p)*sizeof(TCHAR)); 00486 memcpy(p, calc.sDecimal, calc.sDecimal_len*sizeof(TCHAR)); 00487 } 00488 } else { 00489 TCHAR *p = _tcschr(tmp, TEXT('.')); 00490 00491 /* update decimal point when usesep is false */ 00492 if (p != NULL) { 00493 memmove(p+calc.sDecimal_len, p+1, _tcslen(p)*sizeof(TCHAR)); 00494 memcpy(p, calc.sDecimal, calc.sDecimal_len*sizeof(TCHAR)); 00495 } 00496 } 00497 SendDlgItemMessage(hwnd, IDC_TEXT_OUTPUT, WM_SETTEXT, (WPARAM)0, (LPARAM)tmp); 00498 } 00499 00500 static void update_parent_display(HWND hWnd) 00501 { 00502 TCHAR str[8]; 00503 int n = eval_parent_count(); 00504 00505 if (!n) 00506 str[0] = TEXT('\0'); 00507 else 00508 _stprintf(str,TEXT("(=%d"), n); 00509 SendDlgItemMessage(hWnd, IDC_TEXT_PARENT, WM_SETTEXT, 0, (LPARAM)str); 00510 } 00511 00512 static void build_operand(HWND hwnd, DWORD idc) 00513 { 00514 unsigned int i = 0, n; 00515 00516 if (idc == IDC_BUTTON_DOT) { 00517 /* if dot is the first char, it's added automatically */ 00518 if (calc.buffer == calc.ptr) { 00519 *calc.ptr++ = TEXT('0'); 00520 *calc.ptr++ = TEXT('.'); 00521 *calc.ptr = TEXT('\0'); 00522 update_lcd_display(hwnd); 00523 return; 00524 } 00525 /* if pressed dot and it's already in the string, then return */ 00526 if (_tcschr(calc.buffer, TEXT('.')) != NULL) 00527 return; 00528 } 00529 if (idc != IDC_STATIC) { 00530 while (idc != key2code[i].idc) i++; 00531 } 00532 n = calc.ptr - calc.buffer; 00533 if (idc == IDC_BUTTON_0 && n == 0) { 00534 /* no need to put the dot because it's handled by update_lcd_display() */ 00535 calc.buffer[0] = TEXT('0'); 00536 calc.buffer[1] = TEXT('\0'); 00537 update_lcd_display(hwnd); 00538 return; 00539 } 00540 switch (calc.base) { 00541 case IDC_RADIO_HEX: 00542 if (n >= 16) 00543 return; 00544 break; 00545 case IDC_RADIO_DEC: 00546 if (n >= SIZEOF(calc.buffer)-1) 00547 return; 00548 if (calc.sci_in) { 00549 if (idc != IDC_STATIC) 00550 calc.esp = (calc.esp * 10 + (key2code[i].key-'0')) % LOCAL_EXP_SIZE; 00551 if (calc.ptr == calc.buffer) 00552 _stprintf(calc.ptr, TEXT("0.e%+d"), calc.esp); 00553 else { 00554 /* adds the dot at the end if the number has no decimal part */ 00555 if (!_tcschr(calc.buffer, TEXT('.'))) 00556 *calc.ptr++ = TEXT('.'); 00557 _stprintf(calc.ptr, TEXT("e%+d"), calc.esp); 00558 } 00559 update_lcd_display(hwnd); 00560 return; 00561 } 00562 break; 00563 case IDC_RADIO_OCT: 00564 if (n >= 22) 00565 return; 00566 break; 00567 case IDC_RADIO_BIN: 00568 if (n >= 64) 00569 return; 00570 break; 00571 } 00572 calc.ptr += _stprintf(calc.ptr, TEXT("%C"), key2code[i].key); 00573 update_lcd_display(hwnd); 00574 } 00575 00576 static void prepare_rpn_result(calc_number_t *rpn, TCHAR *buffer, int size, int base) 00577 { 00578 if (calc.is_nan) { 00579 rpn_zero(&calc.code); 00580 LoadString(calc.hInstance, IDS_MATH_ERROR, buffer, size); 00581 return; 00582 } 00583 prepare_rpn_result_2(rpn, buffer, size, base); 00584 } 00585 00586 static void display_rpn_result(HWND hwnd, calc_number_t *rpn) 00587 { 00588 calc.sci_in = FALSE; 00589 prepare_rpn_result(rpn, calc.buffer, SIZEOF(calc.buffer), calc.base); 00590 calc.ptr = calc.buffer + _tcslen(calc.buffer); 00591 update_lcd_display(hwnd); 00592 calc.ptr = calc.buffer; 00593 update_parent_display(hwnd); 00594 } 00595 00596 static int get_modifiers(HWND hwnd) 00597 { 00598 int modifiers = 0; 00599 00600 if (SendDlgItemMessage(hwnd, IDC_CHECK_INV, BM_GETCHECK, 0, 0)) 00601 modifiers |= MODIFIER_INV; 00602 if (SendDlgItemMessage(hwnd, IDC_CHECK_HYP, BM_GETCHECK, 0, 0)) 00603 modifiers |= MODIFIER_HYP; 00604 00605 return modifiers; 00606 } 00607 00608 static void convert_text2number(calc_number_t *a) 00609 { 00610 /* if the screen output buffer is empty, then */ 00611 /* the operand is taken from the last input */ 00612 if (calc.buffer == calc.ptr) { 00613 /* if pushed valued is ZERO then we should grab it */ 00614 if (!_tcscmp(calc.buffer, TEXT("0.")) || 00615 !_tcscmp(calc.buffer, TEXT("0"))) 00616 /* this zero is good for both integer and decimal */ 00617 rpn_zero(a); 00618 else 00619 rpn_copy(a, &calc.code); 00620 return; 00621 } 00622 /* ZERO is the default value for all numeric bases */ 00623 rpn_zero(a); 00624 convert_text2number_2(a); 00625 } 00626 00627 static const struct _update_check_menus { 00628 DWORD *sel; 00629 WORD idm; 00630 WORD idc; 00631 } upd[] = { 00632 { &calc.layout, IDM_VIEW_STANDARD, CALC_LAYOUT_STANDARD }, 00633 { &calc.layout, IDM_VIEW_SCIENTIFIC, CALC_LAYOUT_SCIENTIFIC }, 00634 { &calc.layout, IDM_VIEW_CONVERSION, CALC_LAYOUT_CONVERSION }, 00635 /*-----------------------------------------*/ 00636 { &calc.base, IDM_VIEW_HEX, IDC_RADIO_HEX, }, 00637 { &calc.base, IDM_VIEW_DEC, IDC_RADIO_DEC, }, 00638 { &calc.base, IDM_VIEW_OCT, IDC_RADIO_OCT, }, 00639 { &calc.base, IDM_VIEW_BIN, IDC_RADIO_BIN, }, 00640 /*-----------------------------------------*/ 00641 { &calc.degr, IDM_VIEW_DEG, IDC_RADIO_DEG, }, 00642 { &calc.degr, IDM_VIEW_RAD, IDC_RADIO_RAD, }, 00643 { &calc.degr, IDM_VIEW_GRAD, IDC_RADIO_GRAD, }, 00644 /*-----------------------------------------*/ 00645 { &calc.size, IDM_VIEW_QWORD, IDC_RADIO_QWORD, }, 00646 { &calc.size, IDM_VIEW_DWORD, IDC_RADIO_DWORD, }, 00647 { &calc.size, IDM_VIEW_WORD, IDC_RADIO_WORD, }, 00648 { &calc.size, IDM_VIEW_BYTE, IDC_RADIO_BYTE, }, 00649 }; 00650 00651 static void update_menu(HWND hwnd) 00652 { 00653 HMENU hMenu = GetSubMenu(GetMenu(hwnd), 1); 00654 unsigned int x; 00655 00656 for (x=0; x<SIZEOF(upd); x++) { 00657 if (*(upd[x].sel) != upd[x].idc) { 00658 CheckMenuItem(hMenu, upd[x].idm, MF_BYCOMMAND|MF_UNCHECKED); 00659 SendMessage((HWND)GetDlgItem(hwnd,upd[x].idc),BM_SETCHECK,FALSE,0L); 00660 } else { 00661 CheckMenuItem(hMenu, upd[x].idm, MF_BYCOMMAND|MF_CHECKED); 00662 SendMessage((HWND)GetDlgItem(hwnd,upd[x].idc),BM_SETCHECK,TRUE,0L); 00663 } 00664 } 00665 CheckMenuItem(hMenu, IDM_VIEW_GROUP, MF_BYCOMMAND|(calc.usesep ? MF_CHECKED : MF_UNCHECKED)); 00666 } 00667 00668 typedef struct { 00669 WORD idc; 00670 WORD mask; 00671 } radio_config_t; 00672 00673 static const radio_config_t radio_setup[] = { 00674 /* CONTROL-ID hex dec oct bin */ 00675 { IDC_RADIO_QWORD, MAKE_BITMASK4( 1, 0, 1, 1) }, 00676 { IDC_RADIO_DWORD, MAKE_BITMASK4( 1, 0, 1, 1) }, 00677 { IDC_RADIO_WORD, MAKE_BITMASK4( 1, 0, 1, 1) }, 00678 { IDC_RADIO_BYTE, MAKE_BITMASK4( 1, 0, 1, 1) }, 00679 { IDC_RADIO_DEG, MAKE_BITMASK4( 0, 1, 0, 0) }, 00680 { IDC_RADIO_RAD, MAKE_BITMASK4( 0, 1, 0, 0) }, 00681 { IDC_RADIO_GRAD, MAKE_BITMASK4( 0, 1, 0, 0) }, 00682 }; 00683 00684 static void enable_allowed_controls(HWND hwnd, DWORD base) 00685 { 00686 BYTE mask; 00687 int n; 00688 00689 switch (base) { 00690 case IDC_RADIO_DEC: 00691 mask = BITMASK_DEC_MASK; 00692 break; 00693 case IDC_RADIO_HEX: 00694 mask = BITMASK_HEX_MASK; 00695 break; 00696 case IDC_RADIO_OCT: 00697 mask = BITMASK_OCT_MASK; 00698 break; 00699 case IDC_RADIO_BIN: 00700 mask = BITMASK_BIN_MASK; 00701 break; 00702 default: 00703 return; 00704 } 00705 for (n=0; n<SIZEOF(key2code); n++) { 00706 if (key2code[n].mask != 0) { 00707 HWND hCtlWnd = GetDlgItem(hwnd, key2code[n].idc); 00708 BOOL current; 00709 00710 if ((key2code[n].mask & BITMASK_IS_STATS)) 00711 current = IsWindow(calc.hStatWnd) ? TRUE : FALSE; 00712 else 00713 current = (key2code[n].mask & mask) ? TRUE : FALSE; 00714 if (IsWindowEnabled(hCtlWnd) != current) 00715 EnableWindow(hCtlWnd, current); 00716 } 00717 } 00718 } 00719 00720 static void update_radio(HWND hwnd, unsigned int base) 00721 { 00722 HMENU hMenu; 00723 LPCTSTR lpMenuId; 00724 WORD mask; 00725 int n; 00726 00727 switch (base) { 00728 case IDC_RADIO_DEC: 00729 lpMenuId = MAKEINTRESOURCE(IDR_MENU_SCIENTIFIC_1); 00730 mask = BITMASK_DEC_MASK; 00731 break; 00732 case IDC_RADIO_HEX: 00733 lpMenuId = MAKEINTRESOURCE(IDR_MENU_SCIENTIFIC_2); 00734 mask = BITMASK_HEX_MASK; 00735 break; 00736 case IDC_RADIO_OCT: 00737 lpMenuId = MAKEINTRESOURCE(IDR_MENU_SCIENTIFIC_2); 00738 mask = BITMASK_OCT_MASK; 00739 break; 00740 case IDC_RADIO_BIN: 00741 lpMenuId = MAKEINTRESOURCE(IDR_MENU_SCIENTIFIC_2); 00742 mask = BITMASK_BIN_MASK; 00743 break; 00744 default: 00745 return; 00746 } 00747 00748 if (calc.base != base) { 00749 convert_text2number(&calc.code); 00750 convert_real_integer(base); 00751 calc.base = base; 00752 display_rpn_result(hwnd, &calc.code); 00753 00754 hMenu = GetMenu(hwnd); 00755 DestroyMenu(hMenu); 00756 hMenu = LoadMenu(calc.hInstance, lpMenuId); 00757 SetMenu(hwnd, hMenu); 00758 update_menu(hwnd); 00759 00760 for (n=0; n<SIZEOF(radio_setup); n++) 00761 ShowWindow(GetDlgItem(hwnd, radio_setup[n].idc), (radio_setup[n].mask & mask) ? SW_SHOW : SW_HIDE); 00762 00763 enable_allowed_controls(hwnd, base); 00764 } 00765 00766 SendDlgItemMessage(hwnd, calc.base, BM_SETCHECK, BST_CHECKED, 0); 00767 if (base == IDC_RADIO_DEC) 00768 SendDlgItemMessage(hwnd, calc.degr, BM_SETCHECK, BST_CHECKED, 0); 00769 else 00770 SendDlgItemMessage(hwnd, calc.size, BM_SETCHECK, BST_CHECKED, 0); 00771 } 00772 00773 static void update_memory_flag(HWND hWnd, BOOL mem_flag) 00774 { 00775 calc.is_memory = mem_flag; 00776 SendDlgItemMessage(hWnd, IDC_TEXT_MEMORY, WM_SETTEXT, 0, (LPARAM)(mem_flag ? TEXT("M") : TEXT(""))); 00777 } 00778 00779 static void update_n_stats_items(HWND hWnd, TCHAR *buffer) 00780 { 00781 unsigned int n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0); 00782 00783 _stprintf(buffer, TEXT("n=%d"), n); 00784 SendDlgItemMessage(hWnd, IDC_TEXT_NITEMS, WM_SETTEXT, 0, (LPARAM)buffer); 00785 } 00786 00787 static void clean_stat_list(void) 00788 { 00789 statistic_t *p = calc.stat; 00790 00791 while (p != NULL) { 00792 statistic_t *s = p; 00793 p = (statistic_t *)(p->next); 00794 rpn_free(&s->num); 00795 free(s); 00796 } 00797 calc.stat = p; 00798 } 00799 00800 static void delete_stat_item(int n) 00801 { 00802 statistic_t *p = calc.stat; 00803 statistic_t *s; 00804 00805 if (n == 0) { 00806 calc.stat = (statistic_t *)p->next; 00807 rpn_free(&p->num); 00808 free(p); 00809 } else { 00810 s = (statistic_t *)p->next; 00811 while (--n) { 00812 p = s; 00813 s = (statistic_t *)p->next; 00814 } 00815 p->next = s->next; 00816 rpn_free(&s->num); 00817 free(s); 00818 } 00819 } 00820 00821 static char *ReadConversion(const char *formula) 00822 { 00823 int len = strlen(formula); 00824 char *str = (char *)malloc(len+3); 00825 00826 if (str == NULL) 00827 return NULL; 00828 00829 str[0] = '('; 00830 memcpy(str+1, formula, len); 00831 str[len+1] = ')'; 00832 str[len+2] = '\0'; 00833 00834 _tcscpy(calc.source, (*calc.buffer == _T('\0')) ? _T("0") : calc.buffer); 00835 00836 /* clear display content before proceeding */ 00837 calc.ptr = calc.buffer; 00838 calc.buffer[0] = TEXT('\0'); 00839 00840 return str; 00841 } 00842 00843 static INT_PTR CALLBACK DlgStatProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 00844 { 00845 TCHAR buffer[SIZEOF(calc.buffer)]; 00846 DWORD n; 00847 00848 switch (msg) { 00849 case WM_INITDIALOG: 00850 return TRUE; 00851 case WM_COMMAND: 00852 switch (LOWORD(wp)) { 00853 case IDC_LIST_STAT: 00854 if (HIWORD(wp) == CBN_DBLCLK) 00855 SendMessage(hWnd, WM_COMMAND, (WPARAM)IDC_BUTTON_LOAD, 0); 00856 return TRUE; 00857 case IDC_BUTTON_RET: 00858 SetFocus(GetDlgItem(GetParent(hWnd), IDC_BUTTON_FOCUS)); 00859 return TRUE; 00860 case IDC_BUTTON_LOAD: 00861 n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCURSEL, 0, 0); 00862 if (n == (DWORD)-1) 00863 return TRUE; 00864 PostMessage(GetParent(hWnd), WM_LOAD_STAT, (WPARAM)n, 0); 00865 return TRUE; 00866 case IDC_BUTTON_CD: 00867 n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCURSEL, 0, 0); 00868 if (n == (DWORD)-1) 00869 return TRUE; 00870 SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_DELETESTRING, (WPARAM)n, 0); 00871 update_n_stats_items(hWnd, buffer); 00872 delete_stat_item(n); 00873 return TRUE; 00874 case IDC_BUTTON_CAD: 00875 SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_RESETCONTENT, 0, 0); 00876 clean_stat_list(); 00877 update_n_stats_items(hWnd, buffer); 00878 return TRUE; 00879 } 00880 break; 00881 case WM_CLOSE: 00882 clean_stat_list(); 00883 DestroyWindow(hWnd); 00884 return TRUE; 00885 case WM_DESTROY: 00886 PostMessage(GetParent(hWnd), WM_CLOSE_STATS, 0, 0); 00887 return TRUE; 00888 case WM_INSERT_STAT: 00889 prepare_rpn_result(&(((statistic_t *)lp)->num), 00890 buffer, SIZEOF(buffer), 00891 ((statistic_t *)lp)->base); 00892 SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_ADDSTRING, 0, (LPARAM)buffer); 00893 update_n_stats_items(hWnd, buffer); 00894 return TRUE; 00895 } 00896 return FALSE; 00897 } 00898 00899 static WPARAM idm_2_idc(int idm) 00900 { 00901 int x; 00902 00903 for (x=0; x<SIZEOF(upd); x++) { 00904 if (upd[x].idm == idm) 00905 break; 00906 } 00907 return (WPARAM)(upd[x].idc); 00908 } 00909 00910 static void CopyMemToClipboard(void *ptr) 00911 { 00912 if(OpenClipboard(NULL)) { 00913 HGLOBAL clipbuffer; 00914 TCHAR *buffer; 00915 00916 EmptyClipboard(); 00917 clipbuffer = GlobalAlloc(GMEM_DDESHARE, (_tcslen(ptr)+1)*sizeof(TCHAR)); 00918 buffer = (TCHAR *)GlobalLock(clipbuffer); 00919 _tcscpy(buffer, ptr); 00920 GlobalUnlock(clipbuffer); 00921 #ifdef UNICODE 00922 SetClipboardData(CF_UNICODETEXT,clipbuffer); 00923 #else 00924 SetClipboardData(CF_TEXT,clipbuffer); 00925 #endif 00926 CloseClipboard(); 00927 } 00928 } 00929 00930 static void handle_copy_command(HWND hWnd) 00931 { 00932 TCHAR display[sizeof(calc.buffer)]; 00933 00934 SendDlgItemMessage(hWnd, IDC_TEXT_OUTPUT, WM_GETTEXT, (WPARAM)SIZEOF(display), (LPARAM)display); 00935 if (calc.base == IDC_RADIO_DEC && _tcschr(calc.buffer, _T('.')) == NULL) 00936 display[_tcslen(display)-calc.sDecimal_len] = TEXT('\0'); 00937 CopyMemToClipboard(display); 00938 } 00939 00940 static char *ReadClipboard(void) 00941 { 00942 char *buffer = NULL; 00943 00944 if (OpenClipboard(NULL)) { 00945 HANDLE hData = GetClipboardData(CF_TEXT); 00946 char *fromClipboard; 00947 00948 if (hData != NULL) { 00949 fromClipboard = (char *)GlobalLock(hData); 00950 if (strlen(fromClipboard)) 00951 buffer = _strupr(_strdup(fromClipboard)); 00952 GlobalUnlock( hData ); 00953 } 00954 CloseClipboard(); 00955 } 00956 return buffer; 00957 } 00958 00959 static char *handle_sequence_input(HWND hwnd, sequence_t *seq) 00960 { 00961 char *ptr = seq->ptr; 00962 int ch, x; 00963 00964 ch = *ptr++; 00965 if (ch == '\\') 00966 PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_DAT, 0); 00967 else 00968 if (ch == ':') { 00969 ch = *ptr; 00970 if (ch != '\0') 00971 ptr++; 00972 switch (ch) { 00973 case 'C': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MC, 0); break; 00974 case 'E': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_EXP,0); break; 00975 case 'M': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MS, 0); break; 00976 case 'P': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MP, 0); break; 00977 case 'Q': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_CANC, 0); break; 00978 case 'R': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MR, 0); break; 00979 } 00980 } else 00981 if (ch == '$') { 00982 calc.ptr = 00983 _tcscpy(calc.buffer, calc.source) + 00984 _tcslen(calc.source); 00985 } else { 00986 for (x=0; x<SIZEOF(key2code); x++) { 00987 if (!(key2code[x].mask & BITMASK_IS_ASCII) || 00988 (key2code[x].mask & BITMASK_IS_CTRL)) 00989 continue; 00990 if (key2code[x].key == ch) { 00991 PostMessage(hwnd, WM_COMMAND, (WPARAM)key2code[x].idc, 0); 00992 break; 00993 } 00994 } 00995 } 00996 seq->ptr = ptr; 00997 if (*ptr != '\0') 00998 PostMessage(hwnd, seq->wm_msg, 0, 0); 00999 else { 01000 free(seq->data); 01001 seq->data = seq->ptr = ptr = NULL; 01002 } 01003 return ptr; 01004 } 01005 01006 static void run_dat_sta(calc_number_t *a) 01007 { 01008 statistic_t *s = (statistic_t *)malloc(sizeof(statistic_t)); 01009 statistic_t *p = calc.stat; 01010 01011 rpn_alloc(&s->num); 01012 rpn_copy(&s->num, a); 01013 s->base = calc.base; 01014 s->next = NULL; 01015 if (p == NULL) 01016 calc.stat = s; 01017 else { 01018 while (p->next != NULL) 01019 p = (statistic_t *)(p->next); 01020 p->next = s; 01021 } 01022 PostMessage(calc.hStatWnd, WM_INSERT_STAT, 0, (LPARAM)s); 01023 } 01024 01025 static void run_mp(calc_number_t *c) 01026 { 01027 calc_node_t cn; 01028 01029 cn.number = *c; 01030 cn.base = calc.base; 01031 run_operator(&calc.memory, &calc.memory, &cn, RPN_OPERATOR_ADD); 01032 update_memory_flag(calc.hWnd, TRUE); 01033 } 01034 01035 static void run_mm(calc_number_t *c) 01036 { 01037 calc_node_t cn; 01038 01039 cn.number = *c; 01040 cn.base = calc.base; 01041 run_operator(&calc.memory, &calc.memory, &cn, RPN_OPERATOR_SUB); 01042 update_memory_flag(calc.hWnd, TRUE); 01043 } 01044 01045 static void run_ms(calc_number_t *c) 01046 { 01047 rpn_copy(&calc.memory.number, c); 01048 calc.memory.base = calc.base; 01049 update_memory_flag(calc.hWnd, rpn_is_zero(&calc.memory.number) ? FALSE : TRUE); 01050 } 01051 01052 static void run_mw(calc_number_t *c) 01053 { 01054 calc_number_t tmp; 01055 01056 rpn_copy(&tmp, &calc.memory.number); 01057 rpn_copy(&calc.memory.number, c); 01058 calc.memory.base = calc.base; 01059 if (calc.is_memory) 01060 rpn_copy(c, &tmp); 01061 update_memory_flag(calc.hWnd, rpn_is_zero(&calc.memory.number) ? FALSE : TRUE); 01062 } 01063 01064 static statistic_t *upload_stat_number(int n) 01065 { 01066 statistic_t *p = calc.stat; 01067 01068 if (p == NULL) 01069 return p; 01070 01071 while (n--) { 01072 p = (statistic_t *)(p->next); 01073 if (p == NULL) 01074 return p; 01075 } 01076 01077 #ifndef ENABLE_MULTI_PRECISION 01078 if (calc.base != p->base) { 01079 if (calc.base == IDC_RADIO_DEC) 01080 calc.code.f = (double)p->num.i; 01081 else { 01082 calc.code.i = (__int64)p->num.f; 01083 apply_int_mask(&calc.code); 01084 } 01085 } else 01086 #endif 01087 rpn_copy(&calc.code, &p->num); 01088 01089 calc.is_nan = FALSE; 01090 01091 return p; 01092 } 01093 01094 static void run_pow(calc_number_t *number) 01095 { 01096 exec_infix2postfix(number, RPN_OPERATOR_POW); 01097 } 01098 01099 static void run_sqr(calc_number_t *number) 01100 { 01101 exec_infix2postfix(number, RPN_OPERATOR_SQR); 01102 } 01103 01104 static void run_fe(calc_number_t *number) 01105 { 01106 calc.sci_out = ((calc.sci_out == TRUE) ? FALSE : TRUE); 01107 } 01108 01109 static void handle_context_menu(HWND hWnd, WPARAM wp, LPARAM lp) 01110 { 01111 TCHAR text[64]; 01112 HMENU hMenu = CreatePopupMenu(); 01113 BOOL idm; 01114 01115 LoadString(calc.hInstance, IDS_QUICKHELP, text, SIZEOF(text)); 01116 AppendMenu(hMenu, MF_STRING | MF_ENABLED, IDM_HELP_HELP, text); 01117 idm = TrackPopupMenu( hMenu, 01118 TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON, 01119 LOWORD(lp), 01120 HIWORD(lp), 01121 0, 01122 hWnd, 01123 NULL); 01124 DestroyMenu(hMenu); 01125 #ifndef DISABLE_HTMLHELP_SUPPORT 01126 if (idm) { 01127 HH_POPUP popup; 01128 01129 memset(&popup, 0, sizeof(popup)); 01130 popup.cbStruct = sizeof(HH_POPUP); 01131 popup.clrForeground = 1; 01132 popup.clrBackground = -1; 01133 popup.pt.x = LOWORD(lp); 01134 popup.pt.y = HIWORD(lp); 01135 popup.rcMargins.top = -1; 01136 popup.rcMargins.bottom = -1; 01137 popup.rcMargins.left = -1; 01138 popup.rcMargins.right = -1; 01139 popup.idString = GetWindowLongPtr((HWND)wp, GWL_ID); 01140 HtmlHelp((HWND)wp, HTMLHELP_PATH("/popups.txt"), HH_DISPLAY_TEXT_POPUP, (DWORD_PTR)&popup); 01141 } 01142 #else 01143 (void)idm; 01144 #endif 01145 } 01146 01147 static void run_canc(calc_number_t *c) 01148 { 01149 flush_postfix(); 01150 rpn_zero(c); 01151 /* clear also scientific display modes */ 01152 calc.sci_out = FALSE; 01153 calc.sci_in = FALSE; 01154 /* clear state of inv and hyp flags */ 01155 SendDlgItemMessage(calc.hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0); 01156 SendDlgItemMessage(calc.hWnd, IDC_CHECK_HYP, BM_SETCHECK, 0, 0); 01157 } 01158 01159 static void run_rpar(calc_number_t *c) 01160 { 01161 exec_closeparent(c); 01162 } 01163 01164 static void run_lpar(calc_number_t *c) 01165 { 01166 exec_infix2postfix(c, RPN_OPERATOR_PARENT); 01167 } 01168 01169 static LRESULT CALLBACK SubclassButtonProc(HWND hWnd, WPARAM wp, LPARAM lp) 01170 { 01171 LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lp; 01172 DWORD dwStyle; 01173 UINT dwText; 01174 TCHAR text[64]; 01175 int dx, dy, len; 01176 SIZE size; 01177 POINT pt; 01178 01179 if(dis->CtlType == ODT_BUTTON) { 01180 /* 01181 * little exception: 1/x has different color 01182 * in standard and scientific modes 01183 */ 01184 if ((calc.layout == CALC_LAYOUT_STANDARD || 01185 calc.layout == CALC_LAYOUT_CONVERSION) && 01186 IDC_BUTTON_RX == dis->CtlID) { 01187 SetTextColor(dis->hDC, CALC_CLR_BLUE); 01188 } else 01189 for (dx=0; dx<SIZEOF(key2code); dx++) { 01190 if (key2code[dx].idc == dis->CtlID) { 01191 SetTextColor(dis->hDC, key2code[dx].col); 01192 break; 01193 } 01194 } 01195 /* button text to write */ 01196 len = GetWindowText(dis->hwndItem, text, SIZEOF(text)); 01197 /* default state: unpushed & enabled */ 01198 dwStyle = 0; 01199 dwText = 0; 01200 if ((dis->itemState & ODS_DISABLED)) 01201 dwText = DSS_DISABLED; 01202 if ((dis->itemState & ODS_SELECTED)) 01203 dwStyle = DFCS_PUSHED; 01204 01205 DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH | dwStyle); 01206 GetTextExtentPoint32(dis->hDC, text, len, &size); 01207 dx = ((dis->rcItem.right-dis->rcItem.left) - size.cx) >> 1; 01208 dy = ((dis->rcItem.bottom-dis->rcItem.top) - size.cy) >> 1; 01209 if ((dwStyle & DFCS_PUSHED)) { 01210 dx++; 01211 dy++; 01212 } 01213 pt.x = dis->rcItem.left + dx; 01214 pt.y = dis->rcItem.top + dy; 01215 DrawState(dis->hDC, NULL, NULL, (LPARAM)text, 0, pt.x, pt.y, size.cx, size.cy, DST_TEXT | dwText); 01216 } 01217 return 1L; 01218 } 01219 01220 static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 01221 { 01222 unsigned int x; 01223 RECT rc; 01224 01225 switch (msg) { 01226 case WM_DRAWITEM: 01227 return SubclassButtonProc(hWnd, wp, lp); 01228 01229 case WM_INITDIALOG: 01230 calc.hWnd=hWnd; 01231 01232 #ifdef USE_KEYBOARD_HOOK 01233 calc.hKeyboardHook=SetWindowsHookEx( 01234 WH_KEYBOARD, 01235 KeyboardHookProc, 01236 NULL, 01237 GetCurrentThreadId() 01238 ); 01239 #endif 01240 rpn_zero(&calc.code); 01241 calc.sci_out = FALSE; 01242 calc.base = IDC_RADIO_DEC; 01243 calc.size = IDC_RADIO_QWORD; 01244 calc.degr = IDC_RADIO_DEG; 01245 calc.ptr = calc.buffer; 01246 calc.is_nan = FALSE; 01247 enable_allowed_controls(hWnd, IDC_RADIO_DEC); 01248 update_radio(hWnd, IDC_RADIO_DEC); 01249 update_menu(hWnd); 01250 display_rpn_result(hWnd, &calc.code); 01251 update_memory_flag(hWnd, calc.is_memory); 01252 /* remove keyboard focus */ 01253 SetFocus(GetDlgItem(hWnd, IDC_BUTTON_FOCUS)); 01254 /* set our calc icon */ 01255 SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(calc.hInstance, MAKEINTRESOURCE(IDI_CALC_BIG))); 01256 SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(calc.hInstance, MAKEINTRESOURCE(IDI_CALC_SMALL))); 01257 /* update text for decimal button */ 01258 SendDlgItemMessage(hWnd, IDC_BUTTON_DOT, WM_SETTEXT, (WPARAM)0, (LPARAM)calc.sDecimal); 01259 /* Fill combo box for conversion */ 01260 if (calc.layout == CALC_LAYOUT_CONVERSION) 01261 ConvInit(hWnd); 01262 /* Restore the window at the same position it was */ 01263 if (calc.x_coord >= 0 && calc.y_coord >= 0) { 01264 int w, h, sw, sh; 01265 01266 GetWindowRect(hWnd, &rc); 01267 w = rc.right-rc.left; 01268 h = rc.bottom-rc.top; 01269 sw = GetSystemMetrics(SM_CXSCREEN); 01270 sh = GetSystemMetrics(SM_CYSCREEN); 01271 if (calc.x_coord+w > sw) calc.x_coord = sw - w; 01272 if (calc.y_coord+h > sh) calc.y_coord = sh - h; 01273 MoveWindow(hWnd, calc.x_coord, calc.y_coord, w, h, FALSE); 01274 } 01275 break; 01276 case WM_CTLCOLORSTATIC: 01277 if ((HWND)lp == GetDlgItem(hWnd, IDC_TEXT_OUTPUT)) 01278 return (LRESULT)GetStockObject(WHITE_BRUSH); 01279 break; 01280 case WM_HANDLE_CLIPBOARD: 01281 handle_sequence_input(hWnd, &calc.Clipboard); 01282 return TRUE; 01283 case WM_COMMAND: 01284 /* 01285 * if selection of category is changed, we must 01286 * updatethe content of the "from/to" combo boxes. 01287 */ 01288 if (wp == MAKEWPARAM(IDC_COMBO_CATEGORY, CBN_SELCHANGE)) { 01289 ConvAdjust(hWnd, SendDlgItemMessage(hWnd, IDC_COMBO_CATEGORY, CB_GETCURSEL, 0, 0)); 01290 return TRUE; 01291 } 01292 if (HIWORD(wp) != BN_CLICKED && HIWORD(wp) != BN_DBLCLK) 01293 break; 01294 /* avoid flicker if the user selects from keyboard */ 01295 if (GetFocus() != GetDlgItem(hWnd, IDC_BUTTON_FOCUS)) 01296 SetFocus(GetDlgItem(hWnd, IDC_BUTTON_FOCUS)); 01297 switch (LOWORD(wp)) { 01298 case IDM_HELP_ABOUT: 01299 DialogBox(calc.hInstance,MAKEINTRESOURCE(IDD_DIALOG_ABOUT), hWnd, AboutDlgProc); 01300 return TRUE; 01301 case IDM_HELP_HELP: 01302 #ifndef DISABLE_HTMLHELP_SUPPORT 01303 HtmlHelp(hWnd, HTMLHELP_PATH("/general_information.htm"), HH_DISPLAY_TOPIC, (DWORD_PTR)NULL); 01304 #endif 01305 return TRUE; 01306 case IDM_VIEW_STANDARD: 01307 calc.layout = CALC_LAYOUT_STANDARD; 01308 calc.action = IDM_VIEW_STANDARD; 01309 DestroyWindow(hWnd); 01310 save_config(); 01311 return TRUE; 01312 case IDM_VIEW_SCIENTIFIC: 01313 calc.layout = CALC_LAYOUT_SCIENTIFIC; 01314 calc.action = IDM_VIEW_SCIENTIFIC; 01315 DestroyWindow(hWnd); 01316 save_config(); 01317 return TRUE; 01318 case IDM_VIEW_CONVERSION: 01319 calc.layout = CALC_LAYOUT_CONVERSION; 01320 calc.action = IDM_VIEW_CONVERSION; 01321 DestroyWindow(hWnd); 01322 save_config(); 01323 return TRUE; 01324 case IDM_VIEW_HEX: 01325 case IDM_VIEW_DEC: 01326 case IDM_VIEW_OCT: 01327 case IDM_VIEW_BIN: 01328 case IDM_VIEW_DEG: 01329 case IDM_VIEW_RAD: 01330 case IDM_VIEW_GRAD: 01331 case IDM_VIEW_QWORD: 01332 case IDM_VIEW_DWORD: 01333 case IDM_VIEW_WORD: 01334 case IDM_VIEW_BYTE: 01335 SendMessage(hWnd, WM_COMMAND, idm_2_idc(LOWORD(wp)), 0); 01336 return TRUE; 01337 case IDM_EDIT_COPY: 01338 handle_copy_command(hWnd); 01339 return TRUE; 01340 case IDM_EDIT_PASTE: 01341 if (calc.Clipboard.data != NULL) 01342 break; 01343 calc.Clipboard.data = ReadClipboard(); 01344 if (calc.Clipboard.data != NULL) { 01345 /* clear the content of the display before pasting */ 01346 PostMessage(hWnd, WM_COMMAND, IDC_BUTTON_CE, 0); 01347 calc.Clipboard.ptr = calc.Clipboard.data; 01348 calc.Clipboard.wm_msg = WM_HANDLE_CLIPBOARD; 01349 handle_sequence_input(hWnd, &calc.Clipboard); 01350 } 01351 return TRUE; 01352 case IDM_VIEW_GROUP: 01353 calc.usesep = (calc.usesep ? FALSE : TRUE); 01354 update_menu(hWnd); 01355 update_lcd_display(hWnd); 01356 save_config(); 01357 return TRUE; 01358 case IDC_BUTTON_CONVERT: 01359 ConvExecute(hWnd); 01360 return TRUE; 01361 case IDC_BUTTON_CE: { 01362 calc_number_t tmp; 01363 rpn_zero(&tmp); 01364 display_rpn_result(hWnd, &tmp); 01365 } 01366 return TRUE; 01367 case IDC_RADIO_DEC: 01368 case IDC_RADIO_HEX: 01369 case IDC_RADIO_OCT: 01370 case IDC_RADIO_BIN: 01371 /* GNU WINDRES is bugged so I must always force radio update */ 01372 /* (Fix for Win95/98) */ 01373 #ifdef _MSC_VER 01374 if (calc.base == LOWORD(wp)) 01375 break; 01376 #endif 01377 calc.is_nan = FALSE; 01378 update_radio(hWnd, LOWORD(wp)); 01379 return TRUE; 01380 case IDC_RADIO_DEG: 01381 case IDC_RADIO_RAD: 01382 case IDC_RADIO_GRAD: 01383 /* GNU WINDRES is bugged so I must always force radio update */ 01384 /* (Fix for Win95/98) */ 01385 #ifdef _MSC_VER 01386 if (calc.degr == LOWORD(wp)) 01387 break; 01388 #endif 01389 calc.degr = LOWORD(wp); 01390 calc.is_nan = FALSE; 01391 update_menu(hWnd); 01392 return TRUE; 01393 case IDC_RADIO_QWORD: 01394 case IDC_RADIO_DWORD: 01395 case IDC_RADIO_WORD: 01396 case IDC_RADIO_BYTE: 01397 /* GNU WINDRES is bugged so I must always force radio update */ 01398 /* (Fix for Win95/98) */ 01399 #ifdef _MSC_VER 01400 if (calc.size == LOWORD(wp)) 01401 break; 01402 #endif 01403 calc.size = LOWORD(wp); 01404 calc.is_nan = FALSE; 01405 update_menu(hWnd); 01406 /* 01407 * update the content of the display 01408 */ 01409 convert_text2number(&calc.code); 01410 apply_int_mask(&calc.code); 01411 display_rpn_result(hWnd, &calc.code); 01412 return TRUE; 01413 case IDC_BUTTON_1: 01414 case IDC_BUTTON_2: 01415 case IDC_BUTTON_3: 01416 case IDC_BUTTON_4: 01417 case IDC_BUTTON_5: 01418 case IDC_BUTTON_6: 01419 case IDC_BUTTON_7: 01420 case IDC_BUTTON_8: 01421 case IDC_BUTTON_9: 01422 case IDC_BUTTON_0: 01423 case IDC_BUTTON_DOT: 01424 case IDC_BUTTON_A: 01425 case IDC_BUTTON_B: 01426 case IDC_BUTTON_C: 01427 case IDC_BUTTON_D: 01428 case IDC_BUTTON_E: 01429 case IDC_BUTTON_F: 01430 calc.is_nan = FALSE; 01431 build_operand(hWnd, LOWORD(wp)); 01432 return TRUE; 01433 case IDC_BUTTON_PERCENT: 01434 case IDC_BUTTON_ADD: 01435 case IDC_BUTTON_SUB: 01436 case IDC_BUTTON_MULT: 01437 case IDC_BUTTON_DIV: 01438 case IDC_BUTTON_MOD: 01439 case IDC_BUTTON_AND: 01440 case IDC_BUTTON_OR: 01441 case IDC_BUTTON_XOR: 01442 case IDC_BUTTON_LSH: 01443 case IDC_BUTTON_RSH: 01444 case IDC_BUTTON_EQU: 01445 if (calc.is_nan) break; 01446 /* 01447 * LSH button holds the RSH function too with INV modifier, 01448 * but since it's a two operand operator, it must be handled here. 01449 */ 01450 if (LOWORD(wp) == IDC_BUTTON_LSH && 01451 (get_modifiers(hWnd) & MODIFIER_INV)) { 01452 PostMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDC_BUTTON_RSH, BN_CLICKED), 0); 01453 SendDlgItemMessage(hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0); 01454 break; 01455 } 01456 for (x=0; x<SIZEOF(operator_codes); x++) { 01457 if (LOWORD(wp) == operator_codes[x]) { 01458 convert_text2number(&calc.code); 01459 01460 if (calc.ptr == calc.buffer) { 01461 if (calc.last_operator != x) { 01462 if (x != RPN_OPERATOR_EQUAL) 01463 exec_change_infix(); 01464 } else 01465 if (x == RPN_OPERATOR_EQUAL) { 01466 exec_infix2postfix(&calc.code, calc.prev_operator); 01467 rpn_copy(&calc.code, &calc.prev); 01468 } else 01469 break; 01470 } 01471 01472 /* if no change then quit silently, */ 01473 /* without display updates */ 01474 if (!exec_infix2postfix(&calc.code, x)) 01475 break; 01476 01477 display_rpn_result(hWnd, &calc.code); 01478 break; 01479 } 01480 } 01481 return TRUE; 01482 case IDC_BUTTON_BACK: 01483 if (calc.sci_in) { 01484 if (calc.esp == 0) { 01485 TCHAR *ptr; 01486 01487 calc.sci_in = FALSE; 01488 ptr = _tcschr(calc.ptr, TEXT('e')); 01489 if (ptr) 01490 *ptr = TEXT('\0'); 01491 update_lcd_display(hWnd); 01492 } else { 01493 calc.esp /= 10; 01494 build_operand(hWnd, IDC_STATIC); 01495 } 01496 } else 01497 if (calc.ptr != calc.buffer) { 01498 *--calc.ptr = TEXT('\0'); 01499 if (!_tcscmp(calc.buffer, TEXT("-")) || 01500 !_tcscmp(calc.buffer, TEXT("-0")) || 01501 !_tcscmp(calc.buffer, TEXT("0"))) { 01502 calc.ptr = calc.buffer; 01503 calc.buffer[0] = TEXT('\0'); 01504 } 01505 update_lcd_display(hWnd); 01506 } 01507 return TRUE; 01508 case IDC_BUTTON_MC: 01509 rpn_zero(&calc.memory.number); 01510 update_memory_flag(hWnd, FALSE); 01511 return TRUE; 01512 case IDC_BUTTON_MR: 01513 if (calc.is_memory) { 01514 calc.is_nan = FALSE; 01515 rpn_copy(&calc.code, &calc.memory.number); 01516 display_rpn_result(hWnd, &calc.code); 01517 } 01518 return TRUE; 01519 case IDC_BUTTON_EXP: 01520 if (calc.sci_in || calc.is_nan || calc.buffer == calc.ptr) 01521 break; 01522 calc.sci_in = TRUE; 01523 calc.esp = 0; 01524 build_operand(hWnd, IDC_STATIC); 01525 return TRUE; 01526 case IDC_BUTTON_SIGN: 01527 if (calc.sci_in) { 01528 calc.esp = 0-calc.esp; 01529 build_operand(hWnd, IDC_STATIC); 01530 } else { 01531 if (calc.is_nan || calc.buffer[0] == TEXT('\0')) 01532 break; 01533 01534 if (calc.buffer[0] == TEXT('-')) { 01535 /* make the number positive */ 01536 memmove(calc.buffer, calc.buffer+1, sizeof(calc.buffer)-1); 01537 if (calc.buffer != calc.ptr) 01538 calc.ptr--; 01539 } else { 01540 /* if first char is '0' and no dot, it isn't valid */ 01541 if (calc.buffer[0] == TEXT('0') && 01542 calc.buffer[1] != TEXT('.')) 01543 break; 01544 /* make the number negative */ 01545 memmove(calc.buffer+1, calc.buffer, sizeof(calc.buffer)-1); 01546 calc.buffer[0] = TEXT('-'); 01547 if (calc.buffer != calc.ptr) 01548 calc.ptr++; 01549 } 01550 /* If the input buffer is empty, then 01551 we change also the sign of calc.code 01552 because it could be the result of a 01553 previous calculation. */ 01554 if (calc.buffer == calc.ptr) 01555 rpn_sign(&calc.code); 01556 update_lcd_display(hWnd); 01557 } 01558 return TRUE; 01559 case IDC_BUTTON_RIGHTPAR: 01560 case IDC_BUTTON_LEFTPAR: 01561 case IDC_BUTTON_CANC: 01562 case IDC_BUTTON_MP: 01563 case IDC_BUTTON_DAT: 01564 case IDC_BUTTON_FE: 01565 case IDC_BUTTON_DMS: 01566 case IDC_BUTTON_SQRT: 01567 case IDC_BUTTON_S: 01568 case IDC_BUTTON_SUM: 01569 case IDC_BUTTON_AVE: 01570 case IDC_BUTTON_NF: 01571 case IDC_BUTTON_LN: 01572 case IDC_BUTTON_LOG: 01573 case IDC_BUTTON_Xe2: 01574 case IDC_BUTTON_Xe3: 01575 case IDC_BUTTON_PI: 01576 case IDC_BUTTON_NOT: 01577 case IDC_BUTTON_RX: 01578 case IDC_BUTTON_INT: 01579 case IDC_BUTTON_SIN: 01580 case IDC_BUTTON_COS: 01581 case IDC_BUTTON_TAN: 01582 case IDC_BUTTON_XeY: 01583 case IDC_BUTTON_MS: 01584 for (x=0; x<SIZEOF(function_table); x++) { 01585 if (LOWORD(wp) == function_table[x].idc) { 01586 rpn_callback1 cb = NULL; 01587 01588 /* test if NaN state is important or not */ 01589 if (calc.is_nan && function_table[x].check_nan) break; 01590 /* otherwise, it's cleared */ 01591 calc.is_nan = FALSE; 01592 01593 switch (get_modifiers(hWnd) & function_table[x].range) { 01594 case 0: 01595 cb = function_table[x].direct; 01596 break; 01597 case MODIFIER_INV: 01598 cb = function_table[x].inverse; 01599 break; 01600 case MODIFIER_HYP: 01601 cb = function_table[x].hyperb; 01602 break; 01603 case MODIFIER_INV|MODIFIER_HYP: 01604 cb = function_table[x].inv_hyp; 01605 break; 01606 } 01607 if (cb != NULL) { 01608 convert_text2number(&calc.code); 01609 cb(&calc.code); 01610 display_rpn_result(hWnd, &calc.code); 01611 if (!(function_table[x].range & NO_CHAIN)) 01612 exec_infix2postfix(&calc.code, RPN_OPERATOR_NONE); 01613 if (function_table[x].range & MODIFIER_INV) 01614 SendDlgItemMessage(hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0); 01615 if (function_table[x].range & MODIFIER_HYP) 01616 SendDlgItemMessage(hWnd, IDC_CHECK_HYP, BM_SETCHECK, 0, 0); 01617 } 01618 } 01619 } 01620 return TRUE; 01621 case IDC_BUTTON_STA: 01622 if (IsWindow(calc.hStatWnd)) 01623 break; 01624 calc.hStatWnd = CreateDialog(calc.hInstance, 01625 MAKEINTRESOURCE(IDD_DIALOG_STAT), hWnd, (DLGPROC)DlgStatProc); 01626 if (calc.hStatWnd != NULL) { 01627 enable_allowed_controls(hWnd, calc.base); 01628 SendMessage(calc.hStatWnd, WM_SETFOCUS, 0, 0); 01629 } 01630 return TRUE; 01631 } 01632 break; 01633 case WM_CLOSE_STATS: 01634 enable_allowed_controls(hWnd, calc.base); 01635 return TRUE; 01636 case WM_LOAD_STAT: 01637 if (upload_stat_number((int)LOWORD(wp)) != NULL) 01638 display_rpn_result(hWnd, &calc.code); 01639 return TRUE; 01640 case WM_START_CONV: 01641 x = LOWORD(lp); 01642 calc.Convert[x].data = ReadConversion(calc.Convert[x].data); 01643 if (calc.Convert[x].data != NULL) { 01644 calc.Convert[x].ptr = calc.Convert[x].data; 01645 PostMessage(hWnd, HIWORD(lp), 0, 0); 01646 } 01647 return TRUE; 01648 case WM_HANDLE_FROM: 01649 if (calc.is_nan) 01650 break; 01651 if (handle_sequence_input(hWnd, &calc.Convert[0]) == NULL) 01652 PostMessage(hWnd, WM_START_CONV, 0, 01653 MAKELPARAM(0x0001, WM_HANDLE_TO)); 01654 return TRUE; 01655 case WM_HANDLE_TO: 01656 if (!calc.is_nan) 01657 handle_sequence_input(hWnd, &calc.Convert[1]); 01658 return TRUE; 01659 case WM_CLOSE: 01660 calc.action = IDC_STATIC; 01661 DestroyWindow(hWnd); 01662 return TRUE; 01663 case WM_DESTROY: 01664 /* Get (x,y) position of the calculator */ 01665 GetWindowRect(hWnd, &rc); 01666 calc.x_coord = rc.left; 01667 calc.y_coord = rc.top; 01668 #ifdef USE_KEYBOARD_HOOK 01669 UnhookWindowsHookEx(calc.hKeyboardHook); 01670 #endif 01671 PostQuitMessage(0); 01672 return TRUE; 01673 case WM_CONTEXTMENU: 01674 if ((HWND)wp != hWnd) 01675 handle_context_menu(hWnd, wp, lp); 01676 return TRUE; 01677 case WM_ENTERMENULOOP: 01678 calc.is_menu_on = TRUE; 01679 /* Check if a valid format is available in the clipboard */ 01680 EnableMenuItem(GetSubMenu(GetMenu(hWnd), 0), 01681 IDM_EDIT_PASTE, 01682 MF_BYCOMMAND| 01683 (IsClipboardFormatAvailable(CF_TEXT) ? 01684 MF_ENABLED : MF_GRAYED)); 01685 break; 01686 case WM_EXITMENULOOP: 01687 calc.is_menu_on = FALSE; 01688 break; 01689 } 01690 return FALSE; 01691 } 01692 01693 #if defined(__GNUC__) && !defined(__REACTOS__) 01694 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) 01695 #else 01696 int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd) 01697 #endif 01698 { 01699 MSG msg; 01700 DWORD dwLayout; 01701 01702 calc.hInstance = hInstance; 01703 01704 calc.x_coord = -1; 01705 calc.y_coord = -1; 01706 01707 load_config(); 01708 start_rpn_engine(); 01709 01710 do { 01711 /* ignore hwnd: dialogs are already visible! */ 01712 if (calc.layout == CALC_LAYOUT_SCIENTIFIC) 01713 dwLayout = IDD_DIALOG_SCIENTIFIC; 01714 else 01715 if (calc.layout == CALC_LAYOUT_CONVERSION) 01716 dwLayout = IDD_DIALOG_CONVERSION; 01717 else 01718 dwLayout = IDD_DIALOG_STANDARD; 01719 01720 /* This call will always fail if UNICODE for Win9x */ 01721 if (NULL == CreateDialog(hInstance, MAKEINTRESOURCE(dwLayout), NULL, (DLGPROC)DlgMainProc)) 01722 break; 01723 01724 while (GetMessage(&msg, NULL, 0, 0)) { 01725 #ifndef USE_KEYBOARD_HOOK 01726 if ((msg.message == WM_KEYUP || 01727 msg.message == WM_KEYDOWN) && 01728 !calc.is_menu_on) 01729 process_vk_key(msg.wParam, msg.lParam); 01730 #endif 01731 TranslateMessage(&msg); 01732 DispatchMessage(&msg); 01733 } 01734 } while (calc.action != IDC_STATIC); 01735 01736 stop_rpn_engine(); 01737 01738 return 0; 01739 } Generated on Thu Feb 9 04:38:58 2012 for ReactOS by
1.6.3
|