xref: /reactos/base/applications/calc/winmain.c (revision 30b40247)
1ec1b499aSCarlo-Bramini /*
2ec1b499aSCarlo-Bramini  * ReactOS Calc (main program)
3ec1b499aSCarlo-Bramini  *
4ec1b499aSCarlo-Bramini  * Copyright 2007-2017, Carlo Bramini
5ec1b499aSCarlo-Bramini  *
6ec1b499aSCarlo-Bramini  * This program is free software; you can redistribute it and/or
7ec1b499aSCarlo-Bramini  * modify it under the terms of the GNU Lesser General Public
8ec1b499aSCarlo-Bramini  * License as published by the Free Software Foundation; either
9ec1b499aSCarlo-Bramini  * version 2 of the License, or (at your option) any later version.
10ec1b499aSCarlo-Bramini  *
11ec1b499aSCarlo-Bramini  * This library is distributed in the hope that it will be useful,
12ec1b499aSCarlo-Bramini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13ec1b499aSCarlo-Bramini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14ec1b499aSCarlo-Bramini  * Lesser General Public License for more details.
15ec1b499aSCarlo-Bramini  *
16ec1b499aSCarlo-Bramini  * You should have received a copy of the GNU Lesser General Public
17ec1b499aSCarlo-Bramini  * License along with this library; if not, write to the Free Software
18ec1b499aSCarlo-Bramini  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19ec1b499aSCarlo-Bramini  */
20c2c66affSColin Finck 
21ec1b499aSCarlo-Bramini #include "calc.h"
22c2c66affSColin Finck 
23f6c565bcSCarlo-Bramini #define HTMLHELP_PATH(_pt)  _T("%systemroot%\\Help\\calc.chm::") _T(_pt)
24c2c66affSColin Finck 
25c2c66affSColin Finck #define MAKE_BITMASK4(_show_b16, _show_b10, _show_b8, _show_b2) \
26c2c66affSColin Finck     (((_show_b2)  << 0) | \
27c2c66affSColin Finck      ((_show_b8)  << 1) | \
28c2c66affSColin Finck      ((_show_b10) << 2) | \
29c2c66affSColin Finck      ((_show_b16) << 3))
30c2c66affSColin Finck 
31c2c66affSColin Finck #define MAKE_BITMASK5(_transl, _is_stats, _is_ctrl, _show_b16, _show_b10, _show_b8, _show_b2) \
32c2c66affSColin Finck     (((_show_b2)  << 0) | \
33c2c66affSColin Finck      ((_show_b8)  << 1) | \
34c2c66affSColin Finck      ((_show_b10) << 2) | \
35c2c66affSColin Finck      ((_show_b16) << 3) | \
36c2c66affSColin Finck      ((_is_ctrl)  << 5) | \
37c2c66affSColin Finck      ((_is_stats) << 6) | \
38c2c66affSColin Finck      ((_transl)   << 7))
39c2c66affSColin Finck 
40c2c66affSColin Finck #define KEY_IS_UP       0x80000000
41c2c66affSColin Finck #define KEY_WAS_DOWN    0x40000000
42c2c66affSColin Finck 
43c2c66affSColin Finck #define BITMASK_IS_ASCII    0x80
44c2c66affSColin Finck #define BITMASK_IS_STATS    0x40
45c2c66affSColin Finck #define BITMASK_IS_CTRL     0x20
46c2c66affSColin Finck #define BITMASK_HEX_MASK    0x08
47c2c66affSColin Finck #define BITMASK_DEC_MASK    0x04
48c2c66affSColin Finck #define BITMASK_OCT_MASK    0x02
49c2c66affSColin Finck #define BITMASK_BIN_MASK    0x01
50c2c66affSColin Finck 
510b107f2eSCarlo-Bramini #define CALC_CLR_RED        RGB(0xFF, 0x00, 0x00)
520b107f2eSCarlo-Bramini #define CALC_CLR_BLUE       RGB(0x00, 0x00, 0xFF)
530b107f2eSCarlo-Bramini #define CALC_CLR_PURP       RGB(0xFF, 0x00, 0xFF)
54c2c66affSColin Finck 
55c2c66affSColin Finck typedef struct {
56c2c66affSColin Finck     CHAR key; // Virtual key identifier
57c2c66affSColin Finck     WORD idc; // IDC for posting message
58c2c66affSColin Finck } key2code_t;
59c2c66affSColin Finck 
60c2c66affSColin Finck typedef struct {
61c2c66affSColin Finck     WORD     idc;  // IDC for posting message
62c2c66affSColin Finck     CHAR     key;  // Virtual key identifier
63c2c66affSColin Finck     BYTE     mask; // enable/disable into the various modes.
64c2c66affSColin Finck     COLORREF col;  // color used for drawing the text
65c2c66affSColin Finck } key3code_t;
66c2c66affSColin Finck 
67c2c66affSColin Finck #define CTRL_FLAG   0x100
68c2c66affSColin Finck #define ALT_FLAG    0x200
69c2c66affSColin Finck 
70c2c66affSColin Finck #define CTRL_A  (0x0001+'A'-'A')
71c2c66affSColin Finck #define CTRL_C  (0x0001+'C'-'A')
72c2c66affSColin Finck #define CTRL_D  (0x0001+'D'-'A')
73c2c66affSColin Finck #define CTRL_L  (0x0001+'L'-'A')
74c2c66affSColin Finck #define CTRL_M  (0x0001+'M'-'A')
75c2c66affSColin Finck #define CTRL_P  (0x0001+'P'-'A')
76c2c66affSColin Finck #define CTRL_R  (0x0001+'R'-'A')
77c2c66affSColin Finck #define CTRL_S  (0x0001+'S'-'A')
78c2c66affSColin Finck #define CTRL_T  (0x0001+'T'-'A')
79c2c66affSColin Finck #define CTRL_V  (0x0001+'V'-'A')
80c2c66affSColin Finck #define CTRL_Z  (0x0001+'Z'-'A')
81c2c66affSColin Finck 
82c2c66affSColin Finck static const key3code_t key2code[] = {
83c2c66affSColin Finck     /* CONTROL-ID          Key                    asc sta ctl hex dec oct bin */
84c2c66affSColin Finck     { IDC_BUTTON_STA,      CTRL_S,  MAKE_BITMASK5(  1,  0,  1,  1,  1,  1,  1), CALC_CLR_BLUE, },
85c2c66affSColin Finck     { IDC_BUTTON_AVE,      CTRL_A,  MAKE_BITMASK5(  1,  1,  1,  1,  1,  1,  1), CALC_CLR_BLUE, },
86c2c66affSColin Finck     { IDC_BUTTON_SUM,      CTRL_T,  MAKE_BITMASK5(  1,  1,  1,  1,  1,  1,  1), CALC_CLR_BLUE, },
87c2c66affSColin Finck     { IDC_BUTTON_S,        CTRL_D,  MAKE_BITMASK5(  1,  1,  1,  1,  1,  1,  1), CALC_CLR_BLUE, },
88c2c66affSColin Finck     { IDC_BUTTON_MS,       CTRL_M,  MAKE_BITMASK5(  1,  0,  1,  1,  1,  1,  1), CALC_CLR_RED,  },
89c2c66affSColin Finck     { IDC_BUTTON_MR,       CTRL_R,  MAKE_BITMASK5(  1,  0,  1,  1,  1,  1,  1), CALC_CLR_RED,  },
90c2c66affSColin Finck     { IDC_BUTTON_MP,       CTRL_P,  MAKE_BITMASK5(  1,  0,  1,  1,  1,  1,  1), CALC_CLR_RED,  },
91c2c66affSColin Finck     { IDC_BUTTON_MC,       CTRL_L,  MAKE_BITMASK5(  1,  0,  1,  1,  1,  1,  1), CALC_CLR_RED,  },
92c2c66affSColin Finck     { IDC_BUTTON_0,        '0',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_BLUE, },
93c2c66affSColin Finck     { IDC_BUTTON_1,        '1',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_BLUE, },
94c2c66affSColin Finck     { IDC_BUTTON_2,        '2',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  0), CALC_CLR_BLUE, },
95c2c66affSColin Finck     { IDC_BUTTON_3,        '3',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  0), CALC_CLR_BLUE, },
96c2c66affSColin Finck     { IDC_BUTTON_4,        '4',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  0), CALC_CLR_BLUE, },
97c2c66affSColin Finck     { IDC_BUTTON_5,        '5',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  0), CALC_CLR_BLUE, },
98c2c66affSColin Finck     { IDC_BUTTON_6,        '6',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  0), CALC_CLR_BLUE, },
99c2c66affSColin Finck     { IDC_BUTTON_7,        '7',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  0), CALC_CLR_BLUE, },
100c2c66affSColin Finck     { IDC_BUTTON_8,        '8',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  0,  0), CALC_CLR_BLUE, },
101c2c66affSColin Finck     { IDC_BUTTON_9,        '9',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  0,  0), CALC_CLR_BLUE, },
102c2c66affSColin Finck     { IDC_BUTTON_DOT,      '.',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_BLUE, },
103c2c66affSColin Finck     { IDC_BUTTON_DOT,      ',',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), -1,            },
104c2c66affSColin Finck     { IDC_BUTTON_ADD,      '+',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
105c2c66affSColin Finck     { IDC_BUTTON_SUB,      '-',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
106c2c66affSColin Finck     { IDC_BUTTON_MULT,     '*',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
107c2c66affSColin Finck     { IDC_BUTTON_DIV,      '/',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
108c2c66affSColin Finck     { IDC_BUTTON_AND,      '&',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
109c2c66affSColin Finck     { IDC_BUTTON_OR,       '|',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
110c2c66affSColin Finck     { IDC_BUTTON_XOR,      '^',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
111c2c66affSColin Finck     { IDC_BUTTON_LSH,      '<',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
112c2c66affSColin Finck     { IDC_BUTTON_NOT,      '~',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
113c2c66affSColin Finck     { IDC_BUTTON_INT,      ';',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_RED,  },
114c2c66affSColin Finck     { IDC_BUTTON_EQU,      '=',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
115c2c66affSColin Finck     { IDC_BUTTON_A,        'A',     MAKE_BITMASK5(  1,  0,  0,  1,  0,  0,  0), CALC_CLR_BLUE, },
116c2c66affSColin Finck     { IDC_BUTTON_B,        'B',     MAKE_BITMASK5(  1,  0,  0,  1,  0,  0,  0), CALC_CLR_BLUE, },
117c2c66affSColin Finck     { IDC_BUTTON_C,        'C',     MAKE_BITMASK5(  1,  0,  0,  1,  0,  0,  0), CALC_CLR_BLUE, },
118c2c66affSColin Finck     { IDC_BUTTON_D,        'D',     MAKE_BITMASK5(  1,  0,  0,  1,  0,  0,  0), CALC_CLR_BLUE, },
119c2c66affSColin Finck     { IDC_BUTTON_E,        'E',     MAKE_BITMASK5(  1,  0,  0,  1,  0,  0,  0), CALC_CLR_BLUE, },
120c2c66affSColin Finck     { IDC_BUTTON_F,        'F',     MAKE_BITMASK5(  1,  0,  0,  1,  0,  0,  0), CALC_CLR_BLUE, },
121c2c66affSColin Finck     { IDC_CHECK_HYP,       'H',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), -1,            },
122c2c66affSColin Finck     { IDC_CHECK_INV,       'I',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), -1,            },
123c2c66affSColin Finck     { IDC_BUTTON_LOG,      'L',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
124c2c66affSColin Finck     { IDC_BUTTON_DMS,      'M',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
125c2c66affSColin Finck     { IDC_BUTTON_LN,       'N',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
126c2c66affSColin Finck     { IDC_BUTTON_PI,       'P',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_BLUE, },
127c2c66affSColin Finck     { IDC_BUTTON_RX,       'R',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
128c2c66affSColin Finck     { IDC_BUTTON_SIN,      'S',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
129c2c66affSColin Finck     { IDC_BUTTON_COS,      'O',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
130c2c66affSColin Finck     { IDC_BUTTON_TAN,      'T',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
131c2c66affSColin Finck     { IDC_BUTTON_FE,       'V',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
132c2c66affSColin Finck     { IDC_BUTTON_EXP,      'X',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_PURP, },
133c2c66affSColin Finck     { IDC_BUTTON_XeY,      'Y',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_PURP, },
134c2c66affSColin Finck     { IDC_BUTTON_SQRT,     '@',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_BLUE, },
135c2c66affSColin Finck     { IDC_BUTTON_Xe2,      '@',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_PURP, },
136c2c66affSColin Finck     { IDC_BUTTON_Xe3,      '#',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_PURP, },
137c2c66affSColin Finck     { IDC_BUTTON_NF,       '!',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_PURP, },
138c2c66affSColin Finck     { IDC_BUTTON_LEFTPAR,  '(',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_PURP, },
139c2c66affSColin Finck     { IDC_BUTTON_RIGHTPAR, ')',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_PURP, },
140c2c66affSColin Finck     { IDC_BUTTON_MOD,      '%',     MAKE_BITMASK5(  1,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
141c2c66affSColin Finck     { IDC_BUTTON_PERCENT,  '%',     MAKE_BITMASK5(  1,  0,  0,  0,  1,  0,  0), CALC_CLR_BLUE, },
142c2c66affSColin Finck     /*----------------------------------------------------------------------*/
143c2c66affSColin Finck     { IDC_BUTTON_DAT,  VK_INSERT,   MAKE_BITMASK5(  0,  1,  0,  1,  1,  1,  1), CALC_CLR_BLUE, },
144c2c66affSColin Finck     { IDC_BUTTON_EQU,  VK_RETURN,   MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
145c2c66affSColin Finck     { IDC_BUTTON_CANC, VK_ESCAPE,   MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
146c2c66affSColin Finck     { IDC_BUTTON_CE,   VK_DELETE,   MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
147c2c66affSColin Finck     { IDC_BUTTON_BACK, VK_BACK,     MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), CALC_CLR_RED,  },
148c2c66affSColin Finck     { IDC_RADIO_HEX,   VK_F5,       MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), -1,            },
149c2c66affSColin Finck     { IDC_RADIO_DEC,   VK_F6,       MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), -1,            },
150c2c66affSColin Finck     { IDC_RADIO_OCT,   VK_F7,       MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), -1,            },
151c2c66affSColin Finck     { IDC_RADIO_BIN,   VK_F8,       MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), -1,            },
152c2c66affSColin Finck     { IDC_BUTTON_SIGN, VK_F9,       MAKE_BITMASK5(  0,  0,  0,  1,  1,  1,  1), CALC_CLR_BLUE, },
153c2c66affSColin Finck };
154c2c66affSColin Finck 
155c2c66affSColin Finck static const key2code_t key2code_base16[] = {
156c2c66affSColin Finck     { VK_F2,       IDC_RADIO_DWORD, },
157c2c66affSColin Finck     { VK_F3,       IDC_RADIO_WORD, },
158c2c66affSColin Finck     { VK_F4,       IDC_RADIO_BYTE, },
159c2c66affSColin Finck     { VK_F12,      IDC_RADIO_QWORD, },
160c2c66affSColin Finck };
161c2c66affSColin Finck 
162c2c66affSColin Finck static const key2code_t key2code_base10[] = {
163c2c66affSColin Finck     { VK_F2,       IDC_RADIO_DEG, },
164c2c66affSColin Finck     { VK_F3,       IDC_RADIO_RAD, },
165c2c66affSColin Finck     { VK_F4,       IDC_RADIO_GRAD, },
166c2c66affSColin Finck };
167c2c66affSColin Finck 
168c2c66affSColin Finck static const WORD operator_codes[] = {
169c2c66affSColin Finck     /* CONTROL-ID       operator */
170c2c66affSColin Finck     (WORD)IDC_STATIC,   // RPN_OPERATOR_PARENT
171c2c66affSColin Finck     IDC_BUTTON_PERCENT, // RPN_OPERATOR_PERCENT
172c2c66affSColin Finck     IDC_BUTTON_EQU,     // RPN_OPERATOR_EQUAL
173c2c66affSColin Finck     IDC_BUTTON_OR,      // RPN_OPERATOR_OR
174c2c66affSColin Finck     IDC_BUTTON_XOR,     // RPN_OPERATOR_XOR
175c2c66affSColin Finck     IDC_BUTTON_AND,     // RPN_OPERATOR_AND
176c2c66affSColin Finck     IDC_BUTTON_LSH,     // RPN_OPERATOR_LSH
177c2c66affSColin Finck     IDC_BUTTON_RSH,     // RPN_OPERATOR_RSH
178c2c66affSColin Finck     IDC_BUTTON_ADD,     // RPN_OPERATOR_ADD
179c2c66affSColin Finck     IDC_BUTTON_SUB,     // RPN_OPERATOR_SUB
180c2c66affSColin Finck     IDC_BUTTON_MULT,    // RPN_OPERATOR_MULT
181c2c66affSColin Finck     IDC_BUTTON_DIV,     // RPN_OPERATOR_DIV
182c2c66affSColin Finck     IDC_BUTTON_MOD,     // RPN_OPERATOR_MOD
183295eaf4eSCarlo-Bramini     IDC_BUTTON_XeY,     // RPN_OPERATOR_POW
184295eaf4eSCarlo-Bramini     IDC_BUTTON_XrY,     // RPN_OPERATOR_SQR
185c2c66affSColin Finck };
186c2c66affSColin Finck 
187c2c66affSColin Finck typedef void (*rpn_callback1)(calc_number_t *);
188c2c66affSColin Finck 
189c2c66affSColin Finck typedef struct {
190c2c66affSColin Finck     WORD            idc;
191c2c66affSColin Finck     BYTE            range;
192c2c66affSColin Finck     BYTE            check_nan;
193c2c66affSColin Finck     rpn_callback1   direct;
194c2c66affSColin Finck     rpn_callback1   inverse;
195c2c66affSColin Finck     rpn_callback1   hyperb;
196c2c66affSColin Finck     rpn_callback1   inv_hyp;
197c2c66affSColin Finck } function_table_t;
198c2c66affSColin Finck 
199c2c66affSColin Finck static void run_fe(calc_number_t *number);
200c2c66affSColin Finck static void run_dat_sta(calc_number_t *number);
201c2c66affSColin Finck static void run_mp(calc_number_t *c);
202c2c66affSColin Finck static void run_mm(calc_number_t *c);
203c2c66affSColin Finck static void run_ms(calc_number_t *c);
204c2c66affSColin Finck static void run_mw(calc_number_t *c);
205c2c66affSColin Finck static void run_canc(calc_number_t *c);
206c2c66affSColin Finck static void run_rpar(calc_number_t *c);
207c2c66affSColin Finck static void run_lpar(calc_number_t *c);
208c2c66affSColin Finck 
209c2c66affSColin Finck static const function_table_t function_table[] = {
210c2c66affSColin Finck     { IDC_BUTTON_SIN,  MODIFIER_INV|MODIFIER_HYP, 1, rpn_sin,     rpn_asin,    rpn_sinh, rpn_asinh },
211c2c66affSColin Finck     { IDC_BUTTON_COS,  MODIFIER_INV|MODIFIER_HYP, 1, rpn_cos,     rpn_acos,    rpn_cosh, rpn_acosh },
212c2c66affSColin Finck     { IDC_BUTTON_TAN,  MODIFIER_INV|MODIFIER_HYP, 1, rpn_tan,     rpn_atan,    rpn_tanh, rpn_atanh },
213c2c66affSColin Finck     { IDC_BUTTON_INT,  MODIFIER_INV,              1, rpn_int,     rpn_frac,    NULL,     NULL      },
214c2c66affSColin Finck     { IDC_BUTTON_RX,   0,                         1, rpn_reci,    NULL,        NULL,     NULL      },
215c2c66affSColin Finck     { IDC_BUTTON_NOT,  0,                         1, rpn_not,     NULL,        NULL,     NULL      },
216c2c66affSColin Finck     { IDC_BUTTON_PI,   MODIFIER_INV,              0, rpn_pi,      rpn_2pi,     NULL,     NULL      },
217c2c66affSColin Finck     { IDC_BUTTON_Xe2,  MODIFIER_INV,              1, rpn_exp2,    rpn_sqrt,    NULL,     NULL      },
218c2c66affSColin Finck     { IDC_BUTTON_Xe3,  MODIFIER_INV,              1, rpn_exp3,    rpn_cbrt,    NULL,     NULL      },
219c2c66affSColin Finck     { IDC_BUTTON_LN,   MODIFIER_INV,              1, rpn_ln,      rpn_exp,     NULL,     NULL      },
220c2c66affSColin Finck     { IDC_BUTTON_LOG,  MODIFIER_INV,              1, rpn_log,     rpn_exp10,   NULL,     NULL      },
221c2c66affSColin Finck     { IDC_BUTTON_NF,   0,                         1, rpn_fact,    NULL,        NULL,     NULL      },
222295eaf4eSCarlo-Bramini     { IDC_BUTTON_AVE,  MODIFIER_INV,              0, rpn_ave,     rpn_ave2,    NULL,     NULL      },
223295eaf4eSCarlo-Bramini     { IDC_BUTTON_SUM,  MODIFIER_INV,              0, rpn_sum,     rpn_sum2,    NULL,     NULL      },
224c2c66affSColin Finck     { IDC_BUTTON_S,    MODIFIER_INV,              0, rpn_s_m1,    rpn_s,       NULL,     NULL      },
225c2c66affSColin Finck     { IDC_BUTTON_SQRT, MODIFIER_INV,              1, rpn_sqrt,    NULL,        NULL,     NULL      },
226c2c66affSColin Finck     { IDC_BUTTON_DMS,  MODIFIER_INV,              1, rpn_dec2dms, rpn_dms2dec, NULL,     NULL      },
227c2c66affSColin Finck     { IDC_BUTTON_FE,   0,                         1, run_fe,      NULL,        NULL,     NULL      },
228c2c66affSColin Finck     { IDC_BUTTON_DAT,  0,                         1, run_dat_sta, NULL,        NULL,     NULL,     },
229c2c66affSColin Finck     { IDC_BUTTON_MP,   MODIFIER_INV|NO_CHAIN,     1, run_mp,      run_mm,      NULL,     NULL,     },
230c2c66affSColin Finck     { IDC_BUTTON_MS,   MODIFIER_INV|NO_CHAIN,     1, run_ms,      run_mw,      NULL,     NULL,     },
231c2c66affSColin Finck     { IDC_BUTTON_CANC, NO_CHAIN,                  0, run_canc,    NULL,        NULL,     NULL,     },
232c2c66affSColin Finck     { IDC_BUTTON_RIGHTPAR, NO_CHAIN,              1, run_rpar,    NULL,        NULL,     NULL,     },
233c2c66affSColin Finck     { IDC_BUTTON_LEFTPAR,  NO_CHAIN,              0, run_lpar,    NULL,        NULL,     NULL,     },
234c2c66affSColin Finck };
235c2c66affSColin Finck 
2360b107f2eSCarlo-Bramini /* Sub-classing information for theming support */
2370b107f2eSCarlo-Bramini typedef struct{
2380b107f2eSCarlo-Bramini     BOOL    bHover;
2390b107f2eSCarlo-Bramini     WNDPROC oldProc;
2400b107f2eSCarlo-Bramini } BTNINFO,*LPBTNINFO;
2410b107f2eSCarlo-Bramini 
2420b107f2eSCarlo-Bramini 
243c2c66affSColin Finck /*
2440b107f2eSCarlo-Bramini  * Global variable declaration
245c2c66affSColin Finck  */
246c2c66affSColin Finck 
247c2c66affSColin Finck calc_t  calc;
248c2c66affSColin Finck 
2490b107f2eSCarlo-Bramini /* Hot-state info for theming support */
2500b107f2eSCarlo-Bramini BTNINFO BtnInfo[255];
2510b107f2eSCarlo-Bramini UINT    BtnCount;
2520b107f2eSCarlo-Bramini 
UpdateNumberIntl(void)253857a951fSCarlo-Bramini static void UpdateNumberIntl(void)
254c2c66affSColin Finck {
255857a951fSCarlo-Bramini     /* Get current user defaults */
256857a951fSCarlo-Bramini     if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, calc.sDecimal, SIZEOF(calc.sDecimal)))
257ede60035SKatayama Hirofumi MZ         StringCbCopy(calc.sDecimal, sizeof(calc.sDecimal), _T("."));
258c2c66affSColin Finck 
259857a951fSCarlo-Bramini     if (!GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, calc.sThousand, SIZEOF(calc.sThousand)))
260ede60035SKatayama Hirofumi MZ         StringCbCopy(calc.sThousand, sizeof(calc.sThousand), _T(","));
261c2c66affSColin Finck 
262c2c66affSColin Finck     /* get the string lengths */
263c2c66affSColin Finck     calc.sDecimal_len = _tcslen(calc.sDecimal);
264c2c66affSColin Finck     calc.sThousand_len = _tcslen(calc.sThousand);
265c2c66affSColin Finck }
266c2c66affSColin Finck 
LoadRegInt(LPCTSTR lpszApp,LPCTSTR lpszKey,int iDefault)267857a951fSCarlo-Bramini static int LoadRegInt(LPCTSTR lpszApp, LPCTSTR lpszKey, int iDefault)
268c2c66affSColin Finck {
269c2c66affSColin Finck     HKEY  hKey;
270857a951fSCarlo-Bramini     int   iValue;
271857a951fSCarlo-Bramini     DWORD tmp;
272c2c66affSColin Finck 
273857a951fSCarlo-Bramini     if (RegOpenKeyEx(HKEY_CURRENT_USER, lpszApp, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
274c2c66affSColin Finck     {
275857a951fSCarlo-Bramini         /* Try to load integer value */
276857a951fSCarlo-Bramini         tmp = sizeof(int);
277857a951fSCarlo-Bramini 
278857a951fSCarlo-Bramini         if (RegQueryValueEx(hKey, lpszKey, NULL, NULL, (LPBYTE)&iValue, &tmp) == ERROR_SUCCESS)
279857a951fSCarlo-Bramini             iDefault = iValue;
280857a951fSCarlo-Bramini 
281857a951fSCarlo-Bramini         /* close the key */
282857a951fSCarlo-Bramini         RegCloseKey(hKey);
283c2c66affSColin Finck     }
284c2c66affSColin Finck 
285857a951fSCarlo-Bramini     return iDefault;
286857a951fSCarlo-Bramini }
287c2c66affSColin Finck 
SaveRegInt(LPCTSTR lpszApp,LPCTSTR lpszKey,int iValue)288857a951fSCarlo-Bramini static void SaveRegInt(LPCTSTR lpszApp, LPCTSTR lpszKey, int iValue)
289857a951fSCarlo-Bramini {
290857a951fSCarlo-Bramini     HKEY hKey;
291c2c66affSColin Finck 
292857a951fSCarlo-Bramini     if (RegCreateKeyEx(HKEY_CURRENT_USER, lpszApp, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, NULL) == ERROR_SUCCESS)
293857a951fSCarlo-Bramini     {
294857a951fSCarlo-Bramini         RegSetValueEx(hKey, lpszKey, 0, REG_DWORD, (const BYTE*)&iValue, sizeof(int));
295857a951fSCarlo-Bramini 
296857a951fSCarlo-Bramini         /* close the key */
297c2c66affSColin Finck         RegCloseKey(hKey);
298c2c66affSColin Finck     }
299857a951fSCarlo-Bramini }
300857a951fSCarlo-Bramini 
load_config(void)301857a951fSCarlo-Bramini static void load_config(void)
302857a951fSCarlo-Bramini {
303857a951fSCarlo-Bramini     OSVERSIONINFO osvi;
304857a951fSCarlo-Bramini 
305857a951fSCarlo-Bramini     osvi.dwOSVersionInfoSize = sizeof(osvi);
306857a951fSCarlo-Bramini     GetVersionEx(&osvi);
307857a951fSCarlo-Bramini 
308857a951fSCarlo-Bramini     switch (osvi.dwPlatformId) {
309857a951fSCarlo-Bramini     case VER_PLATFORM_WIN32s:
310857a951fSCarlo-Bramini     case VER_PLATFORM_WIN32_WINDOWS:
311857a951fSCarlo-Bramini         /* Try to load last selected layout */
312857a951fSCarlo-Bramini         calc.layout = GetProfileInt(_T("SciCalc"), _T("layout"), CALC_LAYOUT_STANDARD);
313857a951fSCarlo-Bramini 
314857a951fSCarlo-Bramini         /* Try to load last selected formatting option */
315857a951fSCarlo-Bramini         calc.usesep = (GetProfileInt(_T("SciCalc"), _T("UseSep"), FALSE)) ? TRUE : FALSE;
316857a951fSCarlo-Bramini         break;
317857a951fSCarlo-Bramini 
318857a951fSCarlo-Bramini     default: /* VER_PLATFORM_WIN32_NT */
319857a951fSCarlo-Bramini         /* Try to load last selected layout */
320857a951fSCarlo-Bramini         calc.layout = LoadRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("layout"), CALC_LAYOUT_STANDARD);
321857a951fSCarlo-Bramini 
322857a951fSCarlo-Bramini         /* Try to load last selected formatting option */
323857a951fSCarlo-Bramini         calc.usesep = (LoadRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("UseSep"), FALSE)) ? TRUE : FALSE;
324857a951fSCarlo-Bramini         break;
325857a951fSCarlo-Bramini     }
326857a951fSCarlo-Bramini 
327857a951fSCarlo-Bramini     /* memory is empty at startup */
328857a951fSCarlo-Bramini     calc.is_memory = FALSE;
329857a951fSCarlo-Bramini 
330857a951fSCarlo-Bramini     /* Get locale info for numbers */
331857a951fSCarlo-Bramini     UpdateNumberIntl();
332857a951fSCarlo-Bramini }
333857a951fSCarlo-Bramini 
save_config(void)334857a951fSCarlo-Bramini static void save_config(void)
335857a951fSCarlo-Bramini {
336857a951fSCarlo-Bramini     TCHAR buf[32];
337857a951fSCarlo-Bramini     OSVERSIONINFO osvi;
338857a951fSCarlo-Bramini 
339857a951fSCarlo-Bramini     osvi.dwOSVersionInfoSize = sizeof(osvi);
340857a951fSCarlo-Bramini     GetVersionEx(&osvi);
341857a951fSCarlo-Bramini 
342857a951fSCarlo-Bramini     switch (osvi.dwPlatformId) {
343857a951fSCarlo-Bramini     case VER_PLATFORM_WIN32s:
344857a951fSCarlo-Bramini     case VER_PLATFORM_WIN32_WINDOWS:
345ede60035SKatayama Hirofumi MZ         StringCbPrintf(buf, sizeof(buf), _T("%lu"), calc.layout);
346857a951fSCarlo-Bramini         WriteProfileString(_T("SciCalc"), _T("layout"), buf);
347857a951fSCarlo-Bramini         WriteProfileString(_T("SciCalc"), _T("UseSep"), (calc.usesep==TRUE) ? _T("1") : _T("0"));
348857a951fSCarlo-Bramini         break;
349857a951fSCarlo-Bramini 
350857a951fSCarlo-Bramini     default: /* VER_PLATFORM_WIN32_NT */
351857a951fSCarlo-Bramini         SaveRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("layout"), calc.layout);
352857a951fSCarlo-Bramini         SaveRegInt(_T("SOFTWARE\\Microsoft\\Calc"), _T("UseSep"), calc.usesep);
353857a951fSCarlo-Bramini         break;
354857a951fSCarlo-Bramini     }
355857a951fSCarlo-Bramini }
356c2c66affSColin Finck 
post_key_press(LPARAM lParam,WORD idc)357c2c66affSColin Finck static LRESULT post_key_press(LPARAM lParam, WORD idc)
358c2c66affSColin Finck {
359c2c66affSColin Finck     HWND  hCtlWnd = GetDlgItem(calc.hWnd,idc);
360c2c66affSColin Finck     TCHAR ClassName[64];
361c2c66affSColin Finck 
362c2c66affSColin Finck     /* check if the key is enabled! */
363c2c66affSColin Finck     if (!IsWindowEnabled(hCtlWnd))
364c2c66affSColin Finck         return 1;
365c2c66affSColin Finck 
366c2c66affSColin Finck     if (!GetClassName(hCtlWnd, ClassName, SIZEOF(ClassName)))
367c2c66affSColin Finck         return 1;
368c2c66affSColin Finck 
3690b107f2eSCarlo-Bramini     if (!_tcscmp(ClassName, WC_BUTTON)) {
370c2c66affSColin Finck         DWORD dwStyle = GetWindowLongPtr(hCtlWnd, GWL_STYLE) & 0xF;
371c2c66affSColin Finck 
372c2c66affSColin Finck         /* Set states for press/release, but only for push buttons */
373c2c66affSColin Finck         if (dwStyle == BS_PUSHBUTTON || dwStyle == BS_DEFPUSHBUTTON || dwStyle == BS_OWNERDRAW) {
374c2c66affSColin Finck             if (!(lParam & KEY_WAS_DOWN)) {
375c2c66affSColin Finck                 PostMessage(hCtlWnd, BM_SETSTATE, 1, 0);
376c2c66affSColin Finck             } else
377c2c66affSColin Finck             if ((lParam & KEY_IS_UP)) {
378c2c66affSColin Finck                 PostMessage(hCtlWnd, BM_SETSTATE, 0, 0);
379c2c66affSColin Finck                 PostMessage(hCtlWnd, BM_CLICK, 0, 0);
380c2c66affSColin Finck             }
381c2c66affSColin Finck             return 1;
382c2c66affSColin Finck         }
383c2c66affSColin Finck     }
384c2c66affSColin Finck     /* default action: simple click event at key release */
385c2c66affSColin Finck     if ((lParam & KEY_IS_UP)) {
386c2c66affSColin Finck         PostMessage(hCtlWnd, BM_CLICK, 0, 0);
387c2c66affSColin Finck     }
388c2c66affSColin Finck     return 1;
389c2c66affSColin Finck }
390c2c66affSColin Finck 
vk2ascii(unsigned int vk)391c2c66affSColin Finck static int vk2ascii(unsigned int vk)
392c2c66affSColin Finck {
393c2c66affSColin Finck     unsigned short int s;
394c2c66affSColin Finck     int                scan;
395c2c66affSColin Finck     BYTE               state[256];
396c2c66affSColin Finck     HKL                layout=GetKeyboardLayout(0);
397c2c66affSColin Finck 
398c2c66affSColin Finck     if(!GetKeyboardState(state))
399c2c66affSColin Finck         return 0;
400c2c66affSColin Finck 
401c2c66affSColin Finck     scan=MapVirtualKeyEx(vk, 0, layout);
402c2c66affSColin Finck     s = 0;
403c2c66affSColin Finck     if (ToAsciiEx(vk, scan, state, &s, 0, layout)>0) {
404c2c66affSColin Finck         /* convert to upper case */
405c2c66affSColin Finck         if (s >= 'a' && s <= 'z')
406c2c66affSColin Finck             s = s - 'a' + 'A';
407c2c66affSColin Finck         /* add check to CTRL key */
408c2c66affSColin Finck         if (vk >= 'A' && vk <= 'Z' &&
409c2c66affSColin Finck             s >= CTRL_A && s <= CTRL_Z)
410c2c66affSColin Finck             s |= CTRL_FLAG;
411c2c66affSColin Finck         else
412c2c66affSColin Finck         if (GetAsyncKeyState(VK_MENU) < 0)
413c2c66affSColin Finck             s |= ALT_FLAG;
414c2c66affSColin Finck         return s;
415c2c66affSColin Finck     }
416c2c66affSColin Finck     return 0;
417c2c66affSColin Finck }
418c2c66affSColin Finck 
process_vk_key(WPARAM wParam,LPARAM lParam)419c2c66affSColin Finck static int process_vk_key(WPARAM wParam, LPARAM lParam)
420c2c66affSColin Finck {
421c2c66affSColin Finck     const key2code_t *k;
422c2c66affSColin Finck     unsigned int x;
423c2c66affSColin Finck     unsigned short int ch;
424c2c66affSColin Finck 
425c2c66affSColin Finck     ch = vk2ascii(LOWORD(wParam));
426c2c66affSColin Finck     if ((lParam & KEY_IS_UP)) {
427c2c66affSColin Finck         /* Test for "copy" to clipboard */
428c2c66affSColin Finck         if (ch == (CTRL_C|CTRL_FLAG)) {
429c2c66affSColin Finck             SendMessage(calc.hWnd, WM_COMMAND, IDM_EDIT_COPY, 0);
430c2c66affSColin Finck             return 1;
431c2c66affSColin Finck         }
432c2c66affSColin Finck         /* Test for "paste" from clipboard */
433c2c66affSColin Finck         if (ch == (CTRL_V|CTRL_FLAG)) {
434c2c66affSColin Finck             SendMessage(calc.hWnd, WM_COMMAND, IDM_EDIT_PASTE, 0);
435c2c66affSColin Finck             return 1;
436c2c66affSColin Finck         }
437c2c66affSColin Finck         /* Test of help menu */
438c2c66affSColin Finck         if (LOWORD(wParam) == VK_F1) {
439c2c66affSColin Finck             SendMessage(calc.hWnd, WM_COMMAND, IDM_HELP_HELP, 0);
440c2c66affSColin Finck             return 1;
441c2c66affSColin Finck         }
442c2c66affSColin Finck     }
443c2c66affSColin Finck 
444c2c66affSColin Finck     for (x=0; x<SIZEOF(key2code); x++) {
445c2c66affSColin Finck         int key = key2code[x].key;
446c2c66affSColin Finck         if (key2code[x].mask & BITMASK_IS_CTRL)
447c2c66affSColin Finck             key |= CTRL_FLAG;
448c2c66affSColin Finck         if ((key == ch             &&  (key2code[x].mask & BITMASK_IS_ASCII)) ||
449c2c66affSColin Finck             (key == LOWORD(wParam) && !(key2code[x].mask & BITMASK_IS_ASCII))
450c2c66affSColin Finck            ) {
451c2c66affSColin Finck             if (GetDlgItem(calc.hWnd, key2code[x].idc) == NULL)
452c2c66affSColin Finck                 continue;
453c2c66affSColin Finck             return post_key_press(lParam, key2code[x].idc);
454c2c66affSColin Finck         }
455c2c66affSColin Finck     }
456c2c66affSColin Finck     if (calc.layout == CALC_LAYOUT_SCIENTIFIC) {
457c2c66affSColin Finck         if (calc.base == IDC_RADIO_DEC) {
458c2c66affSColin Finck             k = key2code_base10;
459c2c66affSColin Finck             x = SIZEOF(key2code_base10);
460c2c66affSColin Finck         } else {
461c2c66affSColin Finck             k = key2code_base16;
462c2c66affSColin Finck             x = SIZEOF(key2code_base16);
463c2c66affSColin Finck         }
464c2c66affSColin Finck         do {
465c2c66affSColin Finck             if (k->key == LOWORD(wParam)) {
466c2c66affSColin Finck                 return post_key_press(lParam, k->idc);
467c2c66affSColin Finck             }
468c2c66affSColin Finck             k++;
469c2c66affSColin Finck         } while (--x);
470c2c66affSColin Finck     }
471c2c66affSColin Finck     return 0;
472c2c66affSColin Finck }
473c2c66affSColin Finck 
474c2c66affSColin Finck #ifdef USE_KEYBOARD_HOOK
475c2c66affSColin Finck static LRESULT CALLBACK
KeyboardHookProc(int nCode,WPARAM wParam,LPARAM lParam)476c2c66affSColin Finck KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
477c2c66affSColin Finck {
478c2c66affSColin Finck     if(nCode<0 || calc.is_menu_on)
479c2c66affSColin Finck         return CallNextHookEx(calc.hKeyboardHook,nCode,wParam,lParam);
480c2c66affSColin Finck 
481c2c66affSColin Finck     if(nCode==HC_ACTION)
482c2c66affSColin Finck         if (process_vk_key(wParam, lParam))
483c2c66affSColin Finck             return;
484c2c66affSColin Finck 
485c2c66affSColin Finck     return CallNextHookEx(calc.hKeyboardHook,nCode,wParam,lParam);
486c2c66affSColin Finck }
487c2c66affSColin Finck #endif
488c2c66affSColin Finck 
update_lcd_display(HWND hwnd)489c2c66affSColin Finck static void update_lcd_display(HWND hwnd)
490c2c66affSColin Finck {
491c2c66affSColin Finck     /*
492c2c66affSColin Finck      * multiply size of calc.buffer by 2 because it may
493c2c66affSColin Finck      * happen that separator is used between each digit.
494c2c66affSColin Finck      * Also added little additional space for dot and '\0'.
495c2c66affSColin Finck      */
496adbafe64SCarlo-Bramini     TCHAR tmp[MAX_CALC_SIZE * 2 + 2];
497c2c66affSColin Finck 
498adbafe64SCarlo-Bramini     if (calc.buffer[0] == _T('\0'))
499ede60035SKatayama Hirofumi MZ         StringCbCopy(tmp, sizeof(tmp), _T("0"));
500c2c66affSColin Finck     else
501ede60035SKatayama Hirofumi MZ         StringCbCopy(tmp, sizeof(tmp), calc.buffer);
502adbafe64SCarlo-Bramini 
503adbafe64SCarlo-Bramini     /* Add final '.' in decimal mode (if it's missing), but
504adbafe64SCarlo-Bramini      * only if it's a result: no append if it prints "ERROR".
505adbafe64SCarlo-Bramini      */
506adbafe64SCarlo-Bramini     if (calc.base == IDC_RADIO_DEC && !calc.is_nan) {
507adbafe64SCarlo-Bramini         if (_tcschr(tmp, _T('.')) == NULL)
508ede60035SKatayama Hirofumi MZ             StringCbCat(tmp, sizeof(tmp), _T("."));
509c2c66affSColin Finck     }
510c2c66affSColin Finck     /* if separator mode is on, let's add an additional space */
511c2c66affSColin Finck     if (calc.usesep && !calc.sci_in && !calc.sci_out && !calc.is_nan) {
512c2c66affSColin Finck         /* go to the integer part of the string */
513adbafe64SCarlo-Bramini         TCHAR *p = _tcschr(tmp, _T('.'));
514adbafe64SCarlo-Bramini         TCHAR *e = _tcschr(tmp, _T('\0'));
515c2c66affSColin Finck         int    n=0, t;
516c2c66affSColin Finck 
517c2c66affSColin Finck         if (p == NULL) p = e;
518c2c66affSColin Finck         switch (calc.base) {
519c2c66affSColin Finck         case IDC_RADIO_HEX:
520c2c66affSColin Finck         case IDC_RADIO_BIN:
521c2c66affSColin Finck             t = 4;
522c2c66affSColin Finck             break;
523c2c66affSColin Finck         default:
524c2c66affSColin Finck         /* fall here for:
525c2c66affSColin Finck              IDC_RADIO_DEC:
526c2c66affSColin Finck              IDC_RADIO_OCT: */
527c2c66affSColin Finck             t = 3;
528c2c66affSColin Finck             break;
529c2c66affSColin Finck         }
530c2c66affSColin Finck         while (--p > tmp) {
531adbafe64SCarlo-Bramini             if (++n == t && *(p-1) != _T('-')) {
532c2c66affSColin Finck                 memmove(p+1, p, (e-p+1)*sizeof(TCHAR));
533c2c66affSColin Finck                 e++;
534adbafe64SCarlo-Bramini                 *p = _T(' ');
535c2c66affSColin Finck                 n = 0;
536c2c66affSColin Finck             }
537c2c66affSColin Finck         }
538c2c66affSColin Finck         /* if decimal mode, apply regional settings */
539c2c66affSColin Finck         if (calc.base == IDC_RADIO_DEC) {
540c2c66affSColin Finck             TCHAR *p = tmp;
541adbafe64SCarlo-Bramini             TCHAR *e = _tcschr(tmp, _T('.'));
542c2c66affSColin Finck 
543c2c66affSColin Finck             /* searching for thousands default separator */
544c2c66affSColin Finck             while (p < e) {
545adbafe64SCarlo-Bramini                 if (*p == _T(' ')) {
546c2c66affSColin Finck                     memmove(p+calc.sThousand_len, p+1, _tcslen(p)*sizeof(TCHAR));
547c2c66affSColin Finck                     memcpy(p, calc.sThousand, calc.sThousand_len*sizeof(TCHAR));
548c2c66affSColin Finck                     p += calc.sThousand_len;
549c2c66affSColin Finck                 } else
550c2c66affSColin Finck                     p++;
551c2c66affSColin Finck             }
552c2c66affSColin Finck             /* update decimal point too. */
553c2c66affSColin Finck             memmove(p+calc.sDecimal_len, p+1, _tcslen(p)*sizeof(TCHAR));
554c2c66affSColin Finck             memcpy(p, calc.sDecimal, calc.sDecimal_len*sizeof(TCHAR));
555c2c66affSColin Finck         }
556c2c66affSColin Finck     } else {
557adbafe64SCarlo-Bramini         TCHAR *p = _tcschr(tmp, _T('.'));
558c2c66affSColin Finck 
559c2c66affSColin Finck         /* update decimal point when usesep is false */
560c2c66affSColin Finck         if (p != NULL) {
561c2c66affSColin Finck             memmove(p+calc.sDecimal_len, p+1, _tcslen(p)*sizeof(TCHAR));
562c2c66affSColin Finck             memcpy(p, calc.sDecimal, calc.sDecimal_len*sizeof(TCHAR));
563c2c66affSColin Finck         }
564c2c66affSColin Finck     }
565248acabaSCarlo-Bramini     SetDlgItemText(hwnd, IDC_TEXT_OUTPUT, tmp);
566c2c66affSColin Finck }
567c2c66affSColin Finck 
update_parent_display(HWND hWnd)568c2c66affSColin Finck static void update_parent_display(HWND hWnd)
569c2c66affSColin Finck {
570c2c66affSColin Finck     TCHAR str[8];
571c2c66affSColin Finck     int   n = eval_parent_count();
572c2c66affSColin Finck 
573c2c66affSColin Finck     if (!n)
574adbafe64SCarlo-Bramini         str[0] = _T('\0');
575c2c66affSColin Finck     else
576ede60035SKatayama Hirofumi MZ         StringCbPrintf(str, sizeof(str), _T("(=%d"), n);
577248acabaSCarlo-Bramini     SetDlgItemText(hWnd, IDC_TEXT_PARENT, str);
578c2c66affSColin Finck }
579c2c66affSColin Finck 
build_operand(HWND hwnd,DWORD idc)580c2c66affSColin Finck static void build_operand(HWND hwnd, DWORD idc)
581c2c66affSColin Finck {
582c2c66affSColin Finck     unsigned int i = 0, n;
583ede60035SKatayama Hirofumi MZ     size_t cbPtr;
584c2c66affSColin Finck 
585c2c66affSColin Finck     if (idc == IDC_BUTTON_DOT) {
586c2c66affSColin Finck         /* if dot is the first char, it's added automatically */
587c2c66affSColin Finck         if (calc.buffer == calc.ptr) {
588adbafe64SCarlo-Bramini             *calc.ptr++ = _T('0');
589adbafe64SCarlo-Bramini             *calc.ptr++ = _T('.');
590adbafe64SCarlo-Bramini             *calc.ptr   = _T('\0');
591c2c66affSColin Finck             update_lcd_display(hwnd);
592c2c66affSColin Finck             return;
593c2c66affSColin Finck         }
594c2c66affSColin Finck         /* if pressed dot and it's already in the string, then return */
595adbafe64SCarlo-Bramini         if (_tcschr(calc.buffer, _T('.')) != NULL)
596c2c66affSColin Finck             return;
597c2c66affSColin Finck     }
598c2c66affSColin Finck     if (idc != IDC_STATIC) {
599c2c66affSColin Finck         while (idc != key2code[i].idc) i++;
600c2c66affSColin Finck     }
601c2c66affSColin Finck     n = calc.ptr - calc.buffer;
602c2c66affSColin Finck     if (idc == IDC_BUTTON_0 && n == 0) {
603c2c66affSColin Finck         /* no need to put the dot because it's handled by update_lcd_display() */
604adbafe64SCarlo-Bramini         calc.buffer[0] = _T('0');
605adbafe64SCarlo-Bramini         calc.buffer[1] = _T('\0');
606c2c66affSColin Finck         update_lcd_display(hwnd);
607c2c66affSColin Finck         return;
608c2c66affSColin Finck     }
609c2c66affSColin Finck     switch (calc.base) {
610c2c66affSColin Finck     case IDC_RADIO_HEX:
611c2c66affSColin Finck         if (n >= 16)
612c2c66affSColin Finck             return;
613c2c66affSColin Finck         break;
614c2c66affSColin Finck     case IDC_RADIO_DEC:
615c2c66affSColin Finck         if (n >= SIZEOF(calc.buffer)-1)
616c2c66affSColin Finck             return;
617c2c66affSColin Finck         if (calc.sci_in) {
618c2c66affSColin Finck             if (idc != IDC_STATIC)
619c2c66affSColin Finck                 calc.esp = (calc.esp * 10 + (key2code[i].key-'0')) % LOCAL_EXP_SIZE;
620c2c66affSColin Finck             if (calc.ptr == calc.buffer)
621ede60035SKatayama Hirofumi MZ                 StringCbPrintf(calc.ptr, sizeof(calc.buffer), _T("0.e%+d"), calc.esp);
622c2c66affSColin Finck             else {
623c2c66affSColin Finck                 /* adds the dot at the end if the number has no decimal part */
624adbafe64SCarlo-Bramini                 if (!_tcschr(calc.buffer, _T('.')))
625adbafe64SCarlo-Bramini                     *calc.ptr++ = _T('.');
626ede60035SKatayama Hirofumi MZ 
627ede60035SKatayama Hirofumi MZ                 cbPtr = sizeof(calc.buffer) - ((BYTE*)calc.ptr - (BYTE*)calc.buffer);
628ede60035SKatayama Hirofumi MZ                 StringCbPrintf(calc.ptr, cbPtr, _T("e%+d"), calc.esp);
629c2c66affSColin Finck             }
630c2c66affSColin Finck             update_lcd_display(hwnd);
631c2c66affSColin Finck             return;
632c2c66affSColin Finck         }
633c2c66affSColin Finck         break;
634c2c66affSColin Finck     case IDC_RADIO_OCT:
635c2c66affSColin Finck         if (n >= 22)
636c2c66affSColin Finck             return;
637c2c66affSColin Finck         break;
638c2c66affSColin Finck     case IDC_RADIO_BIN:
639c2c66affSColin Finck         if (n >= 64)
640c2c66affSColin Finck             return;
641c2c66affSColin Finck         break;
642c2c66affSColin Finck     }
643ede60035SKatayama Hirofumi MZ 
644ede60035SKatayama Hirofumi MZ     cbPtr = sizeof(calc.buffer) - ((BYTE*)calc.ptr - (BYTE*)calc.buffer);
645ede60035SKatayama Hirofumi MZ     StringCbPrintfEx(calc.ptr, cbPtr, &calc.ptr, NULL, STRSAFE_FILL_ON_FAILURE,
646ede60035SKatayama Hirofumi MZ                      _T("%C"), key2code[i].key);
647ede60035SKatayama Hirofumi MZ 
648c2c66affSColin Finck     update_lcd_display(hwnd);
649c2c66affSColin Finck }
650c2c66affSColin Finck 
prepare_rpn_result(calc_number_t * rpn,TCHAR * buffer,int size,int base)651c2c66affSColin Finck static void prepare_rpn_result(calc_number_t *rpn, TCHAR *buffer, int size, int base)
652c2c66affSColin Finck {
653c2c66affSColin Finck     if (calc.is_nan) {
654c2c66affSColin Finck         rpn_zero(&calc.code);
655c2c66affSColin Finck         LoadString(calc.hInstance, IDS_MATH_ERROR, buffer, size);
656c2c66affSColin Finck         return;
657c2c66affSColin Finck     }
658c2c66affSColin Finck     prepare_rpn_result_2(rpn, buffer, size, base);
659c2c66affSColin Finck }
660c2c66affSColin Finck 
set_rpn_result(HWND hwnd,calc_number_t * rpn)661adbafe64SCarlo-Bramini static void set_rpn_result(HWND hwnd, calc_number_t *rpn)
662c2c66affSColin Finck {
663c2c66affSColin Finck     calc.sci_in = FALSE;
664c2c66affSColin Finck     prepare_rpn_result(rpn, calc.buffer, SIZEOF(calc.buffer), calc.base);
665c2c66affSColin Finck     calc.ptr = calc.buffer + _tcslen(calc.buffer);
666c2c66affSColin Finck     update_lcd_display(hwnd);
667c2c66affSColin Finck     update_parent_display(hwnd);
668c2c66affSColin Finck }
669c2c66affSColin Finck 
display_rpn_result(HWND hwnd,calc_number_t * rpn)670adbafe64SCarlo-Bramini static void display_rpn_result(HWND hwnd, calc_number_t *rpn)
671adbafe64SCarlo-Bramini {
672adbafe64SCarlo-Bramini     set_rpn_result(hwnd, rpn);
673adbafe64SCarlo-Bramini     calc.ptr = calc.buffer;
674adbafe64SCarlo-Bramini }
675adbafe64SCarlo-Bramini 
get_modifiers(HWND hWnd)676248acabaSCarlo-Bramini static int get_modifiers(HWND hWnd)
677c2c66affSColin Finck {
678c2c66affSColin Finck     int modifiers = 0;
679c2c66affSColin Finck 
680248acabaSCarlo-Bramini     if (IsDlgButtonChecked(hWnd, IDC_CHECK_INV) == BST_CHECKED)
681c2c66affSColin Finck         modifiers |= MODIFIER_INV;
682248acabaSCarlo-Bramini     if (IsDlgButtonChecked(hWnd, IDC_CHECK_HYP) == BST_CHECKED)
683c2c66affSColin Finck         modifiers |= MODIFIER_HYP;
684c2c66affSColin Finck 
685c2c66affSColin Finck     return modifiers;
686c2c66affSColin Finck }
687c2c66affSColin Finck 
convert_text2number(calc_number_t * a)688c2c66affSColin Finck static void convert_text2number(calc_number_t *a)
689c2c66affSColin Finck {
690c2c66affSColin Finck     /* if the screen output buffer is empty, then */
691c2c66affSColin Finck     /* the operand is taken from the last input */
692c2c66affSColin Finck     if (calc.buffer == calc.ptr) {
693c2c66affSColin Finck         /* if pushed valued is ZERO then we should grab it */
694adbafe64SCarlo-Bramini         if (!_tcscmp(calc.buffer, _T("0.")) ||
695adbafe64SCarlo-Bramini             !_tcscmp(calc.buffer, _T("0")))
696c2c66affSColin Finck             /* this zero is good for both integer and decimal */
697c2c66affSColin Finck             rpn_zero(a);
698c2c66affSColin Finck         else
699c2c66affSColin Finck             rpn_copy(a, &calc.code);
700c2c66affSColin Finck         return;
701c2c66affSColin Finck     }
702c2c66affSColin Finck     /* ZERO is the default value for all numeric bases */
703c2c66affSColin Finck     rpn_zero(a);
704c2c66affSColin Finck     convert_text2number_2(a);
705c2c66affSColin Finck }
706c2c66affSColin Finck 
707c2c66affSColin Finck static const struct _update_check_menus {
708c2c66affSColin Finck     DWORD  *sel;
709c2c66affSColin Finck     WORD    idm;
710c2c66affSColin Finck     WORD    idc;
711c2c66affSColin Finck } upd[] = {
712c2c66affSColin Finck     { &calc.layout, IDM_VIEW_STANDARD,   CALC_LAYOUT_STANDARD },
713c2c66affSColin Finck     { &calc.layout, IDM_VIEW_SCIENTIFIC, CALC_LAYOUT_SCIENTIFIC },
714c2c66affSColin Finck     { &calc.layout, IDM_VIEW_CONVERSION, CALC_LAYOUT_CONVERSION },
715c2c66affSColin Finck     /*-----------------------------------------*/
716c2c66affSColin Finck     { &calc.base, IDM_VIEW_HEX, IDC_RADIO_HEX, },
717c2c66affSColin Finck     { &calc.base, IDM_VIEW_DEC, IDC_RADIO_DEC, },
718c2c66affSColin Finck     { &calc.base, IDM_VIEW_OCT, IDC_RADIO_OCT, },
719c2c66affSColin Finck     { &calc.base, IDM_VIEW_BIN, IDC_RADIO_BIN, },
720c2c66affSColin Finck     /*-----------------------------------------*/
721c2c66affSColin Finck     { &calc.degr, IDM_VIEW_DEG,  IDC_RADIO_DEG, },
722c2c66affSColin Finck     { &calc.degr, IDM_VIEW_RAD,  IDC_RADIO_RAD, },
723c2c66affSColin Finck     { &calc.degr, IDM_VIEW_GRAD, IDC_RADIO_GRAD, },
724c2c66affSColin Finck     /*-----------------------------------------*/
725c2c66affSColin Finck     { &calc.size, IDM_VIEW_QWORD, IDC_RADIO_QWORD, },
726c2c66affSColin Finck     { &calc.size, IDM_VIEW_DWORD, IDC_RADIO_DWORD, },
727c2c66affSColin Finck     { &calc.size, IDM_VIEW_WORD,  IDC_RADIO_WORD, },
728c2c66affSColin Finck     { &calc.size, IDM_VIEW_BYTE,  IDC_RADIO_BYTE, },
729c2c66affSColin Finck };
730c2c66affSColin Finck 
update_menu(HWND hWnd)731248acabaSCarlo-Bramini static void update_menu(HWND hWnd)
732c2c66affSColin Finck {
733248acabaSCarlo-Bramini     HMENU        hMenu = GetSubMenu(GetMenu(hWnd), 1);
734c2c66affSColin Finck     unsigned int x;
735c2c66affSColin Finck 
736248acabaSCarlo-Bramini     for (x=0; x<SIZEOF(upd); x++) {
737c2c66affSColin Finck         if (*(upd[x].sel) != upd[x].idc) {
738c2c66affSColin Finck             CheckMenuItem(hMenu, upd[x].idm, MF_BYCOMMAND|MF_UNCHECKED);
739248acabaSCarlo-Bramini             CheckDlgButton(hWnd, upd[x].idc, BST_UNCHECKED);
740c2c66affSColin Finck         } else {
741c2c66affSColin Finck             CheckMenuItem(hMenu, upd[x].idm, MF_BYCOMMAND|MF_CHECKED);
742248acabaSCarlo-Bramini             CheckDlgButton(hWnd, upd[x].idc, BST_CHECKED);
743c2c66affSColin Finck         }
744c2c66affSColin Finck     }
745c2c66affSColin Finck     CheckMenuItem(hMenu, IDM_VIEW_GROUP, MF_BYCOMMAND|(calc.usesep ? MF_CHECKED : MF_UNCHECKED));
746c2c66affSColin Finck }
747c2c66affSColin Finck 
748c2c66affSColin Finck typedef struct {
749c2c66affSColin Finck     WORD   idc;
750c2c66affSColin Finck     WORD   mask;
751c2c66affSColin Finck } radio_config_t;
752c2c66affSColin Finck 
753c2c66affSColin Finck static const radio_config_t radio_setup[] = {
754c2c66affSColin Finck     /* CONTROL-ID                     hex dec oct bin */
755c2c66affSColin Finck     { IDC_RADIO_QWORD,  MAKE_BITMASK4(  1,  0,  1,  1) },
756c2c66affSColin Finck     { IDC_RADIO_DWORD,  MAKE_BITMASK4(  1,  0,  1,  1) },
757c2c66affSColin Finck     { IDC_RADIO_WORD,   MAKE_BITMASK4(  1,  0,  1,  1) },
758c2c66affSColin Finck     { IDC_RADIO_BYTE,   MAKE_BITMASK4(  1,  0,  1,  1) },
759c2c66affSColin Finck     { IDC_RADIO_DEG,    MAKE_BITMASK4(  0,  1,  0,  0) },
760c2c66affSColin Finck     { IDC_RADIO_RAD,    MAKE_BITMASK4(  0,  1,  0,  0) },
761c2c66affSColin Finck     { IDC_RADIO_GRAD,   MAKE_BITMASK4(  0,  1,  0,  0) },
762c2c66affSColin Finck };
763c2c66affSColin Finck 
enable_allowed_controls(HWND hwnd,DWORD base)764c2c66affSColin Finck static void enable_allowed_controls(HWND hwnd, DWORD base)
765c2c66affSColin Finck {
766c2c66affSColin Finck     BYTE mask;
767c2c66affSColin Finck     int  n;
768c2c66affSColin Finck 
769c2c66affSColin Finck     switch (base) {
770c2c66affSColin Finck     case IDC_RADIO_DEC:
771c2c66affSColin Finck         mask = BITMASK_DEC_MASK;
772c2c66affSColin Finck         break;
773c2c66affSColin Finck     case IDC_RADIO_HEX:
774c2c66affSColin Finck         mask = BITMASK_HEX_MASK;
775c2c66affSColin Finck         break;
776c2c66affSColin Finck     case IDC_RADIO_OCT:
777c2c66affSColin Finck         mask = BITMASK_OCT_MASK;
778c2c66affSColin Finck         break;
779c2c66affSColin Finck     case IDC_RADIO_BIN:
780c2c66affSColin Finck         mask = BITMASK_BIN_MASK;
781c2c66affSColin Finck         break;
782c2c66affSColin Finck     default:
783c2c66affSColin Finck         return;
784c2c66affSColin Finck     }
785c2c66affSColin Finck     for (n=0; n<SIZEOF(key2code); n++) {
786c2c66affSColin Finck         if (key2code[n].mask != 0) {
787c2c66affSColin Finck             HWND hCtlWnd = GetDlgItem(hwnd, key2code[n].idc);
788c2c66affSColin Finck             BOOL current;
789c2c66affSColin Finck 
790c2c66affSColin Finck             if ((key2code[n].mask & BITMASK_IS_STATS))
791c2c66affSColin Finck                 current = IsWindow(calc.hStatWnd) ? TRUE : FALSE;
792c2c66affSColin Finck             else
793c2c66affSColin Finck                 current = (key2code[n].mask & mask) ? TRUE : FALSE;
794c2c66affSColin Finck             if (IsWindowEnabled(hCtlWnd) != current)
795c2c66affSColin Finck                 EnableWindow(hCtlWnd, current);
796c2c66affSColin Finck         }
797c2c66affSColin Finck     }
798c2c66affSColin Finck }
799c2c66affSColin Finck 
update_radio(HWND hwnd,unsigned int base)800c2c66affSColin Finck static void update_radio(HWND hwnd, unsigned int base)
801c2c66affSColin Finck {
802c2c66affSColin Finck     HMENU   hMenu;
803c2c66affSColin Finck     LPCTSTR lpMenuId;
804c2c66affSColin Finck     WORD    mask;
805c2c66affSColin Finck     int     n;
806c2c66affSColin Finck 
807c2c66affSColin Finck     switch (base) {
808c2c66affSColin Finck     case IDC_RADIO_DEC:
809c2c66affSColin Finck         lpMenuId = MAKEINTRESOURCE(IDR_MENU_SCIENTIFIC_1);
810c2c66affSColin Finck         mask = BITMASK_DEC_MASK;
811c2c66affSColin Finck         break;
812c2c66affSColin Finck     case IDC_RADIO_HEX:
813c2c66affSColin Finck         lpMenuId = MAKEINTRESOURCE(IDR_MENU_SCIENTIFIC_2);
814c2c66affSColin Finck         mask = BITMASK_HEX_MASK;
815c2c66affSColin Finck         break;
816c2c66affSColin Finck     case IDC_RADIO_OCT:
817c2c66affSColin Finck         lpMenuId = MAKEINTRESOURCE(IDR_MENU_SCIENTIFIC_2);
818c2c66affSColin Finck         mask = BITMASK_OCT_MASK;
819c2c66affSColin Finck         break;
820c2c66affSColin Finck     case IDC_RADIO_BIN:
821c2c66affSColin Finck         lpMenuId = MAKEINTRESOURCE(IDR_MENU_SCIENTIFIC_2);
822c2c66affSColin Finck         mask = BITMASK_BIN_MASK;
823c2c66affSColin Finck         break;
824c2c66affSColin Finck     default:
825c2c66affSColin Finck         return;
826c2c66affSColin Finck     }
827c2c66affSColin Finck 
828c2c66affSColin Finck     if (calc.base != base) {
829c2c66affSColin Finck         convert_text2number(&calc.code);
830c2c66affSColin Finck         convert_real_integer(base);
831c2c66affSColin Finck         calc.base = base;
832c2c66affSColin Finck         display_rpn_result(hwnd, &calc.code);
833c2c66affSColin Finck 
834c2c66affSColin Finck         hMenu = GetMenu(hwnd);
835c2c66affSColin Finck         DestroyMenu(hMenu);
836c2c66affSColin Finck         hMenu = LoadMenu(calc.hInstance, lpMenuId);
837c2c66affSColin Finck         SetMenu(hwnd, hMenu);
838c2c66affSColin Finck         update_menu(hwnd);
839c2c66affSColin Finck 
840c2c66affSColin Finck         for (n=0; n<SIZEOF(radio_setup); n++)
841c2c66affSColin Finck             ShowWindow(GetDlgItem(hwnd, radio_setup[n].idc), (radio_setup[n].mask & mask) ? SW_SHOW : SW_HIDE);
842c2c66affSColin Finck 
843c2c66affSColin Finck         enable_allowed_controls(hwnd, base);
844c2c66affSColin Finck     }
845c2c66affSColin Finck 
846248acabaSCarlo-Bramini     CheckRadioButton(hwnd, IDC_RADIO_HEX, IDC_RADIO_BIN, calc.base);
847248acabaSCarlo-Bramini 
848c2c66affSColin Finck     if (base == IDC_RADIO_DEC)
849248acabaSCarlo-Bramini         CheckRadioButton(hwnd, IDC_RADIO_DEG, IDC_RADIO_GRAD, calc.degr);
850c2c66affSColin Finck     else
851248acabaSCarlo-Bramini         CheckRadioButton(hwnd, IDC_RADIO_QWORD, IDC_RADIO_BYTE, calc.size);
852c2c66affSColin Finck }
853c2c66affSColin Finck 
update_memory_flag(HWND hWnd,BOOL mem_flag)854c2c66affSColin Finck static void update_memory_flag(HWND hWnd, BOOL mem_flag)
855c2c66affSColin Finck {
856c2c66affSColin Finck     calc.is_memory = mem_flag;
857248acabaSCarlo-Bramini     SetDlgItemText(hWnd, IDC_TEXT_MEMORY, mem_flag ? _T("M") : _T(""));
858c2c66affSColin Finck }
859c2c66affSColin Finck 
update_n_stats_items(HWND hWnd,TCHAR * buffer,size_t cbBuffer)860ede60035SKatayama Hirofumi MZ static void update_n_stats_items(HWND hWnd, TCHAR *buffer, size_t cbBuffer)
861c2c66affSColin Finck {
862c2c66affSColin Finck     unsigned int n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0);
863c2c66affSColin Finck 
864ede60035SKatayama Hirofumi MZ     StringCbPrintf(buffer, cbBuffer, _T("n=%u"), n);
865248acabaSCarlo-Bramini     SetDlgItemText(hWnd, IDC_TEXT_NITEMS, buffer);
866c2c66affSColin Finck }
867c2c66affSColin Finck 
clean_stat_list(void)868c2c66affSColin Finck static void clean_stat_list(void)
869c2c66affSColin Finck {
870c2c66affSColin Finck     statistic_t *p = calc.stat;
871c2c66affSColin Finck 
872c2c66affSColin Finck     while (p != NULL) {
873c2c66affSColin Finck         statistic_t *s = p;
874c2c66affSColin Finck         p = (statistic_t *)(p->next);
875c2c66affSColin Finck         rpn_free(&s->num);
876c2c66affSColin Finck         free(s);
877c2c66affSColin Finck     }
878c2c66affSColin Finck     calc.stat = p;
879c2c66affSColin Finck }
880c2c66affSColin Finck 
delete_stat_item(int n)881c2c66affSColin Finck static void delete_stat_item(int n)
882c2c66affSColin Finck {
883c2c66affSColin Finck     statistic_t *p = calc.stat;
884c2c66affSColin Finck     statistic_t *s;
885c2c66affSColin Finck 
886c2c66affSColin Finck     if (n == 0) {
887c2c66affSColin Finck         calc.stat = (statistic_t *)p->next;
888c2c66affSColin Finck         rpn_free(&p->num);
889c2c66affSColin Finck         free(p);
890c2c66affSColin Finck     } else {
891c2c66affSColin Finck         s = (statistic_t *)p->next;
892c2c66affSColin Finck         while (--n) {
893c2c66affSColin Finck             p = s;
894c2c66affSColin Finck             s = (statistic_t *)p->next;
895c2c66affSColin Finck         }
896c2c66affSColin Finck         p->next = s->next;
897c2c66affSColin Finck         rpn_free(&s->num);
898c2c66affSColin Finck         free(s);
899c2c66affSColin Finck     }
900c2c66affSColin Finck }
901c2c66affSColin Finck 
ReadConversion(const char * formula)902c2c66affSColin Finck static char *ReadConversion(const char *formula)
903c2c66affSColin Finck {
904055c5a9bSCarlo Bramini     size_t len = strlen(formula);
905c2c66affSColin Finck     char *str = (char *)malloc(len+3);
906c2c66affSColin Finck 
907c2c66affSColin Finck     if (str == NULL)
908c2c66affSColin Finck         return NULL;
909c2c66affSColin Finck 
910c2c66affSColin Finck     str[0] = '(';
911c2c66affSColin Finck     memcpy(str+1, formula, len);
912c2c66affSColin Finck     str[len+1] = ')';
913c2c66affSColin Finck     str[len+2] = '\0';
914c2c66affSColin Finck 
915ede60035SKatayama Hirofumi MZ     StringCbCopy(calc.source, sizeof(calc.source), (*calc.buffer == _T('\0')) ? _T("0") : calc.buffer);
916c2c66affSColin Finck 
917c2c66affSColin Finck     /* clear display content before proceeding */
918c2c66affSColin Finck     calc.ptr = calc.buffer;
919adbafe64SCarlo-Bramini     calc.buffer[0] = _T('\0');
920c2c66affSColin Finck 
921c2c66affSColin Finck     return str;
922c2c66affSColin Finck }
923c2c66affSColin Finck 
DlgStatProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)924c2c66affSColin Finck static INT_PTR CALLBACK DlgStatProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
925c2c66affSColin Finck {
926c2c66affSColin Finck     TCHAR buffer[SIZEOF(calc.buffer)];
927c2c66affSColin Finck     DWORD n;
928c2c66affSColin Finck 
929c2c66affSColin Finck     switch (msg) {
930c2c66affSColin Finck     case WM_INITDIALOG:
931c2c66affSColin Finck         return TRUE;
932c2c66affSColin Finck     case WM_COMMAND:
933c2c66affSColin Finck         switch (LOWORD(wp)) {
934c2c66affSColin Finck         case IDC_LIST_STAT:
935c2c66affSColin Finck             if (HIWORD(wp) == CBN_DBLCLK)
936c2c66affSColin Finck                 SendMessage(hWnd, WM_COMMAND, (WPARAM)IDC_BUTTON_LOAD, 0);
937c2c66affSColin Finck             return TRUE;
938c2c66affSColin Finck         case IDC_BUTTON_RET:
939c2c66affSColin Finck             SetFocus(GetDlgItem(GetParent(hWnd), IDC_BUTTON_FOCUS));
940c2c66affSColin Finck             return TRUE;
941c2c66affSColin Finck         case IDC_BUTTON_LOAD:
942c2c66affSColin Finck             n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCURSEL, 0, 0);
943248acabaSCarlo-Bramini             if (n == LB_ERR)
944c2c66affSColin Finck                 return TRUE;
945c2c66affSColin Finck             PostMessage(GetParent(hWnd), WM_LOAD_STAT, (WPARAM)n, 0);
946c2c66affSColin Finck             return TRUE;
947c2c66affSColin Finck         case IDC_BUTTON_CD:
948c2c66affSColin Finck             n = SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_GETCURSEL, 0, 0);
949248acabaSCarlo-Bramini             if (n == LB_ERR)
950c2c66affSColin Finck                 return TRUE;
951c2c66affSColin Finck             SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_DELETESTRING, (WPARAM)n, 0);
952ede60035SKatayama Hirofumi MZ             update_n_stats_items(hWnd, buffer, sizeof(buffer));
953c2c66affSColin Finck             delete_stat_item(n);
954c2c66affSColin Finck             return TRUE;
955c2c66affSColin Finck         case IDC_BUTTON_CAD:
956c2c66affSColin Finck             SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_RESETCONTENT, 0, 0);
957c2c66affSColin Finck             clean_stat_list();
958ede60035SKatayama Hirofumi MZ             update_n_stats_items(hWnd, buffer, sizeof(buffer));
959c2c66affSColin Finck             return TRUE;
960c2c66affSColin Finck         }
961c2c66affSColin Finck         break;
962c2c66affSColin Finck     case WM_CLOSE:
963c2c66affSColin Finck         DestroyWindow(hWnd);
964c2c66affSColin Finck         return TRUE;
965c2c66affSColin Finck     case WM_DESTROY:
966adbafe64SCarlo-Bramini         clean_stat_list();
967c2c66affSColin Finck         PostMessage(GetParent(hWnd), WM_CLOSE_STATS, 0, 0);
968c2c66affSColin Finck         return TRUE;
969c2c66affSColin Finck     case WM_INSERT_STAT:
970c2c66affSColin Finck         prepare_rpn_result(&(((statistic_t *)lp)->num),
971c2c66affSColin Finck                            buffer, SIZEOF(buffer),
972c2c66affSColin Finck                            ((statistic_t *)lp)->base);
973c2c66affSColin Finck         SendDlgItemMessage(hWnd, IDC_LIST_STAT, LB_ADDSTRING, 0, (LPARAM)buffer);
974ede60035SKatayama Hirofumi MZ         update_n_stats_items(hWnd, buffer, sizeof(buffer));
975c2c66affSColin Finck         return TRUE;
976c2c66affSColin Finck     }
977c2c66affSColin Finck     return FALSE;
978c2c66affSColin Finck }
979c2c66affSColin Finck 
idm_2_idc(int idm)980248acabaSCarlo-Bramini static WPARAM idm_2_idc(int idm)
981c2c66affSColin Finck {
982c2c66affSColin Finck     int x;
983c2c66affSColin Finck 
984c2c66affSColin Finck     for (x=0; x<SIZEOF(upd); x++) {
985c2c66affSColin Finck         if (upd[x].idm == idm)
986248acabaSCarlo-Bramini             break;
987c2c66affSColin Finck     }
988248acabaSCarlo-Bramini     return (WPARAM)(upd[x].idc);
989c2c66affSColin Finck }
990c2c66affSColin Finck 
CopyMemToClipboard(void * ptr)991c2c66affSColin Finck static void CopyMemToClipboard(void *ptr)
992c2c66affSColin Finck {
993c2c66affSColin Finck     if(OpenClipboard(NULL)) {
994c2c66affSColin Finck         HGLOBAL  clipbuffer;
995c2c66affSColin Finck         TCHAR   *buffer;
996ede60035SKatayama Hirofumi MZ         size_t cbBuffer;
997c2c66affSColin Finck 
998c2c66affSColin Finck         EmptyClipboard();
999ede60035SKatayama Hirofumi MZ         cbBuffer = (_tcslen(ptr) + 1) * sizeof(TCHAR);
1000ede60035SKatayama Hirofumi MZ         clipbuffer = GlobalAlloc(GMEM_DDESHARE, cbBuffer);
1001c2c66affSColin Finck         buffer = (TCHAR *)GlobalLock(clipbuffer);
1002ede60035SKatayama Hirofumi MZ         StringCbCopy(buffer, cbBuffer, ptr);
1003c2c66affSColin Finck         GlobalUnlock(clipbuffer);
1004c2c66affSColin Finck #ifdef UNICODE
1005c2c66affSColin Finck         SetClipboardData(CF_UNICODETEXT,clipbuffer);
1006c2c66affSColin Finck #else
1007c2c66affSColin Finck         SetClipboardData(CF_TEXT,clipbuffer);
1008c2c66affSColin Finck #endif
1009c2c66affSColin Finck         CloseClipboard();
1010c2c66affSColin Finck     }
1011c2c66affSColin Finck }
1012c2c66affSColin Finck 
handle_copy_command(HWND hWnd)1013c2c66affSColin Finck static void handle_copy_command(HWND hWnd)
1014c2c66affSColin Finck {
1015adbafe64SCarlo-Bramini     TCHAR display[MAX_CALC_SIZE];
1016adbafe64SCarlo-Bramini     UINT  n;
1017c2c66affSColin Finck 
1018*30b40247SCarlo Bramini     // Read current text from output display
1019adbafe64SCarlo-Bramini     n = GetDlgItemText(hWnd, IDC_TEXT_OUTPUT, display, SIZEOF(display));
1020adbafe64SCarlo-Bramini 
1021*30b40247SCarlo Bramini     // Check if result is a true number
1022*30b40247SCarlo Bramini     if (!calc.is_nan)
1023*30b40247SCarlo Bramini     {
1024*30b40247SCarlo Bramini         // Remove trailing decimal point if no decimal digits exist
1025c2c66affSColin Finck         if (calc.base == IDC_RADIO_DEC && _tcschr(calc.buffer, _T('.')) == NULL)
1026adbafe64SCarlo-Bramini             display[n - calc.sDecimal_len] = _T('\0');
1027*30b40247SCarlo Bramini     }
1028adbafe64SCarlo-Bramini 
1029c2c66affSColin Finck     CopyMemToClipboard(display);
1030c2c66affSColin Finck }
1031c2c66affSColin Finck 
ReadClipboard(void)1032c2c66affSColin Finck static char *ReadClipboard(void)
1033c2c66affSColin Finck {
1034c2c66affSColin Finck     char *buffer = NULL;
1035c2c66affSColin Finck 
1036c2c66affSColin Finck     if (OpenClipboard(NULL)) {
1037c2c66affSColin Finck         HANDLE  hData = GetClipboardData(CF_TEXT);
1038c2c66affSColin Finck         char   *fromClipboard;
1039c2c66affSColin Finck 
1040c2c66affSColin Finck         if (hData != NULL) {
1041c2c66affSColin Finck             fromClipboard = (char *)GlobalLock(hData);
1042adbafe64SCarlo-Bramini             if (fromClipboard[0])
1043c2c66affSColin Finck                 buffer = _strupr(_strdup(fromClipboard));
1044c2c66affSColin Finck             GlobalUnlock( hData );
1045c2c66affSColin Finck         }
1046c2c66affSColin Finck         CloseClipboard();
1047c2c66affSColin Finck     }
1048c2c66affSColin Finck     return buffer;
1049c2c66affSColin Finck }
1050c2c66affSColin Finck 
handle_sequence_input(HWND hwnd,sequence_t * seq)1051c2c66affSColin Finck static char *handle_sequence_input(HWND hwnd, sequence_t *seq)
1052c2c66affSColin Finck {
1053c2c66affSColin Finck     char *ptr = seq->ptr;
1054c2c66affSColin Finck     int ch, x;
1055c2c66affSColin Finck 
1056c2c66affSColin Finck     ch = *ptr++;
1057c2c66affSColin Finck     if (ch == '\\')
1058c2c66affSColin Finck         PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_DAT, 0);
1059c2c66affSColin Finck     else
1060c2c66affSColin Finck     if (ch == ':') {
1061c2c66affSColin Finck         ch = *ptr;
1062c2c66affSColin Finck         if (ch != '\0')
1063c2c66affSColin Finck             ptr++;
1064c2c66affSColin Finck         switch (ch) {
1065c2c66affSColin Finck         case 'C': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MC, 0); break;
1066c2c66affSColin Finck         case 'E': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_EXP,0); break;
1067c2c66affSColin Finck         case 'M': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MS, 0); break;
1068c2c66affSColin Finck         case 'P': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MP, 0); break;
1069c2c66affSColin Finck         case 'Q': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_CANC, 0); break;
1070c2c66affSColin Finck         case 'R': PostMessage(hwnd, WM_COMMAND, (WPARAM)IDC_BUTTON_MR, 0); break;
1071c2c66affSColin Finck         }
1072c2c66affSColin Finck     } else
1073c2c66affSColin Finck     if (ch == '$') {
1074ede60035SKatayama Hirofumi MZ         StringCbCopyEx(calc.buffer, sizeof(calc.buffer), calc.source, &calc.ptr, NULL,
1075ede60035SKatayama Hirofumi MZ                        STRSAFE_FILL_ON_FAILURE);
1076c2c66affSColin Finck     } else {
1077c2c66affSColin Finck         for (x=0; x<SIZEOF(key2code); x++) {
1078c2c66affSColin Finck             if (!(key2code[x].mask & BITMASK_IS_ASCII) ||
1079c2c66affSColin Finck                 (key2code[x].mask & BITMASK_IS_CTRL))
1080c2c66affSColin Finck                 continue;
1081c2c66affSColin Finck             if (key2code[x].key == ch) {
1082c2c66affSColin Finck                 PostMessage(hwnd, WM_COMMAND, (WPARAM)key2code[x].idc, 0);
1083c2c66affSColin Finck                 break;
1084c2c66affSColin Finck             }
1085c2c66affSColin Finck         }
1086c2c66affSColin Finck     }
1087adbafe64SCarlo-Bramini 
1088c2c66affSColin Finck     if (*ptr != '\0')
1089adbafe64SCarlo-Bramini     {
1090adbafe64SCarlo-Bramini         seq->ptr = ptr;
1091c2c66affSColin Finck         PostMessage(hwnd, seq->wm_msg, 0, 0);
1092adbafe64SCarlo-Bramini     } else {
1093c2c66affSColin Finck         free(seq->data);
1094c2c66affSColin Finck         seq->data = seq->ptr = ptr = NULL;
1095c2c66affSColin Finck     }
1096c2c66affSColin Finck     return ptr;
1097c2c66affSColin Finck }
1098c2c66affSColin Finck 
run_dat_sta(calc_number_t * a)1099c2c66affSColin Finck static void run_dat_sta(calc_number_t *a)
1100c2c66affSColin Finck {
1101c2c66affSColin Finck     statistic_t *s = (statistic_t *)malloc(sizeof(statistic_t));
1102c2c66affSColin Finck     statistic_t *p = calc.stat;
1103c2c66affSColin Finck 
1104c2c66affSColin Finck     rpn_alloc(&s->num);
1105c2c66affSColin Finck     rpn_copy(&s->num, a);
1106c2c66affSColin Finck     s->base = calc.base;
1107c2c66affSColin Finck     s->next = NULL;
1108c2c66affSColin Finck     if (p == NULL)
1109c2c66affSColin Finck         calc.stat = s;
1110c2c66affSColin Finck     else {
1111c2c66affSColin Finck         while (p->next != NULL)
1112c2c66affSColin Finck             p = (statistic_t *)(p->next);
1113c2c66affSColin Finck         p->next = s;
1114c2c66affSColin Finck     }
1115c2c66affSColin Finck     PostMessage(calc.hStatWnd, WM_INSERT_STAT, 0, (LPARAM)s);
1116c2c66affSColin Finck }
1117c2c66affSColin Finck 
run_mp(calc_number_t * c)1118c2c66affSColin Finck static void run_mp(calc_number_t *c)
1119c2c66affSColin Finck {
1120c2c66affSColin Finck     calc_node_t cn;
1121c2c66affSColin Finck 
1122c2c66affSColin Finck     cn.number = *c;
1123c2c66affSColin Finck     cn.base = calc.base;
1124c2c66affSColin Finck     run_operator(&calc.memory, &calc.memory, &cn, RPN_OPERATOR_ADD);
1125c2c66affSColin Finck     update_memory_flag(calc.hWnd, TRUE);
1126c2c66affSColin Finck }
1127c2c66affSColin Finck 
run_mm(calc_number_t * c)1128c2c66affSColin Finck static void run_mm(calc_number_t *c)
1129c2c66affSColin Finck {
1130c2c66affSColin Finck     calc_node_t cn;
1131c2c66affSColin Finck 
1132c2c66affSColin Finck     cn.number = *c;
1133c2c66affSColin Finck     cn.base = calc.base;
1134c2c66affSColin Finck     run_operator(&calc.memory, &calc.memory, &cn, RPN_OPERATOR_SUB);
1135c2c66affSColin Finck     update_memory_flag(calc.hWnd, TRUE);
1136c2c66affSColin Finck }
1137c2c66affSColin Finck 
run_ms(calc_number_t * c)1138c2c66affSColin Finck static void run_ms(calc_number_t *c)
1139c2c66affSColin Finck {
1140c2c66affSColin Finck     rpn_copy(&calc.memory.number, c);
1141c2c66affSColin Finck     calc.memory.base = calc.base;
1142c2c66affSColin Finck     update_memory_flag(calc.hWnd, rpn_is_zero(&calc.memory.number) ? FALSE : TRUE);
1143c2c66affSColin Finck }
1144c2c66affSColin Finck 
run_mw(calc_number_t * c)1145c2c66affSColin Finck static void run_mw(calc_number_t *c)
1146c2c66affSColin Finck {
1147c2c66affSColin Finck     calc_number_t tmp;
1148c2c66affSColin Finck 
1149c2c66affSColin Finck     rpn_copy(&tmp, &calc.memory.number);
1150c2c66affSColin Finck     rpn_copy(&calc.memory.number, c);
1151c2c66affSColin Finck     calc.memory.base = calc.base;
1152c2c66affSColin Finck     if (calc.is_memory)
1153c2c66affSColin Finck         rpn_copy(c, &tmp);
1154c2c66affSColin Finck     update_memory_flag(calc.hWnd, rpn_is_zero(&calc.memory.number) ? FALSE : TRUE);
1155c2c66affSColin Finck }
1156c2c66affSColin Finck 
upload_stat_number(int n)1157c2c66affSColin Finck static statistic_t *upload_stat_number(int n)
1158c2c66affSColin Finck {
1159c2c66affSColin Finck     statistic_t *p = calc.stat;
1160c2c66affSColin Finck 
1161c2c66affSColin Finck     if (p == NULL)
1162c2c66affSColin Finck         return p;
1163c2c66affSColin Finck 
1164c2c66affSColin Finck     while (n--) {
1165c2c66affSColin Finck         p = (statistic_t *)(p->next);
1166c2c66affSColin Finck         if (p == NULL)
1167c2c66affSColin Finck             return p;
1168c2c66affSColin Finck     }
1169c2c66affSColin Finck 
1170c2c66affSColin Finck #ifndef ENABLE_MULTI_PRECISION
1171c2c66affSColin Finck     if (calc.base != p->base) {
1172c2c66affSColin Finck         if (calc.base == IDC_RADIO_DEC)
1173c2c66affSColin Finck             calc.code.f = (double)p->num.i;
1174c2c66affSColin Finck         else {
1175c2c66affSColin Finck             calc.code.i = (__int64)p->num.f;
1176c2c66affSColin Finck             apply_int_mask(&calc.code);
1177c2c66affSColin Finck         }
1178c2c66affSColin Finck     } else
1179c2c66affSColin Finck #endif
1180c2c66affSColin Finck         rpn_copy(&calc.code, &p->num);
1181c2c66affSColin Finck 
1182c2c66affSColin Finck     calc.is_nan = FALSE;
1183c2c66affSColin Finck 
1184c2c66affSColin Finck     return p;
1185c2c66affSColin Finck }
1186c2c66affSColin Finck 
run_fe(calc_number_t * number)1187c2c66affSColin Finck static void run_fe(calc_number_t *number)
1188c2c66affSColin Finck {
1189c2c66affSColin Finck     calc.sci_out = ((calc.sci_out != FALSE) ? FALSE : TRUE);
1190c2c66affSColin Finck }
1191c2c66affSColin Finck 
handle_context_menu(HWND hWnd,WPARAM wp,LPARAM lp)1192c2c66affSColin Finck static void handle_context_menu(HWND hWnd, WPARAM wp, LPARAM lp)
1193c2c66affSColin Finck {
1194c2c66affSColin Finck     TCHAR text[64];
1195c2c66affSColin Finck     HMENU hMenu = CreatePopupMenu();
1196c2c66affSColin Finck     BOOL idm;
1197c2c66affSColin Finck 
1198c2c66affSColin Finck     LoadString(calc.hInstance, IDS_QUICKHELP, text, SIZEOF(text));
1199c2c66affSColin Finck     AppendMenu(hMenu, MF_STRING | MF_ENABLED, IDM_HELP_HELP, text);
1200c2c66affSColin Finck     idm = TrackPopupMenu( hMenu,
1201c2c66affSColin Finck                           TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON,
1202c2c66affSColin Finck                           LOWORD(lp),
1203c2c66affSColin Finck                           HIWORD(lp),
1204c2c66affSColin Finck                           0,
1205c2c66affSColin Finck                           hWnd,
1206c2c66affSColin Finck                           NULL);
1207c2c66affSColin Finck     DestroyMenu(hMenu);
1208c2c66affSColin Finck #ifndef DISABLE_HTMLHELP_SUPPORT
1209c2c66affSColin Finck     if (idm) {
1210c2c66affSColin Finck         HH_POPUP popup;
1211c2c66affSColin Finck 
1212c2c66affSColin Finck         memset(&popup, 0, sizeof(popup));
1213c2c66affSColin Finck         popup.cbStruct = sizeof(HH_POPUP);
1214c2c66affSColin Finck         popup.clrForeground = 1;
1215c2c66affSColin Finck         popup.clrBackground = -1;
1216c2c66affSColin Finck         popup.pt.x = LOWORD(lp);
1217c2c66affSColin Finck         popup.pt.y = HIWORD(lp);
1218c2c66affSColin Finck         popup.rcMargins.top    = -1;
1219c2c66affSColin Finck         popup.rcMargins.bottom = -1;
1220c2c66affSColin Finck         popup.rcMargins.left   = -1;
1221c2c66affSColin Finck         popup.rcMargins.right  = -1;
1222c2c66affSColin Finck         popup.idString = GetWindowLongPtr((HWND)wp, GWL_ID);
1223f6c565bcSCarlo-Bramini         calc_HtmlHelp((HWND)wp, HTMLHELP_PATH("/popups.txt"), HH_DISPLAY_TEXT_POPUP, (DWORD_PTR)&popup);
1224c2c66affSColin Finck     }
1225c2c66affSColin Finck #else
1226c2c66affSColin Finck     (void)idm;
1227c2c66affSColin Finck #endif
1228c2c66affSColin Finck }
1229c2c66affSColin Finck 
run_canc(calc_number_t * c)1230c2c66affSColin Finck static void run_canc(calc_number_t *c)
1231c2c66affSColin Finck {
1232c2c66affSColin Finck     flush_postfix();
1233c2c66affSColin Finck     rpn_zero(c);
1234248acabaSCarlo-Bramini 
1235c2c66affSColin Finck     /* clear also scientific display modes */
1236c2c66affSColin Finck     calc.sci_out = FALSE;
1237c2c66affSColin Finck     calc.sci_in  = FALSE;
1238248acabaSCarlo-Bramini 
1239c2c66affSColin Finck     /* clear state of inv and hyp flags */
1240248acabaSCarlo-Bramini     CheckDlgButton(calc.hWnd, IDC_CHECK_INV, BST_UNCHECKED);
1241248acabaSCarlo-Bramini     CheckDlgButton(calc.hWnd, IDC_CHECK_HYP, BST_UNCHECKED);
1242c2c66affSColin Finck }
1243c2c66affSColin Finck 
run_rpar(calc_number_t * c)1244c2c66affSColin Finck static void run_rpar(calc_number_t *c)
1245c2c66affSColin Finck {
1246c2c66affSColin Finck     exec_closeparent(c);
1247c2c66affSColin Finck }
1248c2c66affSColin Finck 
run_lpar(calc_number_t * c)1249c2c66affSColin Finck static void run_lpar(calc_number_t *c)
1250c2c66affSColin Finck {
1251c2c66affSColin Finck     exec_infix2postfix(c, RPN_OPERATOR_PARENT);
1252c2c66affSColin Finck }
1253c2c66affSColin Finck 
SubclassButtonProc(HWND hWnd,WPARAM wp,LPARAM lp)1254c2c66affSColin Finck static LRESULT CALLBACK SubclassButtonProc(HWND hWnd, WPARAM wp, LPARAM lp)
1255c2c66affSColin Finck {
1256c2c66affSColin Finck     LPDRAWITEMSTRUCT dis = (LPDRAWITEMSTRUCT)lp;
1257c2c66affSColin Finck     UINT             dwText;
1258c2c66affSColin Finck     TCHAR            text[64];
1259c2c66affSColin Finck     int              dx, dy, len;
1260c2c66affSColin Finck     SIZE             size;
1261c2c66affSColin Finck     POINT            pt;
1262c2c66affSColin Finck 
12630b107f2eSCarlo-Bramini     if(dis->CtlType == ODT_BUTTON)
12640b107f2eSCarlo-Bramini     {
12650b107f2eSCarlo-Bramini         HTHEME hTheme = NULL;
12660b107f2eSCarlo-Bramini         LPBTNINFO lpBtnInfo;
12670b107f2eSCarlo-Bramini 
12680b107f2eSCarlo-Bramini         if (calc_IsAppThemed() && calc_IsThemeActive())
12690b107f2eSCarlo-Bramini             hTheme = calc_OpenThemeData(hWnd, L"Button");
12700b107f2eSCarlo-Bramini 
12710b107f2eSCarlo-Bramini         if (hTheme)
12720b107f2eSCarlo-Bramini         {
12730b107f2eSCarlo-Bramini             int iState = 0;
12740b107f2eSCarlo-Bramini 
12750b107f2eSCarlo-Bramini             if ((dis->itemState & ODS_DISABLED))
12760b107f2eSCarlo-Bramini                 iState |= PBS_DISABLED;
12770b107f2eSCarlo-Bramini             if ((dis->itemState & ODS_SELECTED))
12780b107f2eSCarlo-Bramini                 iState |= PBS_PRESSED;
12790b107f2eSCarlo-Bramini 
12800b107f2eSCarlo-Bramini             lpBtnInfo = (LPBTNINFO)GetWindowLongPtr(dis->hwndItem, GWLP_USERDATA);
12810b107f2eSCarlo-Bramini             if (lpBtnInfo != NULL)
12820b107f2eSCarlo-Bramini             {
12830b107f2eSCarlo-Bramini                 if (lpBtnInfo->bHover)
12840b107f2eSCarlo-Bramini                     iState |= PBS_HOT;
12850b107f2eSCarlo-Bramini             }
12860b107f2eSCarlo-Bramini 
12870b107f2eSCarlo-Bramini             if (calc_IsThemeBackgroundPartiallyTransparent(hTheme, BP_PUSHBUTTON, iState))
12880b107f2eSCarlo-Bramini             {
12890b107f2eSCarlo-Bramini                 calc_DrawThemeParentBackground(dis->hwndItem, dis->hDC, &dis->rcItem);
12900b107f2eSCarlo-Bramini             }
12910b107f2eSCarlo-Bramini 
12920b107f2eSCarlo-Bramini             // Draw the frame around the control
12930b107f2eSCarlo-Bramini             calc_DrawThemeBackground(hTheme, dis->hDC, BP_PUSHBUTTON, iState, &dis->rcItem, NULL);
12940b107f2eSCarlo-Bramini 
12950b107f2eSCarlo-Bramini             calc_CloseThemeData(hTheme);
12960b107f2eSCarlo-Bramini         } else {
12970b107f2eSCarlo-Bramini             /* default state: unpushed */
12980b107f2eSCarlo-Bramini             DWORD dwStyle = 0;
12990b107f2eSCarlo-Bramini 
13000b107f2eSCarlo-Bramini             if ((dis->itemState & ODS_SELECTED))
13010b107f2eSCarlo-Bramini                 dwStyle = DFCS_PUSHED;
13020b107f2eSCarlo-Bramini 
13030b107f2eSCarlo-Bramini             DrawFrameControl(dis->hDC, &dis->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH | dwStyle);
13040b107f2eSCarlo-Bramini         }
13050b107f2eSCarlo-Bramini 
13060b107f2eSCarlo-Bramini         /* button text to write */
13070b107f2eSCarlo-Bramini         len = GetWindowText(dis->hwndItem, text, SIZEOF(text));
13080b107f2eSCarlo-Bramini 
1309c2c66affSColin Finck         /*
1310c2c66affSColin Finck          * little exception: 1/x has different color
1311c2c66affSColin Finck          * in standard and scientific modes
1312c2c66affSColin Finck          */
1313c2c66affSColin Finck         if ((calc.layout == CALC_LAYOUT_STANDARD ||
1314c2c66affSColin Finck              calc.layout == CALC_LAYOUT_CONVERSION) &&
1315c2c66affSColin Finck             IDC_BUTTON_RX == dis->CtlID) {
1316c2c66affSColin Finck             SetTextColor(dis->hDC, CALC_CLR_BLUE);
1317c2c66affSColin Finck         } else
1318c2c66affSColin Finck         for (dx=0; dx<SIZEOF(key2code); dx++) {
1319c2c66affSColin Finck             if (key2code[dx].idc == dis->CtlID) {
1320c2c66affSColin Finck                 SetTextColor(dis->hDC, key2code[dx].col);
1321c2c66affSColin Finck                 break;
1322c2c66affSColin Finck             }
1323c2c66affSColin Finck         }
13240b107f2eSCarlo-Bramini 
13250b107f2eSCarlo-Bramini         /* No background, to avoid corruption of the texture */
13260b107f2eSCarlo-Bramini         SetBkMode(dis->hDC, TRANSPARENT);
13270b107f2eSCarlo-Bramini 
13280b107f2eSCarlo-Bramini         /* Default state: enabled */
1329c2c66affSColin Finck         dwText = 0;
1330c2c66affSColin Finck         if ((dis->itemState & ODS_DISABLED))
1331c2c66affSColin Finck             dwText = DSS_DISABLED;
1332c2c66affSColin Finck 
13330b107f2eSCarlo-Bramini         /* Draw the text in the button */
1334c2c66affSColin Finck         GetTextExtentPoint32(dis->hDC, text, len, &size);
1335c2c66affSColin Finck         dx = ((dis->rcItem.right-dis->rcItem.left) - size.cx) >> 1;
1336c2c66affSColin Finck         dy = ((dis->rcItem.bottom-dis->rcItem.top) - size.cy) >> 1;
13370b107f2eSCarlo-Bramini         if ((dis->itemState & ODS_SELECTED)) {
1338c2c66affSColin Finck             dx++;
1339c2c66affSColin Finck             dy++;
1340c2c66affSColin Finck         }
1341c2c66affSColin Finck         pt.x = dis->rcItem.left + dx;
1342c2c66affSColin Finck         pt.y = dis->rcItem.top + dy;
1343c2c66affSColin Finck         DrawState(dis->hDC, NULL, NULL, (LPARAM)text, 0, pt.x, pt.y, size.cx, size.cy, DST_TEXT | dwText);
1344c2c66affSColin Finck     }
1345c2c66affSColin Finck     return 1L;
1346c2c66affSColin Finck }
1347c2c66affSColin Finck 
HotButtonProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)13480b107f2eSCarlo-Bramini static INT_PTR CALLBACK HotButtonProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
13490b107f2eSCarlo-Bramini {
13500b107f2eSCarlo-Bramini     LPBTNINFO lpBtnInfo = (LPBTNINFO)GetWindowLongPtr(hWnd, GWLP_USERDATA);
13510b107f2eSCarlo-Bramini     TRACKMOUSEEVENT mouse_event;
13520b107f2eSCarlo-Bramini 
13530b107f2eSCarlo-Bramini     switch (msg) {
13540b107f2eSCarlo-Bramini     case WM_MOUSEMOVE:
13550b107f2eSCarlo-Bramini         mouse_event.cbSize = sizeof(TRACKMOUSEEVENT);
13560b107f2eSCarlo-Bramini         mouse_event.dwFlags = TME_QUERY;
13570b107f2eSCarlo-Bramini         if (!TrackMouseEvent(&mouse_event) || !(mouse_event.dwFlags & (TME_HOVER|TME_LEAVE)))
13580b107f2eSCarlo-Bramini         {
13590b107f2eSCarlo-Bramini             mouse_event.dwFlags = TME_HOVER|TME_LEAVE;
13600b107f2eSCarlo-Bramini             mouse_event.hwndTrack = hWnd;
13610b107f2eSCarlo-Bramini             mouse_event.dwHoverTime = 1;
13620b107f2eSCarlo-Bramini             TrackMouseEvent(&mouse_event);
13630b107f2eSCarlo-Bramini         }
13640b107f2eSCarlo-Bramini         break;
13650b107f2eSCarlo-Bramini 
13660b107f2eSCarlo-Bramini     case WM_MOUSEHOVER:
13670b107f2eSCarlo-Bramini         lpBtnInfo->bHover = TRUE;
13680b107f2eSCarlo-Bramini         InvalidateRect(hWnd, NULL, FALSE);
13690b107f2eSCarlo-Bramini         break;
13700b107f2eSCarlo-Bramini 
13710b107f2eSCarlo-Bramini     case WM_MOUSELEAVE:
13720b107f2eSCarlo-Bramini         lpBtnInfo->bHover = FALSE;
13730b107f2eSCarlo-Bramini         InvalidateRect(hWnd, NULL, FALSE);
13740b107f2eSCarlo-Bramini         break;
13750b107f2eSCarlo-Bramini     }
13760b107f2eSCarlo-Bramini 
13770b107f2eSCarlo-Bramini     return CallWindowProc(lpBtnInfo->oldProc, hWnd, msg, wp, lp);
13780b107f2eSCarlo-Bramini }
13790b107f2eSCarlo-Bramini 
EnumChildProc(HWND hWnd,LPARAM lParam)13800b107f2eSCarlo-Bramini static BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM lParam)
13810b107f2eSCarlo-Bramini {
13820b107f2eSCarlo-Bramini     TCHAR szClass[64];
13830b107f2eSCarlo-Bramini 
13840b107f2eSCarlo-Bramini     if (!GetClassName(hWnd, szClass, SIZEOF(szClass)))
13850b107f2eSCarlo-Bramini         return TRUE;
13860b107f2eSCarlo-Bramini 
13870b107f2eSCarlo-Bramini     if (!_tcscmp(szClass, WC_BUTTON))
13880b107f2eSCarlo-Bramini     {
13890b107f2eSCarlo-Bramini         int *pnCtrls = (int *)lParam;
13900b107f2eSCarlo-Bramini         int nCtrls = *pnCtrls;
13910b107f2eSCarlo-Bramini 
13920b107f2eSCarlo-Bramini         BtnInfo[nCtrls].oldProc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
13930b107f2eSCarlo-Bramini         BtnInfo[nCtrls].bHover  = FALSE;
13940b107f2eSCarlo-Bramini 
13950b107f2eSCarlo-Bramini         SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)&BtnInfo[nCtrls]);
13960b107f2eSCarlo-Bramini         SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)HotButtonProc);
13970b107f2eSCarlo-Bramini 
13980b107f2eSCarlo-Bramini         *pnCtrls = ++nCtrls;
13990b107f2eSCarlo-Bramini     }
14000b107f2eSCarlo-Bramini     return TRUE;
14010b107f2eSCarlo-Bramini }
14020b107f2eSCarlo-Bramini 
OnSettingChange(HWND hWnd,WPARAM wParam,LPARAM lParam)1403857a951fSCarlo-Bramini static INT_PTR CALLBACK OnSettingChange(HWND hWnd, WPARAM wParam, LPARAM lParam)
1404857a951fSCarlo-Bramini {
1405857a951fSCarlo-Bramini     /* Check for user policy and area string valid */
1406857a951fSCarlo-Bramini     if (wParam == 0 && lParam != 0)
1407857a951fSCarlo-Bramini     {
1408857a951fSCarlo-Bramini         LPTSTR lpArea = (LPTSTR)lParam;
1409857a951fSCarlo-Bramini 
1410857a951fSCarlo-Bramini         /* Check if a parameter has been changed into the locale settings */
1411857a951fSCarlo-Bramini         if (!_tcsicmp(lpArea, _T("intl")))
1412857a951fSCarlo-Bramini         {
1413857a951fSCarlo-Bramini             /* Re-load locale parameters */
1414857a951fSCarlo-Bramini             UpdateNumberIntl();
1415857a951fSCarlo-Bramini 
1416857a951fSCarlo-Bramini             /* Update text for decimal button */
1417857a951fSCarlo-Bramini             SetDlgItemText(hWnd, IDC_BUTTON_DOT, calc.sDecimal);
1418857a951fSCarlo-Bramini 
1419857a951fSCarlo-Bramini             /* Update text into the output display */
1420857a951fSCarlo-Bramini             update_lcd_display(hWnd);
1421857a951fSCarlo-Bramini         }
1422857a951fSCarlo-Bramini     }
1423857a951fSCarlo-Bramini     return 0;
1424857a951fSCarlo-Bramini }
1425857a951fSCarlo-Bramini 
DlgMainProc(HWND hWnd,UINT msg,WPARAM wp,LPARAM lp)1426c2c66affSColin Finck static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
1427c2c66affSColin Finck {
1428c2c66affSColin Finck     unsigned int x;
1429c2c66affSColin Finck     RECT         rc;
1430c2c66affSColin Finck 
1431c2c66affSColin Finck     switch (msg) {
1432c2c66affSColin Finck     case WM_DRAWITEM:
1433c2c66affSColin Finck         return SubclassButtonProc(hWnd, wp, lp);
1434c2c66affSColin Finck 
1435c2c66affSColin Finck     case WM_INITDIALOG:
1436f6c565bcSCarlo-Bramini #ifdef DISABLE_HTMLHELP_SUPPORT
14376c16f12dSBișoc George         EnableMenuItem(GetMenu(hWnd), IDM_HELP_HELP, MF_BYCOMMAND | MF_GRAYED);
1438f6c565bcSCarlo-Bramini #endif
1439c2c66affSColin Finck         calc.hWnd=hWnd;
14400b107f2eSCarlo-Bramini         /* Enumerate children and apply hover function */
14410b107f2eSCarlo-Bramini         BtnCount = 0;
14420b107f2eSCarlo-Bramini         EnumChildWindows(hWnd, EnumChildProc, (LPARAM)&BtnCount);
1443c2c66affSColin Finck 
1444c2c66affSColin Finck #ifdef USE_KEYBOARD_HOOK
1445c2c66affSColin Finck         calc.hKeyboardHook=SetWindowsHookEx(
1446c2c66affSColin Finck                                        WH_KEYBOARD,
1447c2c66affSColin Finck                                        KeyboardHookProc,
1448c2c66affSColin Finck                                        NULL,
1449c2c66affSColin Finck                                        GetCurrentThreadId()
1450c2c66affSColin Finck                                       );
1451c2c66affSColin Finck #endif
1452c2c66affSColin Finck         rpn_zero(&calc.code);
1453c2c66affSColin Finck         calc.sci_out = FALSE;
1454c2c66affSColin Finck         calc.base = IDC_RADIO_DEC;
1455c2c66affSColin Finck         calc.size = IDC_RADIO_QWORD;
1456c2c66affSColin Finck         calc.degr = IDC_RADIO_DEG;
1457c2c66affSColin Finck         calc.ptr  = calc.buffer;
1458c2c66affSColin Finck         calc.is_nan = FALSE;
1459c2c66affSColin Finck         enable_allowed_controls(hWnd, IDC_RADIO_DEC);
1460c2c66affSColin Finck         update_radio(hWnd, IDC_RADIO_DEC);
1461c2c66affSColin Finck         update_menu(hWnd);
1462c2c66affSColin Finck         display_rpn_result(hWnd, &calc.code);
1463c2c66affSColin Finck         update_memory_flag(hWnd, calc.is_memory);
1464c2c66affSColin Finck         /* remove keyboard focus */
1465c2c66affSColin Finck         SetFocus(GetDlgItem(hWnd, IDC_BUTTON_FOCUS));
1466c2c66affSColin Finck         /* set our calc icon */
14670b107f2eSCarlo-Bramini         SendMessage(hWnd, WM_SETICON, ICON_BIG,   (LPARAM)calc.hBgIcon);
14680b107f2eSCarlo-Bramini         SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)calc.hSmIcon);
1469c2c66affSColin Finck         /* update text for decimal button */
1470248acabaSCarlo-Bramini         SetDlgItemText(hWnd, IDC_BUTTON_DOT, calc.sDecimal);
1471c2c66affSColin Finck         /* Fill combo box for conversion */
1472c2c66affSColin Finck         if (calc.layout == CALC_LAYOUT_CONVERSION)
1473c2c66affSColin Finck             ConvInit(hWnd);
1474c2c66affSColin Finck         /* Restore the window at the same position it was */
1475c2c66affSColin Finck         if (calc.x_coord >= 0 && calc.y_coord >= 0) {
1476c2c66affSColin Finck             int w, h, sw, sh;
1477c2c66affSColin Finck 
1478c2c66affSColin Finck             GetWindowRect(hWnd, &rc);
1479c2c66affSColin Finck             w = rc.right-rc.left;
1480c2c66affSColin Finck             h = rc.bottom-rc.top;
1481c2c66affSColin Finck             sw = GetSystemMetrics(SM_CXSCREEN);
1482c2c66affSColin Finck             sh = GetSystemMetrics(SM_CYSCREEN);
1483c2c66affSColin Finck             if (calc.x_coord+w > sw) calc.x_coord = sw - w;
1484c2c66affSColin Finck             if (calc.y_coord+h > sh) calc.y_coord = sh - h;
1485c2c66affSColin Finck             MoveWindow(hWnd, calc.x_coord, calc.y_coord, w, h, FALSE);
1486c2c66affSColin Finck         }
1487c2c66affSColin Finck         break;
1488c2c66affSColin Finck     case WM_CTLCOLORSTATIC:
1489c2c66affSColin Finck         if ((HWND)lp == GetDlgItem(hWnd, IDC_TEXT_OUTPUT))
1490c2c66affSColin Finck             return (LRESULT)GetStockObject(WHITE_BRUSH);
1491c2c66affSColin Finck         break;
1492c2c66affSColin Finck     case WM_HANDLE_CLIPBOARD:
1493c2c66affSColin Finck         handle_sequence_input(hWnd, &calc.Clipboard);
1494c2c66affSColin Finck         return TRUE;
1495c2c66affSColin Finck     case WM_COMMAND:
1496c2c66affSColin Finck         /*
1497c2c66affSColin Finck          * if selection of category is changed, we must
1498c2c66affSColin Finck          * update the content of the "from/to" combo boxes.
1499c2c66affSColin Finck          */
1500c2c66affSColin Finck         if (wp == MAKEWPARAM(IDC_COMBO_CATEGORY, CBN_SELCHANGE)) {
1501c2c66affSColin Finck             ConvAdjust(hWnd, SendDlgItemMessage(hWnd, IDC_COMBO_CATEGORY, CB_GETCURSEL, 0, 0));
1502c2c66affSColin Finck             return TRUE;
1503c2c66affSColin Finck         }
1504c2c66affSColin Finck         if (HIWORD(wp) != BN_CLICKED && HIWORD(wp) != BN_DBLCLK)
1505c2c66affSColin Finck             break;
1506c2c66affSColin Finck         /* avoid flicker if the user selects from keyboard */
1507c2c66affSColin Finck         if (GetFocus() != GetDlgItem(hWnd, IDC_BUTTON_FOCUS))
1508c2c66affSColin Finck             SetFocus(GetDlgItem(hWnd, IDC_BUTTON_FOCUS));
1509c2c66affSColin Finck         switch (LOWORD(wp)) {
1510c2c66affSColin Finck         case IDM_HELP_ABOUT:
1511c2c66affSColin Finck         {
1512c2c66affSColin Finck             TCHAR infotitle[100];
1513c2c66affSColin Finck             TCHAR infotext[200];
1514c2c66affSColin Finck             LoadString(calc.hInstance, IDS_CALC_NAME, infotitle, SIZEOF(infotitle));
1515c2c66affSColin Finck             LoadString(calc.hInstance, IDS_AUTHOR, infotext, SIZEOF(infotext));
15160b107f2eSCarlo-Bramini             ShellAbout(hWnd, infotitle, infotext, calc.hBgIcon);
1517c2c66affSColin Finck             return TRUE;
1518c2c66affSColin Finck         }
1519c2c66affSColin Finck         case IDM_HELP_HELP:
1520c2c66affSColin Finck #ifndef DISABLE_HTMLHELP_SUPPORT
1521f6c565bcSCarlo-Bramini             calc_HtmlHelp(hWnd, HTMLHELP_PATH("/general_information.htm"), HH_DISPLAY_TOPIC, (DWORD_PTR)NULL);
1522c2c66affSColin Finck #endif
1523c2c66affSColin Finck             return TRUE;
1524c2c66affSColin Finck         case IDM_VIEW_STANDARD:
1525c2c66affSColin Finck             calc.layout = CALC_LAYOUT_STANDARD;
1526c2c66affSColin Finck             calc.action = IDM_VIEW_STANDARD;
1527c2c66affSColin Finck             DestroyWindow(hWnd);
1528c2c66affSColin Finck             return TRUE;
1529c2c66affSColin Finck         case IDM_VIEW_SCIENTIFIC:
1530c2c66affSColin Finck             calc.layout = CALC_LAYOUT_SCIENTIFIC;
1531c2c66affSColin Finck             calc.action = IDM_VIEW_SCIENTIFIC;
1532c2c66affSColin Finck             DestroyWindow(hWnd);
1533c2c66affSColin Finck             return TRUE;
1534c2c66affSColin Finck         case IDM_VIEW_CONVERSION:
1535c2c66affSColin Finck             calc.layout = CALC_LAYOUT_CONVERSION;
1536c2c66affSColin Finck             calc.action = IDM_VIEW_CONVERSION;
1537c2c66affSColin Finck             DestroyWindow(hWnd);
1538c2c66affSColin Finck             return TRUE;
1539c2c66affSColin Finck         case IDM_VIEW_HEX:
1540c2c66affSColin Finck         case IDM_VIEW_DEC:
1541c2c66affSColin Finck         case IDM_VIEW_OCT:
1542c2c66affSColin Finck         case IDM_VIEW_BIN:
1543c2c66affSColin Finck         case IDM_VIEW_DEG:
1544c2c66affSColin Finck         case IDM_VIEW_RAD:
1545c2c66affSColin Finck         case IDM_VIEW_GRAD:
1546c2c66affSColin Finck         case IDM_VIEW_QWORD:
1547c2c66affSColin Finck         case IDM_VIEW_DWORD:
1548c2c66affSColin Finck         case IDM_VIEW_WORD:
1549c2c66affSColin Finck         case IDM_VIEW_BYTE:
1550248acabaSCarlo-Bramini             SendMessage(hWnd, WM_COMMAND, idm_2_idc(LOWORD(wp)), 0);
1551c2c66affSColin Finck             return TRUE;
1552c2c66affSColin Finck         case IDM_EDIT_COPY:
1553c2c66affSColin Finck             handle_copy_command(hWnd);
1554c2c66affSColin Finck             return TRUE;
1555c2c66affSColin Finck         case IDM_EDIT_PASTE:
1556c2c66affSColin Finck             if (calc.Clipboard.data != NULL)
1557c2c66affSColin Finck                 break;
1558c2c66affSColin Finck             calc.Clipboard.data = ReadClipboard();
1559c2c66affSColin Finck             if (calc.Clipboard.data != NULL) {
1560c2c66affSColin Finck                 /* clear the content of the display before pasting */
1561c2c66affSColin Finck                 PostMessage(hWnd, WM_COMMAND, IDC_BUTTON_CE, 0);
1562c2c66affSColin Finck                 calc.Clipboard.ptr = calc.Clipboard.data;
1563c2c66affSColin Finck                 calc.Clipboard.wm_msg = WM_HANDLE_CLIPBOARD;
1564c2c66affSColin Finck                 handle_sequence_input(hWnd, &calc.Clipboard);
1565c2c66affSColin Finck             }
1566c2c66affSColin Finck             return TRUE;
1567c2c66affSColin Finck         case IDM_VIEW_GROUP:
1568c2c66affSColin Finck             calc.usesep = (calc.usesep ? FALSE : TRUE);
1569c2c66affSColin Finck             update_menu(hWnd);
1570c2c66affSColin Finck             update_lcd_display(hWnd);
1571c2c66affSColin Finck             return TRUE;
1572c2c66affSColin Finck         case IDC_BUTTON_CONVERT:
1573c2c66affSColin Finck             ConvExecute(hWnd);
1574c2c66affSColin Finck             return TRUE;
1575c2c66affSColin Finck         case IDC_BUTTON_CE: {
1576c2c66affSColin Finck             calc_number_t tmp;
1577c2c66affSColin Finck             rpn_zero(&tmp);
1578c2c66affSColin Finck             display_rpn_result(hWnd, &tmp);
1579c2c66affSColin Finck             }
1580c2c66affSColin Finck             return TRUE;
1581c2c66affSColin Finck         case IDC_RADIO_DEC:
1582c2c66affSColin Finck         case IDC_RADIO_HEX:
1583c2c66affSColin Finck         case IDC_RADIO_OCT:
1584c2c66affSColin Finck         case IDC_RADIO_BIN:
1585c2c66affSColin Finck /* GNU WINDRES is bugged so I must always force radio update */
1586c2c66affSColin Finck /* (Fix for Win95/98) */
1587c2c66affSColin Finck #ifdef _MSC_VER
1588c2c66affSColin Finck             if (calc.base == LOWORD(wp))
1589c2c66affSColin Finck                 break;
1590c2c66affSColin Finck #endif
1591c2c66affSColin Finck             calc.is_nan = FALSE;
1592c2c66affSColin Finck             update_radio(hWnd, LOWORD(wp));
1593c2c66affSColin Finck             return TRUE;
1594c2c66affSColin Finck         case IDC_RADIO_DEG:
1595c2c66affSColin Finck         case IDC_RADIO_RAD:
1596c2c66affSColin Finck         case IDC_RADIO_GRAD:
1597c2c66affSColin Finck /* GNU WINDRES is bugged so I must always force radio update */
1598c2c66affSColin Finck /* (Fix for Win95/98) */
1599c2c66affSColin Finck #ifdef _MSC_VER
1600c2c66affSColin Finck             if (calc.degr == LOWORD(wp))
1601c2c66affSColin Finck                 break;
1602c2c66affSColin Finck #endif
1603c2c66affSColin Finck             calc.degr = LOWORD(wp);
1604c2c66affSColin Finck             calc.is_nan = FALSE;
1605c2c66affSColin Finck             update_menu(hWnd);
1606c2c66affSColin Finck             return TRUE;
1607c2c66affSColin Finck         case IDC_RADIO_QWORD:
1608c2c66affSColin Finck         case IDC_RADIO_DWORD:
1609c2c66affSColin Finck         case IDC_RADIO_WORD:
1610c2c66affSColin Finck         case IDC_RADIO_BYTE:
1611c2c66affSColin Finck /* GNU WINDRES is bugged so I must always force radio update */
1612c2c66affSColin Finck /* (Fix for Win95/98) */
1613c2c66affSColin Finck #ifdef _MSC_VER
1614c2c66affSColin Finck             if (calc.size == LOWORD(wp))
1615c2c66affSColin Finck                 break;
1616c2c66affSColin Finck #endif
1617c2c66affSColin Finck             calc.size = LOWORD(wp);
1618c2c66affSColin Finck             calc.is_nan = FALSE;
1619c2c66affSColin Finck             update_menu(hWnd);
1620c2c66affSColin Finck             /*
1621c2c66affSColin Finck              * update the content of the display
1622c2c66affSColin Finck              */
1623c2c66affSColin Finck             convert_text2number(&calc.code);
1624c2c66affSColin Finck             apply_int_mask(&calc.code);
1625c2c66affSColin Finck             display_rpn_result(hWnd, &calc.code);
1626c2c66affSColin Finck             return TRUE;
1627c2c66affSColin Finck         case IDC_BUTTON_1:
1628c2c66affSColin Finck         case IDC_BUTTON_2:
1629c2c66affSColin Finck         case IDC_BUTTON_3:
1630c2c66affSColin Finck         case IDC_BUTTON_4:
1631c2c66affSColin Finck         case IDC_BUTTON_5:
1632c2c66affSColin Finck         case IDC_BUTTON_6:
1633c2c66affSColin Finck         case IDC_BUTTON_7:
1634c2c66affSColin Finck         case IDC_BUTTON_8:
1635c2c66affSColin Finck         case IDC_BUTTON_9:
1636c2c66affSColin Finck         case IDC_BUTTON_0:
1637c2c66affSColin Finck         case IDC_BUTTON_DOT:
1638c2c66affSColin Finck         case IDC_BUTTON_A:
1639c2c66affSColin Finck         case IDC_BUTTON_B:
1640c2c66affSColin Finck         case IDC_BUTTON_C:
1641c2c66affSColin Finck         case IDC_BUTTON_D:
1642c2c66affSColin Finck         case IDC_BUTTON_E:
1643c2c66affSColin Finck         case IDC_BUTTON_F:
1644605fa32dSCarlo Bramini             if (calc.is_nan) break;
1645c2c66affSColin Finck             build_operand(hWnd, LOWORD(wp));
1646c2c66affSColin Finck             return TRUE;
1647c2c66affSColin Finck         case IDC_BUTTON_PERCENT:
1648c2c66affSColin Finck         case IDC_BUTTON_ADD:
1649c2c66affSColin Finck         case IDC_BUTTON_SUB:
1650c2c66affSColin Finck         case IDC_BUTTON_MULT:
1651c2c66affSColin Finck         case IDC_BUTTON_DIV:
1652c2c66affSColin Finck         case IDC_BUTTON_MOD:
1653c2c66affSColin Finck         case IDC_BUTTON_AND:
1654c2c66affSColin Finck         case IDC_BUTTON_OR:
1655c2c66affSColin Finck         case IDC_BUTTON_XOR:
1656c2c66affSColin Finck         case IDC_BUTTON_LSH:
1657c2c66affSColin Finck         case IDC_BUTTON_RSH:
1658c2c66affSColin Finck         case IDC_BUTTON_EQU:
1659295eaf4eSCarlo-Bramini         case IDC_BUTTON_XeY:
1660295eaf4eSCarlo-Bramini         case IDC_BUTTON_XrY:
1661c2c66affSColin Finck             if (calc.is_nan) break;
1662c2c66affSColin Finck             /*
1663295eaf4eSCarlo-Bramini              * LSH and XeY buttons hold also the RSH and XrY functions with INV modifier,
1664295eaf4eSCarlo-Bramini              * but since they are two operand operators, they must be handled here.
1665c2c66affSColin Finck              */
1666295eaf4eSCarlo-Bramini             if ((get_modifiers(hWnd) & MODIFIER_INV))
1667295eaf4eSCarlo-Bramini             {
1668295eaf4eSCarlo-Bramini                 WPARAM IdcSim = IDC_STATIC;
1669295eaf4eSCarlo-Bramini 
1670295eaf4eSCarlo-Bramini                 switch (LOWORD(wp)) {
1671295eaf4eSCarlo-Bramini                 case IDC_BUTTON_LSH: IdcSim = MAKEWPARAM(IDC_BUTTON_RSH, BN_CLICKED); break;
1672295eaf4eSCarlo-Bramini                 case IDC_BUTTON_XeY: IdcSim = MAKEWPARAM(IDC_BUTTON_XrY, BN_CLICKED); break;
1673c2c66affSColin Finck                 }
1674295eaf4eSCarlo-Bramini 
1675295eaf4eSCarlo-Bramini                 if (IdcSim != IDC_STATIC)
1676295eaf4eSCarlo-Bramini                 {
1677295eaf4eSCarlo-Bramini                     PostMessage(hWnd, WM_COMMAND, IdcSim, 0);
1678295eaf4eSCarlo-Bramini                     CheckDlgButton(hWnd, IDC_CHECK_INV, BST_UNCHECKED);
1679adbafe64SCarlo-Bramini                     break;
1680295eaf4eSCarlo-Bramini                 }
1681295eaf4eSCarlo-Bramini             }
1682295eaf4eSCarlo-Bramini 
1683c2c66affSColin Finck             for (x=0; x<SIZEOF(operator_codes); x++) {
1684c2c66affSColin Finck                 if (LOWORD(wp) == operator_codes[x]) {
1685c2c66affSColin Finck                     convert_text2number(&calc.code);
1686c2c66affSColin Finck 
1687c2c66affSColin Finck                     if (calc.ptr == calc.buffer) {
1688c2c66affSColin Finck                         if (calc.last_operator != x) {
1689c2c66affSColin Finck                             if (x != RPN_OPERATOR_EQUAL)
1690c2c66affSColin Finck                                 exec_change_infix();
1691c2c66affSColin Finck                         } else
1692c2c66affSColin Finck                         if (x == RPN_OPERATOR_EQUAL) {
1693c2c66affSColin Finck                             exec_infix2postfix(&calc.code, calc.prev_operator);
1694c2c66affSColin Finck                             rpn_copy(&calc.code, &calc.prev);
1695c2c66affSColin Finck                         } else
1696c2c66affSColin Finck                             break;
1697c2c66affSColin Finck                     }
1698c2c66affSColin Finck 
1699c2c66affSColin Finck                     /* if no change then quit silently, */
1700c2c66affSColin Finck                     /* without display updates */
1701c2c66affSColin Finck                     if (!exec_infix2postfix(&calc.code, x))
1702c2c66affSColin Finck                         break;
1703c2c66affSColin Finck 
1704c2c66affSColin Finck                     display_rpn_result(hWnd, &calc.code);
1705c2c66affSColin Finck                     break;
1706c2c66affSColin Finck                 }
1707c2c66affSColin Finck             }
1708c2c66affSColin Finck             return TRUE;
1709c2c66affSColin Finck         case IDC_BUTTON_BACK:
1710605fa32dSCarlo Bramini             if (calc.is_nan) break;
1711c2c66affSColin Finck             if (calc.sci_in) {
1712c2c66affSColin Finck                 if (calc.esp == 0) {
1713c2c66affSColin Finck                     TCHAR *ptr;
1714c2c66affSColin Finck 
1715c2c66affSColin Finck                     calc.sci_in = FALSE;
1716adbafe64SCarlo-Bramini                     ptr = _tcschr(calc.ptr, _T('e'));
1717c2c66affSColin Finck                     if (ptr)
1718adbafe64SCarlo-Bramini                         *ptr = _T('\0');
1719c2c66affSColin Finck                     update_lcd_display(hWnd);
1720c2c66affSColin Finck                 } else {
1721c2c66affSColin Finck                     calc.esp /= 10;
1722c2c66affSColin Finck                     build_operand(hWnd, IDC_STATIC);
1723c2c66affSColin Finck                 }
1724c2c66affSColin Finck             } else
1725c2c66affSColin Finck             if (calc.ptr != calc.buffer) {
1726adbafe64SCarlo-Bramini                 *--calc.ptr = _T('\0');
1727adbafe64SCarlo-Bramini                 if (!_tcscmp(calc.buffer, _T("-")) ||
1728adbafe64SCarlo-Bramini                     !_tcscmp(calc.buffer, _T("-0")) ||
1729adbafe64SCarlo-Bramini                     !_tcscmp(calc.buffer, _T("0"))) {
1730c2c66affSColin Finck                     calc.ptr = calc.buffer;
1731adbafe64SCarlo-Bramini                     calc.buffer[0] = _T('\0');
1732c2c66affSColin Finck                 }
1733c2c66affSColin Finck                 update_lcd_display(hWnd);
1734c2c66affSColin Finck             }
1735c2c66affSColin Finck             return TRUE;
1736c2c66affSColin Finck         case IDC_BUTTON_MC:
1737c2c66affSColin Finck             rpn_zero(&calc.memory.number);
1738c2c66affSColin Finck             update_memory_flag(hWnd, FALSE);
1739c2c66affSColin Finck             return TRUE;
1740c2c66affSColin Finck         case IDC_BUTTON_MR:
1741c2c66affSColin Finck             if (calc.is_memory) {
1742c2c66affSColin Finck                 calc.is_nan = FALSE;
1743c2c66affSColin Finck                 rpn_copy(&calc.code, &calc.memory.number);
1744c2c66affSColin Finck                 display_rpn_result(hWnd, &calc.code);
1745c2c66affSColin Finck             }
1746c2c66affSColin Finck             return TRUE;
1747c2c66affSColin Finck         case IDC_BUTTON_EXP:
1748c2c66affSColin Finck             if (calc.sci_in || calc.is_nan || calc.buffer == calc.ptr)
1749c2c66affSColin Finck                 break;
1750c2c66affSColin Finck             calc.sci_in = TRUE;
1751c2c66affSColin Finck             calc.esp = 0;
1752c2c66affSColin Finck             build_operand(hWnd, IDC_STATIC);
1753c2c66affSColin Finck             return TRUE;
1754c2c66affSColin Finck         case IDC_BUTTON_SIGN:
1755c2c66affSColin Finck             if (calc.sci_in) {
1756c2c66affSColin Finck                 calc.esp = 0-calc.esp;
1757c2c66affSColin Finck                 build_operand(hWnd, IDC_STATIC);
1758c2c66affSColin Finck             } else {
1759adbafe64SCarlo-Bramini                 if (calc.is_nan || calc.buffer[0] == _T('\0'))
1760c2c66affSColin Finck                     break;
1761c2c66affSColin Finck 
1762adbafe64SCarlo-Bramini                 if (calc.buffer[0] == _T('-')) {
1763c2c66affSColin Finck                     /* make the number positive */
1764c2c66affSColin Finck                     memmove(calc.buffer, calc.buffer+1, sizeof(calc.buffer)-1);
1765c2c66affSColin Finck                     if (calc.buffer != calc.ptr)
1766c2c66affSColin Finck                         calc.ptr--;
1767c2c66affSColin Finck                 } else {
1768c2c66affSColin Finck                     /* if first char is '0' and no dot, it isn't valid */
1769adbafe64SCarlo-Bramini                     if (calc.buffer[0] == _T('0') &&
1770adbafe64SCarlo-Bramini                         calc.buffer[1] != _T('.'))
1771c2c66affSColin Finck                         break;
1772c2c66affSColin Finck                     /* make the number negative */
1773c2c66affSColin Finck                     memmove(calc.buffer+1, calc.buffer, sizeof(calc.buffer)-1);
1774adbafe64SCarlo-Bramini                     calc.buffer[0] = _T('-');
1775c2c66affSColin Finck                     if (calc.buffer != calc.ptr)
1776c2c66affSColin Finck                         calc.ptr++;
1777c2c66affSColin Finck                 }
1778c2c66affSColin Finck                 /* If the input buffer is empty, then
1779c2c66affSColin Finck                    we change also the sign of calc.code
1780c2c66affSColin Finck                    because it could be the result of a
1781c2c66affSColin Finck                    previous calculation. */
1782c2c66affSColin Finck                 if (calc.buffer == calc.ptr)
1783c2c66affSColin Finck                     rpn_sign(&calc.code);
1784c2c66affSColin Finck                 update_lcd_display(hWnd);
1785c2c66affSColin Finck             }
1786c2c66affSColin Finck             return TRUE;
1787c2c66affSColin Finck         case IDC_BUTTON_RIGHTPAR:
1788c2c66affSColin Finck         case IDC_BUTTON_LEFTPAR:
1789c2c66affSColin Finck         case IDC_BUTTON_CANC:
1790c2c66affSColin Finck         case IDC_BUTTON_MP:
1791c2c66affSColin Finck         case IDC_BUTTON_DAT:
1792c2c66affSColin Finck         case IDC_BUTTON_FE:
1793c2c66affSColin Finck         case IDC_BUTTON_DMS:
1794c2c66affSColin Finck         case IDC_BUTTON_SQRT:
1795c2c66affSColin Finck         case IDC_BUTTON_S:
1796c2c66affSColin Finck         case IDC_BUTTON_SUM:
1797c2c66affSColin Finck         case IDC_BUTTON_AVE:
1798c2c66affSColin Finck         case IDC_BUTTON_NF:
1799c2c66affSColin Finck         case IDC_BUTTON_LN:
1800c2c66affSColin Finck         case IDC_BUTTON_LOG:
1801c2c66affSColin Finck         case IDC_BUTTON_Xe2:
1802c2c66affSColin Finck         case IDC_BUTTON_Xe3:
1803c2c66affSColin Finck         case IDC_BUTTON_PI:
1804c2c66affSColin Finck         case IDC_BUTTON_NOT:
1805c2c66affSColin Finck         case IDC_BUTTON_RX:
1806c2c66affSColin Finck         case IDC_BUTTON_INT:
1807c2c66affSColin Finck         case IDC_BUTTON_SIN:
1808c2c66affSColin Finck         case IDC_BUTTON_COS:
1809c2c66affSColin Finck         case IDC_BUTTON_TAN:
1810c2c66affSColin Finck         case IDC_BUTTON_MS:
1811c2c66affSColin Finck             for (x=0; x<SIZEOF(function_table); x++) {
1812c2c66affSColin Finck                 if (LOWORD(wp) == function_table[x].idc) {
1813c2c66affSColin Finck                     rpn_callback1 cb = NULL;
1814c2c66affSColin Finck 
1815c2c66affSColin Finck                     /* test if NaN state is important or not */
1816c2c66affSColin Finck                     if (calc.is_nan && function_table[x].check_nan) break;
1817c2c66affSColin Finck                     /* otherwise, it's cleared */
1818c2c66affSColin Finck                     calc.is_nan = FALSE;
1819c2c66affSColin Finck 
1820c2c66affSColin Finck                     switch (get_modifiers(hWnd) & function_table[x].range) {
1821c2c66affSColin Finck                     case 0:
1822c2c66affSColin Finck                         cb = function_table[x].direct;
1823c2c66affSColin Finck                         break;
1824c2c66affSColin Finck                     case MODIFIER_INV:
1825c2c66affSColin Finck                         cb = function_table[x].inverse;
1826c2c66affSColin Finck                         break;
1827c2c66affSColin Finck                     case MODIFIER_HYP:
1828c2c66affSColin Finck                         cb = function_table[x].hyperb;
1829c2c66affSColin Finck                         break;
1830c2c66affSColin Finck                     case MODIFIER_INV|MODIFIER_HYP:
1831c2c66affSColin Finck                         cb = function_table[x].inv_hyp;
1832c2c66affSColin Finck                         break;
1833c2c66affSColin Finck                     }
1834c2c66affSColin Finck                     if (cb != NULL) {
1835c2c66affSColin Finck                         convert_text2number(&calc.code);
1836c2c66affSColin Finck                         cb(&calc.code);
1837adbafe64SCarlo-Bramini //                        display_rpn_result(hWnd, &calc.code);
1838adbafe64SCarlo-Bramini                         set_rpn_result(hWnd, &calc.code);
1839adbafe64SCarlo-Bramini 
1840adbafe64SCarlo-Bramini                         if ((function_table[x].range & NO_CHAIN))
1841adbafe64SCarlo-Bramini                             calc.ptr = calc.buffer;
1842adbafe64SCarlo-Bramini 
1843295eaf4eSCarlo-Bramini //                        if (!(function_table[x].range & NO_CHAIN))
1844295eaf4eSCarlo-Bramini //                            exec_infix2postfix(&calc.code, RPN_OPERATOR_NONE);
1845c2c66affSColin Finck                         if (function_table[x].range & MODIFIER_INV)
1846248acabaSCarlo-Bramini                             CheckDlgButton(hWnd, IDC_CHECK_INV, BST_UNCHECKED);
1847c2c66affSColin Finck                         if (function_table[x].range & MODIFIER_HYP)
1848248acabaSCarlo-Bramini                             CheckDlgButton(hWnd, IDC_CHECK_HYP, BST_UNCHECKED);
1849c2c66affSColin Finck                     }
1850adbafe64SCarlo-Bramini                     break;
1851c2c66affSColin Finck                 }
1852c2c66affSColin Finck             }
1853c2c66affSColin Finck             return TRUE;
1854c2c66affSColin Finck         case IDC_BUTTON_STA:
1855c2c66affSColin Finck             if (IsWindow(calc.hStatWnd))
1856c2c66affSColin Finck                 break;
1857c2c66affSColin Finck             calc.hStatWnd = CreateDialog(calc.hInstance,
1858c2c66affSColin Finck                                     MAKEINTRESOURCE(IDD_DIALOG_STAT), hWnd, DlgStatProc);
1859c2c66affSColin Finck             if (calc.hStatWnd != NULL) {
1860c2c66affSColin Finck                 enable_allowed_controls(hWnd, calc.base);
1861c2c66affSColin Finck                 SendMessage(calc.hStatWnd, WM_SETFOCUS, 0, 0);
1862c2c66affSColin Finck             }
1863c2c66affSColin Finck             return TRUE;
1864c2c66affSColin Finck         }
1865c2c66affSColin Finck         break;
1866c2c66affSColin Finck     case WM_CLOSE_STATS:
1867adbafe64SCarlo-Bramini         calc.hStatWnd = NULL;
1868c2c66affSColin Finck         enable_allowed_controls(hWnd, calc.base);
1869c2c66affSColin Finck         return TRUE;
1870c2c66affSColin Finck     case WM_LOAD_STAT:
1871c2c66affSColin Finck         if (upload_stat_number((int)LOWORD(wp)) != NULL)
1872c2c66affSColin Finck             display_rpn_result(hWnd, &calc.code);
1873c2c66affSColin Finck         return TRUE;
1874c2c66affSColin Finck     case WM_START_CONV:
1875c2c66affSColin Finck         x = LOWORD(lp);
1876c2c66affSColin Finck         calc.Convert[x].data = ReadConversion(calc.Convert[x].data);
1877c2c66affSColin Finck         if (calc.Convert[x].data != NULL) {
1878c2c66affSColin Finck             calc.Convert[x].ptr = calc.Convert[x].data;
1879c2c66affSColin Finck             PostMessage(hWnd, HIWORD(lp), 0, 0);
1880c2c66affSColin Finck         }
1881c2c66affSColin Finck         return TRUE;
1882c2c66affSColin Finck     case WM_HANDLE_FROM:
1883c2c66affSColin Finck         if (calc.is_nan)
1884c2c66affSColin Finck             break;
1885c2c66affSColin Finck         if (handle_sequence_input(hWnd, &calc.Convert[0]) == NULL)
1886c2c66affSColin Finck             PostMessage(hWnd, WM_START_CONV, 0,
1887c2c66affSColin Finck                         MAKELPARAM(0x0001, WM_HANDLE_TO));
1888c2c66affSColin Finck         return TRUE;
1889c2c66affSColin Finck     case WM_HANDLE_TO:
1890c2c66affSColin Finck         if (!calc.is_nan)
1891c2c66affSColin Finck             handle_sequence_input(hWnd, &calc.Convert[1]);
1892c2c66affSColin Finck         return TRUE;
1893c2c66affSColin Finck     case WM_CLOSE:
1894c2c66affSColin Finck         calc.action = IDC_STATIC;
1895c2c66affSColin Finck         DestroyWindow(hWnd);
1896c2c66affSColin Finck         return TRUE;
1897f6c565bcSCarlo-Bramini 
1898c2c66affSColin Finck     case WM_DESTROY:
1899c2c66affSColin Finck         /* Get (x,y) position of the calculator */
1900c2c66affSColin Finck         GetWindowRect(hWnd, &rc);
1901c2c66affSColin Finck         calc.x_coord = rc.left;
1902c2c66affSColin Finck         calc.y_coord = rc.top;
1903c2c66affSColin Finck #ifdef USE_KEYBOARD_HOOK
1904c2c66affSColin Finck         UnhookWindowsHookEx(calc.hKeyboardHook);
1905c2c66affSColin Finck #endif
1906c2c66affSColin Finck         PostQuitMessage(0);
1907c2c66affSColin Finck         return TRUE;
1908c2c66affSColin Finck     case WM_CONTEXTMENU:
1909c2c66affSColin Finck         if ((HWND)wp != hWnd)
1910c2c66affSColin Finck             handle_context_menu(hWnd, wp, lp);
1911c2c66affSColin Finck         return TRUE;
1912c2c66affSColin Finck     case WM_ENTERMENULOOP:
1913c2c66affSColin Finck         calc.is_menu_on = TRUE;
1914c2c66affSColin Finck         /* Check if a valid format is available in the clipboard */
1915c2c66affSColin Finck         EnableMenuItem(GetSubMenu(GetMenu(hWnd), 0),
1916c2c66affSColin Finck                        IDM_EDIT_PASTE,
1917c2c66affSColin Finck                        MF_BYCOMMAND|
1918c2c66affSColin Finck                        (IsClipboardFormatAvailable(CF_TEXT) ?
1919c2c66affSColin Finck                        MF_ENABLED : MF_GRAYED));
1920c2c66affSColin Finck         break;
1921c2c66affSColin Finck     case WM_EXITMENULOOP:
1922c2c66affSColin Finck         calc.is_menu_on = FALSE;
1923c2c66affSColin Finck         break;
19240b107f2eSCarlo-Bramini 
1925857a951fSCarlo-Bramini     case WM_SETTINGCHANGE:
1926857a951fSCarlo-Bramini         return OnSettingChange(hWnd, wp, lp);
1927857a951fSCarlo-Bramini 
19280b107f2eSCarlo-Bramini     case WM_THEMECHANGED:
19290b107f2eSCarlo-Bramini         InvalidateRect(hWnd, NULL, FALSE);
19300b107f2eSCarlo-Bramini         break;
1931c2c66affSColin Finck     }
1932c2c66affSColin Finck     return FALSE;
1933c2c66affSColin Finck }
1934c2c66affSColin Finck 
1935c2c66affSColin Finck #if defined(__GNUC__) && !defined(__REACTOS__)
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)1936c2c66affSColin Finck int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
1937c2c66affSColin Finck #else
1938c2c66affSColin Finck int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nShowCmd)
1939c2c66affSColin Finck #endif
1940c2c66affSColin Finck {
1941c2c66affSColin Finck     MSG msg;
1942c2c66affSColin Finck     DWORD dwLayout;
1943c2c66affSColin Finck 
19440b107f2eSCarlo-Bramini     /* Initialize controls for theming & manifest support */
1945c2c66affSColin Finck     InitCommonControls();
1946c2c66affSColin Finck 
1947c2c66affSColin Finck     calc.hInstance = hInstance;
1948c2c66affSColin Finck 
1949c2c66affSColin Finck     calc.x_coord = -1;
1950c2c66affSColin Finck     calc.y_coord = -1;
1951c2c66affSColin Finck 
1952c2c66affSColin Finck     load_config();
1953c2c66affSColin Finck     start_rpn_engine();
1954c2c66affSColin Finck 
1955f6c565bcSCarlo-Bramini     HtmlHelp_Start(hInstance);
1956f6c565bcSCarlo-Bramini 
19570b107f2eSCarlo-Bramini     Theme_Start(hInstance);
19580b107f2eSCarlo-Bramini 
19590b107f2eSCarlo-Bramini     calc.hBgIcon = LoadImage(
19600b107f2eSCarlo-Bramini                     hInstance,
19610b107f2eSCarlo-Bramini                     MAKEINTRESOURCE(IDI_CALC),
19620b107f2eSCarlo-Bramini                     IMAGE_ICON,
1963016acd17SSerge Gautherie                     0,
1964016acd17SSerge Gautherie                     0,
1965016acd17SSerge Gautherie                     LR_DEFAULTSIZE | LR_SHARED);
19660b107f2eSCarlo-Bramini 
19670b107f2eSCarlo-Bramini     calc.hSmIcon = LoadImage(
19680b107f2eSCarlo-Bramini                     hInstance,
19690b107f2eSCarlo-Bramini                     MAKEINTRESOURCE(IDI_CALC),
19700b107f2eSCarlo-Bramini                     IMAGE_ICON,
19710b107f2eSCarlo-Bramini                     GetSystemMetrics(SM_CXSMICON),
19720b107f2eSCarlo-Bramini                     GetSystemMetrics(SM_CYSMICON),
1973016acd17SSerge Gautherie                     LR_SHARED);
19740b107f2eSCarlo-Bramini 
1975c2c66affSColin Finck     do {
1976c2c66affSColin Finck         /* ignore hwnd: dialogs are already visible! */
1977c2c66affSColin Finck         if (calc.layout == CALC_LAYOUT_SCIENTIFIC)
1978c2c66affSColin Finck             dwLayout = IDD_DIALOG_SCIENTIFIC;
1979248acabaSCarlo-Bramini         else
1980248acabaSCarlo-Bramini         if (calc.layout == CALC_LAYOUT_CONVERSION)
1981c2c66affSColin Finck             dwLayout = IDD_DIALOG_CONVERSION;
1982c2c66affSColin Finck         else
1983c2c66affSColin Finck             dwLayout = IDD_DIALOG_STANDARD;
1984c2c66affSColin Finck 
1985c2c66affSColin Finck         /* This call will always fail if UNICODE for Win9x */
1986c2c66affSColin Finck         if (NULL == CreateDialog(hInstance, MAKEINTRESOURCE(dwLayout), NULL, DlgMainProc))
1987c2c66affSColin Finck             break;
1988c2c66affSColin Finck 
1989c2c66affSColin Finck         while (GetMessage(&msg, NULL, 0, 0)) {
1990c2c66affSColin Finck #ifndef USE_KEYBOARD_HOOK
1991c2c66affSColin Finck             if ((msg.message == WM_KEYUP ||
1992c2c66affSColin Finck                 msg.message == WM_KEYDOWN) &&
1993c2c66affSColin Finck                 !calc.is_menu_on)
1994c2c66affSColin Finck                 process_vk_key(msg.wParam, msg.lParam);
1995c2c66affSColin Finck #endif
1996c2c66affSColin Finck             TranslateMessage(&msg);
1997c2c66affSColin Finck             DispatchMessage(&msg);
1998c2c66affSColin Finck         }
1999857a951fSCarlo-Bramini 
2000857a951fSCarlo-Bramini         save_config();
2001c2c66affSColin Finck     } while (calc.action != IDC_STATIC);
2002c2c66affSColin Finck 
2003c2c66affSColin Finck     stop_rpn_engine();
2004c2c66affSColin Finck 
20050b107f2eSCarlo-Bramini     Theme_Stop();
2006f6c565bcSCarlo-Bramini     HtmlHelp_Stop();
2007f6c565bcSCarlo-Bramini 
2008c2c66affSColin Finck     return 0;
2009c2c66affSColin Finck }
2010