home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / hexpert / hex.c next >
Encoding:
C/C++ Source or Header  |  1992-01-09  |  21.6 KB  |  1,116 lines

  1. /*----------------------------------------------------------------------------*/
  2. /* Program: hex.c                                  */
  3. /* Date:    27-nov-1988                                  */
  4. /* Desc:    Hex editor source                              */
  5. /* Author:  Dominic Alston                              */
  6. /* Version: 2.4                                      */
  7. /* Revision history:                                   */
  8. /*    25-jan-1989  dom: Added terminal independant code                   */
  9. /*      30-jan-1989  dom: Redesigned screen, added features                   */
  10. /*    03-feb-1989  dom: Modified code.                      */
  11. /*    04-feb-1989  dom: Added own mmi routines                              */
  12. /*      05-feb-1989  dom: Version 2 Increment 0 release finished.             */
  13. /*      06-feb-1989  dom: Fixed goto out of band chars being accepted         */
  14. /*      20-feb-1989  dom: Added version print and readonly feature            */
  15. /*      23-feb-1989  dom: Added screen refresh.                               */
  16. /*----------------------------------------------------------------------------*/
  17.  
  18. #include <sys/types.h>
  19. #include <curses.h>
  20. #include <fcntl.h>
  21. #include <ctype.h>
  22. #include <errno.h>
  23. #include <signal.h>
  24. #include <sys/stat.h>
  25.  
  26. #define VERSION_STAMP "2.4"
  27. #define PAGESIZE 1280
  28. #define BUFSIZE 256
  29. #define READING    0
  30. #define WRITING    1
  31. #define GOTO 2
  32. #define DBUFF_SIZE 32
  33. #define FBUFF_SIZE 16
  34. #define X_PRODUCT 30
  35. #define Y_PRODUCT 0
  36. #define X_MENU1    0
  37. #define Y_MENU1    2
  38. #define X_MENU2    0
  39. #define Y_MENU2    3
  40. #define X_STATUS 0
  41. #define Y_STATUS 5
  42. #define X_FORMAT 76
  43. #define X_POSITION 19
  44. #define X_PROMPT 0
  45. #define Y_PROMPT 6
  46. #define X_INPUT 9
  47. #define X_FIND 9
  48. #define Y_FIND 6
  49. #define X_HEX 0
  50. #define Y_HEX 7
  51. #define X_CHAR 52
  52. #define Y_CHAR 7
  53. #define X_EXIT 0
  54. #define Y_EXIT 23
  55. #define X_VERB 36
  56. #define Y_VERB 5
  57. #define CTRL(c) ((c) & 037)
  58. #define _KEY_EXIT 'q'
  59. #define ENTER '\n'
  60. #define KEY_ESC    '\033'
  61. #define KEY_TAB    '\t'    
  62.  
  63. char *pos_get();
  64. int ctrlc_ast();
  65. static int ch;                /* buffer for single character read           */
  66. static char page[PAGESIZE];    /* buffer for screen display              */
  67. static char *hptr;        /* pointer to page for hex display          */
  68. static char *cptr;        /* pointer to page for character display      */
  69. static char buf[BUFSIZE];    /* buffer for input i/o                  */
  70. static char *bptr;        /* pointer to buf                  */
  71. static char pos[9];        /* buffer for character format of position    */
  72. static char find_buff[FBUFF_SIZE]; /* buffer holding the string for searching */
  73. static int find_length;         /* size of string searched for                */
  74. static char disp_buff[DBUFF_SIZE]; /* buffer holding the search string during */
  75. static int disp_length;
  76. static char hexchars[] = "0123456789ABCDEF";
  77. static char head1[] = "                      Hexpert [v2.4 (c)1988 Dominic Alston]                     ";
  78. static char r_head2[] = 
  79.     "Options: <Up-arrow>  =Page-up    <g>=Goto-position  <c> =Char-find  <q>=Exit   "; /* apm 27/1/85*/
  80. static char r_head3[] = 
  81.     "         <Down-arrow>=Page-down  <h>=Hex-find       <^l>=Refresh              ";
  82. static char head2[] = 
  83.     "Options: <Up-arrow>  =Page-up    <g>=Goto-position  <c>=Char-find  <q> =Exit"; /* apm 27/1/85*/
  84. static char head3[] = 
  85.     "         <Down-arrow>=Page-down  <e>=Edit-buffer    <h>=Hex-find   <^l>=Refresh";
  86. static char head4[] = 
  87.     "Status-  Position: 00000000   Mode: View   File: ";
  88. static char head5[] = 
  89.     "Options: <Enter>=Write-buffer  <Tab>=Toggle hex/char edit                      "; /* apm 27/1/85 */
  90. static char head6[] = 
  91.     "         <Esc>  =Restore buffer & goto view mode                               ";
  92. static char head7[] =
  93.     "Options: <Enter>=Do-search       <Left-arrow>= Move-left                       "; /* apm 27/1/85 */
  94. static char head8[] =
  95.     "         <Esc>  =Goto view mode  <Right-arrow>=Move-right                      ";
  96. static char edit1[] =
  97.     "Options: <Enter>=Goto-position   <Left-arrow>=Move-left                        ";
  98. static char edit2[] =
  99.     "         <Esc>  =Goto view mode  <Right-mode>=Move-right                       ";
  100. static char msg1[] = "pattern not found!";
  101. static char usage_bnr[]=
  102.     "Usage: hex [-vr] 'file'";
  103. static char version_bnr[]=
  104.     "HEXPERT V%s, Dominic Alston..\n";
  105. static char error1[] = "internal error - hex unpaired!";
  106. static int x,y;        /* screen co-ordinates                         */
  107. static int input;    /* file descriptor for input file              */
  108. static int mode;    /* current mode of use                      */
  109. static int readonly;    /* true if input file is read only              */
  110. static int save_flags;    /* dump of terminal info while in RAW mode           */
  111. static int bytes_written;
  112. static int bytes_read;
  113. static char hex_find;    /* true if find mode is currently hex              */
  114. static long position;    /* displacement of current buffer in input file          */
  115. static long lastbyte;   /* displacement of end of file     (Mod 256)            */
  116. static struct stat filedata; /* statistics of the input file,gives file size  */
  117. static int bool_hexfind=FALSE;
  118. extern char *optarg;
  119.  
  120. main(argc,argv)
  121. int argc;
  122. char *argv[];
  123. {
  124.     int c;
  125.     char filenm[80];
  126.  
  127.     while ((c=getopt(argc,argv,"vr:"))!=EOF)
  128.         switch(c)
  129.         {
  130.             case 'v':
  131.                 fprintf(stderr,version_bnr,
  132.                               VERSION_STAMP);
  133.                 exit(-1);
  134.             case 'r':
  135.                 readonly=TRUE;
  136.                 strcpy(filenm,optarg);
  137.                 break;    
  138.             default:
  139.                 fprintf(stderr,"%s\n",usage_bnr);
  140.                 exit(-1);
  141.         }
  142.     if (argc==1)
  143.     {
  144.         fprintf(stderr,"%s\n",usage_bnr);
  145.         exit(-1);
  146.     }
  147.     else
  148.         initialise(filenm[0]==0?argv[1]:filenm);
  149.     toplevel();
  150.     closedown();
  151. }
  152.  
  153. static initialise(filename)
  154. char *filename;
  155. {
  156.     register int i,j; 
  157.     char *ptr;
  158.  
  159.     /* Open file for read & write, if this fails                          */
  160.     /* open file for reading, if fail exit.                              */
  161.     if ((input=open(filename,O_RDWR))==-1) 
  162.         if ((input=open(filename,O_RDONLY))==-1)
  163.         {
  164.             perror(filename);
  165.             exit(-1);
  166.         }
  167.         else
  168.             readonly=TRUE;
  169.     init_term();        /* init curses terminfo                  */
  170.     signal(SIGINT,ctrlc_ast);   /* signal handler for contol c           */
  171.     /* Read the file statistics to find  the                              */
  172.     /* file size and put it in 'lastbyte',                                */
  173.     /* after adjusting to a multiple of 256                               */
  174.     if ((fstat(input,&filedata))==0)
  175.         lastbyte=(filedata.st_size-1) & 0x7fffff00;
  176.     else
  177.         lastbyte = 0;
  178.     /* Clear the display buffer.                               */
  179.     hptr=page;
  180.     for (i=0; i<PAGESIZE; i++) 
  181.         *hptr++=' ';
  182.     attron(A_REVERSE);
  183.     addstr(head1);
  184.     attroff(A_REVERSE);
  185.     toplev_headings();
  186.     mvaddstr(Y_STATUS, X_STATUS,head4);
  187.     /* Display the input file name.                                  */
  188.     i=strlen(filename);
  189.     ptr=filename;
  190.     if (i>33) 
  191.         i=33;
  192.     for (j=0; j<i; j++)
  193.         addch(*ptr++);
  194.     /* Read and display the first 256 bytes                              */
  195.     if (readonly)
  196.     {
  197.         attron(A_BOLD);
  198.         mvaddstr(Y_STATUS,72,"Readonly");
  199.         attroff(A_BOLD);
  200.     }
  201.     refresh();
  202.     position = 0;
  203.     lseek(input,position,0);
  204.     display();
  205.     mode = READING;
  206.     hex_find = FALSE;
  207.     find_length = 0;
  208.     put_prompt();
  209.     refresh();
  210. }
  211.  
  212. static display()
  213. {
  214.     int num;
  215.     register int i;
  216.     int j;
  217.     int jlimit;
  218.     char *pptr;
  219.  
  220.     hptr = page;
  221.     cptr = (hptr + 52);
  222.     bptr = buf;
  223.     pos_print();
  224.     move(Y_HEX, X_HEX);
  225.     if (((num=read(input,buf,BUFSIZE))!=EOF) && (num!=0)) 
  226.     {
  227.         if (num<BUFSIZE) 
  228.         {
  229.             for (i=0; i<PAGESIZE; i++) 
  230.                 *hptr++ = ' ';
  231.             hptr=page;
  232.         }
  233.         for (i=0; i<num; i+=16) 
  234.         {
  235.             jlimit=((num-i)>=16)?16:num-i;
  236.             for (j=0; j<jlimit; j++) 
  237.             {
  238.                 *hptr++=hexchars[(*bptr>>4) & 0xf];
  239.                 *hptr++=hexchars[*bptr & 0xf];
  240.                 *hptr++=' ';
  241.                 *cptr++=((*bptr)>0x1f &&
  242.                      (*bptr)<0x7f?*bptr:'.');
  243.                 bptr++;
  244.             }
  245.             *((cptr-jlimit)+80)='\n';
  246.             hptr+=32;
  247.             cptr=(hptr+52);
  248.         }
  249.     }
  250.     else
  251.         for(i=0; i<PAGESIZE; i++) 
  252.             *hptr++=' ';
  253.     bytes_read=num;
  254.     move(Y_HEX,X_HEX);
  255.     hptr=page;
  256.     for (i=0; i<PAGESIZE; i++)
  257.         addch(*hptr++);
  258.     bytes_written=i; 
  259.     if (bytes_written!=PAGESIZE) 
  260.         closedown();
  261.     put_prompt();
  262.     refresh();
  263. }
  264.  
  265. static closedown()
  266. {
  267.     reset_term();
  268.     exit(0);
  269. }
  270.  
  271. static toplevel()
  272. {
  273.     int num_read;
  274.  
  275.     while ((ch=getch())!=_KEY_EXIT)
  276.     {
  277.         clrtoeol();
  278.         refresh();
  279.         switch(ch) 
  280.         {
  281.             case CTRL('l'):
  282.                 clearok(curscr,TRUE);
  283.                 doupdate();
  284.                 break;
  285.             case KEY_HOME:
  286.                 if (position!=0)
  287.                 {
  288.                     position=0;
  289.                     lseek(input,position,0);
  290.                     display();
  291.                 }
  292.                 else
  293.                     beep();
  294.                 break;
  295.             case KEY_DOWN:    
  296.                 if (position != lastbyte) 
  297.                 {
  298.                     if ((position += 256) > lastbyte)
  299.                         position = lastbyte;
  300.                     lseek(input,position,0);
  301.                     display();
  302.                 }
  303.                 else
  304.                     beep();
  305.                 break;
  306.             case KEY_UP:
  307.                 if (position != 0)
  308.                 {
  309.                     position -= 256;
  310.                     if (position < 0)
  311.                         position = 0;
  312.                     lseek(input,position,0);
  313.                     display();
  314.                 }
  315.                 else
  316.                     beep();
  317.                 break;
  318.             case 'g':
  319.             case 'G':
  320.                 mode=GOTO;
  321.                 if (get_position())
  322.                 {
  323.                     lseek(input,position,0);
  324.                     display();
  325.                 }
  326.                 else
  327.                     pos_print();    
  328.                 toplev_headings();
  329.                 mode=READING;
  330.                 break;
  331.             case 'e':
  332.             case 'E':
  333.                 if (readonly) 
  334.                 {
  335.                     beep();
  336.                     move(6,9);
  337.                     refresh();
  338.                 }
  339.                 else
  340.                     editbuffer();
  341.                 break;
  342.             case 'c':
  343.             case 'C':
  344.             case 'h':
  345.             case 'H':
  346.                 if ((ch=='c') || (ch=='C'))
  347.                     hex_find=FALSE;
  348.                 else
  349.                     hex_find=TRUE;
  350.                 if (get_string()==1)
  351.                     find_string();
  352.                 toplev_headings();
  353.                 break;
  354.             default:    
  355.                 beep();
  356.                 break;
  357.         }
  358.     }
  359. }
  360.  
  361. static get_position()
  362. {
  363.     char num[9];
  364.     char *ptr1,*ptr2;
  365.     int status;
  366.     long posit;
  367.     register int i;
  368.  
  369.     edit_headings();
  370.     posit=0;
  371.     ptr1=num;
  372.     ptr2=pos;
  373.     for (i=0; i<9; i++) 
  374.         (*(ptr1++))=(*(ptr2++));
  375.     move(Y_STATUS,10);
  376.     disp_length=7;
  377.     if ((status=get_str(stdscr,Y_STATUS,X_POSITION,num,'0',8))==-1)
  378.         return(FALSE);
  379.     for (i=0; i<8; i++) 
  380.     {
  381.         posit=(posit<<4)+(num[i] & 0xf);
  382.         if (num[i]>'9') 
  383.             posit+=9;
  384.     }
  385.     if (posit<0) 
  386.         posit=0;
  387.     if (posit<=lastbyte) 
  388.         position=posit;
  389.     else 
  390.         position=lastbyte;
  391.     return(TRUE);
  392. }
  393.  
  394. static trace(a)
  395. char a;
  396. {
  397.     move(1,70);
  398.     addch(a);
  399.     refresh();
  400. }
  401.  
  402. static pos_print()
  403. {
  404.     char *ptr;
  405.  
  406.     ptr=pos+7;
  407.     *ptr--=hexchars[(position & 0xf)];
  408.     *ptr--=hexchars[((position>>4) & 0xf)];
  409.     *ptr--=hexchars[((position>>8) & 0xf)];
  410.     *ptr--=hexchars[((position>>12) & 0xf)];
  411.     *ptr--=hexchars[((position>>16) & 0xf)];
  412.     *ptr--=hexchars[((position>>20) & 0xf)];
  413.     *ptr--=hexchars[((position>>24) & 0xf)];
  414.     *ptr--=hexchars[((position>>28) & 0xf)];
  415.     *(ptr+8)=0;
  416.     mvaddstr(Y_STATUS,X_POSITION,pos);
  417. }
  418.  
  419. static editbuffer()
  420. {
  421.     /* Display edit headings    */
  422.     mvaddstr(Y_MENU1, X_MENU1,head5);
  423.     mvaddstr(Y_MENU2, X_MENU2,head6);
  424.     mvaddstr(Y_VERB, X_VERB,"Edit");
  425.     hex_ed();
  426.     mode = READING;
  427.         toplev_headings();
  428. }
  429.  
  430. /* read_headings: Display read headings */
  431. static toplev_headings()
  432. {
  433.     if (readonly)
  434.     {
  435.         mvaddstr(Y_MENU1, X_MENU1,r_head2);
  436.         mvaddstr(Y_MENU2, X_MENU2,r_head3);
  437.     }
  438.     else
  439.     {
  440.         mvaddstr(Y_MENU1, X_MENU1,head2);
  441.         mvaddstr(Y_MENU2, X_MENU2,head3);
  442.     }
  443.     mvaddstr(Y_VERB, X_VERB,"View");
  444.     move(Y_PROMPT, X_INPUT);
  445.     refresh();
  446. }
  447.  
  448. static char_ed()  /* Entered from hex_ed() when 'TAB' read. */
  449. {
  450.     char *ptr;
  451.     char *hptr;
  452.     char c1,c2;
  453.     int xx;
  454.     int num_read;
  455.  
  456.     /* get byte by mapping on to physical scale from screen scale         */
  457.     ptr=page+(y-7)*80+x;
  458.     move(y,x);
  459.     refresh();
  460.     do
  461.     {
  462.         ch=getch();
  463.         if ((ch)>=0x20 && (ch)<0x7f) 
  464.         {
  465.             addch(ch);
  466.             refresh();
  467.             *ptr = ch;
  468.             c1 = ch & 0xf;
  469.             c2 = (ch >> 4) & 0xf;
  470.             xx = (x - 52) * 3;
  471.             hptr = (ptr - x) + xx;
  472.             *hptr++ = hexchars[c2];
  473.             *hptr   = hexchars[c1];
  474.             move(y,xx);
  475.             addch(*--hptr);
  476.             addch(*++hptr);
  477.             refresh();
  478.             if (x == 67) 
  479.                 if (y < 22) 
  480.                 {
  481.                     ptr +=65;
  482.                     x = 52;
  483.                     y++;
  484.                 }
  485.                 else     
  486.                 {
  487.                     ptr = page + 52;
  488.                     x = 52;
  489.                     y = 7;
  490.                 }
  491.             else     
  492.             {
  493.                 ptr++;
  494.                 x++;
  495.             }
  496.         }
  497.         else if (ch==KEY_RIGHT)
  498.             if (x==67) 
  499.             {
  500.                 if (y<22) 
  501.                 {
  502.                     ptr+=65;
  503.                     x=52;
  504.                     y++;
  505.                 }
  506.                 else     
  507.                 {
  508.                     ptr=page+52;
  509.                     x=52;
  510.                     y=7;
  511.                 }
  512.             }
  513.             else     
  514.             {
  515.                 ptr++;
  516.                 x++;
  517.             }
  518.         else if (ch == KEY_LEFT)
  519.             if (x == 52) 
  520.             {
  521.                 if (y > 7) 
  522.                 {
  523.                     ptr -= 65;
  524.                     x = 67;
  525.                     y--;
  526.                 }
  527.                 else    
  528.                 {
  529.                     ptr += 1215;
  530.                     x = 67;
  531.                     y = 22;
  532.                 }
  533.             }
  534.             else    
  535.             {
  536.                 ptr--;
  537.                 x--;
  538.             }
  539.         else if (ch == KEY_UP) 
  540.             if (y > 7)    
  541.             {
  542.                 ptr -=80;
  543.                 y--;
  544.             }
  545.             else    
  546.             {
  547.                 ptr +=1200;
  548.                 y = 22;
  549.             }
  550.         else if (ch == KEY_DOWN) 
  551.             if (y < 22) 
  552.             {
  553.                 ptr +=80;
  554.                 y++;
  555.             }
  556.             else    
  557.             {
  558.                 ptr -=1200;
  559.                 y = 7;
  560.             }
  561.         else if (ch == KEY_ESC) 
  562.         {
  563.             lseek(input,position,0);
  564.             display();
  565.         }
  566.         else if ((ch == ENTER) || (ch == KEY_TAB))
  567.             /* do nothing */ ;
  568.         else 
  569.             beep();
  570.         move(y,x);
  571.         refresh();
  572.     }
  573.     while ((ch!=ENTER) && 
  574.                (ch!=KEY_TAB) && 
  575.                (ch!=KEY_ESC));
  576.     if (ch==ENTER) 
  577.     {
  578.         hex_to_buf();
  579.         lseek(input,position,0);
  580.         write(input,buf,bytes_read);
  581.     }
  582.     mode=READING;
  583. }
  584.  
  585. static hex_ed()
  586. {
  587.     char *ptr;
  588.     int num_read;
  589.  
  590.     ptr=page;
  591.     x=X_HEX;
  592.     y=Y_HEX;
  593.     move(y,x);
  594.     refresh();
  595.     do
  596.     {
  597.         ch=getch();
  598.         if (isxdigit(ch)) 
  599.         {
  600.             addch(toupper(ch));
  601.             refresh();
  602.             *ptr = ch;
  603.             {
  604.                 char *cptr,c1,c2;
  605.                 int xx;
  606.  
  607.                 if ((x%3) == 1)
  608.                     cptr = ptr - 1;
  609.                 else
  610.                     cptr = ptr;
  611.                 c1 = *cptr++;
  612.                 c2 = *cptr;
  613.                 if (c1 > '9')
  614.                     c1 = (c1 + 9) & 0xf;
  615.                 else
  616.                     c1 = c1 & 0xf;
  617.                 if (c2 > '9')
  618.                     c2 = (c2 + 9) & 0xf;
  619.                 else
  620.                     c2 = c2 & 0xf;
  621.                 c1 = (c1 << 4) + c2;
  622.                 xx = (x/3) + 52;
  623.                 move(y,xx);
  624.                 refresh();
  625.                 if ((c1>=0x20) && (c1<0x7f))
  626.                     addch(c1);
  627.                 else
  628.                     addch('.');
  629.                 refresh();
  630.             }
  631.             ptr++;
  632.             x++;
  633.             if (((x+1)%3)==0) 
  634.             {
  635.                 if (x==47) 
  636.                 {
  637.                     if (y<22) 
  638.                     {
  639.                         ptr+=33;
  640.                         x=0;
  641.                         y++;
  642.                     }
  643.                     else 
  644.                     {
  645.                         ptr=page;
  646.                         x=0;
  647.                         y=7;
  648.                     }
  649.                 }
  650.                 else    
  651.                 {
  652.                     ptr++;
  653.                     x++;
  654.                 }
  655.             }
  656.         }
  657.         else if (ch==KEY_RIGHT) 
  658.         {
  659.             ptr++;
  660.             x++;
  661.             if (((x+1)%3)==0) 
  662.                 if (x==47) 
  663.                     if (y<22) 
  664.                     {
  665.                         ptr+=33;
  666.                         x=0;
  667.                         y++;
  668.                     }
  669.                     else 
  670.                     {
  671.                         ptr=page;
  672.                         x=0;
  673.                         y=7;
  674.                     }
  675.                 else 
  676.                 {
  677.                     ptr++;
  678.                     x++;
  679.                 }
  680.         }
  681.         else if (ch==KEY_LEFT) 
  682.             if (x==0) 
  683.             {
  684.                 if (y>7) 
  685.                 {
  686.                     ptr -= 34;
  687.                     x = 46;
  688.                     y--;
  689.                 }
  690.                 else    
  691.                 {
  692.                     ptr += 1246;
  693.                     x = 46;
  694.                     y = 22;
  695.                 }
  696.             }
  697.             else    
  698.             {
  699.                 ptr--;
  700.                 x--;
  701.                 if (((x+1)%3)==0) 
  702.                 {
  703.                     ptr--;
  704.                     x--;
  705.                 }
  706.             }
  707.         else if (ch == KEY_UP) 
  708.             if (y > 7) 
  709.             {
  710.                 ptr -= 80;
  711.                 y--;
  712.             }
  713.             else     
  714.             {
  715.                 ptr += 1200;
  716.                 y = 22;
  717.             }
  718.         else if (ch == KEY_DOWN) 
  719.             if (y < 22) 
  720.             {
  721.                 ptr += 80;
  722.                 y++;
  723.             }
  724.             else 
  725.             {
  726.                 ptr -= 1200;
  727.                 y = 7;
  728.             }
  729.         else if (ch == KEY_ESC) 
  730.         {
  731.             lseek(input,position,0);
  732.             display();
  733.         }
  734.         else if (ch==ENTER);
  735.         else if (ch==KEY_TAB) 
  736.         { 
  737.             x = (x/3) + 52;
  738.             char_ed();
  739.             x = (x-52) * 3;
  740.             ptr = page + (y-7)*80 + x;
  741.         }
  742.         else 
  743.             beep();
  744.         move(y,x);
  745.         refresh();
  746.     }
  747.     while (ch!=ENTER && ch!=KEY_ESC);
  748.     if (ch==ENTER) 
  749.     {
  750.         hex_to_buf();
  751.         lseek(input,position,0);
  752.         write(input,buf,bytes_read);
  753.     }
  754. }
  755.  
  756. static hex_to_buf()
  757. {
  758.     char c1,c2;
  759.     int i;
  760.     int j;
  761.  
  762.     hptr = page;
  763.     bptr = buf;
  764.     for (i=0;i<16;i++) 
  765.     {
  766.         for (j=0;j<16;j++) 
  767.         {
  768.             c1 = *hptr++;
  769.             if (c1 > '9')
  770.                 c1 = (c1 + 9) & 0xf;
  771.             else
  772.                 c1 = c1 & 0xf;
  773.             c2 = *hptr++;
  774.             if (c2 > '9')
  775.                 c2 = (c2 + 9) & 0xf;
  776.             else
  777.                 c2 = c2 & 0xf;
  778.             *bptr++ = (c1 << 4) + c2;
  779.             hptr++;
  780.         }
  781.         hptr += 32;
  782.     }
  783. }
  784.  
  785.  
  786. static int get_string()
  787. {   
  788.     mvaddstr(Y_MENU1, X_MENU1,head7);
  789.     mvaddstr(Y_MENU2, X_MENU2,head8);
  790.     mvaddstr(Y_VERB, X_VERB,"Find");
  791.     attron(A_BOLD);
  792.     mvaddstr(6,0,"search criteria: ");
  793.     attroff(A_BOLD);
  794.     if ((bool_hexfind && !hex_find) || (!bool_hexfind && hex_find))
  795.     {
  796.         if (hex_find)
  797.             bool_hexfind=TRUE;
  798.         else if (!hex_find)
  799.             bool_hexfind=FALSE;
  800.         find_length=0;
  801.         disp_buff[0]=0;
  802.     }
  803.     if (hex_find)
  804.     {
  805.         buftoh(disp_buff,find_buff,find_length);
  806.         disp_length=find_length*2;
  807.     }
  808.     else
  809.         buftobuf(disp_buff,find_buff,disp_length=find_length);
  810.     if ((disp_length=get_str(stdscr,6,17,disp_buff,'.',
  811.          hex_find?DBUFF_SIZE:FBUFF_SIZE))==-1)
  812.     {
  813.         put_prompt();
  814.         return(FALSE);
  815.     }
  816.     else if (disp_length==0 && hex_find)
  817.         disp_length=find_length*2;
  818.     else if (disp_length==0 && !hex_find)
  819.         disp_length=find_length;
  820.     set_string();
  821.     return(TRUE);
  822. }
  823.  
  824. /* set_string: set up the string for return */
  825. static set_string()
  826. {
  827.     if (hex_find)
  828.     {
  829.         htobuf(find_buff,disp_buff,disp_length);
  830.         find_length=disp_length/2;
  831.     }
  832.     else 
  833.         buftobuf(find_buff,disp_buff,find_length=disp_length);
  834. }
  835.  
  836. /* buftoh: Converts input buffer to hexadecimal display in output string.
  837.  *         String length is used since zero is legitimate.
  838.  */
  839. static buftoh(out_string, in_string, in_size)
  840. char *in_string, *out_string;
  841. int in_size;
  842. {    
  843.     register int i;
  844.  
  845.     for (i=0; i < in_size; i++)
  846.     {
  847.         char ch = *in_string++;
  848.         *out_string++ = hexchars[(ch >> 4) & 0xf]; /* [ch/16]; */
  849.         *out_string++ = hexchars[ ch & 0xf]; /* [ch%16]; */
  850.     }
  851. }
  852.  
  853. /* htobuf: converts hexadecimal display to binary. String length is used
  854.  *         and only hexadecimal pairs are handled.
  855.  */
  856. static htobuf(out_string, in_string, in_size)
  857. char *in_string, *out_string;
  858. int in_size;
  859. {   
  860.     char i;
  861.     int h_value, c_value;
  862.     int byte_val;
  863.  
  864.     if (in_size%2 != 0) 
  865.     {
  866.         put_prompt();
  867.         addstr(error1);
  868.         beep();
  869.         refresh();
  870.         return;
  871.     }
  872.     for (i=0; i < in_size; i++)
  873.     {   
  874.         if ((h_value = *in_string++) >= '0' && h_value <= '9')
  875.                 c_value = h_value -'0';
  876.         else (c_value = 10 + (h_value & 0xf) - ('a' & 0xf));    
  877.         if (!(i%2))
  878.             byte_val = c_value * 16;
  879.         else 
  880.             *out_string++ = byte_val + c_value;
  881.     }
  882. }
  883.  
  884. /* buftobuf: Copy buffer to buffer. Not quite strncopy since zero is valid
  885.  *           and not a terminator.
  886.  */
  887. static buftobuf(out_string,in_string,in_size)
  888. char *in_string,*out_string;
  889. int in_size;
  890. {   
  891.     register int i;
  892.  
  893.     for (i=0; i<in_size; i++)
  894.         (*(out_string++))=(*(in_string++));
  895. }
  896.  
  897. /* find_string: Locates the string which has been specified by the user.
  898.  *        The search is carried out cyclically locating the string
  899.  *        specified at the beginning of the buffer. If the string is
  900.  *        not found we tell the user with a friendly message.
  901.  */
  902. int find_string()
  903. {   
  904.     long start_pos=position; /* hold start position to stop cyclic search */
  905.     int inc_length;
  906.     /* the number of start points for search in one buffer full */
  907.     int num_read; /* number read in this read */
  908.     int found_it=0;
  909.  
  910.     position ++;  /* make sure we move ahead */
  911.     inc_length=BUFSIZE-find_length;
  912.     /* search to the end of the file */
  913.     while (filedata.st_size>=position+find_length && found_it!=1)
  914.     {   
  915.         lseek(input,position,0);
  916.         num_read=read(input,buf,BUFSIZE);
  917.         if (search(buf,&position,num_read-find_length)) 
  918.             found_it=1;
  919.     } 
  920.     /* if still not found then search from beginning              */
  921.     if (found_it!=1)
  922.     {
  923.         position=0;
  924.         while (position<=start_pos && found_it!=1)
  925.         {   
  926.             lseek(input,position,0);
  927.             num_read=read(input,buf,BUFSIZE);
  928.             if (search(buf,&position,position+inc_length<start_pos?
  929.                      (int)inc_length:(int)(start_pos-position)))
  930.                 found_it=1;
  931.         }
  932.     }
  933.     if (found_it!=1)
  934.     {
  935.         put_prompt();
  936.         addstr(msg1);
  937.         beep();
  938.         refresh();
  939.         position = start_pos;
  940.         lseek(input,position,0);
  941.         return;
  942.     }
  943.     lseek(input, position, 0);
  944.     display();
  945. }
  946.  
  947. /* search: Search for the field described by find_buff and find_length in 
  948.  *         the parameter buf incrementing start as far as size.
  949.  *         Returning true if the string is found.
  950.  */
  951. int search(buf,start,size)
  952. char *buf;
  953. long *start;
  954. int size;
  955. {   
  956.     int i, j;
  957.  
  958.     i = 0;
  959.     j = -1;
  960.     while (i != find_length && j++ < size) /* loop through buffer */
  961.     {   
  962.         for (i=0; i<find_length && *(find_buff+i)==*(buf+i); i++)
  963.         /* loop through string (no body) */ ;
  964.         buf++;
  965.         }
  966.     *start+=j;
  967.     return (i==find_length);
  968. }
  969.  
  970. /* initialise term..                                  */
  971. init_term()
  972. {
  973.     initscr();        /* init curses terminfo                      */
  974.     keypad(stdscr,TRUE);    /* allow keypad use                      */
  975.     noecho();        /* set terminal to noecho                     */
  976.     cbreak();        /* raw input                           */
  977. }
  978.  
  979. /* reset term to the way it was                                  */
  980. reset_term()
  981. {
  982.     nocbreak();
  983.     echo();
  984.     endwin();
  985. }
  986.  
  987. /* get string routine                                  */
  988. int get_str(wnd,row,col,str,filler,str_size)
  989. WINDOW *wnd;
  990. int row,col,str_size;
  991. char filler;
  992. char *str;
  993. {
  994.     char out_buff[40];
  995.     int ccol=0,c,erase_flg=0;
  996.     register int i;
  997.     int leave=FALSE;
  998.     int status=0;
  999.  
  1000.     for (i=0; i<str_size; i++)    /* paste filler to field          */
  1001.         mvwaddch(wnd,row,col+i,filler);
  1002.     /* print contents of str                          */
  1003.     for (i=0; i<disp_length; i++)
  1004.         mvwaddch(wnd,row,col+i,str[i]);
  1005.     wmove(wnd,row,col);            /* move to field start          */
  1006.     wrefresh(wnd);                /* refresh whats been done    */
  1007.     while (!leave)
  1008.     {
  1009.         c=wgetch(wnd);
  1010.         switch(c)
  1011.         {
  1012.             case '\n':
  1013.             case '\r':
  1014.                 leave=TRUE;
  1015.                 break;
  1016.             case KEY_HOME:
  1017.                 ccol=0;
  1018.                 wmove(wnd,row,col+ccol);
  1019.                 refresh();
  1020.                 break;
  1021.             case CTRL('h'):
  1022.                 if (ccol>0)
  1023.                 {
  1024.                     if (--ccol<0)
  1025.                         ccol=0;
  1026.                           mvwaddch(wnd,row,col+ccol,filler);
  1027.                     wmove(wnd,row,col+ccol);
  1028.                     *(str+ccol)=' ';
  1029.                     wrefresh(wnd);
  1030.                 }
  1031.                 else
  1032.                     beep();
  1033.                 break;
  1034.             case KEY_ESC:            /* if escape pressed */
  1035.                 status=(char)-1;
  1036.                 leave=TRUE;
  1037.                 break;
  1038.             case KEY_LEFT:
  1039.                 erase_flg=1;
  1040.                 if (ccol>0)
  1041.                 {
  1042.                     if (--ccol<0)
  1043.                         ccol=0;
  1044.                               wmove(wnd,row,col+ccol);
  1045.                     wrefresh(wnd);
  1046.                 }
  1047.                 else
  1048.                     beep();
  1049.                 break;
  1050.             case KEY_RIGHT:
  1051.                 if (ccol<str_size-1)
  1052.                 {
  1053.                     if (++ccol>str_size)
  1054.                         ccol=str_size;
  1055.                         wmove(wnd,row,col+ccol);
  1056.                     wrefresh(wnd);
  1057.                 }
  1058.                 else
  1059.                     beep();
  1060.                 break;    
  1061.             default:            /* other chars         */
  1062.                 if ((((hex_find || mode==GOTO) && 
  1063.                         isxdigit(c)) || 
  1064.                     ((!hex_find && mode!=GOTO) && 
  1065.                     (c>=0x20 && c<0x7f))) &&
  1066.                     ccol<str_size)
  1067.                 {
  1068.                     if (erase_flg==0)
  1069.                         for (i=0; i<str_size; i++)
  1070.                         {
  1071.                             mvwaddch(wnd,row,col+i,
  1072.                                 filler);
  1073.                             str[i]=' ';
  1074.                         }
  1075.                     mvwaddch(wnd,row,col+ccol,c);
  1076.                     wrefresh(wnd);
  1077.                     *(str+ccol)=c;
  1078.                     if (++ccol>str_size)
  1079.                         ccol=str_size;
  1080.                 }
  1081.                 else
  1082.                     beep();
  1083.                 break;
  1084.         }
  1085.         erase_flg=1;
  1086.     }
  1087.     if (status==0)
  1088.         status=ccol;
  1089.     return(status);
  1090. }
  1091.  
  1092. ctrlc_ast(sig)
  1093. int sig;
  1094. {
  1095.     if (sig==SIGINT)
  1096.         closedown();
  1097.     else
  1098.         signal(SIGINT,ctrlc_ast);
  1099. }
  1100.  
  1101. put_prompt()
  1102. {
  1103.     move(6,0);
  1104.     clrtoeol();
  1105.     attron(A_BOLD);
  1106.     mvaddstr(Y_PROMPT, X_PROMPT,"command> ");
  1107.     attroff(A_BOLD);
  1108. }
  1109.  
  1110. edit_headings()
  1111. {
  1112.     mvaddstr(Y_MENU1, X_MENU1,edit1);
  1113.     mvaddstr(Y_MENU2, X_MENU2,edit2);
  1114.     mvaddstr(Y_VERB, X_VERB,"Goto");
  1115. }
  1116.