refactored some code. compiles now without suppresing any warning with gcc-6.3.0.
[AROS.git] / workbench / tools / Calculator.c
blob9bd53f32333af46319183b63f092a144f095391e
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 Command line options:
6 1. PUBSCREEN <name>: the name of the public screen to open the window on
7 2. TAPE <filename>: the name of a file to record the user interactions
8 into
9 */
10 #include <exec/types.h>
11 #include <dos/dos.h>
12 #include <intuition/intuition.h>
13 #include <intuition/classes.h>
14 #include <libraries/mui.h>
16 #include <proto/exec.h>
17 #include <proto/dos.h>
18 #include <proto/intuition.h>
19 #include <proto/locale.h>
20 #include <proto/alib.h>
21 #include <proto/muimaster.h>
22 #include <proto/utility.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
28 const char *version = "$VER: Calculator 1.4 (08.08.2013) © AROS Dev Team";
30 #define ARG_TEMPLATE "PUBSCREEN,TAPE/K"
31 enum {ARG_PUBSCREEN,ARG_TAPE,NUM_ARGS};
33 /* The pattern of the tape name in case we log to a RAW: window */
34 #define RAW_TAPE_NAME "RAW:%d/%d/%d/%d/Calculator Tape/INACTIVE/SCREEN%s"
36 enum
38 BTYPE_0 = 0,
39 BTYPE_1,
40 BTYPE_2,
41 BTYPE_3,
42 BTYPE_4,
43 BTYPE_5,
44 BTYPE_6,
45 BTYPE_7,
46 BTYPE_8,
47 BTYPE_9,
48 BTYPE_COMMA,
49 BTYPE_BS,
50 BTYPE_CA,
51 BTYPE_CE,
52 BTYPE_MUL,
53 BTYPE_DIV,
54 BTYPE_SUB,
55 BTYPE_ADD,
56 BTYPE_SIGN,
57 BTYPE_EQU
60 #define NUM_BUTTONS 20
61 #define DECIMAL_BUTTON_INDEX 16
63 struct CalcButtonInfo
65 const char *label;
66 ULONG btype;
67 char shortcut;
70 struct CalcButtonInfo BUTTONS[] =
72 {"7", BTYPE_7, '7'}, {"8", BTYPE_8, '8'}, {"9", BTYPE_9, '9'}, {"CA", BTYPE_CA, 'A'}, {"CE", BTYPE_CE, 'E'},
73 {"4", BTYPE_4, '4'}, {"5", BTYPE_5, '5'}, {"6", BTYPE_6, '6'}, {"*", BTYPE_MUL, '*'}, {":", BTYPE_DIV, ':'},
74 {"1", BTYPE_1, '1'}, {"2", BTYPE_2, '2'}, {"3", BTYPE_3, '3'}, {"+", BTYPE_ADD, '+'}, {"-", BTYPE_SUB, '-'},
75 {"0", BTYPE_0, '0'}, {".", BTYPE_COMMA, '.'}, {"<<", BTYPE_BS, 8}, {"+/-", BTYPE_SIGN, 's'}, {"=", BTYPE_EQU, '='}
79 * Most of the application state is local or in BOOPSI objects.
80 * The only global state is to communicate the command line arguments
82 static char pubscrname[256];
83 static char tapename[256];
84 static BOOL use_tape;
86 /**********************************************************************
87 Tape BOOPSI class
88 **********************************************************************/
90 #define TAPEA_FILEHANDLE (TAG_USER + 20)
91 #define TAPEM_NEWLINE (TAG_USER + 21)
92 #define TAPEM_PRINT_LVAL (TAG_USER + 22)
93 #define TAPEM_PRINT_RVAL (TAG_USER + 23)
94 #define TAPEM_PRINT_RESULT (TAG_USER + 24)
96 struct TapeData
98 BPTR tapefh;
101 struct MUIMP_PrintLval
103 STACKED ULONG MethodID;
104 STACKED const char *str;
107 struct MUIMP_PrintRval
109 STACKED ULONG MethodID;
110 STACKED char operator;
111 STACKED const char *str;
114 struct MUIMP_PrintResult
116 STACKED ULONG MethodID;
117 STACKED const char *str;
120 IPTR mNewTape(struct IClass *cl, Object *obj, struct opSet *msg)
122 struct TagItem *tagListState = msg->ops_AttrList, *tag;
123 Object *instance = (Object *) DoSuperMethodA(cl, obj, (APTR) msg);
124 struct TapeData *data = INST_DATA(cl, instance);
125 data->tapefh = BNULL;
127 while ((tag = (struct TagItem *) NextTagItem(&tagListState)))
129 switch (tag->ti_Tag)
131 case TAPEA_FILEHANDLE:
132 data->tapefh = (BPTR) tag->ti_Data;
133 break;
134 default:
135 break;
138 return (IPTR) instance;
141 IPTR mDisposeTape(struct IClass *cl, Object *obj, struct opSet *msg)
143 struct TapeData *data = INST_DATA(cl, obj);
144 if (data->tapefh) Close(data->tapefh);
145 return DoSuperMethodA(cl, obj, (APTR) msg);
148 IPTR mTapeNewline(struct IClass *cl, Object *obj, APTR msg)
150 struct TapeData *data = INST_DATA(cl, obj);
151 if (data->tapefh) FPutC(data->tapefh, '\n');
152 return (IPTR) obj;
155 IPTR mTapePrintLval(struct IClass *cl, Object *obj, struct MUIMP_PrintLval *msg)
157 struct TapeData *data = INST_DATA(cl, obj);
158 if (data->tapefh)
160 FPutC(data->tapefh, '\t');
161 FPuts(data->tapefh, msg->str);
162 FPutC(data->tapefh, '\n');
163 Flush(data->tapefh);
165 return (IPTR) obj;
168 IPTR mTapePrintRval(struct IClass *cl, Object *obj, struct MUIMP_PrintRval *msg)
170 struct TapeData *data = INST_DATA(cl, obj);
171 if (data->tapefh)
173 FPutC(data->tapefh, msg->operator);
174 FPutC(data->tapefh, '\t');
175 FPuts(data->tapefh, msg->str);
176 FPutC(data->tapefh, '\n');
177 Flush(data->tapefh);
179 return (IPTR) obj;
182 IPTR mTapePrintResult(struct IClass *cl, Object *obj, struct MUIMP_PrintResult *msg)
184 struct TapeData *data = INST_DATA(cl, obj);
185 if (data->tapefh)
187 FPuts(data->tapefh, "=\t");
188 FPuts(data->tapefh, msg->str);
189 FPutC(data->tapefh, '\n');
190 Flush(data->tapefh);
192 return (IPTR) obj;
195 ULONG mSet(struct IClass *cl, Object *obj, struct opSet *msg)
197 struct TagItem *tagListState = msg->ops_AttrList, *tag;
198 struct TapeData *data = INST_DATA(cl, obj);
200 while ((tag = (struct TagItem *) NextTagItem(&tagListState)))
202 switch (tag->ti_Tag)
204 case TAPEA_FILEHANDLE:
205 data->tapefh = (BPTR) tag->ti_Data;
206 break;
207 default:
208 break;
211 return (IPTR) obj;
214 BOOPSI_DISPATCHER(IPTR, TapeDispatcher, cl, obj, msg)
216 switch (msg->MethodID)
218 case OM_NEW: return mNewTape(cl, obj, (APTR) msg);
219 case OM_DISPOSE: return mDisposeTape(cl, obj, (APTR) msg);
220 case OM_SET: return mSet(cl, obj, (APTR) msg);
222 case TAPEM_NEWLINE: return mTapeNewline(cl, obj, (APTR) msg);
223 case TAPEM_PRINT_LVAL: return mTapePrintLval(cl, obj, (struct MUIMP_PrintLval *) msg);
224 case TAPEM_PRINT_RVAL: return mTapePrintRval(cl, obj, (struct MUIMP_PrintRval *) msg);
225 case TAPEM_PRINT_RESULT: return mTapePrintResult(cl, obj, (struct MUIMP_PrintResult *) msg);
227 return DoSuperMethodA(cl, obj, msg);
229 BOOPSI_DISPATCHER_END
231 static Class *make_tape_class(void)
233 Class *cl;
234 cl = MakeClass(NULL, ROOTCLASS, NULL, sizeof(struct TapeData), 0);
235 if (cl) cl->cl_Dispatcher.h_Entry = TapeDispatcher;
236 return cl;
239 /**********************************************************************
240 Calculator BOOPSI class
241 **********************************************************************/
243 #define MAX_DIGITS 13
244 #define OM_ADD_KEY (TAG_USER + 30)
245 #define CALCA_DISPLAY (TAG_USER + 31)
246 #define CALCA_TAPE (TAG_USER + 32)
247 #define CALCA_DECIMAL_POINT (TAG_USER + 33)
249 #define EDIT_BUFFER_SIZE MAX_DIGITS + 2 /* space for '-' sign and terminator byte */
250 const char *INITIAL_DISPLAY = "\033r0";
251 enum { STATE_LEFTVAL, STATE_OP, STATE_RIGHTVAL, STATE_EQU };
253 struct CalculatorData
255 char edit_buffer[EDIT_BUFFER_SIZE];
256 int num_digits;
257 int state;
258 char decimal_point;
260 double lvalue, rvalue;
261 int op;
262 Object *display, *tape;
265 struct MUIMP_CalcKey
267 STACKED ULONG MethodID;
268 STACKED ULONG btype;
271 static char op2char(int op)
273 switch (op) {
274 case BTYPE_MUL: return '*';
275 case BTYPE_DIV: return '*';
276 case BTYPE_SUB: return '-';
277 case BTYPE_ADD: return '+';
278 default: return '?';
282 static void clear_edit_buffer(struct CalculatorData *data)
284 memset(data->edit_buffer, 0, EDIT_BUFFER_SIZE);
285 data->num_digits = 0;
288 IPTR mNewCalc(struct IClass *cl, Object *obj, struct opSet *msg)
290 struct TagItem *tagListState = msg->ops_AttrList, *tag;
291 Object *instance = (Object *) DoSuperMethodA(cl, obj, (APTR) msg);
292 struct CalculatorData *data = INST_DATA(cl, instance);
293 clear_edit_buffer(data);
294 data->display = NULL;
295 data->tape = NULL;
296 data->state = STATE_LEFTVAL;
297 data->decimal_point = '.';
299 while ((tag = (struct TagItem *) NextTagItem(&tagListState)))
301 switch (tag->ti_Tag)
303 case CALCA_DISPLAY:
304 data->display = (Object *) tag->ti_Data;
305 break;
306 case CALCA_TAPE:
307 data->tape = (Object *) tag->ti_Data;
308 break;
309 case CALCA_DECIMAL_POINT:
310 data->decimal_point = (char) tag->ti_Data;
311 break;
312 default:
313 break;
316 return (IPTR) instance;
319 IPTR mDisposeCalc(struct IClass *cl, Object *obj, struct opSet *msg)
321 return DoSuperMethodA(cl, obj, (APTR) msg);
324 static BOOL is_operator(int btype)
326 return btype >= BTYPE_MUL && btype <= BTYPE_ADD;
329 static BOOL can_insert_comma(struct CalculatorData *data)
331 if (data->num_digits == 0) return TRUE;
332 else
334 int i;
335 for (i = 0; i < data->num_digits; i++)
337 if (data->edit_buffer[i] == '.') return FALSE;
339 return TRUE;
343 static double eval_result(double lvalue, double rvalue, int op)
345 switch (op)
347 case BTYPE_MUL: return lvalue * rvalue;
348 case BTYPE_DIV: return lvalue / rvalue;
349 case BTYPE_SUB: return lvalue - rvalue;
350 case BTYPE_ADD: return lvalue + rvalue;
351 default: return 0;
356 static void localize_buffer(char *buffer, char decimal_point, int from, int to)
358 int i;
359 for (i = from; i < to; i ++)
361 if (buffer[i] == '.')
363 buffer[i] = decimal_point;
364 break;
369 * Rendering is centralized in this function, by copying
370 * the edit buffer into and manipulating the display buffer.
371 * MUI/Zune's text field right-justifies text through the inclusion
372 * of the "Esc-r" control sequence.
374 static void display_state(struct CalculatorData *data)
376 /* add 2 extra chars: Esc+'r' */
377 static char display_buffer[EDIT_BUFFER_SIZE + 2];
379 if (data->num_digits == 0)
381 SetAttrs(data->display, MUIA_Text_Contents, INITIAL_DISPLAY, TAG_DONE);
383 else
385 memset(display_buffer, 0, EDIT_BUFFER_SIZE + 2);
386 display_buffer[0] = '\033';
387 display_buffer[1] = 'r';
388 memcpy(display_buffer + 2, data->edit_buffer, data->num_digits);
389 localize_buffer(display_buffer, data->decimal_point, 2, MAX_DIGITS + 3);
390 SetAttrs(data->display, MUIA_Text_Contents, display_buffer, TAG_DONE);
394 static const char *localize_display(struct CalculatorData *data)
396 static char buffer[EDIT_BUFFER_SIZE];
397 memset(buffer, 0, MAX_DIGITS + 1);
398 memcpy(buffer, data->edit_buffer, data->num_digits);
399 localize_buffer(buffer, data->decimal_point, 0, MAX_DIGITS + 1);
400 return buffer;
403 static void toggle_sign(struct CalculatorData *data)
405 BOOL sign_found = FALSE;
406 int i;
407 if (data->state == STATE_LEFTVAL) data->lvalue = -data->lvalue;
408 else if (data->state == STATE_RIGHTVAL) data->rvalue = -data->rvalue;
410 for (i = 0; i < EDIT_BUFFER_SIZE; i++)
412 if (data->edit_buffer[i] == '-')
414 sign_found = TRUE;
415 break;
419 if (sign_found)
421 /* eliminate the sign by shifting to the left */
422 data->num_digits--;
423 memmove(data->edit_buffer, data->edit_buffer + 1, data->num_digits);
424 data->edit_buffer[data->num_digits] = 0;
426 else
428 /* add sign by shifting to the right and inserting - */
429 memmove(data->edit_buffer + 1, data->edit_buffer, data->num_digits);
430 data->num_digits++;
431 data->edit_buffer[0] = '-';
432 data->edit_buffer[data->num_digits] = 0;
434 display_state(data);
438 * This method implements the main logic of the calculator by performing transitions
439 * of a state machine.
441 IPTR mAddCalcKey(struct IClass *cl, Object *obj, struct MUIMP_CalcKey *msg)
443 struct CalculatorData *data = INST_DATA(cl, obj);
444 if (msg->btype <= BTYPE_9 && data->num_digits < MAX_DIGITS)
446 if (data->state == STATE_OP)
448 data->state = STATE_RIGHTVAL;
449 clear_edit_buffer(data);
451 if (data->state == STATE_EQU)
453 data->state = STATE_LEFTVAL;
454 clear_edit_buffer(data);
456 char digit = '0' + msg->btype;
457 data->edit_buffer[data->num_digits++] = digit;
458 display_state(data);
461 else if (msg->btype == BTYPE_COMMA && can_insert_comma(data))
463 data->edit_buffer[data->num_digits++] = '.';
464 display_state(data);
466 else if (is_operator(msg->btype))
468 if (data->state == STATE_LEFTVAL || data->state == STATE_EQU)
470 data->lvalue = strtod(data->edit_buffer, NULL);
471 data->state = STATE_OP;
472 data->op = msg->btype;
473 if (data->tape) DoMethod(data->tape, TAPEM_PRINT_LVAL, localize_display(data));
476 else if (msg->btype == BTYPE_EQU)
478 if (data->tape) DoMethod(data->tape, TAPEM_PRINT_RVAL, op2char(data->op), localize_display(data));
480 data->rvalue = strtod(data->edit_buffer, NULL);
481 data->state = STATE_EQU;
482 data->lvalue = eval_result(data->lvalue, data->rvalue, data->op);
483 snprintf(data->edit_buffer, MAX_DIGITS, "%f", data->lvalue);
484 /* note that there is no strnlen() in AROS !!! */
485 data->num_digits = strlen(data->edit_buffer);
487 display_state(data);
488 if (data->tape) DoMethod(data->tape, TAPEM_PRINT_RESULT, localize_display(data));
490 else if (msg->btype == BTYPE_CA)
492 data->lvalue = 0;
493 data->rvalue = 0;
494 data->op = BTYPE_ADD;
495 data->state = STATE_LEFTVAL;
496 clear_edit_buffer(data);
498 display_state(data);
499 if (data->tape) DoMethod(data->tape, TAPEM_NEWLINE);
501 else if (msg->btype == BTYPE_CE &&
502 (data->state == STATE_LEFTVAL || data->state == STATE_RIGHTVAL))
504 clear_edit_buffer(data);
505 display_state(data);
508 else if (msg->btype == BTYPE_SIGN && data->state != STATE_OP)
510 toggle_sign(data);
512 else if (msg->btype == BTYPE_BS &&
513 (data->state == STATE_LEFTVAL || data->state == STATE_RIGHTVAL) &&
514 data->num_digits > 0)
516 data->edit_buffer[--data->num_digits] = 0;
517 display_state(data);
519 return (IPTR) obj;
522 BOOPSI_DISPATCHER(IPTR, CalculatorDispatcher, cl, obj, msg)
524 switch (msg->MethodID)
526 case OM_NEW: return mNewCalc(cl, obj, (APTR) msg);
527 case OM_DISPOSE: return mDisposeCalc(cl, obj, (APTR) msg);
528 case OM_ADD_KEY: return (IPTR) mAddCalcKey(cl, obj, (struct MUIMP_CalcKey *) msg);
530 return DoSuperMethodA(cl, obj, msg);
532 BOOPSI_DISPATCHER_END
534 static Class *make_calculator_class(void)
536 Class *cl;
537 cl = MakeClass(NULL, ROOTCLASS, NULL, sizeof(struct CalculatorData), 0);
538 if (cl) cl->cl_Dispatcher.h_Entry = CalculatorDispatcher;
539 return cl;
542 /**********************************************************************
543 Main program
544 **********************************************************************/
546 static void cleanup(char *msg)
548 WORD rc;
549 if (msg)
551 fprintf(stderr, "Calculator: %s\n", msg);
552 rc = RETURN_WARN;
554 else
556 rc = RETURN_OK;
558 exit(rc);
561 static void dos_error(void)
563 static char tempstring[256];
564 Fault(IoErr(), 0, tempstring, 255);
565 cleanup(tempstring);
568 static char retrieve_decimal_point(void)
570 struct Locale *loc;
571 char result = '.';
573 if ((loc = OpenLocale(0)))
575 result = loc->loc_DecimalPoint[0];
576 CloseLocale(loc);
578 return result;
581 static void get_arguments(void)
583 struct RDArgs *rdargs;
584 IPTR args[NUM_ARGS];
585 int i;
587 for (i = 0; i < NUM_ARGS; i++) args[i] = (IPTR) NULL;
589 if (!(rdargs = ReadArgs(ARG_TEMPLATE, (IPTR *) args,0))) dos_error();
591 if (args[ARG_PUBSCREEN]) {
592 strncpy(pubscrname, (const char *) args[ARG_PUBSCREEN], 255);
595 if (args[ARG_TAPE])
597 use_tape = TRUE;
598 strncpy(tapename, (const char *) args[ARG_TAPE], 255);
600 if (rdargs) FreeArgs(rdargs);
603 static void open_raw_tape_if_needed(Object *window, Object *obj_tape)
605 if (use_tape && !strlen(tapename))
607 int x, y, w, h;
608 struct Window *win;
609 BPTR tapefh;
611 GetAttr(MUIA_Window_Window, window, (IPTR *) &win);
612 w = win->Width * 5 / 4;
613 h = win->Height;
614 x = win->LeftEdge;
615 y = win->TopEdge;
617 if (x > (win->WScreen->Width - (x + w))) x -= w;
618 else x += win->WScreen->Width;
620 snprintf(tapename, 255, RAW_TAPE_NAME, x, y, w, h, pubscrname);
621 tapefh = Open(tapename, MODE_NEWFILE);
622 SetAttrs(obj_tape, TAPEA_FILEHANDLE, tapefh);
626 int main(void)
628 Class *cl_calc = NULL, *cl_tape = NULL;
629 Object *app = NULL, *window = NULL, *display = NULL, *button[NUM_BUTTONS],
630 *obj_calc, *obj_tape;
631 char decimal_point, decimal_label[2];
632 struct Screen *pub_screen = NULL;
633 BPTR tapefh = BNULL;
634 int i;
636 get_arguments();
637 decimal_point = retrieve_decimal_point();
638 snprintf(decimal_label, 2, "%c", decimal_point);
640 display = TextObject,
641 StringFrame,
642 MUIA_Text_Contents, INITIAL_DISPLAY,
643 MUIA_ShortHelp, "Display",
644 End;
646 cl_tape = make_tape_class();
648 if (use_tape && strlen(tapename)) {
649 tapefh = Open(tapename, MODE_NEWFILE);
652 if (tapefh) {
653 obj_tape = NewObject(cl_tape, NULL, TAPEA_FILEHANDLE, tapefh, TAG_DONE);
655 else
657 obj_tape = NewObject(cl_tape, NULL, TAG_DONE);
660 cl_calc = make_calculator_class();
661 obj_calc = NewObject(cl_calc, NULL,
662 CALCA_DISPLAY, display,
663 CALCA_TAPE, obj_tape,
664 CALCA_DECIMAL_POINT, decimal_point,
665 TAG_DONE);
667 for (i = 0; i < NUM_BUTTONS; i++)
669 button[i] = (i != DECIMAL_BUTTON_INDEX) ?
670 SimpleButton(BUTTONS[i].label) : SimpleButton(decimal_label);
671 if (BUTTONS[i].shortcut)
673 SetAttrs(button[i], MUIA_ControlChar, BUTTONS[i].shortcut, TAG_DONE);
677 if (strlen(pubscrname))
679 pub_screen = LockPubScreen((CONST_STRPTR) pubscrname);
680 if (!pub_screen)
682 printf("Can't lock public screen '%s' -> fallback to Wanderer!\n", pubscrname);
683 memset(pubscrname, 0, 256);
684 strcpy(pubscrname, "Workbench");
685 pub_screen = LockPubScreen((CONST_STRPTR) pubscrname);
689 app = ApplicationObject,
690 MUIA_Application_Title, "Calculator",
691 MUIA_Application_Version, "1.4",
692 MUIA_Application_Copyright, "©2007-2013, AROS Dev Team",
693 MUIA_Application_Author, "AROS Team",
694 MUIA_Application_Description, "Simple desktop calculator",
695 MUIA_Application_Base, "calculator",
696 SubWindow, window = WindowObject,
697 MUIA_Window_Title, "Calculator",
698 MUIA_Window_ID, MAKE_ID('C', 'A', 'L', 'C'),
699 MUIA_Window_AppWindow, TRUE,
700 MUIA_Window_Screen, pub_screen,
701 WindowContents, VGroup,
702 Child, display,
704 Child, HGroup, GroupSpacing(5), MUIA_Group_SameWidth, TRUE,
705 Child, button[0],
706 Child, button[1],
707 Child, button[2],
708 Child, button[3],
709 Child, button[4],
710 End,
712 Child, HGroup, GroupSpacing(5), MUIA_Group_SameWidth, TRUE,
713 Child, button[5],
714 Child, button[6],
715 Child, button[7],
716 Child, button[8],
717 Child, button[9],
718 End,
720 Child, HGroup, GroupSpacing(5), MUIA_Group_SameWidth, TRUE,
721 Child, button[10],
722 Child, button[11],
723 Child, button[12],
724 Child, button[13],
725 Child, button[14],
726 End,
728 Child, HGroup, GroupSpacing(5), MUIA_Group_SameWidth, TRUE,
729 Child, button[15],
730 Child, button[16],
731 Child, button[17],
732 Child, button[18],
733 Child, button[19],
734 End,
736 End,
737 End,
738 End;
740 DoMethod(window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
741 app, 2, MUIM_Application_ReturnID,
742 MUIV_Application_ReturnID_Quit);
744 for (i = 0; i < NUM_BUTTONS; i++)
746 DoMethod(button[i], MUIM_Notify, MUIA_Pressed, FALSE,
747 obj_calc, 2, OM_ADD_KEY, BUTTONS[i].btype);
750 SetAttrs(window, MUIA_Window_Open, TRUE, TAG_DONE);
751 open_raw_tape_if_needed(window, obj_tape);
753 if (pub_screen) UnlockPubScreen(0, pub_screen);
755 BOOL running = TRUE;
756 ULONG sigs = 0, id;
758 while (running) {
759 id = DoMethod(app, MUIM_Application_NewInput, (IPTR) &sigs);
761 switch(id)
763 case MUIV_Application_ReturnID_Quit:
764 running = FALSE;
765 break;
766 default:
767 break;
769 if (running && sigs)
771 sigs = Wait(sigs | SIGBREAKF_CTRL_C);
772 if (sigs & SIGBREAKF_CTRL_C) break;
776 set((APTR) window, MUIA_Window_Open, FALSE);
777 MUI_DisposeObject(app);
779 DisposeObject(obj_calc);
780 DisposeObject(obj_tape);
781 FreeClass(cl_calc);
782 FreeClass(cl_tape);
784 cleanup(NULL);
785 return 0;