home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Vectronix 2
/
VECTRONIX2.iso
/
FILES_07
/
ACS.ZIP
/
ACS
/
RECHNER
/
RECHNER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-28
|
9KB
|
416 lines
/*
Beispielapplikation für ACS
"Taschenrechner"
23.9.91 Stefan Bachert
*/
#include <string.h>
#include <stdio.h>
#include <acs.h>
#include <rechner.h>
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 <rechner.ah>
/*
* 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)
/*
* Führe 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] == '/') { /* ausführen */
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 zurück
*/
{
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 durchgeführt */
}
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;
}