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