/* Beispielapplikation fr ACS "Taschenrechner" 23.9.91 Stefan Bachert */ #include #include #include #include static void calc_0 (void); static void calc_1 (void); static void calc_2 (void); static void calc_3 (void); static void calc_4 (void); static void calc_5 (void); static void calc_6 (void); static void calc_7 (void); static void calc_8 (void); static void calc_9 (void); static void calc_ac (void); static void calc_back (void); static void calc_div (void); static void calc_mul (void); static void calc_plus (void); static void calc_minus (void); static void calc_is (void); static void calc_sign (void); static void calc_accept (void); static void calc_dot (void); static Awindow *calc_make (void *x); static int calc_service (Awindow *window, int task, void *in_out); #define CALC_VALUE (10001) #include /* * User Struktur */ #define DISPLAY_SIZE (14) typedef struct { double val [2]; char op [2]; char display [DISPLAY_SIZE + 2]; } CALC; static void update (Awindow *window) /* * Frischt das Display auf */ { CALC *user; user = window-> user; strcpy (window-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext, user-> display); if (user-> display [DISPLAY_SIZE - 1] == ' ') window-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext [DISPLAY_SIZE - 1] = '0'; (window-> obchange) (window, CALC_DISPLAY, window-> work [CALC_DISPLAY]. ob_state); } static void new_digit (char digit) /* * šbertrage das Digit in das Display */ { CALC *user; char *p; user = ev_window-> user; if (user-> op [0] == 'E') return; /* Fehler passiert */ if (user-> display [1] != ' ') return; /* display voll */ p = user-> display; while (*p == ' ') p ++; if (*p != '0') { /* nullen nicht schieben */ strcpy (user-> display, user-> display + 1); }; user-> display [DISPLAY_SIZE - 1] = digit; update (ev_window); } static void calc_0 (void) { new_digit ('0'); }; static void calc_1 (void) { new_digit ('1'); }; static void calc_2 (void) { new_digit ('2'); }; static void calc_3 (void) { new_digit ('3'); }; static void calc_4 (void) { new_digit ('4'); }; static void calc_5 (void) { new_digit ('5'); }; static void calc_6 (void) { new_digit ('6'); }; static void calc_7 (void) { new_digit ('7'); }; static void calc_8 (void) { new_digit ('8'); }; static void calc_9 (void) { new_digit ('9'); }; static void calc_dot (void) { CALC *user; user = ev_window-> user; if (strchr (user-> display, '.') != NULL) return; /* nur ein . */ new_digit ('.'); } static void cleardisp (Awindow *window) /* * L”sche nur display */ { CALC *user; user = window-> user; strncpy (user-> display, " ", DISPLAY_SIZE); user-> display [DISPLAY_SIZE] = '\0'; } static void clear (Awindow *window) /* * L”sche alles */ { CALC *user; int i; cleardisp (window); user = window-> user; for (i = 0; i < sizeof (user-> op); i ++) { user-> val [i] = 0.0; user-> op [i] = '='; }; } static double oper (Awindow *window, double v2) /* * Fhre operation durch */ { CALC *user; double v1; char op; int i; user = window-> user; v1 = user-> val [0]; op = user-> op [0]; for (i = 0; i < sizeof (user-> op) - 1; i ++) { /* stack korrektur */ user-> val [i] = user-> val [i + 1]; user-> op [i] = user-> op [i + 1]; }; user-> op [sizeof (user-> op) - 1] = '='; switch (op) { case '+': return v1 + v2; case '-': return v1 - v2; case '*': return v1 * v2; case '/': if (v2 != 0.0) return v1 / v2; }; strcpy (window-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext, ERR_DIV0); (window-> obchange) (window, CALC_DISPLAY, window-> work [CALC_DISPLAY]. ob_state); user-> op [0] = 'E'; return 0.0; } static void doit (char op) /* * bearbeitet die operationen */ { double new; char string [40]; CALC *user; int i; Awindow *window; window = ev_window; user = window-> user; if (user-> op [0] == 'E') return; /* Fehler passiert */ if (user-> display [DISPLAY_SIZE - 1] == ' ') { switch (user-> op [0]) { /* kein neues Display */ case '*': case '/': if (op == '*' || op == '/') { user-> op [0] = op; return; }; new = 1.0; break; case '+': case '-': /* neutrales Element */ if (op == '+' || op == '-') { user-> op [0] = op; return; }; new = 0.0; break; /* neutrales Element */ case '=': if (op == '=') return; /* sinnlos */ new = user-> val [0]; /* letzter wert */ }; } else { if (user-> display [0] == ' ') { sscanf (user-> display, " %lf", &new); } else { sscanf (user-> display, "%lf", &new); }; }; while (TRUE) { if (op == '+' || op == '-' || op == '=') { if (user-> op [0] == '=') { break; } else { new = oper (window, new); if (user-> op [0] == 'E') return; /* Fehler */ }; } else if (op == '*' || op == '/') { if (user-> op [0] == '*' || user-> op [0] == '/') { /* ausfhren */ new = oper (window, new); if (user-> op [0] == 'E') return; /* Fehler */ } else { /* +, -, = zuvor also stapeln */ for (i = ((int) sizeof (user-> op)) - 1; i > 0; i --) { user-> val [i] = user-> val [i - 1]; user-> op [i] = user-> op [i - 1]; }; break; }; } else { /* gibt (noch) nicht */ break; }; }; user-> val [0] = new; user-> op [0] = op; sprintf (string, " %12f", new); strncpy (user-> display, string, DISPLAY_SIZE); user-> display [DISPLAY_SIZE] = '\0'; update (window); cleardisp (window); } static void calc_ac (void) /* * L”sche */ { clear (ev_window); update (ev_window); } static void calc_back (void) /* * Schritt zurck */ { CALC *user; char temp [32]; user = ev_window-> user; if (user-> display [DISPLAY_SIZE - 1] == ' ') return; /* display leer */ strcpy (temp, user-> display); strcpy (user-> display + 1, temp); user-> display [0] = ' '; user-> display [DISPLAY_SIZE] = '\0'; update (ev_window); } static void calc_sign (void) /* * Vorzeichen wechsel */ { CALC *user; char *p; Awindow *window; window = ev_window; user = window-> user; if (user-> op [0] == 'E') return; /* Fehler passiert */ if (user-> display [DISPLAY_SIZE - 1] == ' ') { /* leeres Display */ strcpy (user-> display, window-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext); }; p = user-> display; while (*p == ' ') p ++; if (*p == '0') return; /* 0 im display */ if (*p == '-') { /* ist negativ */ *p = ' '; /* kein Vorzeichen */ } else { /* wird negativ */ *(p - 1) = '-'; }; update (window); } static void calc_div (void) { doit ('/'); }; static void calc_mul (void) { doit ('*'); }; static void calc_plus (void) { doit ('+'); }; static void calc_minus (void) { doit ('-'); }; static void calc_is (void) { doit ('='); }; static void calc_accept (void) /* * šbernehme gezogene Werte */ { Awindow *wi; AOBJECT *aob; CALC *user; int nr; wi = Aselect. window; if (wi == ev_window) return; /* vom eigene Fenster -> unfug */ Aselect. next = 0; nr = Adr_next (); if (nr >= 0) { /* Es muss eigentlich immer was da sein */ aob = (AOBJECT *) wi-> work + nr + 1; if (aob-> type == CALC_VALUE) { /* ist von einem Rechner */ Adr_del (wi, nr); /* entferne aus liste */ user = ev_window-> user; strcpy (user-> display, aob-> userp1); /* bernehme Wert */ update (ev_window); }; }; } static Awindow *calc_make (void *x) /* * Erzeuge Fenster */ { Awindow *wi; CALC *user; user = Ax_malloc (sizeof (CALC)); /* benutzerobjekt */ if (user == NULL) return NULL; wi = Awi_create (&RECHNER); /* erzeuge */ if (wi == NULL) return NULL; wi-> user = user; ((AOBJECT *) wi-> work + CALC_DISPLAY + 1)-> userp1 = wi-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext; /* Trage wert ein */ clear (wi); update (wi); if (application) { (wi-> open) (wi); /* ”ffne gleich */ }; return wi; } static void term (Awindow *window) /* * Gebe alles wieder frei */ { Ax_free (window-> user); Awi_delete (window); } static int calc_service (Awindow *window, int task, void *in_out) /* * Service routine */ { switch (task) { /* welche Routine */ case AS_TERM: term (window); break; case AS_DELETE: /* auf papierkorb gezogen */ Adr_unselect (); /* deselectieren */ clear (window); /* wie AC */ update (window); break; default: return FALSE; /* kein Wert */ }; return TRUE; /* wurde durchgefhrt */ } int ACSinit (void) /* * Doppelklick auf NEU erzeugt einen neuen Rechner */ { Awindow *window; if (application) { window = Awi_root (); /* root window */ if (window == NULL) return FAIL; /* lege NEU Icon an */ (window-> service) (window, AS_NEWCALL, &RECHNER. create); }; return OK; }