home *** CD-ROM | disk | FTP | other *** search
/ CD-ROM Aktief 1995 #6 / CDA_6.iso / shell / utils / disked29.arj / SOURCE.ZIP / MYLIB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-23  |  21.9 KB  |  944 lines

  1. /* MYLIB.C  Generic Library Functions */
  2.  
  3. /* Public Domain -- Gregg Jennings 1989-1995 */
  4.  
  5. /* This source file may be freely used and distributed without restriction. */
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <conio.h>
  10. #include <string.h>
  11. #include <dos.h>
  12.  
  13. #include "mylib.h"
  14. #include "console.h"          /* for console I/O (my print() etc.) */
  15.  
  16. /*
  17.    The following are for DISKED use.  The #ifdefs are for
  18.    marking the DISKED specific code.  These Should be removed
  19.    for general usage.
  20. */
  21.  
  22. #ifdef DISKED
  23. #include "disked.h"
  24. static void displval(int x, int base, int c);
  25. static int getlnum(unsigned int max, unsigned *num, int base);
  26. #endif
  27.  
  28.  
  29. #define _tohex(c)   ( (c<='9') ? (c-'0') : (c-'7') )
  30.  
  31. /*
  32.    Convert two ASCII hex-valid chars to one hex number.
  33.    A '0' and a 'd' returns the value 0x0d.  The second
  34.    argument can be a '\r'.
  35.  
  36.    No checking for validity.
  37.  
  38.    ver 1.1 9/91    fixed ascii mask error, added _tohex() macro
  39.    ver 1.0 12/90
  40. */
  41.  
  42. unsigned char hexbyte(register int a,register int b)
  43. {
  44.     a=toupper(a);
  45.     b=toupper(b);
  46.  
  47.     if (b=='\r') {      /* swap if '\r' */
  48.         b=a;
  49.         a='0';
  50.     }
  51.     return((unsigned char)((_tohex(a)*16)+_tohex(b)));
  52. }
  53. /*
  54.  * Display a number to the console with leading zeros or space
  55.  * and a certain length, and any base from 2 to 36.
  56.  *
  57.  * pn    print int number
  58.  * pln   print long number
  59.  *
  60.  *   Returns: number of digits.
  61.  *
  62.  *   ver 1.0 9/91     eliminated all but 2 divisions pln(), 3 in pn()
  63.  *   ver 0.1 12/90
  64.  */
  65.  
  66. int pn(unsigned int n, int base)
  67. {
  68. int r=1;
  69. int i;
  70.  
  71.     if (n/base)
  72.         r+=pn(n/base,base);
  73.     i=n%base;
  74.     output((i>9) ? i+'A'-10 : i+'0');
  75.     return(r);
  76. }
  77.  
  78. int pln(unsigned long n, int base)
  79. {
  80. int r=1;
  81. long l;
  82. int i;
  83.  
  84.    if (((l=n/(long)base))>0)
  85.         r+=pln(l,base);
  86.     i=(int)(n%(long)base);
  87.     if (i>9)
  88.         output(i+'A'-10);
  89.     else
  90.         output(i+'0');
  91.     return(r);
  92. }
  93.  
  94. /*
  95.  * Display a number to the console with leading zeros or space
  96.  * and a certain length, and any base from 2 to 36.
  97.  *
  98.  * pnlz   print number leading zero
  99.  * pnls   print number leading space
  100.  * plnlz  print long number leading zero
  101.  * plnls  print long number leading space
  102.  *
  103.  *   ver 1.0   9/91
  104.  */
  105.  
  106. void pnlz(unsigned int n, unsigned int length, int base)
  107. {
  108. register int t;
  109.  
  110.     for (t=length-getlen(n,base);t>0;t--)
  111.         output('0');
  112.     pn(n,base);
  113. }
  114.  
  115. void pnls(unsigned int n, unsigned int length, int base)
  116. {
  117. register int t;
  118.  
  119.     for (t=length-getlen(n,base);t>0;t--)
  120.         output(' ');
  121.     pn(n,base);
  122. }
  123.  
  124. void plnlz(unsigned long n, unsigned int length, int base)
  125. {
  126. register int i;
  127.  
  128.     for (i=length-getlength(n,base);i>0;i--)
  129.         output('0');
  130.     pln(n,base);
  131. }
  132.  
  133. void plnls(unsigned long n, unsigned int length, int base)
  134. {
  135. register int i;
  136.  
  137.     for (i=length-getlength(n,base);i>0;i--)
  138.         output(' ');
  139.     pln(n,base);
  140. }
  141.  
  142. /*
  143.  * get the display length (number of digits) of a
  144.  * number, i.e. 100 dec returns 3, 64 hex (100 dec)
  145.  * returns 2
  146.  */
  147.  
  148. int getlen(register unsigned int n, register int base)
  149. {
  150. int j;
  151.  
  152.     for (j = 1; n >= (unsigned int)base; n /= base,++j)
  153.         ;
  154.     return(j);
  155. }
  156.  
  157. /*
  158.     Get length of number.
  159.     Pass: long number, int base (1 to 26).
  160.     Returns: the number of digits the number needs to be displayed.
  161.  
  162.     ver 0.1 12/90
  163.     ver 0.2 3/91    changed to long
  164. */
  165.  
  166. int getlength(unsigned long l, int base)
  167. {
  168. register int r;
  169.  
  170.     for (r=1;l>=(unsigned long)base;l/=(long)base,++r)
  171.         ;
  172.     return(r);
  173. }
  174.  
  175. /*
  176.     Convert a string containing escape sequences
  177.     to their correct values.
  178.  
  179.     Returns: the converted string's length.
  180.  
  181.     ver 1.1 9/91    changed \x to fixed 2 chars (\x0d not \xd)
  182.     ver 1.0 3/91
  183.     ver 0.1 12/90
  184. */
  185.  
  186. int convert(register char *a)
  187. {
  188. register char *s;
  189. int j;
  190.  
  191.     s=a;
  192.     for (j=0;*a!='\0';a++,j++) {
  193.         if (*a=='\\') {
  194.             switch (*++a) {
  195.             case 'x':
  196.                 *(s+j)=hexbyte(*(a+1),*(a+2));
  197.                 a+=2;
  198.                 break;
  199.             case 'a':
  200.                 *(s+j)='\a';
  201.                 break;
  202.             case 'b':
  203.                 *(s+j)='\b';
  204.                 break;
  205.             case 'f':
  206.                 *(s+j)='\f';
  207.                 break;
  208.             case 'n':
  209.                 *(s+j)='\n';
  210.                 break;
  211.             case 'r':
  212.                 *(s+j)='\r';
  213.                 break;
  214.             case 't':
  215.                 *(s+j)='\t';
  216.                 break;
  217.             case 'v':
  218.                 *(s+j)='\v';
  219.                 break;
  220.             case '0':
  221.                 *(s+j)='\0';
  222.                 break;
  223.             case '\\':
  224.                 *(s+j)='\\';
  225.                 break;
  226.             default:
  227.                 break;
  228.             }
  229.         }
  230.         else
  231.             *(s+j)=*a;
  232.     }
  233.     *(s+j)='\0';
  234.     a=s;
  235.     return(j);
  236. }
  237. /*
  238.     Display the current directory in a combination DIR /P /W
  239.     format.
  240.  
  241.     ver 0.3 9/91   call to lpd()
  242.     ver 0.2 3/91
  243. */
  244.  
  245. #ifdef DISKED
  246. extern unsigned int disk;
  247. extern unsigned avail_clusters;
  248. extern unsigned secs_cluster;
  249. extern unsigned sec_size;
  250. #endif
  251.  
  252. void directory(void)
  253. {
  254. int files=0;
  255. struct _find_t file;
  256. struct _diskfree_t ds;
  257. long dsize,fsize = 0L;
  258.  
  259.    output('\n');
  260.    if (_dos_findfirst("*.*",0x3f,&file)==0)
  261.    {
  262.       do
  263.       {
  264.          pname(file.name);
  265.          print("  ");
  266.          if (file.attrib&_A_SUBDIR)
  267.             print("  <DIR>");
  268.          else if (file.attrib&_A_VOLID)
  269.             print("  <VOL>");
  270.          else
  271.          {
  272.             plnls(file.size,7,10);
  273.             fsize+=file.size;
  274.          }
  275.          ++files;
  276.          print((files%3==0) ? "\n" : "   ");
  277.          if (files%60==0)
  278.             pause();
  279.       } while (_dos_findnext(&file)==0);    /* while being found*/
  280.    }
  281.    if (files==0)
  282.            print("no files");
  283.    output('\n');
  284.  
  285. #ifdef DISKED
  286.    if (avail_clusters==0)
  287.    {
  288.       _dos_getdiskfree(disk,&ds);
  289.       dsize = ((long)ds.avail_clusters*(long)ds.sectors_per_cluster*(long)ds.bytes_per_sector);
  290.    }
  291.    else
  292.       dsize = ((long)avail_clusters*(long)secs_cluster*(long)sec_size);
  293. #else
  294.    {
  295.       unsigned disk;
  296.       _dos_getdrive(&disk);
  297.       _dos_getdiskfree(disk,&ds);
  298.       dsize = ((long)ds.avail_clusters*(long)ds.sectors_per_cluster*(long)ds.bytes_per_sector);
  299.    }
  300. #endif
  301.    print(" file space %ld, disk space %ld\n",fsize,dsize);
  302. }
  303.  
  304. /*
  305.     Displays the filename returned by _dos_findnext() in a nice
  306.     format.
  307.  
  308.     ver 0.2 3/91
  309. */
  310.  
  311. void pname(char *s)
  312. {
  313. register int i;
  314. register int j;
  315.  
  316.    i=0;
  317.    output(' ');
  318.    while (s[i]!='.' && s[i]!='\0')
  319.       output(s[i++]);
  320.    j= (s[i]!='\0') ? i+1 : i;
  321.    while (i++<8)
  322.       output(' ');
  323.    if (s[j])
  324.       output('.');
  325.    else
  326.       output(' ');
  327.    while (i++<=11)
  328.       output( (s[j]=='\0') ? ' ' : s[j++]);
  329. }
  330.  
  331. /*
  332.     Modified K&R index() for a non-null terminated string.
  333.  
  334.     ver 0.1 12/90
  335. */
  336.  
  337. int search(unsigned char *s,unsigned char *t,size_t size, size_t len)
  338. {
  339. unsigned int i;
  340. register unsigned int j,k;
  341.  
  342.     if (size>len) {
  343.         size-=len;
  344.         for (i=0;i<=size;i++) {
  345.             for (j=i,k=0;k<len && s[j]==t[k];j++,k++)
  346.                 continue;
  347.             if (k==len)
  348.                 return(i);
  349.         }
  350.     }
  351.     return(-1);
  352. }
  353.  
  354. /* case-insensitive search 11-93 */
  355.  
  356. int isearch(unsigned char *s,unsigned char *t, size_t size, size_t len)
  357. {
  358. unsigned int i;
  359. register size_t j,k;
  360.  
  361.    if (size > len)
  362.    {
  363.       size-=len;
  364.       for (i=0;i <= size;i++)
  365.       {
  366.          for (j=i,k=0;k<len && (s[j]==t[k] || toupper(s[j]) == toupper(t[k]));j++,k++)
  367.             continue;
  368.        if (k==len)
  369.           return(i);
  370.       }
  371.    }
  372.    return(-1);
  373. }
  374. /*
  375.    Display a string with a question mark and return TRUE if a 'y'
  376.    is found on console, else return FALSE.
  377.  
  378.    mode: 0  no mov/clr
  379.    (bit) 1  cursor back to "Yes/No "
  380.          2  cursor back to arg s
  381.          4  clreol if "Yes"
  382.  
  383.    ver 0.3 9/93  added cursor, clreol
  384.    ver 0.2 3/91
  385.    ver 0.1 12/91
  386. */
  387.  
  388. int getver(register char *s,int mode)
  389. {
  390. int c;
  391.  
  392.    if (mode&2)          /* mov arg */
  393.       savecursor();
  394.    print(s);
  395.    output('?');
  396.    output(' ');
  397.    if (mode&1)          /* mov yn */
  398.       savecursor();
  399.    c=input();
  400.    if (tolower(c)!='y')
  401.    {
  402.       print("No ");
  403.       c = 0;
  404.       if (mode)
  405.          restcursor();
  406.    }
  407.    else
  408.    {
  409.       print("Yes");
  410.       c = 1;
  411.       if (mode)
  412.          restcursor();
  413.       if (mode&4)
  414.          clreol();
  415.    }
  416.    return c;
  417. }
  418. /*
  419.     Get number from console by calling getstr() and sscanf().
  420.     Handles base of 10 or 16 only.
  421.  
  422.     Pass: long maximum number, pointer to number, int base (1 to 26).
  423.  
  424.     Returns: TRUE  (1)  if number okay
  425.          FALSE (0)  if no entry
  426.          ERROR (-1) if too big a number
  427.          ABORT (-2) on ESC or ^C
  428.  
  429.     Calls: getstr()
  430.  
  431.     ver 0.1 12/90
  432.     ver 1.0 2/91    pass pointer
  433. */
  434.  
  435. int getnumber(unsigned long max, void *num, int base)
  436. {
  437. char tmpstr[11];    /* longest number is unsigned long of 10 digits */
  438. char form[4];     /* format string for sscanf() */
  439. int i;
  440. unsigned long l;
  441. long *pl=num;       /* make sure we have enough space */
  442.  
  443.    i=0;
  444.    form[i++]='%';
  445.    form[i++]='l';
  446.    (base==10) ? (form[i]='d') : (form[i]='x');
  447.    form[++i]='\0';
  448.    i=getstr(tmpstr,getlength(max,base),(base==10)?_DIGIT:_HEX);
  449.    if (i<0)
  450.    {
  451.       if (i==ERROR)
  452.          i=0;
  453.       return(i);
  454.    }
  455.    sscanf(tmpstr,form,&l);
  456.    if (l>max)
  457.       return(ERROR);
  458.    *pl=l;
  459.    return(TRUE);
  460. }
  461.  
  462. int getnum(unsigned int max, unsigned *num, int base)
  463. {
  464. char tmpstr[7];            /* longest number is unsigned 6 digits */
  465. char form[3];              /* format string for sscanf() */
  466. int i;
  467. unsigned int u;
  468. unsigned int *pu=num;      /* make sure we have enough space */
  469.  
  470.    i = 0;
  471.    form[i++] = '%';
  472.    (base == 10) ? (form[i] = 'u') : (form[i] = 'x');
  473.    form[++i] = '\0';
  474.    i = getstr(tmpstr,getlen(max,base),(base == 10) ? _DIGIT : _HEX);
  475.    if (i < 0)
  476.    {
  477.       if (i == ERROR)
  478.          i = 0;
  479.       return i;
  480.    }
  481.    sscanf(tmpstr,form,&u);
  482.    if (u > max)
  483.       return ERROR;
  484.    *pu = u;
  485.    return TRUE;
  486. }
  487.  
  488. /*
  489.     Get a string from console, masking to hex or decimal
  490.     numbers only or punctuation, depending on the mask value,
  491.     with CP/M editing control keys.
  492.  
  493.     Pass: pointer to string, int max length, int mask.
  494.  
  495.     Returns:   -2 on ESC or ^C
  496.                -1 on no input ('\r')
  497.                -3 on no input (space or ',')
  498.  
  499.     ver 1.1 17-Mar-1994    better input type checking
  500.     ver 1.0 9/93           added -3 return
  501.     ver 0.1 12/90
  502. */
  503.  
  504. int getstr(char *s,unsigned int len,int mask)
  505. {
  506. register unsigned int i;
  507. register int c = 0;
  508.  
  509.    savecursor();
  510.    for (i = 0; i < len; )
  511.    {
  512.       switch (c = input())
  513.       {
  514.          case '\b':
  515.             if (i)
  516.             {
  517.                output(c);
  518.                output(' ');
  519.                output(c);
  520.                --i;
  521.             }
  522.             break;
  523.          case 'U'-'@':           /* ^U to delete */
  524.             if (i)
  525.             {
  526.                restcursor();
  527.                clreol();
  528.                i = 0;
  529.             }
  530.             break;
  531.          case 0x1b:              /* ESC to abort */
  532.          case 'C'-'@':           /* ^C */
  533.             i = 0;
  534.             goto end_input;      /* goto's!?!?!? -- Yeah! They work! */
  535.  
  536.          case ',':
  537.             if (mask & _PUNCT)
  538.                goto use_it;
  539.             else
  540.                goto end_input;
  541.  
  542.          case ' ':
  543.             if (mask & _BLANK)
  544.                goto use_it;
  545.             else
  546.                goto end_input;
  547.  
  548.          case '\r':              /* end of input */
  549.             goto end_input;
  550.  
  551.          default:
  552. use_it:
  553.             if (mask == _DIGIT && (!isdigit(c)))
  554.                continue;
  555.             if (mask == _HEX && (!isxdigit(c)))
  556.                continue;
  557.             if (!(mask & _CONTROL) && iscntrl(c))
  558.                continue;
  559.             output(c);        /* save and echo numbers */
  560.             s[i++] = (char)c;
  561.             break;
  562.       }
  563.    }
  564.  
  565. end_input:
  566.  
  567.    s[i] = '\0';
  568.    if (!i)
  569.       return (c=='\r') ? ERROR : -3;
  570.    return i;
  571. }
  572.  
  573. /***
  574. *  Edit a buffer, in a debugger type format.  Asks for the starting
  575. *  point of the editing.  Checks for end of buffer and wraps around.
  576. *  Allows hex and ASCII substitutions, jumps to a buffer location, and
  577. *  hex number fills.
  578. *
  579. *  A complicated, horrible looking function but it works.
  580. *
  581. *  Uses getnum(), bdos(), hexbyte(), dispval() and <ctype.h>.
  582. *
  583. *  1.1   23-Mar-1995    fixed '=' test of > bufend ( >= !)
  584. *  1.0   15-Mar-1995    restructured (tabs and whitespsace)
  585. *                       changes for file tracking (getlnum(), displval())
  586. *
  587. *  GAJ  initial
  588. *  GAJ  added ASCII subs
  589. *  GAJ  1-8-89 added ^x
  590. *  GAJ  1-9-89 added \c
  591. *  GAJ  3-8-89 updated help
  592. *  GAJ  12-8-90 cleaned up
  593. ****/
  594.  
  595. int change(register unsigned char *buffer, unsigned int bufend, int base)
  596. {
  597. unsigned int a;
  598. unsigned int b;
  599. int c;                  /* chars gotten from the console */
  600. unsigned int n,i;       /* x = buffer index, n = getval, i = general purpose*/
  601. register unsigned int x;
  602. int inquote,ad;         /* for inputing a string */
  603. int l;
  604. char t[66];
  605.  
  606.    if (bufend <= 0)
  607.       return 0;
  608.  
  609.    n = 0;
  610. #ifdef DISKED
  611.    if (ft_track)
  612.       i = getlnum(bufend,&n,base);
  613.    else
  614. #endif
  615.       i = getnum(bufend,&n,base);
  616.    if (i == ABORT)
  617.       return 0;
  618.  
  619.    ad = getlen(bufend,base);
  620.    x = n;
  621.    inquote = FALSE;
  622.    output('\n');
  623.  
  624.    for (;;)
  625.    {
  626.       c = buffer[x];
  627. #ifdef DISKED
  628.       if (ft_track)
  629.          displval(x,base,c);
  630.       else
  631. #endif
  632.          dispval(x,ad,base,c);         /* display address, byte, and ASCII */
  633.       if (!inquote)
  634.          a = input()&0xff;
  635.  
  636.       if (a=='\\')                  /* search */
  637.       {
  638.          output(a);                          /* echo */
  639.          a = input()&0xff;                   /* get */
  640.          if (a=='^')                         /* control */
  641.          {
  642.             output(a);                       /* echo */
  643.             b = input()&0xff;                /* get */
  644.             if (isalpha(b))                  /* letter */
  645.             {
  646.                a = toupper(b);               /* upper */
  647.                output(a);                    /* echo */
  648.                c = (a-'@');                  /* convert */
  649.             }
  650.             else continue;                   /* else redo */
  651.          }
  652.          else if (a == '\'')        /* get ASCII */
  653.          {
  654.             output(a);
  655.             b = input()&0xff;
  656.             if (b >= ' ')                    /* is okay? */
  657.             {
  658.                output(b);                    /* echo */
  659.                c = b;                        /* set */
  660.             }
  661.             else continue;                   /* else redo */
  662.          }
  663.          else if (isxdigit(a))      /* get hex */
  664.          {
  665.             output(a);
  666.             b = input()&0xff;                /* get second */
  667.             if (isxdigit(b) || b == '\r')
  668.             {
  669.                if (b != '\r')
  670.                   output(b);
  671.                c = hexbyte(a,b);             /* convert */
  672.             }
  673.             else continue;
  674.          }
  675.                                              /* search loop */
  676.          i = x;                              /* save place */
  677.          while (c != (int)buffer[++x])
  678.          {
  679.             if (x == bufend)                 /* wrap at end */
  680.                x = 0;
  681.             if (x == i)                      /* stop */
  682.                break;
  683.          }
  684.          continue;
  685.       }
  686.       else if (a == '\"')           /* get string */
  687.       {
  688.          output(a);
  689.          inquote = FALSE;                    /* bool for continuing */
  690.          if ((l = getstr(t,63,_TEXT)) > 0)
  691.          {
  692.             for (i = 0; i < (unsigned)l; i++)/* copy string */
  693.             {
  694.                buffer[x++] = t[i];
  695.                if (x == bufend)              /* wrap around */
  696.                   x = 0;
  697.             }
  698.          }
  699.          else continue;
  700.          if (l == 63)
  701.             inquote = TRUE;
  702.          continue;
  703.       }
  704.       else if (a == '^')            /* get control */
  705.       {
  706.          output(a);
  707.          b = input()&0xff;
  708.          if (isalpha(b))
  709.          {
  710.             b = toupper(b);
  711.             output(b);
  712.             buffer[x] = (char)(b-'@');
  713.          }
  714.          else continue;
  715.       }
  716.       else if (a == '\'')           /* get ASCII */
  717.       {
  718.          output(a);
  719.          b = input()&0xff;
  720.          if (b >= ' ')                       /* is okay? */
  721.          {
  722.             output(b);                       /* yes, display and set */
  723.             buffer[x] = (char)b;
  724.          }
  725.          else continue;
  726.       }
  727.       else if (a == '=')            /* jump to addr */
  728.       {
  729.          output(a);
  730. #ifdef DISKED
  731.          if (ft_track)
  732.             i = getlnum(bufend,&n,base);
  733.          else
  734. #endif
  735.             i = getnum(bufend,&n,base);
  736.          if (i < 1)
  737.             continue;
  738.          if (n >= bufend)
  739.             continue;
  740.          x = n;
  741.          continue;
  742.       }
  743.       else if (a == '\r' || a == ' ')  /* go to next */
  744.          ;
  745.       else if (a == '\t')              /* goto 0000: */
  746.       {
  747.          x = 0;
  748.          continue;
  749.       }
  750.       else if (a == '.' || a == ESC)   /* exit */
  751.          break;
  752.       else if (a == '\b')              /* go to previous */
  753.       {
  754.          if (--x == 0xffff)
  755.          {
  756.             x = (bufend-1);                   /* if end, wrap */
  757.             output('\n');
  758.          }
  759.          continue;
  760.       }
  761.       else if (a=='/' || a=='?')
  762.       {
  763.          print("\n\n\txx     enter hex value xx");
  764.          print("\n\t'c     enter ASCII char c");
  765.          print("\n\t^c     enter control char c");
  766.          print("\n\t\"s     enter string s");
  767.          print("\n\tCR/SP  next location");
  768.          print("\n\tBS     previous location");
  769.          print("\n\tTAB    goto location 00");
  770.          print("\n\t=n     goto location n");
  771.          print("\n\t\\xx    goto hex value xx");
  772.          print("\n\t\\\'c    goto char c");
  773.          print("\n\t\\^c    goto control char c");
  774.          print("\n\t-x1,x2 write x1, x2 times");
  775.          print("\n\t+x1,x2 replace all x1, with x2");
  776.          print("\n\t.|ESC  end\n");
  777.          continue;
  778.       }
  779.       else if (a == '-')               /* fill */
  780.       {
  781.          output(a);
  782.          if (getnum(0xff,&a,16) < 1)
  783.             continue;
  784.          output(',');
  785.          if (getnum(bufend,&b,16) < 1)          /* get second byte */
  786.             continue;
  787.          n = x;                                 /* save position */
  788.          for (i = 0; i < b; i++)                /* all okay, fill it */
  789.          {
  790.             buffer[x] = (char)a;
  791.             if (++x == bufend)                  /* wrap around at end */
  792.                x = 0;
  793.          }
  794.          x = n;                                 /* restore position */
  795.          continue;
  796.       }
  797.       else if (a == '+')               /* fill */
  798.       {
  799.          output(a);
  800.          if (getnum(0xff,&a,16) < 1)            /* get first byte */
  801.             continue;
  802.          output(',');
  803.          if (getnum(0xff,&b,16) < 1)            /* get second byte */
  804.             continue;
  805.          if (a==b)
  806.             continue;
  807.          for (i = 0; i < bufend; i++)           /* all okay, fill it */
  808.          {
  809.             if (buffer[i] == (unsigned char)a)
  810.                buffer[i] = (unsigned char)b;
  811.          }
  812.          continue;
  813.       }
  814.       else if (isxdigit(a))
  815.       {
  816.          output(a);
  817.          b = input()&0xff;                      /* get second */
  818.          if (isxdigit(b) || b == '\r')
  819.          {
  820.             if (b != '\r')
  821.                output(b);
  822.             buffer[x] = hexbyte(a,b);           /* convert */
  823.          }
  824.          else continue;
  825.       }
  826.       else continue;
  827.       if (++x == bufend)      /* increment pointer, wrap if end */
  828.       {
  829.          x = 0;
  830.          output('\n');
  831.       }
  832.    }
  833.    output('\n');
  834.    return 1;
  835. }
  836.  
  837. void dispval(int x, int len, int base, int c)
  838. {
  839.     output('\n');
  840.     pnlz(x,len,base);
  841.     output(':');
  842.     output(' ');
  843.     pnlz(c,2,16);
  844.     output(' ');
  845.     if (isprint(c)) {
  846.         output('\'');
  847.         output(c);
  848.         output('\'');
  849.     }
  850.     else if (iscntrl(c)) {
  851.         output('^');
  852.         output(c+'@');
  853.         output(' ');
  854.     }
  855.     else
  856.         put(3,' ');
  857.     put(2,' ');
  858. }
  859.  
  860. #ifdef DISKED
  861. static void displval(int x, int base, int c)
  862. {
  863. long l = filebytes();
  864.  
  865.    if (base == 10)
  866.       print("\n%08ld: ",(long)x + l);
  867.    else
  868.       print("\n%06lx: ",(long)x + l);
  869.    print("%02x ",c);
  870.    if (isprint(c))
  871.       print("'%c'  ",c);
  872.    else if (iscntrl(c))
  873.       print("^%c   ",c+'@');
  874.    else
  875.       print("     ");
  876. }
  877.  
  878. static int getlnum(unsigned int max, unsigned *num, int base)
  879. {
  880. int i;
  881. long n,l = filebytes();
  882.  
  883.    n = 0L;
  884.    if ((i = getnumber(l + max,&n,base)) > 0)
  885.    {
  886.       if (n < l)
  887.          *num = 0;
  888.       else
  889.          *num = (int)(n - l);
  890.    }
  891.    return i;
  892. }
  893. #endif
  894.  
  895. void pause(void)
  896. {
  897.     savecursor();
  898.     print("<more>");
  899.     input();
  900.     restcursor();
  901.     clreol();
  902. }
  903.  
  904. /* view file to screen */
  905.  
  906. void viewfile(char *filename, int display)
  907. {
  908. char buf[255];
  909. FILE *fh;
  910. int i = 1;
  911.  
  912.    if (stricmp(filename,"none") == 0 || filename[0] == '\0')
  913.       return;
  914.  
  915.    if ((fh = fopen(filename,"r")) == NULL)
  916.    {
  917.       perror(filename);
  918.       return;
  919.    }
  920.    if (display)
  921.       print(" %s File Contents:\n",filename);
  922.    output('\n');
  923.  
  924.    while (!feof(fh))
  925.    {
  926.       if (fgets(buf,255,fh) == NULL)
  927.          break;
  928.       print(buf);
  929.       if (++i == 23)
  930.       {
  931.          print("<more>\r");
  932.          i = input();
  933.          if (i == 0)
  934.             input();
  935.          print("      \r");
  936.          if (i == ESC)
  937.             break;
  938.          else
  939.             i = 0;
  940.       }
  941.    }
  942.    fclose(fh);
  943. }
  944.