home *** CD-ROM | disk | FTP | other *** search
/ Vectronix 2 / VECTRONIX2.iso / FILES_07 / ACS.ZIP / ACS / RECHNER / RECHNER.C < prev    next >
C/C++ Source or Header  |  1992-01-28  |  9KB  |  416 lines

  1. /*
  2.     Beispielapplikation    für ACS
  3.  
  4.     "Taschenrechner"
  5.  
  6.     23.9.91            Stefan Bachert
  7.  
  8. */
  9.  
  10. #include    <string.h>
  11. #include    <stdio.h>
  12. #include    <acs.h>
  13. #include    <rechner.h>
  14.  
  15. static void calc_0        (void);
  16. static void calc_1        (void);
  17. static void calc_2        (void);
  18. static void calc_3        (void);
  19. static void calc_4        (void);
  20. static void calc_5        (void);
  21. static void calc_6        (void);
  22. static void calc_7        (void);
  23. static void calc_8        (void);
  24. static void calc_9        (void);
  25. static void calc_ac        (void);
  26. static void calc_back    (void);
  27. static void calc_div    (void);
  28. static void calc_mul    (void);
  29. static void calc_plus    (void);
  30. static void calc_minus    (void);
  31. static void calc_is        (void);
  32. static void calc_sign    (void);
  33. static void calc_accept    (void);
  34. static void calc_dot    (void);
  35. static Awindow *calc_make    (void *x);
  36. static int calc_service    (Awindow *window, int task, void *in_out);
  37.  
  38. #define CALC_VALUE        (10001)
  39.  
  40. #include    <rechner.ah>
  41.  
  42. /*
  43.  *    User Struktur
  44.  */
  45.  
  46. #define DISPLAY_SIZE (14)
  47.  
  48. typedef struct {
  49.     double    val [2];
  50.     char    op [2];
  51.     char    display [DISPLAY_SIZE + 2];
  52.     } CALC;
  53.  
  54.  
  55. static void update (Awindow *window)
  56.     /*
  57.      *    Frischt das Display auf
  58.      */
  59. {
  60.   CALC *user;
  61.  
  62.   user = window-> user;
  63.   strcpy (window-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext, user-> display);
  64.   if (user-> display [DISPLAY_SIZE - 1] == ' ')
  65.     window-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext [DISPLAY_SIZE - 1] = '0'; 
  66.   (window-> obchange) (window, CALC_DISPLAY, window-> work [CALC_DISPLAY]. ob_state);
  67. }
  68.  
  69.  
  70. static void new_digit (char digit)
  71.     /*
  72.      *    Übertrage das Digit in das Display
  73.      */
  74. {
  75.   CALC *user;
  76.   char *p;
  77.  
  78.   user = ev_window-> user;
  79.  
  80.   if (user-> op [0] == 'E') return; /* Fehler passiert */
  81.   if (user-> display [1] != ' ') return;    /* display voll */
  82.  
  83.   p = user-> display;
  84.  
  85.   while (*p == ' ') p ++;
  86.   if (*p != '0') {            /* nullen nicht schieben */
  87.     strcpy (user-> display, user-> display + 1);
  88.   };
  89.   user-> display [DISPLAY_SIZE - 1] = digit;  
  90.   update (ev_window);
  91. }
  92.  
  93.  
  94. static void calc_0        (void)    { new_digit ('0'); };
  95. static void calc_1        (void)    { new_digit ('1'); };
  96. static void calc_2        (void)    { new_digit ('2'); };
  97. static void calc_3        (void)    { new_digit ('3'); };
  98. static void calc_4        (void)    { new_digit ('4'); };
  99. static void calc_5        (void)    { new_digit ('5'); };
  100. static void calc_6        (void)    { new_digit ('6'); };
  101. static void calc_7        (void)    { new_digit ('7'); };
  102. static void calc_8        (void)    { new_digit ('8'); };
  103. static void calc_9        (void)    { new_digit ('9'); };
  104. static void calc_dot    (void)
  105. {
  106.   CALC *user;
  107.  
  108.   user = ev_window-> user;
  109.   if (strchr (user-> display, '.') != NULL) return;    /* nur ein . */
  110.   new_digit ('.');
  111. }
  112.  
  113.  
  114. static void cleardisp (Awindow *window)
  115.     /*
  116.      *    Lösche nur display
  117.      */
  118. {
  119.   CALC *user;
  120.  
  121.   user = window-> user;
  122.   strncpy (user-> display, "                         ", DISPLAY_SIZE);
  123.   user-> display [DISPLAY_SIZE] = '\0';
  124. }
  125.  
  126.  
  127. static void clear (Awindow *window)
  128.     /*
  129.      *    Lösche alles
  130.      */
  131. {
  132.   CALC *user;
  133.   int i;
  134.  
  135.   cleardisp (window);
  136.   user = window-> user;
  137.   for (i = 0; i < sizeof (user-> op); i ++) {
  138.     user-> val [i] = 0.0;
  139.     user-> op [i] = '=';
  140.   };
  141. }
  142.  
  143.  
  144. static double oper (Awindow *window, double v2)
  145.     /*
  146.      *    Führe operation durch
  147.      */
  148. {
  149.   CALC *user;
  150.   double v1;
  151.   char op;
  152.   int i;
  153.  
  154.   user = window-> user;
  155.  
  156.   v1 = user-> val [0];
  157.   op = user-> op [0];
  158.  
  159.   for (i = 0; i < sizeof (user-> op) - 1; i ++) {    /* stack korrektur */
  160.     user-> val [i] = user-> val [i + 1];
  161.     user-> op  [i] = user-> op  [i + 1];
  162.   };
  163.   user-> op [sizeof (user-> op) - 1] = '=';
  164.  
  165.   switch (op) {
  166.   case '+':    return v1 + v2;
  167.   case '-':    return v1 - v2;
  168.   case '*':    return v1 * v2;
  169.   case '/':    if (v2 != 0.0) return v1 / v2;
  170.   };
  171.   strcpy (window-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext, ERR_DIV0);
  172.   (window-> obchange) (window, CALC_DISPLAY, window-> work [CALC_DISPLAY]. ob_state);
  173.   user-> op [0] = 'E';
  174.   return 0.0;
  175. }
  176.  
  177.  
  178. static void doit (char op)
  179.     /*
  180.      *    bearbeitet die operationen
  181.      */
  182. {
  183.   double new;
  184.   char string [40];
  185.   CALC *user;
  186.   int i;
  187.   Awindow *window;
  188.  
  189.   window = ev_window;
  190.   user = window-> user;
  191.   if (user-> op [0] == 'E') return; /* Fehler passiert */
  192.   if (user-> display [DISPLAY_SIZE - 1] == ' ') {
  193.     switch (user-> op [0]) {    /* kein neues Display */
  194.       case '*': case '/':
  195.         if (op == '*' || op == '/') {
  196.           user-> op [0] = op;
  197.           return;
  198.         };
  199.         new = 1.0; break;
  200.       case '+': case '-':        /* neutrales Element */
  201.         if (op == '+' || op == '-') {
  202.           user-> op [0] = op;
  203.           return;
  204.         };
  205.         new = 0.0; break;        /* neutrales Element */
  206.       case '=':
  207.         if (op == '=') return;            /* sinnlos */
  208.         new = user-> val [0];            /* letzter wert */
  209.     };
  210.   } else {
  211.     if (user-> display [0] == ' ') {
  212.       sscanf (user-> display, " %lf", &new);
  213.     } else {
  214.       sscanf (user-> display, "%lf", &new);
  215.     };
  216.   };
  217.  
  218.   while (TRUE) {
  219.     if (op == '+' || op == '-' || op == '=') {
  220.       if (user-> op [0] == '=') {
  221.         break;
  222.       } else {
  223.         new = oper (window, new);
  224.         if (user-> op [0] == 'E') return; /* Fehler */
  225.       };
  226.     } else if (op == '*' || op == '/') {
  227.       if (user-> op [0] == '*' || user-> op [0] == '/') {    /* ausführen */
  228.         new = oper (window, new);
  229.         if (user-> op [0] == 'E') return; /* Fehler */
  230.       } else {    /* +, -, =  zuvor also stapeln */
  231.         for (i = ((int) sizeof (user-> op)) - 1; i > 0; i --) {
  232.           user-> val [i] = user-> val [i - 1];
  233.           user-> op  [i] = user-> op  [i - 1];
  234.         };
  235.         break;
  236.       };
  237.     } else {        /* gibt (noch) nicht */
  238.       break;
  239.     };
  240.   };
  241.   user-> val [0] = new;
  242.   user-> op [0] = op;
  243.   sprintf (string, " %12f", new);
  244.   strncpy (user-> display, string, DISPLAY_SIZE);
  245.   user-> display [DISPLAY_SIZE] = '\0';
  246.   update (window);
  247.   cleardisp (window);
  248. }
  249.  
  250.  
  251. static void calc_ac        (void)
  252.     /*
  253.      *    Lösche
  254.      */
  255. {
  256.   clear (ev_window);
  257.   update (ev_window);
  258. }
  259.  
  260.  
  261. static void calc_back    (void)
  262.     /*
  263.      *    Schritt zurück
  264.      */
  265. {
  266.   CALC *user;
  267.   char temp [32];
  268.  
  269.   user = ev_window-> user;
  270.  
  271.   if (user-> display [DISPLAY_SIZE - 1] == ' ') return;    /* display leer */
  272.  
  273.   strcpy (temp, user-> display);
  274.   strcpy (user-> display + 1, temp);
  275.   user-> display [0] = ' ';
  276.   user-> display [DISPLAY_SIZE] = '\0';
  277.   update (ev_window);
  278. }
  279.  
  280. static void calc_sign    (void)
  281.     /*
  282.      *    Vorzeichen wechsel
  283.      */
  284. {
  285.   CALC *user;
  286.   char *p;
  287.   Awindow *window;
  288.  
  289.   window = ev_window;
  290.   user = window-> user;
  291.   if (user-> op [0] == 'E') return; /* Fehler passiert */
  292.   if (user-> display [DISPLAY_SIZE - 1] == ' ') {    /* leeres Display */
  293.     strcpy (user-> display, window-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext);
  294.   };
  295.   p = user-> display;
  296.   while (*p == ' ') p ++;
  297.   if (*p == '0') return;            /* 0 im display */
  298.   if (*p == '-') {                    /* ist negativ */
  299.     *p = ' ';                        /* kein Vorzeichen */
  300.   } else {                            /* wird negativ */
  301.     *(p - 1) = '-';
  302.   };
  303.   update (window);
  304. }
  305.  
  306.  
  307. static void calc_div    (void)    { doit ('/'); };
  308. static void calc_mul    (void)    { doit ('*'); };
  309. static void calc_plus    (void)    { doit ('+'); };
  310. static void calc_minus    (void)    { doit ('-'); };
  311. static void calc_is        (void)    { doit ('='); };
  312.  
  313.  
  314. static void calc_accept    (void)
  315.     /*
  316.      *    Übernehme gezogene Werte
  317.      */
  318. {
  319.   Awindow *wi;
  320.   AOBJECT *aob;
  321.   CALC *user;
  322.   int nr;
  323.  
  324.   wi = Aselect. window;
  325.  
  326.   if (wi == ev_window) return;     /* vom eigene Fenster -> unfug */
  327.  
  328.   Aselect. next = 0;
  329.   nr = Adr_next ();
  330.   if (nr >= 0) {                /* Es muss eigentlich immer was da sein */
  331.     aob = (AOBJECT *) wi-> work + nr + 1;
  332.     if (aob-> type == CALC_VALUE) {        /* ist von einem Rechner */
  333.       Adr_del (wi, nr);                    /* entferne aus liste */
  334.       user = ev_window-> user;
  335.       strcpy (user-> display, aob-> userp1);    /* übernehme Wert */
  336.       update (ev_window);
  337.     };
  338.   };
  339. }
  340.  
  341.  
  342. static Awindow *calc_make    (void *x)
  343.     /*
  344.      *    Erzeuge Fenster
  345.      */
  346. {
  347.   Awindow *wi;
  348.   CALC *user;
  349.  
  350.   user = Ax_malloc (sizeof (CALC));        /* benutzerobjekt */
  351.   if (user == NULL) return NULL;
  352.  
  353.   wi = Awi_create (&RECHNER);            /* erzeuge */
  354.   if (wi == NULL) return NULL;
  355.  
  356.   wi-> user = user;
  357.  
  358.   ((AOBJECT *) wi-> work + CALC_DISPLAY + 1)-> userp1 =
  359.         wi-> work [CALC_DISPLAY]. ob_spec. tedinfo-> te_ptext;    /* Trage wert ein */
  360.  
  361.   clear (wi);
  362.   update (wi);
  363.  
  364.   if (application) {
  365.     (wi-> open) (wi);                    /* öffne gleich */
  366.   };
  367.   return wi;
  368. }
  369.  
  370.  
  371. static void term (Awindow *window)
  372.     /*
  373.      *    Gebe alles wieder frei
  374.      */
  375. {
  376.   Ax_free (window-> user);
  377.   Awi_delete (window);
  378. }
  379.  
  380.  
  381. static int calc_service    (Awindow *window, int task, void *in_out)
  382.     /*
  383.      *    Service routine
  384.      */
  385. {
  386.   switch (task)    {                /* welche Routine */
  387.     case AS_TERM:
  388.       term (window);
  389.       break;
  390.     case AS_DELETE:                /* auf papierkorb gezogen */
  391.       Adr_unselect ();            /* deselectieren */
  392.       clear (window);            /* wie AC */
  393.       update (window);
  394.       break;      
  395.     default:
  396.       return FALSE;                /* kein Wert */
  397.   };
  398.   return TRUE;                    /* wurde durchgeführt */
  399. }
  400.  
  401.  
  402. int ACSinit (void)
  403.     /*
  404.      *    Doppelklick auf NEU erzeugt einen neuen Rechner
  405.      */
  406. {
  407.   Awindow *window;
  408.  
  409.   if (application) {
  410.     window = Awi_root ();                        /* root window */
  411.     if (window == NULL) return FAIL;            /* lege NEU Icon an */
  412.     (window-> service) (window, AS_NEWCALL, &RECHNER. create);
  413.   };
  414.   return OK;
  415. }
  416.