Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

winmain.c

Go 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 doxygen 1.6.3

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.