/* DESKCALC (STD) -- Desk Calculator */ /* DESKCALC (STD) -- Taschenrechner */ /* // Copyright (c) 1994-2012 Oliver Bartels F+E, Muenchen // Author: Manfred Baumeister // Changes History: // rl (120427) RELEASED FOR BAE V7.8. // rl (101019) RELEASED FOR BAE V7.6. // rl (091020) RELEASED FOR BAE V7.4. // rl (081014) RELEASED FOR BAE V7.2. // rl (071029) RELEASED FOR BAE V7.0. // rl (060829) RELEASED FOR BAE V6.8. // rl (050906) RELEASED FOR BAE V6.6. // rl (040811) RELEASED FOR BAE V6.4. // rl (030904) RELEASED FOR BAE V6.2. // rl (021209) RELEASED FOR BAE V6.0. // rl (020618) RELEASED FOR BAE V5.4. // rl (010625) RELEASED FOR BAE V5.0. // rl (000508) RELEASED FOR BAE V4.6. // rl (991116) RELEASED FOR BAE V4.4. // rl (980910) RELEASED FOR BAE V4.2. // mb (980723) ENHANCEMENT: // Try to call Windows calc program when running // under Windows (requires at least UL Version 29!). // rl (970929) RELEASED FOR BAE V4.0. // mb (961105) CHANGE: // Desk Calculator layout adapted/changed for Windows/Motif // pulldown menu interfaces (i.e. button background color // bars suppressed when running in pulldown menu interface). // mb (960919) RELEASED FOR BAE V3.4. // mb (95) RELEASED FOR BAE V3.2. // mb (941130) ORIGINAL CODING. // // DESCRIPTION // // The deskcalc User Language program activates a popup menu // with a desk calculator providing basic arithmetic operations // and trigonometric functions. When used under Windows, deskcalc // tries to launch the Windows Calculator (calc.exe). */ // Includes #include "pop.ulh" // User Language popup utilities #include "popdraw.ulh" // User Language popup draw. util. // Disable undo state request #pragma ULCALLERNOUNDO // Globals int PULLDWN = bae_swconfig(3)==BAE_WinPulldwn || bae_swconfig(3)==BAE_MotifPdwn /* BAE pulldown menu interface flag */; int POPUPROWS = PULLDWN?14:22 /* Popup rows count */; int POPUPCOLS = PULLDWN?30:48 /* Popup columns count */; #define BCOLOR 7 // Button color #define CLSCOLOR 2 // CLS button color #define OFFCOLOR 4 // OFF button color #define MAXDIG 13 // Max. digits in display #define VAL_Err "Error" // Invalid (erroneous) value item #define VAL_NaN "NaN" // Inv. (Not a Number) value item #define VAL_Inf "Inf" // Invalid (Infinity) value item #define OP_INV (-1) // Invalid operator #define OP_ADD 0 // Addition operator #define OP_SUB 1 // Subtraction operator #define OP_MUL 2 // Multiplication operator #define OP_DIV 3 // Division operator #define OP_VAL 4 // Value operator #define OP_RES 5 // Result operator #define OP_SQRT 6 // Square root operator #define OP_SQR 7 // Square operator #define OP_MM 8 // Mil to mm conversion operator #define OP_MIL 9 // mm to mil conversion operator #define OP_NEG 10 // Negation operator #define OP_REC 11 // Reciprocal operator #define OP_SIN 12 // Sine operator #define OP_COS 13 // Cosine operator #define OP_TAN 14 // Tangent operator #define OP_ASIN 15 // Arc sine operator #define OP_ACOS 16 // Arc cosine operator #define OP_ATAN 17 // Arc tangent operator #define OP_EXP 18 // Exponential e^X operator #define OP_LN 19 // Natural logarithm (base e) op. #define OP_LOG 20 // Common logaritm (base ten) op. #define UNITDEG 1 // Degree angle units #define UNITRAD 2 // Radians angle units #define UNITGRA 3 // Grad angle units // Globals static double mlx = POPMIN /* Popup window lower X percentage */; static double mly = POPMIN /* Popup window lower Y percentage */; static double mux /* Popup window upper X percentage */; static double muy /* Popup window upper Y percentage */; static string keybuffer /* Keyboard buffer string */; static string valstr /* Current input value string */; static int vallen /* Current input value length */; static int dotflag /* Input dot flag */; static int UNITANG = UNITDEG /* Current angle units */; static double angfac = cvtangle(1.0,1,2) /* Angle multiplication factor */; static double values[] /* Value stack */; static int valuen /* Value stack counter */; static int opl[] /* Operator stack */; static struct button { // Button descriptor int row,col /* Button text coordinates */; string text /* Button display text */; string answer /* Button answer text */; int color /* Button color */; }; static int row0 = PULLDWN? 2: 2 /* Row 0 coordinate */; static int row1 = PULLDWN? 6: 7 /* Row 1 coordinate */; static int row2 = PULLDWN? 8:11 /* Row 2 coordinate */; static int row3 = PULLDWN?10:15 /* Row 3 coordinate */; static int row4 = PULLDWN?12:19 /* Row 4 coordinate */; static int col1 = PULLDWN? 1: 2 /* Column 1 coordinate */; static int col2 = PULLDWN? 3: 6 /* Column 2 coordinate */; static int col3 = PULLDWN? 5:10 /* Column 3 coordinate */; static int col4 = PULLDWN? 7:14 /* Column 4 coordinate */; static int col5 = PULLDWN? 9:18 /* Column 5 coordinate */; static int col6 = PULLDWN?13:24 /* Column 6 coordinate */; static int col7 = PULLDWN?17:30 /* Column 7 coordinate */; static int col8 = PULLDWN?21:36 /* Column 8 coordinate */; static int col9 = PULLDWN?26:43 /* Column 10 coordinate */; static int colcls = PULLDWN?19:37 /* Column CLS coordinate */; static int coloff = PULLDWN?25:43 /* Column OFF coordinate */; static int rowhd = PULLDWN? 4: 2 /* Row header coordinate */; static int colhd = PULLDWN?18:20 /* Column header coordinate */; struct button buttl[] = { // Button list {row1,col1, "7", "_7", BCOLOR}, {row2,col1, "4", "_4", BCOLOR}, {row3,col1, "1", "_1", BCOLOR}, {row4,col1, "0", "_0", BCOLOR}, {row1,col2, "8", "_8", BCOLOR}, {row2,col2, "5", "_5", BCOLOR}, {row3,col2, "2", "_2", BCOLOR}, {row4,col2, ".", "_.", BCOLOR}, {row1,col3, "9", "_9", BCOLOR}, {row2,col3, "6", "_6", BCOLOR}, {row3,col3, "3", "_3", BCOLOR}, {row4,col3, "=", "_=", BCOLOR}, {row1,col4, "+", "_+", BCOLOR}, {row2,col4, "-", "_-", BCOLOR}, {row3,col4, "*", "_*", BCOLOR}, {row4,col4, "/", "_/", BCOLOR}, {row1,col5, PULLDWN ? "MIL->MM" : " MIL->MM ", "_m", BCOLOR}, {row2,col5, PULLDWN ? "MM->MIL" : " MM->MIL ", "_i", BCOLOR}, {row3,col5, "SQR", "_s", BCOLOR}, {row4,col5, "+/-", "_n", BCOLOR}, {row3,col6, "X^2", "_q", BCOLOR}, {row4,col6, "1/X", "_r", BCOLOR}, {row1,col7, "SIN", "_S", BCOLOR}, {row2,col7, "COS", "_C", BCOLOR}, {row3,col7, "TAN", "_T", BCOLOR}, {row4,col7, "e^X", "_E", BCOLOR}, {row1,col8, "ASIN", "_B", BCOLOR}, {row2,col8, "ACOS", "_D", BCOLOR}, {row3,col8, "ATAN", "_A", BCOLOR}, {row4,col8, " LN ", "_l", BCOLOR}, {row1,col9, "DEG", "_X", BCOLOR}, {row2,col9, "RAD", "_Y", BCOLOR}, {row3,col9, "GRA", "_Z", BCOLOR}, {row4,col9, "LOG", "_L", BCOLOR}, {row0,colcls,"CLS", "_c", CLSCOLOR}, {row0,coloff,"OFF", "_o", OFFCOLOR} }; int buttn = arylength(buttl) /* Button count */; // Main program void main() { string answer /* Answer string */; int op /* Operator code */; int doff /* Stack display offset */; // Try to call Windows calculator if running in Windows // Check if running in Windows if (bae_swconfig(3)==BAE_WinStd || bae_swconfig(3)==BAE_WinPulldwn) { // Done if Windows calc successfully launched if (launch("calc")==0) return; } // Calculate the popup top boundary if ((muy=mly+calcpopheight(POPUPROWS))>POPMAX) muy=POPMAX; // Calculate the popup right boundary if ((mux=mlx+calcpopwidth(POPUPCOLS))>POPMAX) mux=POPMAX; // Show the popup menu bae_popshow(POPUPROWS,POPUPCOLS,mlx,mly,mux,muy); // Clear calculator status calcclear(); // Do the input loop while ((answer=calcpop())!="_o" && answer!=UINPOPABORT) { // Check if valid input if (answer=="" || answer[0]!='_') continue; // Get button code switch (answer[1]) { // Clear case 'c' : calcclear(); continue; // Dot input case '.' : // Check if dot allowed if (!dotflag && vallen1) calcstacktop(); break; // Result operator case OP_RES : // Evaluate stack while (valuen>1) calcstacktop(); // Clear stack if valid result if (opl[valuen]!=OP_INV) { valuen=0; opl[valuen]=OP_VAL; } doff=1; break; // Square root operator case OP_SQRT : // Check operand if (values[valuen-1]<0.0) { // Invalid operand opl[valuen-1]=OP_INV; } else { // Calculate result values[valuen-1]=sqrt(values[valuen-1]); opl[valuen-1]=OP_VAL; } valuen--; doff=1; break; // Square operator case OP_SQR : values[valuen-1]*=values[valuen-1]; opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // Mil to mm conversion operator case OP_MM : values[valuen-1]=cvtlength(values[valuen-1],3,2); opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // mm to mil conversion operator case OP_MIL : values[valuen-1]=cvtlength(values[valuen-1],2,3); opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // Negation operator case OP_NEG : values[valuen-1]*=(-1); opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // Reciprocal operator case OP_REC : // Check operand if (values[valuen-1]==0.0) { // Invalid operand opl[valuen-1]=OP_INV; } else { // Calculate result values[valuen-1]=1/values[valuen-1]; opl[valuen-1]=OP_VAL; } valuen--; doff=1; break; // Sine operator case OP_SIN : values[valuen-1]=sin(angfac*values[valuen-1]); opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // Cosine operator case OP_COS : values[valuen-1]=cos(angfac*values[valuen-1]); opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // Tangent operator case OP_TAN : values[valuen-1]=tan(angfac*values[valuen-1]); opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // Arc sine operator case OP_ASIN : // Check operand if (values[valuen-1]<(-1.0) || values[valuen-1]>1.0) { // Invalid operand opl[valuen-1]=OP_INV; } else { // Calculate result values[valuen-1]= asin(values[valuen-1])/angfac; opl[valuen-1]=OP_VAL; } valuen--; doff=1; break; // Arc cosine operator case OP_ACOS : // Check operand if (values[valuen-1]<(-1.0) || values[valuen-1]>1.0) { // Invalid operand opl[valuen-1]=OP_INV; } else { // Calculate result values[valuen-1]= acos(values[valuen-1])/angfac; opl[valuen-1]=OP_VAL; } valuen--; doff=1; break; // Arc tangent operator case OP_ATAN : values[valuen-1]=atan(values[valuen-1])/angfac; opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // Exponetial e^X operator case OP_EXP : values[valuen-1]=exp(values[valuen-1]); opl[valuen-1]=OP_VAL; valuen--; doff=1; break; // Natural logarithm (base e) operator case OP_LN : // Check operand if (values[valuen-1]<=0.0) { // Invalid operand opl[valuen-1]=OP_INV; } else { // Calculate result values[valuen-1]=log(values[valuen-1]); opl[valuen-1]=OP_VAL; } valuen--; doff=1; break; // Common logarithm (base ten) operator case OP_LOG : // Check operand if (values[valuen-1]<=0.0) { // Invalid result opl[valuen-1]=OP_INV; } else { // Calculate result values[valuen-1]=log10(values[valuen-1]); opl[valuen-1]=OP_VAL; } valuen--; doff=1; break; default : // Check if prior operator if (valuen<2) // No prior operator break; // Check prior operator type switch (opl[valuen-2]) { // High priority operator case OP_MUL : case OP_DIV : // Calculate high priority term calcstacktop(); break; } break; } // Build the display string valstr=(opl[valuen-1+doff]==OP_INV) ? VAL_Err : buildvalstr(values[valuen-1+doff]); } // Restore the popup area bae_poprestore(); } void calcclear() /* // Clear calculator status */ { // Clear input state keybuffer=""; dotflag=0; // Init zero value valstr="0"; vallen=1; // Init operator stack opl[0]=OP_VAL; values[0]=0.0; valuen=0; } void calcstacktop() /* // Combine stack top values */ { // Do operator action switch (opl[valuen-2]) { case OP_ADD : values[valuen-2]+=values[valuen-1]; break; case OP_SUB : values[valuen-2]-=values[valuen-1]; break; case OP_MUL : values[valuen-2]*=values[valuen-1]; break; case OP_DIV : // Check divisor if (values[valuen-1]==0.0) // Divide by zero causes invalid result opl[valuen-1]=OP_INV; else // Calculate result values[valuen-2]/=values[valuen-1]; break; } opl[valuen-2]=opl[valuen-1]; valuen--; } string buildvalstr(double val) /* // Build string representation of double value // Return value : // string representing double value // Parameters : // double val : Value */ { string vstr /* Value string */; string fstr /* Format string */; int vlen /* Value string length */; int i /* Loop control variable */; sprintf(vstr,"%.11f",val); // Check if display overflow if ((vlen=strlen(vstr))>MAXDIG) { // Adjust rounding to display digits sprintf(fstr,"%%.%df",(vlen-MAXDIG)<12 ? 11-vlen+MAXDIG : 0); sprintf(vstr,fstr,val); vlen=strlen(vstr); } // Remove trailing blanks/zeros for (i=vlen-1;i>=1;i--) { if (vstr[i]=='0' || vstr[i]==' ') vstr[i]='\0'; else break; } // Check if integer value if (i>0 && vstr[i]=='.') // Drop point vstr[i]='\0'; // Check if display overflow if (strlen(vstr)>MAXDIG) vstr[MAXDIG]='\0'; // Return string return(vstr); } string calcpop() /* // Build calculator popup and prompt for input */ { struct button butt /* Button */; string dispstr /* Display string */; string answer /* Answer string */; int i /* Loop variable */; // Display the header string bae_poptext(rowhd,colhd,PULLDWN ? "BAEDescCalc" : "BAE DeskCalc"); // Display the buttons for (i=0;i