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