New bitmap method SetRGBConversionFunction which can be used to
[tangerine.git] / workbench / tools / calculator.c
blobbe11de1374d1459258bb609c80df3db8f11d13a1
1 /*
2 Copyright © 1995-2003, 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 FILE *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.1 (1.5.2001)";
148 static LONG 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) fclose(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,(LONG *)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 = fopen(tapename,"w")))
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 (!matherr) LeftValToLED();
519 return matherr;
522 static void RefreshLED(void)
524 strcpy(visledstring,ledstring);
526 if ((ledstring[0] == ',') ||
527 (ledstring[0] == '\0') ||
528 ((ledstring[0] >= '0') && (ledstring[0] <= '9')))
530 visledstring[0] = '\0';
532 if ((ledstring[0] == ',') ||
533 (ledstring[0] == '.') ||
534 (ledstring[0] == '\0'))
536 strcpy(visledstring,"0");
538 strcat(visledstring,ledstring);
541 GT_SetGadgetAttrs(gad[BTYPE_LED],
542 win,
544 GTTX_Text,(IPTR)visledstring,
545 TAG_DONE);
548 static void HandleButton(WORD type)
550 char *matherr = 0;
551 WORD checklen;
552 BOOL refresh_led = FALSE;
554 switch(type)
556 case BTYPE_0:
557 case BTYPE_1:
558 case BTYPE_2:
559 case BTYPE_3:
560 case BTYPE_4:
561 case BTYPE_5:
562 case BTYPE_6:
563 case BTYPE_7:
564 case BTYPE_8:
565 case BTYPE_9:
566 checklen = vallen;
567 if ((strchr(ledstring,comma))) checklen--;
568 if ((strchr(ledstring,'-'))) checklen--;
570 if (checklen < MAX_VAL_LEN)
572 if (state == STATE_OP)
574 state = STATE_RIGHTVAL;
575 } else if (state == STATE_EQU)
577 state = STATE_LEFTVAL;
580 if ((vallen > 0) || (type != BTYPE_0))
582 ledstring[vallen++] = type + '0';
584 ledstring[vallen] = '\0';
586 refresh_led = TRUE;
588 } /* if (vallen < MAX_VAL_LEN) */
589 break;
591 case BTYPE_COMMA:
592 if (!strchr(ledstring,comma))
594 if (state == STATE_OP)
596 state = STATE_RIGHTVAL;
597 } else if (state == STATE_EQU)
599 state = STATE_LEFTVAL;
602 ledstring[vallen++] = comma;
603 ledstring[vallen] = '\0';
605 refresh_led = TRUE;
607 } /* if (!strchr(ledstring,comma)) */
608 break;
610 case BTYPE_CA:
611 vallen = 0;
612 leftval = 0.0;
613 rightval = 0.0;
614 operation = BTYPE_ADD;
616 state = STATE_LEFTVAL;
618 strcpy(ledstring,"0");
619 refresh_led = TRUE;
621 if (tapefh) fputs("\n",tapefh);
622 break;
624 case BTYPE_CE:
625 vallen = 0;
626 strcpy(ledstring,"0");
627 refresh_led = TRUE;
629 switch (state)
631 case STATE_LEFTVAL:
632 leftval = 0.0;
633 break;
635 case STATE_OP:
636 case STATE_RIGHTVAL:
637 rightval = 0.0;
638 break;
640 break;
642 case BTYPE_BS:
643 if (vallen)
645 ledstring[--vallen] = '\0';
646 if (vallen == 0) strcpy(ledstring,"0");
647 refresh_led = TRUE;
649 break;
651 case BTYPE_SIGN:
652 switch(state)
654 case STATE_LEFTVAL:
655 case STATE_RIGHTVAL:
656 if (ledstring[0] == '-')
658 strcpy(ledstring,&ledstring[1]);
659 } else {
660 strcpy(tempstring,ledstring);
661 strcpy(ledstring,"-");
662 strcat(ledstring,tempstring);
664 refresh_led = TRUE;
665 break;
667 case STATE_EQU:
668 leftval = -leftval;
669 LeftValToLED();
670 refresh_led = TRUE;
671 break;
673 break;
675 case BTYPE_ADD:
676 case BTYPE_SUB:
677 case BTYPE_MUL:
678 case BTYPE_DIV:
679 switch(state)
681 case STATE_LEFTVAL:
682 case STATE_EQU:
683 GetLeftValue();
684 rightval = leftval;
686 state = STATE_OP;
687 vallen = 0;
688 strcpy(ledstring,"0");
690 if (tapefh)
692 fprintf(tapefh,"\t%s\n",visledstring);
693 fflush(tapefh);
695 break;
697 case STATE_OP:
698 break;
700 case STATE_RIGHTVAL:
701 GetRightValue();
702 matherr = DoOperation();
703 state = STATE_OP;
704 vallen = 0;
705 refresh_led = TRUE;
707 if (tapefh)
709 fprintf(tapefh,"%s\t%s\n",(operation == BTYPE_ADD) ? "+" :
710 (operation == BTYPE_SUB) ? "-" :
711 (operation == BTYPE_DIV) ? ":" :
712 "×" ,visledstring);
713 fflush(tapefh);
715 break;
717 } /* switch(state) */
719 operation = type;
720 break;
722 case BTYPE_EQU:
723 if (state == STATE_LEFTVAL)
725 GetLeftValue();
726 if (tapefh)
728 fprintf(tapefh,"\t%s\n",visledstring);
729 fflush(tapefh);
732 else if (state == STATE_RIGHTVAL)
734 GetRightValue();
735 if (tapefh)
737 fprintf(tapefh,"%s\t%s\n",(operation == BTYPE_ADD) ? "+" :
738 (operation == BTYPE_SUB) ? "-" :
739 (operation == BTYPE_DIV) ? ":" :
740 "×" ,visledstring);
741 fflush(tapefh);
745 matherr = DoOperation();
746 state = STATE_EQU;
748 vallen = 0;
750 if (!matherr)
752 RefreshLED();
753 if (tapefh)
755 fprintf(tapefh,"=\t%s\n",visledstring);
756 fflush(tapefh);
758 } else {
759 refresh_led = TRUE;
761 break;
763 } /* switch(type) */
765 if (matherr)
767 leftval = rightval = 0.0;
768 state = STATE_LEFTVAL;
769 operation = BTYPE_ADD;
770 vallen = 0;
771 strcpy(ledstring,matherr);
772 refresh_led = TRUE;
775 if (refresh_led) RefreshLED();
779 static void HandleAll(void)
781 struct IntuiMessage *msg;
782 WORD icode,i;
783 ULONG signals;
785 BOOL quitme = FALSE;
787 if (dotape) OpenTape();
789 while(!quitme)
791 signals = Wait(1L << win->UserPort->mp_SigBit | SIGBREAKF_CTRL_C);
793 if (signals & (1L << win->UserPort->mp_SigBit))
795 while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort)))
797 switch(msg->Class)
799 case IDCMP_CLOSEWINDOW:
800 quitme = TRUE;
801 break;
803 case IDCMP_REFRESHWINDOW:
804 GT_BeginRefresh(win);
805 GT_EndRefresh(win,TRUE);
806 break;
808 case IDCMP_GADGETUP:
809 HandleButton(((struct Gadget *)msg->IAddress)->GadgetID);
810 break;
812 case IDCMP_VANILLAKEY:
813 icode = toupper(msg->Code);
815 for(i = 0;i < NUM_BUTTONS;i++)
817 if ((icode == bi[i].key1) ||
818 (icode == bi[i].key2))
820 icode = bi[i].type;
821 break;
824 if (i < NUM_BUTTONS)
826 HandleButton(icode);
827 } else if (icode == 27)
829 quitme = TRUE;
831 break;
833 } /* switch(msg->Class) */
835 ReplyMsg((struct Message *)msg);
836 } /* while ((msg = (struct IntuiMessage *)GetMsg(win->UserPort))) */
837 } /* if(signals & (1L << win->UserPort->mp_SigBit)) */
838 if (signals & SIGBREAKF_CTRL_C)
839 quitme = TRUE;
841 } /* while(!quitme) */
844 int main(void)
846 OpenLibs();
847 GetArguments();
848 DoLocale();
849 GetVisual();
850 InitGUI();
851 MakeGadgets();
852 MakeWin();
853 HandleAll();
854 Cleanup(0);
855 return 0;