Fix IO memory access .. SB128 driver makes noises in VMWare - CMI is untested (Curren...
[AROS.git] / workbench / tools / calculator.c
blob14ca03d8a4e8af75919c3855b7b70f8309a24165
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <intuition/intuition.h>
7 #include <libraries/gadtools.h>
8 #include <libraries/locale.h>
10 #include <proto/exec.h>
11 #include <proto/dos.h>
12 #include <proto/intuition.h>
13 #include <proto/graphics.h>
14 #include <proto/gadtools.h>
15 #include <proto/locale.h>
16 #include <proto/alib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <stdlib.h>
22 #include <math.h>
24 #define ARG_TEMPLATE "PUBSCREEN,TAPE/K"
26 enum {ARG_PUBSCREEN,ARG_TAPE,NUM_ARGS};
28 #define MAX_VAL_LEN 13
30 #define INNER_SPACING_X 4
31 #define INNER_SPACING_Y 4
33 #define BUTTON_SPACING_X 4
34 #define BUTTON_SPACING_Y 4
36 #define BUTTON_LED_SPACING 4
38 #define NUM_BUTTONS 20
39 #define NUM_BUTTON_COLS 5
40 #define NUM_BUTTON_ROWS 4
42 #define BUTTON_EXTRA_WIDTH 8
43 #define BUTTON_EXTRA_HEIGHT 4
45 #define LED_EXTRA_HEIGHT 4
47 enum
49 STATE_LEFTVAL, STATE_OP, STATE_RIGHTVAL, STATE_EQU
52 enum
54 BTYPE_0,
55 BTYPE_1,
56 BTYPE_2,
57 BTYPE_3,
58 BTYPE_4,
59 BTYPE_5,
60 BTYPE_6,
61 BTYPE_7,
62 BTYPE_8,
63 BTYPE_9,
64 BTYPE_COMMA,
65 BTYPE_BS,
66 BTYPE_CA,
67 BTYPE_CE,
68 BTYPE_MUL,
69 BTYPE_DIV,
70 BTYPE_SUB,
71 BTYPE_ADD,
72 BTYPE_SIGN,
73 BTYPE_EQU,
75 BTYPE_LED
78 struct ButtonInfo
80 char *text;
81 WORD type;
82 char key1;
83 char key2;
86 static struct ButtonInfo bi[NUM_BUTTONS] =
88 {"7" ,BTYPE_7 , '7' , 0 },
89 {"8" ,BTYPE_8 , '8' , 0 },
90 {"9" ,BTYPE_9 , '9' , 0 },
91 {"CA" ,BTYPE_CA , 'A' , 127 },
92 {"CE" ,BTYPE_CE , 'E' , 0 },
94 {"4" ,BTYPE_4 , '4' , 0 },
95 {"5" ,BTYPE_5 , '5' , 0 },
96 {"6" ,BTYPE_6 , '6' , 0 },
97 {"×" ,BTYPE_MUL , '*' , 'X' },
98 {":" ,BTYPE_DIV , '/' , ':' },
100 {"1" ,BTYPE_1 , '1' , 0 },
101 {"2" ,BTYPE_2 , '2' , 0 },
102 {"3" ,BTYPE_3 , '3' , 0 },
103 {"+" ,BTYPE_ADD , '+' , 0 },
104 {"-" ,BTYPE_SUB , '-' , 0 },
106 {"0" ,BTYPE_0 , '0' , 0 },
107 {"." ,BTYPE_COMMA , '.' , ',' },
108 {"«" ,BTYPE_BS , 8 , 0 },
109 {"±" ,BTYPE_SIGN , 'S' , 0 },
110 {"=" ,BTYPE_EQU , '=' , 13 }
114 struct IntuitionBase *IntuitionBase;
115 struct GfxBase *GfxBase;
116 struct Library *GadToolsBase;
117 #ifndef __MORPHOS__
118 struct LocaleBase *LocaleBase;
119 #else
120 struct Library *LocaleBase;
121 #endif
123 static struct Screen *scr;
124 static struct DrawInfo *dri;
125 static struct Gadget *gadlist, *gad[NUM_BUTTONS + 2];
126 static struct Window *win;
127 static struct RDArgs *MyArgs;
128 static APTR vi;
129 static BPTR tapefh;
131 static WORD win_borderleft,win_bordertop;
132 static WORD buttonwidth,buttonheight,ledheight;
133 static WORD inner_winwidth,inner_winheight;
134 static WORD vallen,state,operation;
136 static BOOL dotape;
138 static double leftval,rightval;
140 static char comma,*pubscrname;
141 static char ledstring[256],visledstring[256],
142 tempstring[256],tapename[256];
144 static char *deftapename = "RAW:%ld/%ld/%ld/%ld/Calculator Tape/INACTIVE/SCREEN%s";
146 UBYTE version[] = "$VER: Calculator 1.3 (07.10.2007) © AROS Dev Team";
148 static IPTR Args[NUM_ARGS];
150 static void Cleanup(char *msg)
152 WORD rc;
154 if (msg)
156 printf("Calculator: %s\n",msg);
157 rc = RETURN_WARN;
158 } else {
159 rc = RETURN_OK;
162 if (tapefh) Close(tapefh);
164 if (win) CloseWindow(win);
166 if (gadlist) FreeGadgets(gadlist);
168 if (vi) FreeVisualInfo(vi);
169 if (dri) FreeScreenDrawInfo(scr,dri);
170 if (scr) UnlockPubScreen(0,scr);
172 if (MyArgs) FreeArgs(MyArgs);
174 if (LocaleBase) CloseLibrary((struct Library *)LocaleBase);
175 if (GadToolsBase) CloseLibrary(GadToolsBase);
176 if (GfxBase) CloseLibrary((struct Library *)GfxBase);
177 if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
179 exit (rc);
182 static void DosError(void)
184 Fault(IoErr(),0,tempstring,255);
185 Cleanup(tempstring);
188 static void OpenLibs(void)
190 if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",39)))
192 Cleanup("Can't open intuition.library V39!");
195 if (!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",39)))
197 Cleanup("Can't open graphics.library V39!");
200 if (!(GadToolsBase = OpenLibrary("gadtools.library",39)))
202 Cleanup("Can't open gadtools.library V39!");
205 LocaleBase = (struct LocaleBase *)OpenLibrary("locale.library",39);
208 static void GetArguments(void)
210 if (!(MyArgs = ReadArgs(ARG_TEMPLATE,(IPTR *)Args,0)))
212 DosError();
215 pubscrname = (char *)Args[ARG_PUBSCREEN];
217 if (Args[ARG_TAPE])
219 strcpy(tapename,(char *)Args[ARG_TAPE]);
220 dotape = TRUE;
224 static void DoLocale(void)
226 struct Locale *loc;
228 comma = '.';
230 if ((loc = OpenLocale(0)))
232 comma = loc->loc_DecimalPoint[0];
233 CloseLocale(loc);
236 bi[16].text[0] = comma;
239 static void GetVisual(void)
241 if (pubscrname) scr = LockPubScreen(pubscrname);
243 if (!scr)
245 if (!(scr = LockPubScreen(0)))
247 Cleanup("Can't lock screen!");
251 if (!(dri = GetScreenDrawInfo(scr)))
253 Cleanup("Can't get drawinfo!");
256 if (!(vi = GetVisualInfo(scr,0)))
258 Cleanup("Can't get visual info!");
261 win_borderleft = scr->WBorLeft;
263 /* SDuvan: was scr->WBorTop + scr->Font->ta_YSize + 1 */
264 win_bordertop = scr->WBorTop + dri->dri_Font->tf_YSize + 1;
268 static void InitGUI(void)
270 static struct RastPort temprp;
272 WORD i,len;
274 InitRastPort(&temprp);
275 SetFont(&temprp,dri->dri_Font);
277 buttonheight = dri->dri_Font->tf_YSize + BUTTON_EXTRA_HEIGHT;
279 for(i = 0;i < NUM_BUTTONS;i++)
281 len = TextLength(&temprp,bi[i].text,strlen(bi[i].text));
282 if (len > buttonwidth) buttonwidth = len;
285 buttonwidth += BUTTON_EXTRA_WIDTH;
287 ledheight = dri->dri_Font->tf_YSize + LED_EXTRA_HEIGHT;
289 inner_winwidth = buttonwidth * NUM_BUTTON_COLS +
290 BUTTON_SPACING_X * (NUM_BUTTON_COLS - 1) +
291 INNER_SPACING_X * 2;
293 inner_winheight = buttonheight * NUM_BUTTON_ROWS +
294 BUTTON_SPACING_Y * (NUM_BUTTON_ROWS - 1) +
295 BUTTON_LED_SPACING +
296 ledheight +
297 INNER_SPACING_Y * 2;
299 #ifdef __AROS__
300 DeinitRastPort(&temprp);
301 #endif
302 strcpy(ledstring,"0");
305 static void MakeGadgets(void)
307 struct Gadget *mygad = 0;
308 struct NewGadget ng = {0};
309 WORD col,row,i;
311 ng.ng_VisualInfo = vi;
313 mygad = CreateContext(&gadlist);
315 ng.ng_GadgetID = BTYPE_LED;
317 ng.ng_LeftEdge = win_borderleft + INNER_SPACING_X;
318 ng.ng_TopEdge = win_bordertop + INNER_SPACING_Y;
319 ng.ng_Width = inner_winwidth - INNER_SPACING_X * 2;
320 ng.ng_Height = ledheight;
322 mygad = gad[BTYPE_LED] = CreateGadget(TEXT_KIND,
323 mygad,
324 &ng,
325 GTTX_Text, (IPTR) ledstring,
326 GTTX_CopyText,TRUE,
327 GTTX_Border,TRUE,
328 GTTX_Justification,GTJ_RIGHT,
329 TAG_DONE);
331 i = 0;
333 ng.ng_TopEdge = win_bordertop +
334 INNER_SPACING_Y +
335 ledheight +
336 BUTTON_LED_SPACING;
338 ng.ng_Width = buttonwidth;
339 ng.ng_Height = buttonheight;
341 for(row = 0; row < NUM_BUTTON_ROWS; row++)
343 for(col = 0; col < NUM_BUTTON_COLS; col++, i++)
345 ng.ng_GadgetID = bi[i].type;
347 ng.ng_LeftEdge = win_borderleft +
348 INNER_SPACING_X +
349 col * (buttonwidth + BUTTON_SPACING_X);
351 ng.ng_GadgetText = bi[i].text;
353 mygad = gad[bi[i].type] = CreateGadgetA(BUTTON_KIND,
354 mygad,
355 &ng,
358 } /* for(col = 0;col < NUM_BUTTON_COLS; col++) */
360 ng.ng_TopEdge += buttonheight + BUTTON_SPACING_Y;
362 } /* for(row = 0; row < NUM_BUTTON_ROWS; row++) */
364 if (!mygad)
366 Cleanup("Can't create gadgets!");
371 static void MakeWin(void)
373 win = OpenWindowTags(0,WA_PubScreen,(IPTR)scr,
374 WA_Left,scr->MouseX,
375 WA_Top,scr->MouseY,
376 WA_InnerWidth,inner_winwidth,
377 WA_InnerHeight,inner_winheight,
378 WA_AutoAdjust,TRUE,
379 WA_Title,(IPTR)"Calculator",
380 WA_CloseGadget,TRUE,
381 WA_DepthGadget,TRUE,
382 WA_DragBar,TRUE,
383 WA_Activate,TRUE,
384 WA_SimpleRefresh,TRUE,
385 WA_IDCMP,IDCMP_CLOSEWINDOW |
386 IDCMP_GADGETUP |
387 IDCMP_VANILLAKEY |
388 IDCMP_RAWKEY |
389 IDCMP_REFRESHWINDOW,
390 WA_Gadgets,(IPTR)gadlist,
391 TAG_DONE);
393 if (!win) Cleanup("Can't open window!");
395 GT_RefreshWindow(win,0);
397 ScreenToFront(win->WScreen);
400 static void OpenTape(void)
402 struct List *l;
403 struct PubScreenNode *psn;
404 char *scrname = "";
405 WORD x,y,w,h;
407 if (!(tapename[0]))
409 l = LockPubScreenList();
411 psn = (struct PubScreenNode *)l->lh_Head;
413 while (psn->psn_Node.ln_Succ)
415 if (psn->psn_Screen == scr)
417 if (psn->psn_Node.ln_Name)
419 scrname = psn->psn_Node.ln_Name;
421 break;
423 psn = (struct PubScreenNode *)psn->psn_Node.ln_Succ;
426 UnlockPubScreenList();
428 w = win->Width * 5 / 4;
429 h = win->Height;
431 x = win->LeftEdge;
432 y = win->TopEdge;
434 if (x > (scr->Width - (x + w)))
436 x -= w;
437 } else {
438 x += win->Width;
440 sprintf(tapename,deftapename,x,y,w,h,scrname);
443 if (!(tapefh = Open(tapename,MODE_NEWFILE)))
445 DisplayBeep(scr);
449 static double GetValue(void)
451 double val;
452 char c = 0,*sp;
454 sp = strchr(ledstring,comma);
455 if (sp)
457 c = *sp;
458 *sp = '.';
461 val = strtod(ledstring,0);
463 if (sp) *sp = c;
465 return val;
468 static void GetLeftValue(void)
470 leftval = GetValue();
473 static void GetRightValue(void)
475 rightval = GetValue();
478 static void LeftValToLED(void)
480 char *sp;
482 sprintf(ledstring,"%f",leftval);
484 sp = strchr(ledstring,'.');
485 if (!sp) sp = strchr(ledstring,',');
486 if (sp) *sp = comma;
489 static char *DoOperation(void)
491 char *matherr = 0;
493 switch (operation)
495 case BTYPE_ADD:
496 leftval += rightval;
497 break;
499 case BTYPE_SUB:
500 leftval -= rightval;
501 break;
503 case BTYPE_MUL:
504 leftval *= rightval;
505 break;
507 case BTYPE_DIV:
508 if (rightval == 0.0)
510 matherr = "Division by zero!";
511 } else {
512 leftval /= rightval;
514 break;
517 if (leftval > 9999999999999.0) // because of MAX_VAL_LEN
519 matherr = "Buffer overflow!";
522 if (!matherr) LeftValToLED();
524 return matherr;
527 static void RefreshLED(void)
529 strcpy(visledstring,ledstring);
531 if ((ledstring[0] == ',') ||
532 (ledstring[0] == '\0') ||
533 ((ledstring[0] >= '0') && (ledstring[0] <= '9')))
535 visledstring[0] = '\0';
537 if ((ledstring[0] == ',') ||
538 (ledstring[0] == '.') ||
539 (ledstring[0] == '\0'))
541 strcpy(visledstring,"0");
543 strcat(visledstring,ledstring);
546 GT_SetGadgetAttrs(gad[BTYPE_LED],
547 win,
549 GTTX_Text,(IPTR)visledstring,
550 TAG_DONE);
553 static void HandleButton(WORD type)
555 char *matherr = 0;
556 WORD checklen;
557 BOOL refresh_led = FALSE;
559 switch(type)
561 case BTYPE_0:
562 case BTYPE_1:
563 case BTYPE_2:
564 case BTYPE_3:
565 case BTYPE_4:
566 case BTYPE_5:
567 case BTYPE_6:
568 case BTYPE_7:
569 case BTYPE_8:
570 case BTYPE_9:
571 checklen = vallen;
572 if ((strchr(ledstring,comma))) checklen--;
573 if ((strchr(ledstring,'-'))) checklen--;
575 if (checklen < MAX_VAL_LEN)
577 if (state == STATE_OP)
579 state = STATE_RIGHTVAL;
580 } else if (state == STATE_EQU)
582 state = STATE_LEFTVAL;
585 if ((vallen > 0) || (type != BTYPE_0))
587 ledstring[vallen++] = type + '0';
589 ledstring[vallen] = '\0';
591 refresh_led = TRUE;
593 } /* if (vallen < MAX_VAL_LEN) */
594 break;
596 case BTYPE_COMMA:
597 if (!strchr(ledstring,comma))
599 if (state == STATE_OP)
601 state = STATE_RIGHTVAL;
602 } else if (state == STATE_EQU)
604 state = STATE_LEFTVAL;
607 ledstring[vallen++] = comma;
608 ledstring[vallen] = '\0';
610 refresh_led = TRUE;
612 } /* if (!strchr(ledstring,comma)) */
613 break;
615 case BTYPE_CA:
616 vallen = 0;
617 leftval = 0.0;
618 rightval = 0.0;
619 operation = BTYPE_ADD;
621 state = STATE_LEFTVAL;
623 strcpy(ledstring,"0");
624 refresh_led = TRUE;
626 if (tapefh) FPutC(tapefh, '\n');
627 break;
629 case BTYPE_CE:
630 vallen = 0;
631 strcpy(ledstring,"0");
632 refresh_led = TRUE;
634 switch (state)
636 case STATE_LEFTVAL:
637 leftval = 0.0;
638 break;
640 case STATE_OP:
641 case STATE_RIGHTVAL:
642 rightval = 0.0;
643 break;
645 break;
647 case BTYPE_BS:
648 if (vallen)
650 ledstring[--vallen] = '\0';
651 if (vallen == 0) strcpy(ledstring,"0");
652 refresh_led = TRUE;
654 break;
656 case BTYPE_SIGN:
657 switch(state)
659 case STATE_LEFTVAL:
660 case STATE_RIGHTVAL:
661 if (ledstring[0] == '-')
663 strcpy(ledstring,&ledstring[1]);
664 } else {
665 strcpy(tempstring,ledstring);
666 strcpy(ledstring,"-");
667 strcat(ledstring,tempstring);
669 refresh_led = TRUE;
670 break;
672 case STATE_EQU:
673 leftval = -leftval;
674 LeftValToLED();
675 refresh_led = TRUE;
676 break;
678 break;
680 case BTYPE_ADD:
681 case BTYPE_SUB:
682 case BTYPE_MUL:
683 case BTYPE_DIV:
684 switch(state)
686 case STATE_LEFTVAL:
687 case STATE_EQU:
688 GetLeftValue();
689 rightval = leftval;
691 state = STATE_OP;
692 vallen = 0;
693 strcpy(ledstring,"0");
695 if (tapefh)
697 FPutC(tapefh, '\t');
698 FPuts(tapefh, visledstring);
699 FPutC(tapefh, '\n');
700 Flush(tapefh);
702 break;
704 case STATE_OP:
705 break;
707 case STATE_RIGHTVAL:
708 GetRightValue();
709 matherr = DoOperation();
710 state = STATE_OP;
711 vallen = 0;
712 refresh_led = TRUE;
714 if (tapefh)
716 FPuts(tapefh,
717 (operation == BTYPE_ADD) ? "+" :
718 (operation == BTYPE_SUB) ? "-" :
719 (operation == BTYPE_DIV) ? ":" :
720 "×");
721 FPutC(tapefh, '\t');
722 FPuts(tapefh, visledstring);
723 FPutC(tapefh, '\n');
724 Flush(tapefh);
726 break;
728 } /* switch(state) */
730 operation = type;
731 break;
733 case BTYPE_EQU:
734 if (state == STATE_LEFTVAL)
736 GetLeftValue();
737 if (tapefh)
739 FPutC(tapefh, '\t');
740 FPuts(tapefh, visledstring);
741 FPutC(tapefh, '\n');
742 Flush(tapefh);
745 else if (state == STATE_RIGHTVAL)
747 GetRightValue();
748 if (tapefh)
750 FPuts(tapefh,
751 (operation == BTYPE_ADD) ? "+" :
752 (operation == BTYPE_SUB) ? "-" :
753 (operation == BTYPE_DIV) ? ":" :
754 "×");
755 FPutC(tapefh, '\t');
756 FPuts(tapefh, visledstring);
757 FPutC(tapefh, '\n');
758 Flush(tapefh);
762 matherr = DoOperation();
763 state = STATE_EQU;
765 vallen = 0;
767 if (!matherr)
769 RefreshLED();
770 if (tapefh)
772 FPuts(tapefh, "=\t");
773 FPuts(tapefh, visledstring);
774 FPutC(tapefh, '\n');
775 Flush(tapefh);
777 } else {
778 refresh_led = TRUE;
780 break;
782 } /* switch(type) */
784 if (matherr)
786 leftval = rightval = 0.0;
787 state = STATE_LEFTVAL;
788 operation = BTYPE_ADD;
789 vallen = 0;
790 strcpy(ledstring,matherr);
791 refresh_led = TRUE;
794 if (refresh_led) RefreshLED();
798 static void HandleAll(void)
800 struct IntuiMessage *msg;
801 WORD icode,i;
802 ULONG signals;
804 BOOL quitme = FALSE;
806 if (dotape) OpenTape();
808 while(!quitme)
810 signals = Wait(1L << win->UserPort->mp_SigBit | SIGBREAKF_CTRL_C);
812 if (signals & (1L << win->UserPort->mp_SigBit))
814 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
816 switch(msg->Class)
818 case IDCMP_CLOSEWINDOW:
819 quitme = TRUE;
820 break;
822 case IDCMP_REFRESHWINDOW:
823 GT_BeginRefresh(win);
824 GT_EndRefresh(win,TRUE);
825 break;
827 case IDCMP_GADGETUP:
828 HandleButton(((struct Gadget *)msg->IAddress)->GadgetID);
829 break;
831 case IDCMP_VANILLAKEY:
832 icode = toupper(msg->Code);
834 for(i = 0;i < NUM_BUTTONS;i++)
836 if ((icode == bi[i].key1) ||
837 (icode == bi[i].key2))
839 icode = bi[i].type;
840 break;
843 if (i < NUM_BUTTONS)
845 HandleButton(icode);
846 } else if (icode == 27)
848 quitme = TRUE;
850 break;
852 } /* switch(msg->Class) */
854 ReplyMsg((struct Message *)msg);
855 } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
856 } /* if(signals & (1L << win->UserPort->mp_SigBit)) */
857 if (signals & SIGBREAKF_CTRL_C)
858 quitme = TRUE;
860 } /* while(!quitme) */
863 int main(void)
865 OpenLibs();
866 GetArguments();
867 DoLocale();
868 GetVisual();
869 InitGUI();
870 MakeGadgets();
871 MakeWin();
872 HandleAll();
873 Cleanup(0);
874 return 0;