home *** CD-ROM | disk | FTP | other *** search
- /*-> c.io */
-
- /* Modifications for ANSI C under RISC-OS:
- *
- * Date Modification
- * 13-may-90 types header
- * 14-may-90 replace iabs() by abs()
- * 14-may-90 movmem() replaced by memmove()
- * 6-jun-90 rehash of ReadKey() to make it event driven
- * 8-jun-90 modified GetKey() to do nothing
- *
- * compiler complains about non-use of x in NbStr(); cured by dummy assignment
- */
-
- #include "stdlib.h"
- #include "stdio.h"
- #include <math.h>
- #include "string.h"
-
- #include "wimp.h"
- #include "dbox.h"
- #include "menu.h"
-
- #include "types.h"
- #include "hp11.h"
- #include "arc_hp11.h"
- #include "ami_amiga.h"
- #include "ins.h"
- #include "io.h"
- #include "kbd.h"
- #include "codes.h"
- #include "prog_codes.h"
-
- #define MAXRUN 4 /* Length of time running is displayed */
-
- #define FOREVER for (;;)
-
- static char *stpich(char *p, int c) /* insert character c at front of string p
- */
- {
- memmove(p + 1, p, strlen(p) + 1);
- *p = c;
-
- return(p);
- }
-
- int GetKey() /* Read a key & wait for its release */
- {
- /* int key; now global */
-
- return(key);
- }
-
- enum KeyTypes ReadKey(code) /* Read a complete key sequence, & return
- its type, instruction or action. */
- register int *code;
- {
- static struct Key *curtkey;
- static int offset;
- static BOOL noKey; /* if an invalid sequence is returned, don't read a new
- key, reuse the one which caused the error. This is
- set to false when that happens */
- register enum KeyTypes ret;
-
- noKey = TRUE; /* no key read */
- do {
- switch (keyflag) {
- case MidSeq: /* we were in the middle of reading a sequence,
- in another function, so go back there */
- if (ret = (*(curtkey->Suffix))(code), ret == Null) return(Null);
- /* each function returns Null if unfinished */
- keyflag = NewSeq; /* set scene for fresh call to ReadKey() */
- if (ret != Invalid) return(ret); /* if successful */
- key = *code; /* else, invalid keycode was returned in code
- field for reuse */
- noKey = FALSE; /* a key is already available */
-
- case NewSeq: /* this is a fresh entry to ReadKey() */
- Rdoffset = 0; /* reset for REGdec */
- offset = 0; /* f or g not pressed */
- case PreFix: /* now find the prefixed key */
- /* This loop reads a key from the main, f or g shifted
- keyboards. Further refinements (eg sto) are done
- algorithmically, to save space */
- Dispf(FALSE); Dispg(FALSE); /* are these needed ? */
- noKey = TRUE;
- if (key == 31) { /* f pressed, toggle its status */
- keyflag = PreFix;
- offset = (offset == NUMKEYS) ? 0 : (Dispf(TRUE), NUMKEYS);
- RelKey();
- return(Null); /* have handled key so return */
- }
- else if (key == 32) { /* g */
- keyflag = PreFix;
- offset = (offset == NUMKEYS + NUMKEYS) ? 0 : (Dispg(TRUE),
- NUMKEYS + NUMKEYS);
- RelKey();
- return(Null); /* have handled key so return */
- }
- if (User && key < 5) offset ^= NUMKEYS; /* Toggle f for first
- five keys. This doesn't
- affect g because the bit
- patterns are exclusive
- (42 & 84 = 0) */
- Dispf(FALSE); Dispg(FALSE);
- curtkey = mainKbd + offset + key; /* find address of (eventually
- shifted) key */
- switch (curtkey->Sort) {
- case Action:
- *code = curtkey->Act;
- keyflag = NewSeq;
- return(Action);
- case Instruction:
- *code = curtkey->Code;
- keyflag = NewSeq;
- return(Instruction);
- case Prefix: /* Key is prefix, execute corresponding routine */
- RelKey();
- keyflag = MidSeq;
- return(Null); /* need another key to continue */
- case Invalid: /* An inavlid f or g sequence was entered,
- retry it with the f or g prefix stripped.
- Therefore all obtainable main keyboard
- sequences must exist, otherwise the
- program enters an infinite loop retrying
- constantly the same nonexistent keycode */
- key %= NUMKEYS;
- noKey = FALSE;
- break;
- }
- }
- } while (!noKey);
- }
-
- /* Return position n on the liquid cristal display in string t */
- int scrpos(t, n)
- char *t;
- register int n;
- {
- register char *s = t;
- register int pos;
-
- pos = 0;
- while (pos <= n && *s) { /* go on till end of string or beyond position n on
- display */
- if (*s != '.' && *s != ',') pos++; /* . & , take no space on the display
- */
- s++;
- }
- return((int)((s - t) - 1 - (pos - n))); /* pos - n is there to take care of
- the overshoot. If n is beyond the end of the string, the position returned may well be wildly beyond the actual end of the string */
- }
-
- /* Return the length taken up on the screen by the string */
- int scrlen(s)
- register char *s;
- {
- register int cnt = 0;
-
- while (*s) {
- if (*s != '.' && *s != ',') cnt++; /* . & , take no space on the display
- */
- s++;
- }
-
- return(cnt);
- }
-
- /* format string s in hp11 display format (without exponent) so that it takes
- n spaces in the display. s isn't modified */
- static char *CvtStd(char *s, int n)
- {
- static char buf[20];
- register char *p;
- register int i, nb;
- register int digit_separator = comma ? '.' : ','; /* separator according to
- current setting */
-
- strcpy(buf, s); /* copy string to safe work buffer */
-
- if ((p = strchr(buf, '.')) == NULL) { /* find position of . */
- p = buf + strlen(buf);
- if (!entering) *p = comma ? ',' : '.';
- *(p + 1) = '\0';
- }
- else if (comma) *p = ','; /* Replace . by , if necessary */
-
- while ((p -= 3) - buf > 1) /* Add , (or .) to string every 3 digits */
- stpich(p, digit_separator);
-
- nb = n - scrlen(buf);
- for (i = 1; i <= nb; i++) strcat(buf, " "); /* pad with spaces to required
- screen length */
- buf[scrpos(buf, n) + 1] = '\0'; /* cut at n characters */
-
- return(buf);
- }
-
- /* format string s in hp11 display format (with exponent) */
- static char *CvtExpo(char *s, char *e)
- {
- if (strlen(e) > 3) { /* deal with roundoff towards 1e100 when nb too big */
- e = " 99"; /* exponent is 99 */
- strncpy(s + 1, "9.999999999", strlen(s + 1)); /* mantissa is enough 9's
- */
- }
-
- return(strcat(CvtStd(s, 8), e));
- }
-
- /* convert x to scientific format with n digits. Returns it in a static buffer
- (from CvtStd) */
- static char *Scient(double x, int n)
- {
- char buf[20];
- register char *pe;
-
- sprintf(buf, "% .*E", n, x); /* Scientific format with n digits */
- pe = strchr(buf, 'E'); /* split string into mantissa & exponent */
- *pe++ = '\0';
- /* if (*pe == '+') *pe = ' '; A + is displayed as a space by the Display
- routine anyway */
-
- return(CvtExpo(buf, pe));
- }
-
- /* Convert x to fix n format */
- static char *Fixed(double x, int n)
- {
- char buf[80];
-
- sprintf(buf, "% .*f", n, x);
-
- return(CvtStd(buf, 11));
- }
-
- /* Eng n format */
- static char *Engin(double x, int n)
- {
- char expbuf[10], buf[80];
- register char *pe;
- double mantissa;
- register int exponent, dif;
-
- sprintf(buf, "%.*E", n, x); /* print enough digits */
- *(pe = strchr(buf, 'E')) = '\0';
- mantissa = atof(buf); /* get mantissa & exponent */
- exponent = atoi(pe + 1);
-
- /* Round exponent down to a multiple of 3 */
- dif = exponent % 3;
- if (dif < 0) dif += 3;
- exponent -= dif; /* calculate new exponent & mantissa */
- mantissa *= pow(10.0, (double)dif);
-
- /* Convert them to string */
- sprintf(buf, "% .*f", (n - dif > 0) ? n - dif : 0, mantissa);
- sprintf(expbuf, "%c%02d", (exponent < 0) ? '-' : ' ', abs(exponent)); /*
- pad exponent with 0's, hence %02d not %2d */
-
- return(CvtExpo(buf, expbuf));
- }
-
- /* Display current trig mode */
- static void DispAngle(void)
- {
- switch (Angles) {
- case grad: DispG(TRUE); DispRAD(TRUE); break;
- case rad: DispG(FALSE); DispRAD(TRUE); break;
- case deg: DispG(FALSE); DispRAD(FALSE); break;
- }
- }
-
- /* Display current x value in normal mode, running in run mode */
- void Disp()
- {
- static int runcnt = MAXRUN;
- static BOOL runon;
-
- if(hp11_show_stack) { /* this is first to avoid corrupting Display() arg */
- if (!entering) dbox_setfield(hp11_stack_dbox_handle,HP11_X_REG,NbStr(X));
- dbox_setfield(hp11_stack_dbox_handle, HP11_Y_REG, NbStr(Y));
- dbox_setfield(hp11_stack_dbox_handle, HP11_Z_REG, NbStr(Z));
- dbox_setfield(hp11_stack_dbox_handle, HP11_T_REG, NbStr(T));
- }
- if (running) { /* Flash running on and off every MAXRUN calls */
- if (fast) { /* Display Running only once in fast mode */
- if (!runon) {
- Display(" Running");
- runon = TRUE; /* Running displayed */
- }
- }
- else if (runcnt-- == 0) Display("");
- else if (runcnt <= -MAXRUN) {
- runcnt = MAXRUN;
- Display(" Running");
- }
- }
- else {
- runon = FALSE; /* Running not displayed */
- if (entering) /* Display number entry strings */
- if (expo) Display(CvtExpo(strx, expx)); /* with exponent */
- else Display(CvtStd(strx, 11));
- else
- Display(NbStr(X));
-
- DispAngle();
- if (User) DispUSER(TRUE);
- else DispUSER(FALSE);
- }
- }
-
- char *NbStr(x)
- double x;
- {
- switch (Mode) { /* Display x according to display mode */
- case fix:if ((fabs(x) >= minfix / 2.0 || x == 0.0) && fabs(x) < 1E10) {
- /* Number can be displayed in fix mode */
- return(Fixed(x, Digits));
- }
- /* fall through for call to Scient */
- case sci:return(Scient(x, Digits));
- case eng:return(Engin(x, Digits));
- }
- }
-
- /* Display Error n, & wait for a key to be pressed */
- void Error(n)
- int n;
- {
- register char *buf;
-
- entering = FALSE; /* end of digit entry */
- error = TRUE; /* an error has occured */
- buf = " Error ";
- buf[8] = n; buf[9] ='\0';
-
- if (!running) RelKey();
- Display(buf);
- GetKey();
- }
-
- /* Display current program line */
- void DisplayLine()
- {
- register int c1 = keycodes[Prog[PC]].c1, c2 = keycodes[Prog[PC]].c2,
- c3 = keycodes[Prog[PC]].c3;
- static char _buf[20], _insbuf[20];
- register char *buf = _buf, *insbuf = _insbuf;
- register int point = comma ? ',' : '.'; /* separator according to current
- setting */
- sprintf(buf, " %03d-", PC); /* prepare program line */
-
- /* Prepare instruction buffer */
- if (PC == 0) insbuf[0] = '\0'; /* nothing at line 0 */
- else switch (keycodes[Prog[PC]].Type) { /* there are 6 methods for
- displaying a line */
- case ONECODE: sprintf(insbuf, "%6d", c1); break; /* nn eg SIN or 9 */
- case TWOCODE: sprintf(insbuf, "%3d%3d", c1, c2); break; /* nn nn eg g
- LOG */
- case TWOCODE_9: sprintf(insbuf, "%4d%2d", c1, c2); break; /* nn n eg STO
- 5*/
- case TWOCODE_PT: sprintf(insbuf, "%4d %c%1d", c1, point, c2); break; /*
- nn .n eg RCL .6 */
- case THREECODE: sprintf(insbuf, "%2d,%2d,%2d", c1, c2, c3); break; /*
- nn,nn,nn eg f HYP SIN */
- case THREECODE_PT: sprintf(insbuf, "%2d,%2d, %c%1d", c1, c2, point, c3);
- break; /* nn,nn, .n eg STO + .0 */
- }
-
- Display(strcat(buf, insbuf));
-
- DispAngle();
- if (User) DispUSER(TRUE);
- else DispUSER(FALSE);
- }
-
-