home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 5 / DATAFILE_PDCD5.iso / utilities / h / hp11 / Amiga_Code / c / io < prev    next >
Encoding:
Text File  |  1992-05-07  |  12.3 KB  |  378 lines

  1. /*->  c.io  */
  2.  
  3. /*  Modifications for ANSI C under RISC-OS:
  4.  *
  5.  *     Date               Modification
  6.  *  13-may-90   types header
  7.  *  14-may-90   replace iabs() by abs()
  8.  *  14-may-90   movmem() replaced by memmove()
  9.  *   6-jun-90   rehash of ReadKey() to make it event driven
  10.  *   8-jun-90   modified GetKey() to do nothing
  11.  *
  12.  *  compiler complains about non-use of x in NbStr(); cured by dummy assignment
  13.  */
  14.  
  15. #include "stdlib.h"
  16. #include "stdio.h"
  17. #include <math.h>
  18. #include "string.h"
  19.  
  20. #include "wimp.h"
  21. #include "dbox.h"
  22. #include "menu.h"
  23.  
  24. #include "types.h"
  25. #include "hp11.h"
  26. #include "arc_hp11.h"
  27. #include "ami_amiga.h"
  28. #include "ins.h"
  29. #include "io.h"
  30. #include "kbd.h"
  31. #include "codes.h"
  32. #include "prog_codes.h"
  33.  
  34. #define MAXRUN 4 /* Length of time running is displayed */
  35.  
  36. #define FOREVER for (;;)
  37.  
  38. static char *stpich(char *p, int c) /* insert character c at front of string p
  39.  */
  40. {
  41.    memmove(p + 1, p, strlen(p) + 1);
  42.    *p = c;
  43.  
  44.    return(p);
  45. }
  46.  
  47. int GetKey() /* Read a key & wait for its release */
  48. {
  49. /*   int key;  now global */
  50.  
  51.    return(key);
  52. }
  53.  
  54. enum KeyTypes ReadKey(code) /* Read a complete key sequence, & return
  55.                                             its type, instruction or action. */
  56. register int *code;
  57. {
  58.    static   struct Key *curtkey;
  59.    static   int offset;
  60.    static   BOOL noKey; /* if an invalid sequence is returned, don't read a new
  61.                            key, reuse the one which caused the error. This is
  62.                            set to false when that happens */
  63.    register enum KeyTypes ret;
  64.  
  65.    noKey = TRUE;                                             /*  no key read */
  66.    do {
  67.       switch (keyflag) {
  68.          case MidSeq:        /* we were in the middle of reading a sequence,
  69.                                        in another function, so go back there */
  70.             if (ret = (*(curtkey->Suffix))(code), ret == Null) return(Null); 
  71.                                  /* each function returns Null if unfinished */
  72.             keyflag = NewSeq;       /* set scene for fresh call to ReadKey() */
  73.             if (ret != Invalid) return(ret);                /* if successful */
  74.             key = *code;       /* else, invalid keycode was returned in code 
  75.                                                              field for reuse */
  76.             noKey = FALSE;                     /* a key is already available */
  77.  
  78.          case NewSeq:                  /* this is a fresh entry to ReadKey() */
  79.             Rdoffset = 0;                                /* reset for REGdec */
  80.             offset = 0;                                /* f or g not pressed */
  81.          case PreFix:                           /* now find the prefixed key */
  82.                       /* This loop reads a key from the main, f or g shifted
  83.                             keyboards. Further refinements (eg sto) are done
  84.                                               algorithmically, to save space */
  85.             Dispf(FALSE); Dispg(FALSE);                /* are these needed ? */
  86.             noKey = TRUE;
  87.             if (key == 31) {                 /* f pressed, toggle its status */
  88.                keyflag = PreFix;
  89.                offset = (offset == NUMKEYS) ? 0 : (Dispf(TRUE), NUMKEYS);
  90.                RelKey();
  91.                return(Null);                   /* have handled key so return */
  92.             }
  93.             else if (key == 32) {                                       /* g */
  94.                keyflag = PreFix;
  95.                offset = (offset == NUMKEYS + NUMKEYS) ? 0 : (Dispg(TRUE), 
  96.                                                             NUMKEYS + NUMKEYS);
  97.                RelKey();
  98.                return(Null);                   /* have handled key so return */
  99.             }
  100.             if (User && key < 5) offset ^= NUMKEYS;    /* Toggle f for first
  101.                                                     five keys.  This doesn't
  102.                                                     affect g because the bit
  103.                                                     patterns are exclusive
  104.                                                                (42 & 84 = 0) */
  105.             Dispf(FALSE); Dispg(FALSE);
  106.             curtkey = mainKbd + offset + key; /* find address of (eventually
  107.                                                                 shifted) key */
  108.             switch (curtkey->Sort) {
  109.                case Action:
  110.                   *code = curtkey->Act;
  111.                   keyflag = NewSeq;
  112.                   return(Action);
  113.                case Instruction:
  114.                   *code = curtkey->Code;
  115.                   keyflag = NewSeq;
  116.                   return(Instruction);
  117.                case Prefix:  /* Key is prefix, execute corresponding routine */
  118.                   RelKey();
  119.                   keyflag = MidSeq;
  120.                   return(Null);              /* need another key to continue */
  121.                case Invalid:      /* An inavlid f or g sequence was entered, 
  122.                                      retry it with the f or g prefix stripped.
  123.                                      Therefore all obtainable main keyboard
  124.                                      sequences must exist, otherwise the 
  125.                                      program enters an infinite loop retrying 
  126.                                      constantly the same nonexistent keycode */
  127.                    key %= NUMKEYS;
  128.                    noKey = FALSE;
  129.                    break;
  130.             }
  131.       }
  132.    } while (!noKey);
  133. }
  134.  
  135. /* Return position n on the liquid cristal display in string t */
  136. int scrpos(t, n)
  137. char *t;
  138. register int n;
  139. {
  140.    register char *s = t;
  141.    register int pos;
  142.  
  143.    pos = 0;
  144.    while (pos <= n && *s) { /* go on till end of string or beyond position n on
  145.  display */
  146.       if (*s != '.' && *s != ',') pos++; /* . & , take no space on the display
  147.  */
  148.       s++;
  149.    }
  150.    return((int)((s - t) - 1 - (pos - n))); /* pos - n  is there to take care of
  151.  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 */
  152. }
  153.  
  154. /* Return the length taken up on the screen by the string */
  155. int scrlen(s)
  156. register char *s;
  157. {
  158.    register int cnt = 0;
  159.  
  160.    while (*s) {
  161.       if (*s != '.' && *s != ',') cnt++; /* . & , take no space on the display
  162.  */
  163.       s++;
  164.    }
  165.  
  166.    return(cnt);
  167. }
  168.  
  169. /* format string s in hp11 display format (without exponent) so that it takes
  170.  n spaces in the display. s isn't modified */
  171. static char *CvtStd(char *s, int n)
  172. {
  173.    static char buf[20];
  174.    register char *p;
  175.    register int i, nb;
  176.    register int digit_separator = comma ? '.' : ','; /* separator according to
  177.  current setting */
  178.  
  179.    strcpy(buf, s); /* copy string to safe work buffer */
  180.  
  181.    if ((p = strchr(buf, '.')) == NULL) { /* find position of . */
  182.       p = buf + strlen(buf);
  183.       if (!entering) *p = comma ? ',' : '.';
  184.       *(p + 1) = '\0';
  185.    }
  186.    else if (comma) *p = ','; /* Replace . by , if necessary */
  187.  
  188.    while ((p -= 3) - buf > 1) /* Add , (or .) to string every 3 digits */
  189.       stpich(p, digit_separator);
  190.  
  191.    nb = n - scrlen(buf);
  192.    for (i = 1; i <= nb; i++) strcat(buf, " "); /* pad with spaces to required
  193.  screen length */
  194.    buf[scrpos(buf, n) + 1] = '\0'; /* cut at n characters */
  195.  
  196.    return(buf);
  197. }
  198.  
  199. /* format string s in hp11 display format (with exponent) */
  200. static char *CvtExpo(char *s, char *e)
  201. {
  202.    if (strlen(e) > 3) { /* deal with roundoff towards 1e100 when nb too big */
  203.       e = " 99"; /* exponent is 99 */
  204.       strncpy(s + 1, "9.999999999", strlen(s + 1)); /* mantissa is enough 9's
  205.  */
  206.    }
  207.  
  208.    return(strcat(CvtStd(s, 8), e));
  209. }
  210.  
  211. /* convert x to scientific format with n digits. Returns it in a static buffer
  212.  (from CvtStd) */
  213. static char *Scient(double x, int n)
  214. {
  215.    char buf[20];
  216.    register char *pe;
  217.  
  218.    sprintf(buf, "% .*E", n, x); /* Scientific format with n digits */
  219.    pe = strchr(buf, 'E'); /* split string into mantissa & exponent */
  220.    *pe++ = '\0';
  221.    /* if (*pe == '+') *pe = ' '; A + is displayed as a space by the Display
  222.  routine anyway */
  223.  
  224.    return(CvtExpo(buf, pe));
  225. }
  226.  
  227. /* Convert x to fix n format */
  228. static char *Fixed(double x, int n)
  229. {
  230.    char buf[80];
  231.  
  232.    sprintf(buf, "% .*f", n, x);
  233.  
  234.    return(CvtStd(buf, 11));
  235. }
  236.  
  237. /* Eng n format */
  238. static char *Engin(double x, int n)
  239. {
  240.    char expbuf[10], buf[80];
  241.    register char *pe;
  242.    double mantissa;
  243.    register int exponent, dif;
  244.  
  245.    sprintf(buf, "%.*E", n, x); /* print enough digits */
  246.    *(pe = strchr(buf, 'E')) = '\0';
  247.    mantissa = atof(buf); /* get mantissa & exponent */
  248.    exponent = atoi(pe + 1);
  249.  
  250.    /* Round exponent down to a multiple of 3 */
  251.    dif = exponent % 3;
  252.    if (dif < 0) dif += 3;
  253.    exponent -= dif; /* calculate new exponent & mantissa */
  254.    mantissa *= pow(10.0, (double)dif);
  255.  
  256.    /* Convert them to string */
  257.    sprintf(buf, "% .*f", (n - dif > 0) ? n - dif : 0, mantissa);
  258.    sprintf(expbuf, "%c%02d", (exponent < 0) ? '-' : ' ', abs(exponent)); /*
  259.  pad exponent with 0's, hence %02d not %2d */
  260.  
  261.    return(CvtExpo(buf, expbuf));
  262. }
  263.  
  264. /* Display current trig mode */
  265. static void DispAngle(void)
  266. {
  267.    switch (Angles) {
  268.       case grad: DispG(TRUE);  DispRAD(TRUE);  break;
  269.       case rad:  DispG(FALSE); DispRAD(TRUE);  break;
  270.       case deg:  DispG(FALSE); DispRAD(FALSE); break;
  271.    }
  272. }
  273.  
  274. /* Display current x value in normal mode, running in run mode */
  275. void Disp()
  276. {
  277.    static int runcnt = MAXRUN;
  278.    static BOOL runon;
  279.  
  280.    if(hp11_show_stack) {  /* this is first to avoid corrupting Display() arg */
  281.       if (!entering) dbox_setfield(hp11_stack_dbox_handle,HP11_X_REG,NbStr(X));
  282.       dbox_setfield(hp11_stack_dbox_handle, HP11_Y_REG, NbStr(Y));
  283.       dbox_setfield(hp11_stack_dbox_handle, HP11_Z_REG, NbStr(Z));
  284.       dbox_setfield(hp11_stack_dbox_handle, HP11_T_REG, NbStr(T));
  285.    }
  286.    if (running) { /* Flash running on and off every MAXRUN calls */
  287.       if (fast) { /* Display Running only once in fast mode */
  288.         if (!runon) {
  289.            Display("  Running");
  290.            runon = TRUE; /* Running displayed */
  291.         }
  292.       }
  293.       else if (runcnt-- == 0) Display("");
  294.       else if (runcnt <= -MAXRUN) {
  295.         runcnt = MAXRUN;
  296.         Display("  Running");
  297.       }
  298.    }
  299.    else {
  300.       runon = FALSE; /* Running not displayed */
  301.       if (entering) /* Display number entry strings */
  302.         if (expo) Display(CvtExpo(strx, expx)); /* with exponent */
  303.         else Display(CvtStd(strx, 11));
  304.       else
  305.         Display(NbStr(X));
  306.  
  307.       DispAngle();
  308.       if (User) DispUSER(TRUE);
  309.       else DispUSER(FALSE);
  310.    }
  311. }
  312.  
  313. char *NbStr(x)
  314. double x;
  315. {
  316.    switch (Mode) { /* Display x according to display mode */
  317.       case fix:if ((fabs(x) >= minfix / 2.0 || x == 0.0) && fabs(x) < 1E10) {
  318.                  /* Number can be displayed in fix mode */
  319.                  return(Fixed(x, Digits));
  320.               }
  321.               /* fall through for call to Scient */
  322.       case sci:return(Scient(x, Digits));
  323.       case eng:return(Engin(x, Digits));
  324.    }
  325. }
  326.  
  327. /* Display Error n, & wait for a key to be pressed */
  328. void Error(n)
  329. int n;
  330. {
  331.    register char *buf;
  332.  
  333.    entering = FALSE; /* end of digit entry */
  334.    error = TRUE; /* an error has occured */
  335.    buf = "  Error  ";
  336.    buf[8] = n; buf[9] ='\0';
  337.  
  338.    if (!running) RelKey();
  339.    Display(buf);
  340.    GetKey();
  341. }
  342.  
  343. /* Display current program line */
  344. void DisplayLine()
  345. {
  346.    register int c1 = keycodes[Prog[PC]].c1, c2 = keycodes[Prog[PC]].c2,
  347.                c3 = keycodes[Prog[PC]].c3;
  348.    static char _buf[20], _insbuf[20];
  349.    register char *buf = _buf, *insbuf = _insbuf;
  350.    register int point = comma ? ',' : '.'; /* separator according to current
  351.                                                                      setting */
  352.    sprintf(buf, " %03d-", PC); /* prepare program line */
  353.  
  354.    /* Prepare instruction buffer */
  355.    if (PC == 0) insbuf[0] = '\0'; /* nothing at line 0 */
  356.    else switch (keycodes[Prog[PC]].Type) { /* there are 6 methods for
  357.  displaying a line */
  358.       case ONECODE: sprintf(insbuf, "%6d", c1); break; /*     nn eg SIN or 9 */
  359.       case TWOCODE: sprintf(insbuf, "%3d%3d", c1, c2); break; /*  nn nn eg g
  360.  LOG */
  361.       case TWOCODE_9: sprintf(insbuf, "%4d%2d", c1, c2); break; /*  nn n eg STO
  362.  5*/
  363.       case TWOCODE_PT: sprintf(insbuf, "%4d %c%1d", c1, point, c2); break; /*
  364.  nn .n eg RCL .6 */
  365.       case THREECODE: sprintf(insbuf, "%2d,%2d,%2d", c1, c2, c3); break; /*
  366.  nn,nn,nn eg f HYP SIN */
  367.       case THREECODE_PT: sprintf(insbuf, "%2d,%2d, %c%1d", c1, c2, point, c3);
  368.  break; /* nn,nn, .n eg STO + .0 */
  369.    }
  370.  
  371.    Display(strcat(buf, insbuf));
  372.  
  373.    DispAngle();
  374.    if (User) DispUSER(TRUE);
  375.    else DispUSER(FALSE);
  376. }
  377.  
  378.