1 /********************************************************************************
2 * *
3 * F O X D e s k t o p C a l c u l a t o r *
4 * *
5 *********************************************************************************
6 * Copyright (C) 2001,2021 by Jeroen van der Zijp. All Rights Reserved. *
7 *********************************************************************************
8 * This program is free software: you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation, either version 3 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
20 ********************************************************************************/
21 #include "fx.h"
22 #include "fxkeys.h"
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <sys/stat.h>
26 #include <signal.h>
27 #ifndef WIN32
28 #include <unistd.h>
29 #endif
30 #include <ctype.h>
31 #include <math.h>
32 #include "icons.h"
33 #include "Calculator.h"
34 #include "Preferences.h"
35 #include "HelpWindow.h"
36
37
38 #define BINARY_LIMIT 32 // 32 bits
39 #define OCTAL_LIMIT 11 // 11 digits
40 #define DECIMAL_LIMIT 16 // +1.234567890123456E-308
41 #define HEXADECIMAL_LIMIT 8 // 8 hexadecimal digits
42
43 #define GOLDEN 1.6180339887498948482045868343 // Golden ratio
44 #define INVGOLDEN (1.0/GOLDEN) // Inverse golden ratio
45
46 #define DEG2RAD(x) (((2.0*PI)/360.0)*(x)) // Degrees to radians
47 #define GRA2RAD(x) ((PI/200.0)*(x)) // Grad to radians
48 #define RAD2DEG(x) ((360.0/(2.0*PI))*(x)) // Radians to degrees
49 #define RAD2GRA(x) ((200.0/PI)*(x)) // Radians to grad
50
51
52 /*
53 Notes:
54
55 - On window enter, direct keyboard focus to numeric input buttons
56 - When clicking on the display focus should stay on buttons
57 - On resize I'd like x-y aspect to remain the same
58 - Would be nice if font size more or less follows window size
59 - History option in display to retrieve back earlier results
60 (stored when pressing '=')
61 - Add button to return largest prime smaller than x.
62 - Add buttons for lcm/gcd.
63 */
64
65 /*******************************************************************************/
66
67
68
69 // Map
70 FXDEFMAP(Calculator) CalculatorMap[]={
71 FXMAPFUNCS(SEL_COMMAND,Calculator::ID_MODE,Calculator::ID_GRA,Calculator::onCmdAngle),
72 FXMAPFUNCS(SEL_UPDATE,Calculator::ID_MODE,Calculator::ID_GRA,Calculator::onUpdAngle),
73 FXMAPFUNCS(SEL_COMMAND,Calculator::ID_BASE,Calculator::ID_HEX,Calculator::onCmdBase),
74 FXMAPFUNCS(SEL_UPDATE,Calculator::ID_BASE,Calculator::ID_HEX,Calculator::onUpdBase),
75 FXMAPFUNCS(SEL_UPDATE,Calculator::ID_0,Calculator::ID_F,Calculator::onUpdDigit),
76 FXMAPFUNCS(SEL_COMMAND,Calculator::ID_0,Calculator::ID_F,Calculator::onCmdDigit),
77 FXMAPFUNCS(SEL_COMMAND,Calculator::ID_COLOR_DISPLAY,Calculator::ID_COLOR_CLEAR,Calculator::onCmdColor),
78 FXMAPFUNCS(SEL_CHANGED,Calculator::ID_COLOR_DISPLAY,Calculator::ID_COLOR_CLEAR,Calculator::onCmdColor),
79 FXMAPFUNCS(SEL_UPDATE,Calculator::ID_COLOR_DISPLAY,Calculator::ID_COLOR_CLEAR,Calculator::onUpdColor),
80 FXMAPFUNC(SEL_COMMAND,Calculator::ID_EXPONENT_ALWAYS,Calculator::onCmdExponent),
81 FXMAPFUNC(SEL_COMMAND,Calculator::ID_EXPONENT_NEVER,Calculator::onCmdExponent),
82 FXMAPFUNC(SEL_UPDATE,Calculator::ID_EXPONENT_ALWAYS,Calculator::onUpdExponent),
83 FXMAPFUNC(SEL_UPDATE,Calculator::ID_EXPONENT_NEVER,Calculator::onUpdExponent),
84 FXMAPFUNC(SEL_COMMAND,Calculator::ID_ENGINEERING_MODE,Calculator::onCmdEngineeringMode),
85 FXMAPFUNC(SEL_UPDATE,Calculator::ID_ENGINEERING_MODE,Calculator::onUpdEngineeringMode),
86 FXMAPFUNC(SEL_COMMAND,Calculator::ID_PRECISION,Calculator::onCmdPrecision),
87 FXMAPFUNC(SEL_UPDATE,Calculator::ID_PRECISION,Calculator::onUpdPrecision),
88 FXMAPFUNC(SEL_COMMAND,Calculator::ID_QUESTION,Calculator::onCmdQuestion),
89 FXMAPFUNC(SEL_COMMAND,Calculator::ID_BEEP,Calculator::onCmdBeep),
90 FXMAPFUNC(SEL_UPDATE,Calculator::ID_BEEP,Calculator::onUpdBeep),
91 FXMAPFUNC(SEL_COMMAND,Calculator::ID_FONT,Calculator::onCmdFont),
92 FXMAPFUNC(SEL_COMMAND,Calculator::ID_PREFERENCES,Calculator::onCmdPreferences),
93 FXMAPFUNC(SEL_COMMAND,Calculator::ID_CLEAR,Calculator::onCmdClear),
94 FXMAPFUNC(SEL_COMMAND,Calculator::ID_CLEARALL,Calculator::onCmdClearAll),
95 FXMAPFUNC(SEL_COMMAND,Calculator::ID_INV,Calculator::onCmdInverse),
96 FXMAPFUNC(SEL_COMMAND,Calculator::ID_HYP,Calculator::onCmdHyper),
97 FXMAPFUNC(SEL_COMMAND,Calculator::ID_MEM_REC,Calculator::onCmdMemRec),
98 FXMAPFUNC(SEL_COMMAND,Calculator::ID_MEM_ADD,Calculator::onCmdMemAdd),
99 FXMAPFUNC(SEL_COMMAND,Calculator::ID_MEM_SUB,Calculator::onCmdMemSub),
100 FXMAPFUNC(SEL_COMMAND,Calculator::ID_MEM_CLR,Calculator::onCmdMemClr),
101 FXMAPFUNC(SEL_COMMAND,Calculator::ID_PNT,Calculator::onCmdPoint),
102 FXMAPFUNC(SEL_UPDATE,Calculator::ID_PNT,Calculator::onUpdPoint),
103 FXMAPFUNC(SEL_COMMAND,Calculator::ID_EXP,Calculator::onCmdExp),
104 FXMAPFUNC(SEL_UPDATE,Calculator::ID_EXP,Calculator::onUpdExp),
105 FXMAPFUNC(SEL_COMMAND,Calculator::ID_DELETE,Calculator::onCmdDelete),
106 FXMAPFUNC(SEL_COMMAND,Calculator::ID_SIN,Calculator::onCmdSin),
107 FXMAPFUNC(SEL_UPDATE,Calculator::ID_SIN,Calculator::onUpdSin),
108 FXMAPFUNC(SEL_COMMAND,Calculator::ID_COS,Calculator::onCmdCos),
109 FXMAPFUNC(SEL_UPDATE,Calculator::ID_COS,Calculator::onUpdCos),
110 FXMAPFUNC(SEL_COMMAND,Calculator::ID_TAN,Calculator::onCmdTan),
111 FXMAPFUNC(SEL_UPDATE,Calculator::ID_TAN,Calculator::onUpdTan),
112 FXMAPFUNC(SEL_COMMAND,Calculator::ID_LOG,Calculator::onCmdLog),
113 FXMAPFUNC(SEL_UPDATE,Calculator::ID_LOG,Calculator::onUpdLog),
114 FXMAPFUNC(SEL_COMMAND,Calculator::ID_LN,Calculator::onCmdLn),
115 FXMAPFUNC(SEL_UPDATE,Calculator::ID_LN,Calculator::onUpdLn),
116 FXMAPFUNC(SEL_COMMAND,Calculator::ID_PI,Calculator::onCmdPi),
117 FXMAPFUNC(SEL_UPDATE,Calculator::ID_PI,Calculator::onUpdPi),
118 FXMAPFUNC(SEL_COMMAND,Calculator::ID_FAC,Calculator::onCmdFac),
119 FXMAPFUNC(SEL_UPDATE,Calculator::ID_FAC,Calculator::onUpdFac),
120 FXMAPFUNC(SEL_COMMAND,Calculator::ID_PER,Calculator::onCmdPer),
121 FXMAPFUNC(SEL_UPDATE,Calculator::ID_PER,Calculator::onUpdPer),
122 FXMAPFUNC(SEL_COMMAND,Calculator::ID_COM,Calculator::onCmdCom),
123 FXMAPFUNC(SEL_UPDATE,Calculator::ID_COM,Calculator::onUpdCom),
124 FXMAPFUNC(SEL_COMMAND,Calculator::ID_RECIP,Calculator::onCmdRecip),
125 FXMAPFUNC(SEL_UPDATE,Calculator::ID_RECIP,Calculator::onUpdRecip),
126 FXMAPFUNC(SEL_COMMAND,Calculator::ID_PLUSMIN,Calculator::onCmdPlusMin),
127 FXMAPFUNC(SEL_COMMAND,Calculator::ID_XTOY,Calculator::onCmdXToY),
128 FXMAPFUNC(SEL_UPDATE,Calculator::ID_XTOY,Calculator::onUpdXToY),
129 FXMAPFUNC(SEL_COMMAND,Calculator::ID_SQRT,Calculator::onCmdSqrt),
130 FXMAPFUNC(SEL_UPDATE,Calculator::ID_SQRT,Calculator::onUpdSqrt),
131 FXMAPFUNC(SEL_COMMAND,Calculator::ID_SHL,Calculator::onCmdShl),
132 FXMAPFUNC(SEL_UPDATE,Calculator::ID_SHL,Calculator::onUpdShl),
133 FXMAPFUNC(SEL_COMMAND,Calculator::ID_SHR,Calculator::onCmdShr),
134 FXMAPFUNC(SEL_UPDATE,Calculator::ID_SHR,Calculator::onUpdShr),
135 FXMAPFUNC(SEL_COMMAND,Calculator::ID_2LOG,Calculator::onCmd2Log),
136 FXMAPFUNC(SEL_UPDATE,Calculator::ID_2LOG,Calculator::onUpd2Log),
137 FXMAPFUNC(SEL_COMMAND,Calculator::ID_LPAR,Calculator::onCmdLPar),
138 FXMAPFUNC(SEL_COMMAND,Calculator::ID_RPAR,Calculator::onCmdRPar),
139 FXMAPFUNC(SEL_COMMAND,Calculator::ID_AND,Calculator::onCmdAnd),
140 FXMAPFUNC(SEL_COMMAND,Calculator::ID_OR,Calculator::onCmdOr),
141 FXMAPFUNC(SEL_COMMAND,Calculator::ID_XOR,Calculator::onCmdXor),
142 FXMAPFUNC(SEL_COMMAND,Calculator::ID_NOT,Calculator::onCmdNot),
143 FXMAPFUNC(SEL_COMMAND,Calculator::ID_MUL,Calculator::onCmdMul),
144 FXMAPFUNC(SEL_COMMAND,Calculator::ID_DIV,Calculator::onCmdDiv),
145 FXMAPFUNC(SEL_COMMAND,Calculator::ID_MOD,Calculator::onCmdMod),
146 FXMAPFUNC(SEL_UPDATE,Calculator::ID_MOD,Calculator::onUpdMod),
147 FXMAPFUNC(SEL_COMMAND,Calculator::ID_ADD,Calculator::onCmdAdd),
148 FXMAPFUNC(SEL_COMMAND,Calculator::ID_SUB,Calculator::onCmdSub),
149 FXMAPFUNC(SEL_COMMAND,Calculator::ID_ENTER,Calculator::onCmdEnter),
150 };
151
152
153 // Implementation
154 FXIMPLEMENT(Calculator,FXMainWindow,CalculatorMap,ARRAYNUMBER(CalculatorMap))
155
156
157 // Use a trick to get a nan
158 #if FOX_BIGENDIAN
159 static const FXuint nanny[2]={0x7fffffff,0xffffffff};
160 #else
161 static const FXuint nanny[2]={0xffffffff,0x7fffffff};
162 #endif
163
164 // Double precision nan
165 static const FXdouble& dblnan=*((const FXdouble*)(const void*)nanny);
166
167
168 // Operator priorities
169 static const FXuchar priority[]={
170 1, // DY_OR
171 1, // DY_XOR
172 1, // DY_AND
173 2, // DY_SUB
174 2, // DY_ADD
175 3, // DY_MOD
176 3, // DY_IDIV
177 3, // DY_DIV
178 3, // DY_MUL
179 4, // DY_XTOY
180 4, // DY_XTOINVY
181 5, // DY_PER
182 5, // DY_COM
183 8, // DY_LPAR
184 8, // DY_RPAR
185 };
186
187
188
189 /*******************************************************************************/
190
191 // Construct calculator dialog
Calculator(FXApp * a)192 Calculator::Calculator(FXApp* a):FXMainWindow(a,"FOX Calculator",NULL,NULL,DECOR_ALL, 0,0,0,0, 0,0){
193
194 // Default font used by default, duh!
195 font=NULL;
196
197 // Make some icons
198 bigicon=new FXGIFIcon(getApp(),bigcalc);
199 smallicon=new FXGIFIcon(getApp(),tinycalc);
200 cmem=new FXBMPIcon(getApp(),constmem);
201 quest=new FXGIFIcon(getApp(),question);
202
203 // Application icons
204 setIcon(bigicon);
205 setMiniIcon(smallicon);
206
207 // Interior
208 FXVerticalFrame *vert=new FXVerticalFrame(this,LAYOUT_FILL_X,0,0,0,0, 8,8,8,4, 1,1);
209 FXHorizontalFrame *displayframe=new FXHorizontalFrame(vert,LAYOUT_FILL_X,0,0,0,0, 0,0,0,0);
210 new FXButton(displayframe,"FOX Calculator",bigicon,this,ID_PREFERENCES,ICON_BEFORE_TEXT|JUSTIFY_LEFT|LAYOUT_FILL_Y,0,0,0,0, 4,4,2,2);
211 new FXButton(displayframe,FXString::null,quest,this,ID_QUESTION,ICON_BEFORE_TEXT|JUSTIFY_LEFT|LAYOUT_FILL_Y,0,0,0,0, 4,4,2,2);
212 display=new FXTextField(displayframe,16,this,ID_TEXT,TEXTFIELD_READONLY|FRAME_SUNKEN|FRAME_THICK|JUSTIFY_RIGHT|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0,0,0,0, 4,4,1,1);
213 new FXLabel(vert,FXString::null,cmem,LAYOUT_RIGHT,0,0,0,0, 0,0,0,0);
214
215 FXHorizontalFrame *modeframe=new FXHorizontalFrame(this,LAYOUT_FILL_X,0,0,0,0, 8,8,0,4, 8,8);
216
217 FXHorizontalFrame *baseframe=new FXHorizontalFrame(modeframe,FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH, 0,0,0,0, 0,0,0,0 ,0,0);
218
219 numbase[0]=new FXButton(baseframe,"&Hex",NULL,this,ID_HEX,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y);
220 numbase[1]=new FXButton(baseframe,"D&ec",NULL,this,ID_DEC,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y);
221 numbase[2]=new FXButton(baseframe,"&Oct",NULL,this,ID_OCT,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y);
222 numbase[3]=new FXButton(baseframe,"&Bin",NULL,this,ID_BIN,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y);
223
224 FXHorizontalFrame *degframe=new FXHorizontalFrame(modeframe,FRAME_SUNKEN|LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH, 0,0,0,0, 0,0,0,0 ,0,0);
225
226 angmode[0]=new FXButton(degframe,"&Deg",NULL,this,ID_DEG,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 2,2,2,2);
227 angmode[1]=new FXButton(degframe,"&Rad",NULL,this,ID_RAD,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 2,2,2,2);
228 angmode[2]=new FXButton(degframe,"&Gra",NULL,this,ID_GRA,FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 2,2,2,2);
229
230 // Frame for button blocks
231 FXHorizontalFrame *buttonframe=new FXHorizontalFrame(this,LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH, 0,0,0,0, 4,4,4,4, 0,0);
232
233 // Functions block
234 FXMatrix *funcblock=new FXMatrix(buttonframe,6,MATRIX_BY_ROWS|LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH|PACK_UNIFORM_HEIGHT);
235 inverse=new FXButton(funcblock,"inv",NULL,this,ID_INV,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
236 functions[0]=new FXButton(funcblock,"+/-",NULL,this,ID_PLUSMIN,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
237 functions[1]=new FXButton(funcblock,"1/x",NULL,this,ID_RECIP,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
238 functions[2]=new FXButton(funcblock,"x^y",NULL,this,ID_XTOY,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
239 functions[3]=new FXButton(funcblock,"sqrt",NULL,this,ID_SQRT,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
240 functions[4]=new FXButton(funcblock,"2log",NULL,this,ID_2LOG,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
241
242 functions[5]=new FXButton(funcblock,"pi",NULL,this,ID_PI,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
243 functions[6]=new FXButton(funcblock,"SHL",NULL,this,ID_SHL,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
244 functions[7]=new FXButton(funcblock,"SHR",NULL,this,ID_SHR,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
245 functions[8]=new FXButton(funcblock,"x!",NULL,this,ID_FAC,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
246 functions[9]=new FXButton(funcblock,"nPr",NULL,this,ID_PER,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
247 functions[10]=new FXButton(funcblock,"nCr",NULL,this,ID_COM,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
248
249 hyper2=new FXButton(funcblock,"hyp",NULL,this,ID_HYP,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
250 functions[11]=new FXButton(funcblock,"sin",NULL,this,ID_SIN,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
251 functions[12]=new FXButton(funcblock,"cos",NULL,this,ID_COS,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
252 functions[13]=new FXButton(funcblock,"tan",NULL,this,ID_TAN,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
253 functions[14]=new FXButton(funcblock,"log",NULL,this,ID_LOG,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
254 functions[15]=new FXButton(funcblock,"ln",NULL,this,ID_LN,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
255
256 digit[10]=new FXButton(funcblock,"A",NULL,this,ID_A,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
257 digit[11]=new FXButton(funcblock,"B",NULL,this,ID_B,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
258 digit[12]=new FXButton(funcblock,"C",NULL,this,ID_C,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
259 digit[13]=new FXButton(funcblock,"D",NULL,this,ID_D,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
260 digit[14]=new FXButton(funcblock,"E",NULL,this,ID_E,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
261 digit[15]=new FXButton(funcblock,"F",NULL,this,ID_F,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 8,8,1,1);
262
263 // Main block
264 FXMatrix *mainblock=new FXMatrix(buttonframe,5,MATRIX_BY_ROWS|LAYOUT_FILL_X|LAYOUT_FILL_Y|PACK_UNIFORM_WIDTH|PACK_UNIFORM_HEIGHT);
265 memory[0]=new FXButton(mainblock,"MR",NULL,this,ID_MEM_REC,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
266 digit[7]=new FXButton(mainblock,"7",NULL,this,ID_7,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
267 digit[4]=new FXButton(mainblock,"4",NULL,this,ID_4,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
268 digit[1]=new FXButton(mainblock,"1",NULL,this,ID_1,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
269 digit[0]=new FXButton(mainblock,"0",NULL,this,ID_0,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
270
271 memory[1]=new FXButton(mainblock,"M+",NULL,this,ID_MEM_ADD,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
272 digit[8]=new FXButton(mainblock,"8",NULL,this,ID_8,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
273 digit[5]=new FXButton(mainblock,"5",NULL,this,ID_5,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
274 digit[2]=new FXButton(mainblock,"2",NULL,this,ID_2,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
275 operators[0]=new FXButton(mainblock,".",NULL,this,ID_PNT,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
276
277 memory[2]=new FXButton(mainblock,"M-",NULL,this,ID_MEM_SUB,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
278 digit[9]=new FXButton(mainblock,"9",NULL,this,ID_9,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
279 digit[6]=new FXButton(mainblock,"6",NULL,this,ID_6,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
280 digit[3]=new FXButton(mainblock,"3",NULL,this,ID_3,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
281 operators[1]=new FXButton(mainblock,"EXP",NULL,this,ID_EXP,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
282
283 memory[3]=new FXButton(mainblock,"MC",NULL,this,ID_MEM_CLR,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
284 operators[2]=new FXButton(mainblock,"(",NULL,this,ID_LPAR,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
285 operators[3]=new FXButton(mainblock,"*",NULL,this,ID_MUL,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
286 operators[4]=new FXButton(mainblock,"+",NULL,this,ID_ADD,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
287 operators[5]=new FXButton(mainblock,"=",NULL,this,ID_ENTER,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
288
289 clearbtn=new FXButton(mainblock,"C",NULL,this,ID_CLEAR,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
290 operators[6]=new FXButton(mainblock,")",NULL,this,ID_RPAR,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
291 operators[7]=new FXButton(mainblock,"/",NULL,this,ID_DIV,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
292 operators[8]=new FXButton(mainblock,"-",NULL,this,ID_SUB,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
293 operators[9]=new FXButton(mainblock,"mod",NULL,this,ID_MOD,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
294
295 clearallbtn=new FXButton(mainblock,"AC",NULL,this,ID_CLEARALL,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
296 operators[10]=new FXButton(mainblock,"AND",NULL,this,ID_AND,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
297 operators[11]=new FXButton(mainblock,"OR",NULL,this,ID_OR,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
298 operators[12]=new FXButton(mainblock,"XOR",NULL,this,ID_XOR,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
299 operators[13]=new FXButton(mainblock,"NOT",NULL,this,ID_NOT,BUTTON_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_ROW|LAYOUT_FILL_X|LAYOUT_FILL_Y,0,0,0,0, 1,1,2,2);
300
301 // Hot keys for digits
302 digit[0]->addHotKey(MKUINT(KEY_0,0));
303 digit[0]->addHotKey(MKUINT(KEY_KP_0,0));
304 digit[1]->addHotKey(MKUINT(KEY_1,0));
305 digit[1]->addHotKey(MKUINT(KEY_KP_1,0));
306 digit[2]->addHotKey(MKUINT(KEY_2,0));
307 digit[2]->addHotKey(MKUINT(KEY_KP_2,0));
308 digit[3]->addHotKey(MKUINT(KEY_3,0));
309 digit[3]->addHotKey(MKUINT(KEY_KP_3,0));
310 digit[4]->addHotKey(MKUINT(KEY_4,0));
311 digit[4]->addHotKey(MKUINT(KEY_KP_4,0));
312 digit[5]->addHotKey(MKUINT(KEY_5,0));
313 digit[5]->addHotKey(MKUINT(KEY_KP_5,0));
314 digit[6]->addHotKey(MKUINT(KEY_6,0));
315 digit[6]->addHotKey(MKUINT(KEY_KP_6,0));
316 digit[7]->addHotKey(MKUINT(KEY_7,0));
317 digit[7]->addHotKey(MKUINT(KEY_KP_7,0));
318 digit[8]->addHotKey(MKUINT(KEY_8,0));
319 digit[8]->addHotKey(MKUINT(KEY_KP_8,0));
320 digit[9]->addHotKey(MKUINT(KEY_9,0));
321 digit[9]->addHotKey(MKUINT(KEY_KP_9,0));
322
323 // Hot keys for hex
324 digit[10]->addHotKey(MKUINT(KEY_a,0));
325 digit[11]->addHotKey(MKUINT(KEY_b,0));
326 digit[12]->addHotKey(MKUINT(KEY_c,0));
327 digit[13]->addHotKey(MKUINT(KEY_d,0));
328 digit[14]->addHotKey(MKUINT(KEY_e,0));
329 digit[15]->addHotKey(MKUINT(KEY_f,0));
330
331 // Hot keys for operators
332 operators[0]->addHotKey(MKUINT(KEY_period,0));
333 operators[0]->addHotKey(MKUINT(KEY_KP_Decimal,0));
334 operators[1]->addHotKey(MKUINT(KEY_E,SHIFTMASK));
335 operators[2]->addHotKey(MKUINT(KEY_parenleft,SHIFTMASK));
336 operators[3]->addHotKey(MKUINT(KEY_asterisk,SHIFTMASK));
337 operators[3]->addHotKey(MKUINT(KEY_KP_Multiply,0));
338 operators[4]->addHotKey(MKUINT(KEY_plus,SHIFTMASK));
339 operators[4]->addHotKey(MKUINT(KEY_KP_Add,0));
340 operators[5]->addHotKey(MKUINT(KEY_equal,0));
341 operators[6]->addHotKey(MKUINT(KEY_parenright,SHIFTMASK));
342 operators[7]->addHotKey(MKUINT(KEY_slash,0));
343 operators[7]->addHotKey(MKUINT(KEY_KP_Divide,0));
344 operators[8]->addHotKey(MKUINT(KEY_minus,0));
345 operators[8]->addHotKey(MKUINT(KEY_KP_Subtract,0));
346 operators[9]->addHotKey(MKUINT(KEY_percent,SHIFTMASK));
347 operators[10]->addHotKey(MKUINT(KEY_ampersand,SHIFTMASK));
348 operators[11]->addHotKey(MKUINT(KEY_bar,SHIFTMASK));
349 operators[12]->addHotKey(MKUINT(KEY_asciicircum,SHIFTMASK));
350 operators[13]->addHotKey(MKUINT(KEY_asciitilde,SHIFTMASK));
351
352 // Shifting
353 functions[6]->addHotKey(MKUINT(KEY_less,SHIFTMASK));
354 functions[7]->addHotKey(MKUINT(KEY_greater,SHIFTMASK));
355 functions[8]->addHotKey(MKUINT(KEY_exclam,SHIFTMASK));
356
357 inverse->addHotKey(MKUINT(KEY_i,0));
358 hyper2->addHotKey(MKUINT(KEY_h,0));
359
360 // Add accelerators
361 getAccelTable()->addAccel(MKUINT(KEY_Q,0),this,FXSEL(SEL_COMMAND,ID_CLOSE));
362 getAccelTable()->addAccel(MKUINT(KEY_q,0),this,FXSEL(SEL_COMMAND,ID_CLOSE));
363 getAccelTable()->addAccel(MKUINT(KEY_q,CONTROLMASK),this,FXSEL(SEL_COMMAND,ID_CLOSE));
364 getAccelTable()->addAccel(MKUINT(KEY_Escape,0),this,FXSEL(SEL_COMMAND,ID_CLEAR));
365 getAccelTable()->addAccel(MKUINT(KEY_BackSpace,0),this,FXSEL(SEL_COMMAND,ID_DELETE));
366 getAccelTable()->addAccel(MKUINT(KEY_Delete,0),this,FXSEL(SEL_COMMAND,ID_DELETE));
367 getAccelTable()->addAccel(MKUINT(KEY_KP_Delete,0),this,FXSEL(SEL_COMMAND,ID_DELETE));
368 getAccelTable()->addAccel(MKUINT(KEY_Return,0),this,FXSEL(SEL_COMMAND,ID_ENTER));
369 getAccelTable()->addAccel(MKUINT(KEY_KP_Enter,0),this,FXSEL(SEL_COMMAND,ID_ENTER));
370
371 // Initialize stuff
372 display->setText("0");
373 recall=0.0;
374 numstack[0]=0.0;
375 numsp=0;
376 opsp=-1;
377 limit=DECIMAL_LIMIT;
378 digits=1;
379 base=NUM_DEC;
380 angles=ANG_RAD;
381 precision=16;
382 exponent=EXPONENT_IFNEEDED;
383 beep=true;
384 parens=0;
385 modifiers=0;
386 }
387
388
389 // Create and show window
create()390 void Calculator::create(){
391 readRegistry();
392 FXMainWindow::create();
393 show();
394 }
395
396
397 // Destroy calculator dialog
~Calculator()398 Calculator::~Calculator(){
399 delete font;
400 delete bigicon;
401 delete smallicon;
402 delete cmem;
403 delete quest;
404 }
405
406
407 /*******************************************************************************/
408
409
410 // Set digit color
setDigitColor(FXColor clr)411 void Calculator::setDigitColor(FXColor clr){
412 FXColor hilite=makeHiliteColor(clr);
413 FXColor shadow=makeShadowColor(clr);
414 for(FXuint i=0; i<10; i++){
415 digit[i]->setBackColor(clr);
416 digit[i]->setHiliteColor(hilite);
417 digit[i]->setShadowColor(shadow);
418 }
419 }
420
421
422 // Get digit color
getDigitColor() const423 FXColor Calculator::getDigitColor() const {
424 return digit[0]->getBackColor();
425 }
426
427
428 // Set digit color
setHexDigitColor(FXColor clr)429 void Calculator::setHexDigitColor(FXColor clr){
430 FXColor hilite=makeHiliteColor(clr);
431 FXColor shadow=makeShadowColor(clr);
432 for(FXuint i=10; i<16; i++){
433 digit[i]->setBackColor(clr);
434 digit[i]->setHiliteColor(hilite);
435 digit[i]->setShadowColor(shadow);
436 }
437 }
438
439
440 // Get digit color
getHexDigitColor() const441 FXColor Calculator::getHexDigitColor() const {
442 return digit[10]->getBackColor();
443 }
444
445
446 // Set operator color
setOperatorColor(FXColor clr)447 void Calculator::setOperatorColor(FXColor clr){
448 FXColor hilite=makeHiliteColor(clr);
449 FXColor shadow=makeShadowColor(clr);
450 for(FXuint i=0; i<14; i++){
451 operators[i]->setBackColor(clr);
452 operators[i]->setHiliteColor(hilite);
453 operators[i]->setShadowColor(shadow);
454 }
455 }
456
457
458 // Get operator color
getOperatorColor() const459 FXColor Calculator::getOperatorColor() const {
460 return operators[0]->getBackColor();
461 }
462
463
464 // Set function color
setFunctionColor(FXColor clr)465 void Calculator::setFunctionColor(FXColor clr){
466 FXColor hilite=makeHiliteColor(clr);
467 FXColor shadow=makeShadowColor(clr);
468 for(FXuint i=0; i<16; i++){
469 functions[i]->setBackColor(clr);
470 functions[i]->setHiliteColor(hilite);
471 functions[i]->setShadowColor(shadow);
472 }
473 }
474
475
476 // Get function color
getFunctionColor() const477 FXColor Calculator::getFunctionColor() const {
478 return functions[0]->getBackColor();
479 }
480
481
482 // Set memory color
setMemoryColor(FXColor clr)483 void Calculator::setMemoryColor(FXColor clr){
484 FXColor hilite=makeHiliteColor(clr);
485 FXColor shadow=makeShadowColor(clr);
486 for(FXuint i=0; i<4; i++){
487 memory[i]->setBackColor(clr);
488 memory[i]->setHiliteColor(hilite);
489 memory[i]->setShadowColor(shadow);
490 }
491 }
492
493
494 // Get memory color
getMemoryColor() const495 FXColor Calculator::getMemoryColor() const {
496 return memory[0]->getBackColor();
497 }
498
499
500 // Set inverse color
setInverseColor(FXColor clr)501 void Calculator::setInverseColor(FXColor clr){
502 inverse->setBackColor(clr);
503 inverse->setHiliteColor(makeHiliteColor(clr));
504 inverse->setShadowColor(makeShadowColor(clr));
505 }
506
507
508 // Get inverse color
getInverseColor() const509 FXColor Calculator::getInverseColor() const {
510 return inverse->getBackColor();
511 }
512
513
514 // Set hyp color
setHyperColor(FXColor clr)515 void Calculator::setHyperColor(FXColor clr){
516 hyper2->setBackColor(clr);
517 hyper2->setHiliteColor(makeHiliteColor(clr));
518 hyper2->setShadowColor(makeShadowColor(clr));
519 }
520
521
522 // Get hyp color
getHyperColor() const523 FXColor Calculator::getHyperColor() const {
524 return hyper2->getBackColor();
525 }
526
527
528 // Set clear color
setClearColor(FXColor clr)529 void Calculator::setClearColor(FXColor clr){
530 clearbtn->setBackColor(clr);
531 clearbtn->setHiliteColor(makeHiliteColor(clr));
532 clearbtn->setShadowColor(makeShadowColor(clr));
533 }
534
535
536 // Get clear color
getClearColor() const537 FXColor Calculator::getClearColor() const {
538 return clearbtn->getBackColor();
539 }
540
541
542 // Set clear all color
setClearAllColor(FXColor clr)543 void Calculator::setClearAllColor(FXColor clr){
544 clearallbtn->setBackColor(clr);
545 clearallbtn->setHiliteColor(makeHiliteColor(clr));
546 clearallbtn->setShadowColor(makeShadowColor(clr));
547 }
548
549
550 // Get clear all color
getClearAllColor() const551 FXColor Calculator::getClearAllColor() const {
552 return clearallbtn->getBackColor();
553 }
554
555
556 // Set display color
setDisplayColor(FXColor clr)557 void Calculator::setDisplayColor(FXColor clr){
558 display->setBackColor(clr);
559 display->setSelTextColor(clr);
560 display->setHiliteColor(makeHiliteColor(clr));
561 display->setShadowColor(makeShadowColor(clr));
562 }
563
564
565 // Get display color
getDisplayColor() const566 FXColor Calculator::getDisplayColor() const {
567 return display->getBackColor();
568 }
569
570
571 // Set display color
setDisplayNumberColor(FXColor clr)572 void Calculator::setDisplayNumberColor(FXColor clr){
573 display->setTextColor(clr);
574 display->setSelBackColor(clr);
575 }
576
577
578 // Get display color
getDisplayNumberColor() const579 FXColor Calculator::getDisplayNumberColor() const {
580 return display->getTextColor();
581 }
582
583
584 // Set numeric base color
setBaseColor(FXColor clr)585 void Calculator::setBaseColor(FXColor clr){
586 FXColor hilite=FXRGB(FXREDVAL(clr)+((255-FXREDVAL(clr))*3)/8,
587 FXGREENVAL(clr)+((255-FXGREENVAL(clr))*3)/8,
588 FXBLUEVAL(clr)+((255-FXBLUEVAL(clr))*3)/8);
589 FXColor shadow=makeShadowColor(clr);
590 for(FXuint i=0; i<4; i++){
591 numbase[i]->setBackColor(clr);
592 numbase[i]->setHiliteColor(hilite);
593 numbase[i]->setShadowColor(shadow);
594 }
595 }
596
597
598 // Get numeric base color
getBaseColor() const599 FXColor Calculator::getBaseColor() const {
600 return numbase[0]->getBackColor();
601 }
602
603
604 // Set angle mode color
setAngleColor(FXColor clr)605 void Calculator::setAngleColor(FXColor clr){
606 FXColor hilite=FXRGB(FXREDVAL(clr)+((255-FXREDVAL(clr))*3)/8,
607 FXGREENVAL(clr)+((255-FXGREENVAL(clr))*3)/8,
608 FXBLUEVAL(clr)+((255-FXBLUEVAL(clr))*3)/8);
609 FXColor shadow=makeShadowColor(clr);
610 for(FXuint i=0; i<3; i++){
611 angmode[i]->setBackColor(clr);
612 angmode[i]->setHiliteColor(hilite);
613 angmode[i]->setShadowColor(shadow);
614 }
615 }
616
617
618 // Get angle mode color
getAngleColor() const619 FXColor Calculator::getAngleColor() const {
620 return angmode[0]->getBackColor();
621 }
622
623
624 // Set display font
setDisplayFont(FXFont * fnt)625 void Calculator::setDisplayFont(FXFont* fnt){
626 display->setFont(fnt);
627 }
628
629
630 // Return display font
getDisplayFont() const631 FXFont* Calculator::getDisplayFont() const {
632 return display->getFont();
633 }
634
635
636 // Read registry
readRegistry()637 void Calculator::readRegistry(){
638 FXString fontspec;
639
640 // Position
641 FXint xx=getApp()->reg().readIntEntry("SETTINGS","x",50);
642 FXint yy=getApp()->reg().readIntEntry("SETTINGS","y",50);
643 FXint ww=getApp()->reg().readIntEntry("SETTINGS","w",0);
644 FXint hh=getApp()->reg().readIntEntry("SETTINGS","h",0);
645
646 // Read colors
647 FXColor digitclr=getApp()->reg().readColorEntry("SETTINGS","digitcolor",FXRGB(94,209,204));
648 FXColor hexdigitclr=getApp()->reg().readColorEntry("SETTINGS","hexdigitcolor",FXRGB(151,189,206));
649 FXColor operatorclr=getApp()->reg().readColorEntry("SETTINGS","operatorcolor",FXRGB(255,222,163));
650 FXColor functionclr=getApp()->reg().readColorEntry("SETTINGS","functioncolor",FXRGB(158,213,188));
651 FXColor memoryclr=getApp()->reg().readColorEntry("SETTINGS","memorycolor",FXRGB(181,207,227));
652 FXColor inverseclr=getApp()->reg().readColorEntry("SETTINGS","inversecolor",FXRGB(224,222,69));
653 FXColor hyperclr=getApp()->reg().readColorEntry("SETTINGS","hypercolor",FXRGB(224,222,69));
654 FXColor clearclr=getApp()->reg().readColorEntry("SETTINGS","clearcolor",FXRGB(238,148,0));
655 FXColor clearallclr=getApp()->reg().readColorEntry("SETTINGS","clearallcolor",FXRGB(238,118,0));
656 FXColor displayclr=getApp()->reg().readColorEntry("SETTINGS","displaycolor",FXRGB(255,255,255));
657 FXColor numberclr=getApp()->reg().readColorEntry("SETTINGS","displaynumbercolor",FXRGB(0,0,0));
658 FXColor numbaseclr=getApp()->reg().readColorEntry("SETTINGS","numbasecolor",FXRGB(203,203,203));
659 FXColor angmodeclr=getApp()->reg().readColorEntry("SETTINGS","anglemodecolor",FXRGB(203,203,203));
660
661 // Number base
662 FXint nbase=getApp()->reg().readIntEntry("SETTINGS","base",NUM_DEC);
663
664 // Angle type
665 FXint amode=getApp()->reg().readIntEntry("SETTINGS","angles",ANG_RAD);
666
667 // Exponent mode
668 FXint expmode=getApp()->reg().readIntEntry("SETTINGS","exponent",EXPONENT_IFNEEDED);
669
670 // Engineering mode
671 FXint engmode=getApp()->reg().readBoolEntry("SETTINGS","engineering",false);
672
673 // Precision
674 FXint prec=getApp()->reg().readIntEntry("SETTINGS","precision",10);
675
676 // Beep
677 FXbool noise=getApp()->reg().readIntEntry("SETTINGS","beep",true);
678
679 // Memory cell
680 recall=getApp()->reg().readRealEntry("SETTINGS","memory",0.0);
681
682 // Font
683 fontspec=getApp()->reg().readStringEntry("SETTINGS","displayfont","");
684 if(!fontspec.empty()){
685 font=new FXFont(getApp(),fontspec);
686 setDisplayFont(font);
687 }
688
689 setDigitColor(digitclr);
690 setHexDigitColor(hexdigitclr);
691 setOperatorColor(operatorclr);
692 setFunctionColor(functionclr);
693 setMemoryColor(memoryclr);
694 setInverseColor(inverseclr);
695 setHyperColor(hyperclr);
696 setClearColor(clearclr);
697 setClearAllColor(clearallclr);
698 setDisplayColor(displayclr);
699 setDisplayNumberColor(numberclr);
700 setBaseColor(numbaseclr);
701 setAngleColor(angmodeclr);
702
703 // Number base
704 setBase(nbase);
705 setAngles(amode);
706 setPrecision(prec);
707 setExponentMode(expmode);
708 setEngineeringMode(engmode);
709 setBeep(noise);
710
711 setX(xx);
712 setY(yy);
713 setWidth(ww);
714 setHeight(hh);
715 }
716
717
718 // Write registry
writeRegistry()719 void Calculator::writeRegistry(){
720 FXString fontspec;
721
722 // Position
723 getApp()->reg().writeIntEntry("SETTINGS","x",getX());
724 getApp()->reg().writeIntEntry("SETTINGS","y",getY());
725 getApp()->reg().writeIntEntry("SETTINGS","w",getWidth());
726 getApp()->reg().writeIntEntry("SETTINGS","h",getHeight());
727
728 // Write colors
729 getApp()->reg().writeColorEntry("SETTINGS","digitcolor",getDigitColor());
730 getApp()->reg().writeColorEntry("SETTINGS","hexdigitcolor",getHexDigitColor());
731 getApp()->reg().writeColorEntry("SETTINGS","operatorcolor",getOperatorColor());
732 getApp()->reg().writeColorEntry("SETTINGS","functioncolor",getFunctionColor());
733 getApp()->reg().writeColorEntry("SETTINGS","memorycolor",getMemoryColor());
734 getApp()->reg().writeColorEntry("SETTINGS","inversecolor",getInverseColor());
735 getApp()->reg().writeColorEntry("SETTINGS","hypercolor",getHyperColor());
736 getApp()->reg().writeColorEntry("SETTINGS","clearcolor",getClearColor());
737 getApp()->reg().writeColorEntry("SETTINGS","clearallcolor",getClearAllColor());
738 getApp()->reg().writeColorEntry("SETTINGS","displaycolor",getDisplayColor());
739 getApp()->reg().writeColorEntry("SETTINGS","displaynumbercolor",getDisplayNumberColor());
740 getApp()->reg().writeColorEntry("SETTINGS","numbasecolor",getBaseColor());
741 getApp()->reg().writeColorEntry("SETTINGS","anglemodecolor",getAngleColor());
742
743 // Number base
744 getApp()->reg().writeIntEntry("SETTINGS","base",getBase());
745
746 // Angle type
747 getApp()->reg().writeIntEntry("SETTINGS","angles",getAngles());
748
749 // Exponent mode
750 getApp()->reg().writeIntEntry("SETTINGS","exponent",getExponentMode());
751
752 // Engineering mode
753 getApp()->reg().writeIntEntry("SETTINGS","engineering",getEngineeringMode());
754
755 // Precision
756 getApp()->reg().writeIntEntry("SETTINGS","precision",getPrecision());
757
758 // Beep
759 getApp()->reg().writeIntEntry("SETTINGS","beep",getBeep());
760
761 // Memory contents
762 getApp()->reg().writeRealEntry("SETTINGS","memory",recall);
763
764 // Font
765 fontspec=getDisplayFont()->getFont();
766 getApp()->reg().writeStringEntry("SETTINGS","displayfont",fontspec.text());
767 }
768
769
770 /*******************************************************************************/
771
772 // Get display text
getDisplayText() const773 FXString Calculator::getDisplayText() const {
774 return display->getText();
775 }
776
777
778 // Display text
setDisplayText(const FXString & txt)779 void Calculator::setDisplayText(const FXString& txt){
780 display->setText(txt);
781 }
782
783
784 // Get displayed value
getDisplayValue() const785 FXdouble Calculator::getDisplayValue() const {
786 FXdouble val;
787 if(base==10)
788 val=getDisplayText().toDouble();
789 else
790 val=(FXdouble)getDisplayText().toLong(base);
791 return val;
792 }
793
794
795 // Redisplay new value
setDisplayValue(FXdouble val)796 void Calculator::setDisplayValue(FXdouble val){
797 FXString string;
798 if(Math::fpNan(val)){
799 setDisplayText("ERROR");
800 if(beep) getApp()->beep();
801 }
802 else if(Math::fpInfinite(val)){
803 if(Math::fpSign(val)){
804 setDisplayText("-INF");
805 }
806 else{
807 setDisplayText("+INF");
808 }
809 if(beep) getApp()->beep();
810 }
811 else if(base==10){
812 if(val==0.0) val=0.0; // Don't ever print out -0 instead of 0
813 setDisplayText(string.fromDouble(val,precision,exponent));
814 }
815 else{
816 setDisplayText(string.fromLong((FXlong)((0.0<=val)?val+0.5:val-0.5),base));
817 }
818 }
819
820
821 /*******************************************************************************/
822
823 // Push to number stack
pushnum(FXdouble num)824 FXdouble Calculator::pushnum(FXdouble num){
825 FXASSERT(numsp<STACKLEN);
826 numstack[++numsp]=num;
827 return num;
828 }
829
830
831 // Replace number on top of stack
setnum(FXdouble num)832 FXdouble Calculator::setnum(FXdouble num){
833 FXASSERT(0<=numsp && numsp<STACKLEN);
834 numstack[numsp]=num;
835 return num;
836 }
837
838
839 // Pop number of stack
popnum()840 FXdouble Calculator::popnum(){
841 FXASSERT(0<=numsp);
842 return numstack[numsp--];
843 }
844
845
846 // Return number on top of stack
getnum()847 FXdouble Calculator::getnum(){
848 FXASSERT(0<=numsp && numsp<STACKLEN);
849 return numstack[numsp];
850 }
851
852
853 // Set number base
setBase(FXint b)854 void Calculator::setBase(FXint b){
855 switch(b){
856 case 2: base=2; limit=BINARY_LIMIT; break;
857 case 8: base=8; limit=OCTAL_LIMIT; break;
858 case 10: base=10; limit=DECIMAL_LIMIT; break;
859 case 16: base=16; limit=HEXADECIMAL_LIMIT; break;
860 }
861 setDisplayValue(getnum());
862 modifiers=0;
863 }
864
865
866 // Set exponent mode
setExponentMode(FXuchar expmode)867 void Calculator::setExponentMode(FXuchar expmode){
868 exponent=(expmode&3)|(exponent&4);
869 setDisplayValue(getnum());
870 modifiers=0;
871 }
872
873
874 // Set exponent mode
setEngineeringMode(FXbool engmode)875 void Calculator::setEngineeringMode(FXbool engmode){
876 exponent^=((0-engmode)^exponent)&4;
877 setDisplayValue(getnum());
878 modifiers=0;
879 }
880
881
882 // Set precision
setPrecision(FXint prec)883 void Calculator::setPrecision(FXint prec){
884 precision=prec;
885 setDisplayValue(getnum());
886 modifiers=0;
887 }
888
889
890 // Argument to sine, cosine, etc
trigarg(FXdouble a) const891 FXdouble Calculator::trigarg(FXdouble a) const {
892 switch(angles){
893 case ANG_DEG: return DEG2RAD(a);
894 case ANG_GRA: return GRA2RAD(a);
895 case ANG_RAD: return a;
896 }
897 return a;
898 }
899
900
901 // Result from arcsine, arccosine, etc
trigres(FXdouble r) const902 FXdouble Calculator::trigres(FXdouble r) const {
903 switch(angles){
904 case ANG_DEG: return RAD2DEG(r);
905 case ANG_GRA: return RAD2GRA(r);
906 case ANG_RAD: return r;
907 }
908 return r;
909 }
910
911
912 // Factorial
913 //
914 // result = n!
915 //
factorial(FXdouble n)916 static FXdouble factorial(FXdouble n){
917 FXdouble num=Math::floor(n);
918 FXdouble result=1.0;
919 if(0.0<=num && num==n){
920 while(num>0.0){
921 if(!Math::fpFinite(result)) break;
922 result=result*num;
923 num=num-1.0;
924 }
925 return result;
926 }
927 return dblnan;
928 }
929
930
931 // Permutations
932 //
933 // n!
934 // result = ------
935 // (n-r)!
936 //
permutations(FXdouble n,FXdouble r)937 static FXdouble permutations(FXdouble n,FXdouble r){
938 FXdouble num=Math::floor(n);
939 FXdouble den=Math::floor(r);
940 FXdouble result=1.0;
941 if(0.0<=num && 0.0<=den && den<=num && num==n && den==r){
942 while(den>0.0){
943 if(!Math::fpFinite(result)) break;
944 result=result*num;
945 num=num-1.0;
946 den=den-1.0;
947 }
948 return result;
949 }
950 return dblnan;
951 }
952
953
954 // Combinations
955 //
956 // n!
957 // result = ----------
958 // r! (n-r)!
959 //
combinations(FXdouble n,FXdouble r)960 static FXdouble combinations(FXdouble n,FXdouble r){
961 FXdouble num=Math::floor(n);
962 FXdouble den=Math::floor(r);
963 FXdouble res1=1.0;
964 FXdouble res2=1.0;
965 if(0.0<=num && 0.0<=den && den<=num && num==n && den==r){
966 while(den>0.0){
967 if(!Math::fpFinite(res1)) break;
968 res1=res1*num;
969 res2=res2*den;
970 num=num-1.0;
971 den=den-1.0;
972 }
973 return res1/res2;
974 }
975 return dblnan;
976 }
977
978
979 // Reset calculator
clearAll()980 void Calculator::clearAll(){
981 setDisplayValue(0.0);
982 numstack[0]=0.0;
983 numsp=0;
984 opsp=-1;
985 parens=0;
986 modifiers=0;
987 }
988
989
990 // Clear calculator
clear()991 void Calculator::clear(){
992 setDisplayValue(0.0);
993 setnum(0.0);
994 modifiers=0;
995 }
996
997
998 // Perform unary operator
unary(FXuchar op)999 void Calculator::unary(FXuchar op){
1000 FXdouble acc,val;
1001 FXASSERT(0<=numsp);
1002 val=getnum();
1003 acc=0.0;
1004 switch(op){
1005 case UN_NOT:
1006 acc=(FXdouble) (~((FXlong)Math::floor(val)));
1007 break;
1008 case UN_NEG:
1009 acc=-val;
1010 break;
1011 case UN_SHL:
1012 acc=(FXdouble) (((FXulong)Math::floor(val))<<1);
1013 break;
1014 case UN_SHR:
1015 acc=(FXdouble) (((FXulong)Math::floor(val))>>1);
1016 break;
1017 case UN_SAR:
1018 acc=(FXdouble) (((FXlong)Math::floor(val))>>1);
1019 break;
1020 case UN_RECIP:
1021 acc=1.0/val;
1022 break;
1023 case UN_FAC:
1024 acc=factorial(val);
1025 break;
1026 case UN_SQRT:
1027 acc=Math::sqrt(val);
1028 break;
1029 case UN_QUAD:
1030 acc=val*val;
1031 break;
1032 case UN_2LOG:
1033 acc=Math::log2(val);
1034 break;
1035 case UN_2TOX:
1036 acc=Math::exp2(val);
1037 break;
1038 case UN_LOG:
1039 acc=Math::log10(val);
1040 break;
1041 case UN_10TOX:
1042 acc=Math::exp10(val);
1043 break;
1044 case UN_LN:
1045 acc=Math::log(val);
1046 break;
1047 case UN_EXP:
1048 acc=Math::exp(val);
1049 break;
1050 case UN_SIN:
1051 acc=Math::sin(trigarg(val));
1052 break;
1053 case UN_COS:
1054 acc=Math::cos(trigarg(val));
1055 break;
1056 case UN_TAN:
1057 acc=Math::tan(trigarg(val));
1058 break;
1059 case UN_ASIN:
1060 acc=trigres(Math::asin(val));
1061 break;
1062 case UN_ACOS:
1063 acc=trigres(Math::acos(val));
1064 break;
1065 case UN_ATAN:
1066 acc=trigres(Math::atan(val));
1067 break;
1068 case UN_SINH:
1069 acc=Math::sinh(val);
1070 break;
1071 case UN_COSH:
1072 acc=Math::cosh(val);
1073 break;
1074 case UN_TANH:
1075 acc=Math::tanh(val);
1076 break;
1077 case UN_ASINH:
1078 acc=Math::asinh(val);
1079 break;
1080 case UN_ACOSH:
1081 acc=Math::acosh(val);
1082 break;
1083 case UN_ATANH:
1084 acc=Math::atanh(val);
1085 default:
1086 break;
1087 }
1088 setnum(acc);
1089 setDisplayValue(acc);
1090 modifiers=0;
1091 }
1092
1093
1094 // Perform operator
dyop(FXuchar op)1095 void Calculator::dyop(FXuchar op){
1096 FXdouble acc,val;
1097 FXASSERT(0<=numsp);
1098 val=popnum();
1099 FXASSERT(0<=numsp);
1100 acc=getnum();
1101 switch(op){
1102 case DY_OR:
1103 acc=(FXdouble) (((FXulong)Math::floor(acc)) | ((FXulong)Math::floor(val)));
1104 break;
1105 case DY_XOR:
1106 acc=(FXdouble) (((FXulong)Math::floor(acc)) ^ ((FXulong)Math::floor(val)));
1107 break;
1108 case DY_AND:
1109 acc=(FXdouble) (((FXulong)Math::floor(acc)) & ((FXulong)Math::floor(val)));
1110 break;
1111 case DY_SUB:
1112 acc=acc-val;
1113 break;
1114 case DY_ADD:
1115 acc=acc+val;
1116 break;
1117 case DY_MOD: // Theo Veenker <Theo.Veenker@let.uu.nl> suggested this new definition of "mod":
1118 val=Math::fabs(val); // x = a div |b| ; with a round toward 0
1119 acc=Math::fmod(acc,val); // y = a mod |b|
1120 break; // a = x * |b| + y
1121 case DY_IDIV:
1122 modf(acc/val,&acc);
1123 break;
1124 case DY_DIV:
1125 acc=acc/val;
1126 break;
1127 case DY_MUL:
1128 acc=acc*val;
1129 break;
1130 case DY_XTOY:
1131 acc=Math::pow(acc,val);
1132 break;
1133 case DY_XTOINVY:
1134 acc=Math::pow(acc,1.0/val);
1135 break;
1136 case DY_PER:
1137 acc=permutations(acc,val);
1138 break;
1139 case DY_COM:
1140 acc=combinations(acc,val);
1141 default:
1142 break;
1143 }
1144 setnum(acc);
1145 setDisplayValue(acc);
1146 modifiers=0;
1147 }
1148
1149
1150 // Enter operator
dyadic(FXuchar op)1151 void Calculator::dyadic(FXuchar op){
1152 if(opsp<0 || opstack[opsp]==DY_LPAR || priority[op]>priority[opstack[opsp]]){
1153 pushnum(getnum());
1154 opstack[++opsp]=op;
1155 }
1156 else{
1157 dyop(opstack[opsp]);
1158 pushnum(getnum());
1159 opstack[opsp]=op;
1160 }
1161 modifiers=0;
1162 }
1163
1164
1165 // Enter evaluate
evaluate()1166 void Calculator::evaluate(){
1167 FXuchar op;
1168 while(0<=opsp){
1169 op=opstack[opsp--];
1170 if(op!=DY_LPAR)
1171 dyop(op);
1172 else
1173 parens--;
1174 }
1175 setDisplayValue(getnum());
1176 modifiers=0;
1177 }
1178
1179
1180 // Left parentheses
lparen()1181 void Calculator::lparen(){
1182 opstack[++opsp]=DY_LPAR;
1183 setnum(0.0);
1184 setDisplayValue(0.0);
1185 parens++;
1186 modifiers=0;
1187 }
1188
1189
1190 // Right parentheses
rparen()1191 void Calculator::rparen(){
1192 FXuchar op;
1193 while(0<=opsp){
1194 op=opstack[opsp--];
1195 if(op==DY_LPAR){ parens--; break; }
1196 dyop(op);
1197 }
1198 setDisplayValue(getnum());
1199 modifiers=0;
1200 }
1201
1202
1203 /*******************************************************************************/
1204
1205 // Close the window and save registry
close(FXbool notify)1206 FXbool Calculator::close(FXbool notify){
1207 writeRegistry();
1208 return FXMainWindow::close(notify);
1209 }
1210
1211
1212 // Change preferences
onCmdPreferences(FXObject *,FXSelector,void *)1213 long Calculator::onCmdPreferences(FXObject*,FXSelector,void*){
1214 Preferences preferences(this);
1215 preferences.setX(getX()+80);
1216 preferences.setY(getY()+80);
1217 preferences.execute(PLACEMENT_DEFAULT);
1218 return 1;
1219 }
1220
1221
1222 // Change colors
onCmdColor(FXObject *,FXSelector sel,void * ptr)1223 long Calculator::onCmdColor(FXObject*,FXSelector sel,void* ptr){
1224 FXColor clr=(FXColor)(FXuval)ptr;
1225 switch(FXSELID(sel)){
1226 case ID_COLOR_DISPLAY: setDisplayColor(clr); break;
1227 case ID_COLOR_DISPLAYNUMBER: setDisplayNumberColor(clr); break;
1228 case ID_COLOR_DIGITS: setDigitColor(clr); break;
1229 case ID_COLOR_HEXDIGITS: setHexDigitColor(clr); break;
1230 case ID_COLOR_OPERATORS: setOperatorColor(clr); break;
1231 case ID_COLOR_FUNCTIONS: setFunctionColor(clr); break;
1232 case ID_COLOR_MEMORY: setMemoryColor(clr); break;
1233 case ID_COLOR_BASE: setBaseColor(clr); break;
1234 case ID_COLOR_ANGLES: setAngleColor(clr); break;
1235 case ID_COLOR_INVERT: setInverseColor(clr); break;
1236 case ID_COLOR_HYPER: setHyperColor(clr); break;
1237 case ID_COLOR_CLEARALL: setClearAllColor(clr); break;
1238 case ID_COLOR_CLEAR: setClearColor(clr); break;
1239 }
1240 return 1;
1241 }
1242
1243
1244 // Update colors
onUpdColor(FXObject * sender,FXSelector sel,void *)1245 long Calculator::onUpdColor(FXObject* sender,FXSelector sel,void*){
1246 FXColor clr;
1247 switch(FXSELID(sel)){
1248 case ID_COLOR_DISPLAY: clr=getDisplayColor(); break;
1249 case ID_COLOR_DISPLAYNUMBER: clr=getDisplayNumberColor(); break;
1250 case ID_COLOR_DIGITS: clr=getDigitColor(); break;
1251 case ID_COLOR_HEXDIGITS: clr=getHexDigitColor(); break;
1252 case ID_COLOR_OPERATORS: clr=getOperatorColor(); break;
1253 case ID_COLOR_FUNCTIONS: clr=getFunctionColor(); break;
1254 case ID_COLOR_MEMORY: clr=getMemoryColor(); break;
1255 case ID_COLOR_BASE: clr=getBaseColor(); break;
1256 case ID_COLOR_ANGLES: clr=getAngleColor(); break;
1257 case ID_COLOR_INVERT: clr=getInverseColor(); break;
1258 case ID_COLOR_HYPER: clr=getHyperColor(); break;
1259 case ID_COLOR_CLEARALL: clr=getClearAllColor(); break;
1260 case ID_COLOR_CLEAR: clr=getClearColor(); break;
1261 }
1262 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&clr);
1263 return 1;
1264 }
1265
1266
1267 // Change font
onCmdFont(FXObject *,FXSelector,void *)1268 long Calculator::onCmdFont(FXObject*,FXSelector,void*){
1269 FXFontDialog fontdlg(this,"Change Display Font",DECOR_BORDER|DECOR_TITLE);
1270 FXFontDesc fontdesc=getDisplayFont()->getFontDesc();
1271 fontdlg.setFontDesc(fontdesc);
1272 if(fontdlg.execute()){
1273 FXFont *oldfont=font;
1274 fontdesc=fontdlg.getFontDesc();
1275 font=new FXFont(getApp(),fontdesc);
1276 font->create();
1277 setDisplayFont(font);
1278 delete oldfont;
1279 }
1280 return 1;
1281 }
1282
1283
1284 // Change exponential notation
onCmdExponent(FXObject *,FXSelector sel,void * ptr)1285 long Calculator::onCmdExponent(FXObject*,FXSelector sel,void* ptr){
1286 if((FXSELID(sel)==ID_EXPONENT_ALWAYS) && ptr) setExponentMode(EXPONENT_ALWAYS);
1287 else if((FXSELID(sel)==ID_EXPONENT_NEVER) && ptr) setExponentMode(EXPONENT_NEVER);
1288 else setExponentMode(EXPONENT_IFNEEDED);
1289 return 1;
1290 }
1291
1292
1293 // Update exponential notation
onUpdExponent(FXObject * sender,FXSelector sel,void *)1294 long Calculator::onUpdExponent(FXObject* sender,FXSelector sel,void*){
1295 if(FXSELID(sel)==ID_EXPONENT_ALWAYS && getExponentMode()==EXPONENT_ALWAYS)
1296 sender->handle(this,FXSEL(SEL_COMMAND,ID_CHECK),NULL);
1297 else if(FXSELID(sel)==ID_EXPONENT_NEVER && getExponentMode()==EXPONENT_NEVER)
1298 sender->handle(this,FXSEL(SEL_COMMAND,ID_CHECK),NULL);
1299 else
1300 sender->handle(this,FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
1301 return 1;
1302 }
1303
1304
1305 // Change engineering notation
onCmdEngineeringMode(FXObject *,FXSelector,void *)1306 long Calculator::onCmdEngineeringMode(FXObject*,FXSelector,void*){
1307 setEngineeringMode(!getEngineeringMode());
1308 return 1;
1309 }
1310
1311
1312 // Update exponential notation
onUpdEngineeringMode(FXObject * sender,FXSelector,void *)1313 long Calculator::onUpdEngineeringMode(FXObject* sender,FXSelector,void*){
1314 if(getEngineeringMode())
1315 sender->handle(this,FXSEL(SEL_COMMAND,ID_CHECK),NULL);
1316 else
1317 sender->handle(this,FXSEL(SEL_COMMAND,ID_UNCHECK),NULL);
1318 return 1;
1319 }
1320
1321
1322 // Change precision
onCmdPrecision(FXObject * sender,FXSelector,void *)1323 long Calculator::onCmdPrecision(FXObject* sender,FXSelector,void*){
1324 FXint prec=16;
1325 sender->handle(this,FXSEL(SEL_COMMAND,ID_GETINTVALUE),(void*)&prec);
1326 setPrecision(prec);
1327 return 1;
1328 }
1329
1330
1331 // Update precision
onUpdPrecision(FXObject * sender,FXSelector,void *)1332 long Calculator::onUpdPrecision(FXObject* sender,FXSelector,void*){
1333 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETINTVALUE),(void*)&precision);
1334 return 1;
1335 }
1336
1337
1338 // Change beep mode
onCmdBeep(FXObject *,FXSelector,void *)1339 long Calculator::onCmdBeep(FXObject*,FXSelector,void*){
1340 beep=!beep;
1341 return 1;
1342 }
1343
1344
1345 // Update beep mode
onUpdBeep(FXObject * sender,FXSelector,void *)1346 long Calculator::onUpdBeep(FXObject* sender,FXSelector,void*){
1347 sender->handle(this,beep ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK), NULL);
1348 return 1;
1349 }
1350
1351
1352 // Popup help
onCmdQuestion(FXObject *,FXSelector,void *)1353 long Calculator::onCmdQuestion(FXObject*,FXSelector,void*){
1354 HelpWindow helpwindow(this,"Calculator Help");
1355 helpwindow.setHelp(help);
1356 helpwindow.setX(getX()+80);
1357 helpwindow.setY(getY()+80);
1358 helpwindow.execute(PLACEMENT_DEFAULT);
1359 return 1;
1360 }
1361
1362
1363 // Change angle mode
onCmdAngle(FXObject *,FXSelector sel,void *)1364 long Calculator::onCmdAngle(FXObject*,FXSelector sel,void*){
1365 angles=(FXSELID(sel)-ID_MODE);
1366 return 1;
1367 }
1368
1369
1370 // Update radio button for angle mode
onUpdAngle(FXObject * sender,FXSelector sel,void *)1371 long Calculator::onUpdAngle(FXObject* sender,FXSelector sel,void*){
1372 sender->handle(this,angles==(FXSELID(sel)-ID_MODE) ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK), NULL);
1373 return 1;
1374 }
1375
1376
1377 // Change angle mode
onCmdBase(FXObject *,FXSelector sel,void *)1378 long Calculator::onCmdBase(FXObject*,FXSelector sel,void*){
1379 setBase(FXSELID(sel)-ID_BASE);
1380 return 1;
1381 }
1382
1383
1384 // Update radio button for angle mode
onUpdBase(FXObject * sender,FXSelector sel,void *)1385 long Calculator::onUpdBase(FXObject* sender,FXSelector sel,void*){
1386 sender->handle(this,base==(FXSELID(sel)-ID_BASE) ? FXSEL(SEL_COMMAND,ID_CHECK) : FXSEL(SEL_COMMAND,ID_UNCHECK), NULL);
1387 return 1;
1388 }
1389
1390
1391 // Update digits based on base
onUpdDigit(FXObject * sender,FXSelector sel,void *)1392 long Calculator::onUpdDigit(FXObject* sender,FXSelector sel,void*){
1393 sender->handle(this,(FXSELID(sel)-ID_0)<base ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE), NULL);
1394 return 1;
1395 }
1396
1397
1398 // Update digits based on base
onCmdDigit(FXObject *,FXSelector sel,void *)1399 long Calculator::onCmdDigit(FXObject*,FXSelector sel,void*){
1400 FXString text=getDisplayText();
1401 FXint pos;
1402 if(!(modifiers&MOD_ENT)){ text=""; digits=0; }
1403 if((base==10) && (pos=text.find('E'))>=0){
1404 pos++; // Skip 'E'
1405 if(text[pos]=='-' || text[pos]=='+') pos++; // Skip sign
1406 if(text[pos]=='0' || (text[pos] && text[pos+1] && text[pos+2])){
1407 while(text[pos+1]){ text[pos]=text[pos+1]; pos++; }
1408 text[pos]=FXString::value2Digit[FXSELID(sel)-ID_0];
1409 }
1410 else{
1411 text.append(FXString::value2Digit[FXSELID(sel)-ID_0]);
1412 }
1413 }
1414 else if(digits<limit){
1415 text+=FXString::value2Digit[FXSELID(sel)-ID_0];
1416 digits++;
1417 }
1418 setDisplayText(text);
1419 setnum(getDisplayValue());
1420 modifiers|=MOD_ENT;
1421 return 1;
1422 }
1423
1424
1425 // Decimal point
onCmdPoint(FXObject *,FXSelector,void *)1426 long Calculator::onCmdPoint(FXObject*,FXSelector,void*){
1427 FXString text=getDisplayText();
1428 if(!(modifiers&MOD_ENT)){ text="0"; digits=1; }
1429 if(base==10 && text.find('.')<0 && text.find('E')<0) text+='.';
1430 setDisplayText(text);
1431 setnum(getDisplayValue());
1432 modifiers|=MOD_ENT;
1433 return 1;
1434 }
1435
1436
1437 // Update decimal point
onUpdPoint(FXObject * sender,FXSelector,void *)1438 long Calculator::onUpdPoint(FXObject* sender,FXSelector,void*){
1439 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1440 return 1;
1441 }
1442
1443
1444 // Exponent
onCmdExp(FXObject *,FXSelector,void *)1445 long Calculator::onCmdExp(FXObject*,FXSelector,void*){
1446 FXString text=getDisplayText();
1447 if(!(modifiers&MOD_ENT)){ text="0"; digits=1; }
1448 if(base==10 && text.find('E')<0) text+="E+0";
1449 setDisplayText(text);
1450 setnum(getDisplayValue());
1451 modifiers|=MOD_ENT;
1452 return 1;
1453 }
1454
1455
1456 // Update exponent
onUpdExp(FXObject * sender,FXSelector,void *)1457 long Calculator::onUpdExp(FXObject* sender,FXSelector,void*){
1458 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1459 return 1;
1460 }
1461
1462
1463 // Plus minus +/-
onCmdPlusMin(FXObject *,FXSelector,void *)1464 long Calculator::onCmdPlusMin(FXObject*,FXSelector,void*){
1465 FXString text=getDisplayText();
1466 FXint pos;
1467 if(modifiers&MOD_ENT){
1468 if((base==10) && (pos=text.find('E'))>=0){
1469 if(text[pos+1]=='+') text[pos+1]='-';
1470 else if(text[pos+1]=='-') text[pos+1]='+';
1471 else text.insert(pos+1,'-');
1472 }
1473 else{
1474 if(text[0]=='-') text.erase(0);
1475 else if(text[0]=='+') text[0]='-';
1476 else if(text!="0") text.prepend('-');
1477 }
1478 setDisplayText(text);
1479 setnum(getDisplayValue());
1480 }
1481 else{
1482 unary(UN_NEG);
1483 }
1484 return 1;
1485 }
1486
1487
1488 // Delete last character
onCmdDelete(FXObject *,FXSelector,void *)1489 long Calculator::onCmdDelete(FXObject*,FXSelector,void*){
1490 FXString text=getDisplayText();
1491 FXint len;
1492 if(modifiers&MOD_ENT){
1493 len=text.length();
1494 if(0<len){
1495 if(base==10 && text.find('E')>=0){
1496 len--;
1497 if(0<len && (text[len-1]=='+' || text[len-1]=='-')) len--;
1498 if(0<len && text[len-1]=='E') len--;
1499 }
1500 else{
1501 len--;
1502 if(isdigit(text[len])) digits--;
1503 if(0<len && (text[len-1]=='+' || text[len-1]=='-')) len--;
1504 if(0<len && text[len-1]=='.') len--;
1505 }
1506 text.trunc(len);
1507 }
1508 if(len<=0){
1509 text="0";
1510 modifiers&=~MOD_ENT;
1511 digits=1;
1512 }
1513 setDisplayText(text);
1514 setnum(getDisplayValue());
1515 }
1516 else{
1517 clear();
1518 }
1519 return 1;
1520 }
1521
1522
1523 // Clear entry
onCmdClear(FXObject *,FXSelector,void *)1524 long Calculator::onCmdClear(FXObject*,FXSelector,void*){
1525 clear();
1526 return 1;
1527 }
1528
1529
1530 // Clear entry
onCmdClearAll(FXObject *,FXSelector,void *)1531 long Calculator::onCmdClearAll(FXObject*,FXSelector,void*){
1532 clearAll();
1533 return 1;
1534 }
1535
1536
1537 // Inverse
onCmdInverse(FXObject *,FXSelector,void *)1538 long Calculator::onCmdInverse(FXObject*,FXSelector,void*){
1539 modifiers^=MOD_INV;
1540 return 1;
1541 }
1542
1543
1544 // Hyper
onCmdHyper(FXObject *,FXSelector,void *)1545 long Calculator::onCmdHyper(FXObject*,FXSelector,void*){
1546 modifiers^=MOD_HYP;
1547 return 1;
1548 }
1549
1550
1551 // Sine button
onCmdSin(FXObject *,FXSelector,void *)1552 long Calculator::onCmdSin(FXObject*,FXSelector,void*){
1553 unary(UN_SIN+(modifiers&(MOD_INV|MOD_HYP)));
1554 return 1;
1555 }
1556
1557
1558 // Update sine button
onUpdSin(FXObject * sender,FXSelector,void *)1559 long Calculator::onUpdSin(FXObject* sender,FXSelector,void*){
1560 FXString label="sin";
1561 if(modifiers&MOD_INV) label.prepend('a');
1562 if(modifiers&MOD_HYP) label.append('h');
1563 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1564 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1565 return 1;
1566 }
1567
1568
1569 // Cosine button
onCmdCos(FXObject *,FXSelector,void *)1570 long Calculator::onCmdCos(FXObject*,FXSelector,void*){
1571 unary(UN_COS+(modifiers&(MOD_INV|MOD_HYP)));
1572 return 1;
1573 }
1574
1575
1576 // Update cosine button
onUpdCos(FXObject * sender,FXSelector,void *)1577 long Calculator::onUpdCos(FXObject* sender,FXSelector,void*){
1578 FXString label="cos";
1579 if(modifiers&MOD_INV) label.prepend('a');
1580 if(modifiers&MOD_HYP) label.append('h');
1581 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1582 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1583 return 1;
1584 }
1585
1586
1587 // Tangent button
onCmdTan(FXObject *,FXSelector,void *)1588 long Calculator::onCmdTan(FXObject*,FXSelector,void*){
1589 unary(UN_TAN+(modifiers&(MOD_INV|MOD_HYP)));
1590 return 1;
1591 }
1592
1593
1594 // Update tangent button
onUpdTan(FXObject * sender,FXSelector,void *)1595 long Calculator::onUpdTan(FXObject* sender,FXSelector,void*){
1596 FXString label="tan";
1597 if(modifiers&MOD_INV) label.prepend('a');
1598 if(modifiers&MOD_HYP) label.append('h');
1599 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1600 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1601 return 1;
1602 }
1603
1604
1605 // Log button
onCmdLog(FXObject *,FXSelector,void *)1606 long Calculator::onCmdLog(FXObject*,FXSelector,void*){
1607 unary(UN_LOG+(modifiers&MOD_INV));
1608 return 1;
1609 }
1610
1611
1612 // Update Log button
onUpdLog(FXObject * sender,FXSelector,void *)1613 long Calculator::onUpdLog(FXObject* sender,FXSelector,void*){
1614 FXString label=(modifiers&MOD_INV)?"10^x":"log";
1615 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1616 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1617 return 1;
1618 }
1619
1620
1621 // Ln button
onCmdLn(FXObject *,FXSelector,void *)1622 long Calculator::onCmdLn(FXObject*,FXSelector,void*){
1623 unary(UN_LN+(modifiers&MOD_INV));
1624 return 1;
1625 }
1626
1627
1628 // Update Ln button
onUpdLn(FXObject * sender,FXSelector,void *)1629 long Calculator::onUpdLn(FXObject* sender,FXSelector,void*){
1630 FXString label=(modifiers&MOD_INV)?"e^x":"ln";
1631 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1632 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1633 return 1;
1634 }
1635
1636
1637 // Update PI button
onCmdPi(FXObject *,FXSelector,void *)1638 long Calculator::onCmdPi(FXObject*,FXSelector,void*){
1639 setnum((modifiers&MOD_HYP)?((modifiers&MOD_INV)?INVGOLDEN:GOLDEN):((modifiers&MOD_INV)?EULER:PI));
1640 setDisplayValue(getnum());
1641 modifiers=0;
1642 return 1;
1643 }
1644
1645
1646 // Update PI button
onUpdPi(FXObject * sender,FXSelector,void *)1647 long Calculator::onUpdPi(FXObject* sender,FXSelector,void*){
1648 FXString label=(modifiers&MOD_HYP) ? (modifiers&MOD_INV) ? "1/phi" : "phi" : (modifiers&MOD_INV) ? "e" : "pi";
1649 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1650 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1651 return 1;
1652 }
1653
1654
1655 // Factorial
onCmdFac(FXObject *,FXSelector,void *)1656 long Calculator::onCmdFac(FXObject*,FXSelector,void*){
1657 unary(UN_FAC);
1658 return 1;
1659 }
1660
1661
1662 // Update factorial
onUpdFac(FXObject * sender,FXSelector,void *)1663 long Calculator::onUpdFac(FXObject* sender,FXSelector,void*){
1664 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1665 return 1;
1666 }
1667
1668
1669 // Permutations
onCmdPer(FXObject *,FXSelector,void *)1670 long Calculator::onCmdPer(FXObject*,FXSelector,void*){
1671 dyadic(DY_PER);
1672 return 1;
1673 }
1674
1675
1676 // Update permutations
onUpdPer(FXObject * sender,FXSelector,void *)1677 long Calculator::onUpdPer(FXObject* sender,FXSelector,void*){
1678 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1679 return 1;
1680 }
1681
1682
1683 // Combinations
onCmdCom(FXObject *,FXSelector,void *)1684 long Calculator::onCmdCom(FXObject*,FXSelector,void*){
1685 dyadic(DY_COM);
1686 return 1;
1687 }
1688
1689
1690 // Update combinations
onUpdCom(FXObject * sender,FXSelector,void *)1691 long Calculator::onUpdCom(FXObject* sender,FXSelector,void*){
1692 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1693 return 1;
1694 }
1695
1696
1697 // Reciprocal
onCmdRecip(FXObject *,FXSelector,void *)1698 long Calculator::onCmdRecip(FXObject*,FXSelector,void*){
1699 unary(UN_RECIP);
1700 return 1;
1701 }
1702
1703
1704 // Update reciprocal
onUpdRecip(FXObject * sender,FXSelector,void *)1705 long Calculator::onUpdRecip(FXObject* sender,FXSelector,void*){
1706 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1707 return 1;
1708 }
1709
1710
1711 // X ^ Y
onCmdXToY(FXObject *,FXSelector,void *)1712 long Calculator::onCmdXToY(FXObject*,FXSelector,void*){
1713 dyadic(DY_XTOY+(modifiers&MOD_INV));
1714 return 1;
1715 }
1716
1717
1718 // Update X ^ Y
onUpdXToY(FXObject * sender,FXSelector,void *)1719 long Calculator::onUpdXToY(FXObject* sender,FXSelector,void*){
1720 FXString label=(modifiers&MOD_INV)?"x^1/y":"x^y";
1721 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1722 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1723 return 1;
1724 }
1725
1726
1727 // Sqrt
onCmdSqrt(FXObject *,FXSelector,void *)1728 long Calculator::onCmdSqrt(FXObject*,FXSelector,void*){
1729 unary(UN_SQRT+(modifiers&MOD_INV));
1730 return 1;
1731 }
1732
1733
1734 // Update Sqrt
onUpdSqrt(FXObject * sender,FXSelector,void *)1735 long Calculator::onUpdSqrt(FXObject* sender,FXSelector,void*){
1736 FXString label=(modifiers&MOD_INV)?"x^2":"sqrt";
1737 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1738 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1739 return 1;
1740 }
1741
1742
1743 // Shift left
onCmdShl(FXObject *,FXSelector,void *)1744 long Calculator::onCmdShl(FXObject*,FXSelector,void*){
1745 unary(UN_SHL);
1746 return 1;
1747 }
1748
1749
1750 // Update Shift left
onUpdShl(FXObject * sender,FXSelector,void *)1751 long Calculator::onUpdShl(FXObject* sender,FXSelector,void*){
1752 FXString label="SHL";
1753 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1754 return 1;
1755 }
1756
1757
1758 // Shift right
onCmdShr(FXObject *,FXSelector,void *)1759 long Calculator::onCmdShr(FXObject*,FXSelector,void*){
1760 unary(UN_SHR+(modifiers&MOD_INV));
1761 return 1;
1762 }
1763
1764
1765 // Update Shift right
onUpdShr(FXObject * sender,FXSelector,void *)1766 long Calculator::onUpdShr(FXObject* sender,FXSelector,void*){
1767 FXString label=(modifiers&MOD_INV)?"SAR":"SHR";
1768 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1769 return 1;
1770 }
1771
1772
1773 // Base 2 log
onCmd2Log(FXObject *,FXSelector,void *)1774 long Calculator::onCmd2Log(FXObject*,FXSelector,void*){
1775 unary(UN_2LOG+(modifiers&MOD_INV));
1776 return 1;
1777 }
1778
1779
1780 // Update Base 2 log
onUpd2Log(FXObject * sender,FXSelector,void *)1781 long Calculator::onUpd2Log(FXObject* sender,FXSelector,void*){
1782 FXString label=(modifiers&MOD_INV)?"2^x":"2log";
1783 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1784 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1785 return 1;
1786 }
1787
1788
1789 // Left parenth
onCmdLPar(FXObject *,FXSelector,void *)1790 long Calculator::onCmdLPar(FXObject*,FXSelector,void*){
1791 lparen();
1792 return 1;
1793 }
1794
1795
1796 // Right parenth
onCmdRPar(FXObject *,FXSelector,void *)1797 long Calculator::onCmdRPar(FXObject*,FXSelector,void*){
1798 rparen();
1799 return 1;
1800 }
1801
1802
1803 // Bitwise AND
onCmdAnd(FXObject *,FXSelector,void *)1804 long Calculator::onCmdAnd(FXObject*,FXSelector,void*){
1805 dyadic(DY_AND);
1806 return 1;
1807 }
1808
1809
1810 // Bitwise OR
onCmdOr(FXObject *,FXSelector,void *)1811 long Calculator::onCmdOr(FXObject*,FXSelector,void*){
1812 dyadic(DY_OR);
1813 return 1;
1814 }
1815
1816
1817 // Bitwise XOR
onCmdXor(FXObject *,FXSelector,void *)1818 long Calculator::onCmdXor(FXObject*,FXSelector,void*){
1819 dyadic(DY_XOR);
1820 return 1;
1821 }
1822
1823
1824 // Bitwise NOT
onCmdNot(FXObject *,FXSelector,void *)1825 long Calculator::onCmdNot(FXObject*,FXSelector,void*){
1826 unary(UN_NOT);
1827 return 1;
1828 }
1829
1830
1831 // Multiply
onCmdMul(FXObject *,FXSelector,void *)1832 long Calculator::onCmdMul(FXObject*,FXSelector,void*){
1833 dyadic(DY_MUL);
1834 return 1;
1835 }
1836
1837
1838 // Divide
onCmdDiv(FXObject *,FXSelector,void *)1839 long Calculator::onCmdDiv(FXObject*,FXSelector,void*){
1840 dyadic(DY_DIV);
1841 return 1;
1842 }
1843
1844
1845 // Modulo
onCmdMod(FXObject *,FXSelector,void *)1846 long Calculator::onCmdMod(FXObject*,FXSelector,void*){
1847 dyadic(DY_MOD+(modifiers&MOD_INV));
1848 return 1;
1849 }
1850
1851
1852 // Update mod
onUpdMod(FXObject * sender,FXSelector,void *)1853 long Calculator::onUpdMod(FXObject* sender,FXSelector,void*){
1854 FXString label=(modifiers&MOD_INV)?"div":"mod";
1855 sender->handle(this,FXSEL(SEL_COMMAND,ID_SETSTRINGVALUE),(void*)&label);
1856 sender->handle(this,(base==10) ? FXSEL(SEL_COMMAND,ID_ENABLE) : FXSEL(SEL_COMMAND,ID_DISABLE),NULL);
1857 return 1;
1858 }
1859
1860
1861 // Add
onCmdAdd(FXObject *,FXSelector,void *)1862 long Calculator::onCmdAdd(FXObject*,FXSelector,void*){
1863 dyadic(DY_ADD);
1864 return 1;
1865 }
1866
1867
1868 // Sub
onCmdSub(FXObject *,FXSelector,void *)1869 long Calculator::onCmdSub(FXObject*,FXSelector,void*){
1870 dyadic(DY_SUB);
1871 return 1;
1872 }
1873
1874
1875 // Enter
onCmdEnter(FXObject *,FXSelector,void *)1876 long Calculator::onCmdEnter(FXObject*,FXSelector,void*){
1877 evaluate();
1878 return 1;
1879 }
1880
1881
1882 // Recall from memory
onCmdMemRec(FXObject *,FXSelector,void *)1883 long Calculator::onCmdMemRec(FXObject*,FXSelector,void*){
1884 setnum(recall);
1885 setDisplayValue(recall);
1886 modifiers=0;
1887 return 1;
1888 }
1889
1890
1891 // Add to memory
onCmdMemAdd(FXObject *,FXSelector,void *)1892 long Calculator::onCmdMemAdd(FXObject*,FXSelector,void*){
1893 recall+=getnum();
1894 modifiers=0;
1895 return 1;
1896 }
1897
1898
1899 // Subtract from memory
onCmdMemSub(FXObject *,FXSelector,void *)1900 long Calculator::onCmdMemSub(FXObject*,FXSelector,void*){
1901 recall-=getnum();
1902 modifiers=0;
1903 return 1;
1904 }
1905
1906
1907 // Clear memory
onCmdMemClr(FXObject *,FXSelector,void *)1908 long Calculator::onCmdMemClr(FXObject*,FXSelector,void*){
1909 recall=0.0;
1910 modifiers=0;
1911 return 1;
1912 }
1913
1914
1915