#include "exec/types.h" #include "stdlib.h" #include "stdio.h" #include #include "string.h" #include "hp11/hp11.h" #include "hp11/amiga/amiga.h" #include "hp11/ins.h" #include "hp11/io.h" #include "hp11/kbd.h" #include "hp11/codes.h" #include "hp11/prog_codes.h" #define MAXRUN 4 /* Length of time running is displayed */ #define FOREVER for (;;) int comma; static char *stpich(char *p, int c) /* insert character c at front of string p */ { movmem(p, p + 1, strlen(p) + 1); *p = c; return(p); } int GetKey() /* Read a key & wait for its release */ { int key; key = PollKey(TRUE); RelKey(); return(key); } enum KeyTypes ReadKey(code) /* Read a complete key sequence, & return its type, intrsuction or action. */ register WORD *code; { register struct Key *curtkey; register int key, offset; register 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 */ FOREVER { offset = 0; /* f or g not pressed */ FOREVER { /* This loop reads a key from the main, f or g shifted keyboards. Further refinements (eg sto) are done algorithmically, to save space */ if (noKey) key = PollKey(TRUE); /* obtain next key */ Dispf(FALSE); Dispg(FALSE); noKey = TRUE; if (key == 31) { /* f pressed, toggle its status */ offset = (offset == NUMKEYS) ? 0 : (Dispf(TRUE), NUMKEYS); RelKey(); } else if (key == 32) { /* g */ offset = (offset == NUMKEYS + NUMKEYS) ? 0 : (Dispg(TRUE), NUMKEYS + NUMKEYS); RelKey(); } else break;/* got a key, exit from loop */ } 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; return(Action); case Instruction: *code = curtkey->Code; return(Instruction); case Prefix: /* Key is a prefix, execute corresponding routine */ RelKey(); ret = (*(curtkey->Suffix))(code); if (ret != Invalid) return(ret); /* if successful */ key = *code; /* else, invalid keycode returnedin code field for reuse */ noKey = FALSE; /* a key is already available */ break; 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; } } } /* 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) ? '-' : ' ', iabs(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); case rad:DispRAD(TRUE); case deg:break; } } /* Display current x value in normal mode, running in run mode */ void Disp() { static int runcnt = MAXRUN; static BOOL runon; 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); } } 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; 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); }