home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / tools / workbench / fv-220 / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-19  |  39.4 KB  |  1,568 lines

  1. /* fv is a binary file editor written by Chris Hooper (cdh@mtu.edu)
  2.  *    on 6-2-91 and has gone through many revisions since then.
  3.  *      Much inspiration was given by Bill Moore, the first real user!
  4.  *
  5.  *   Author:  CHRISTOPHER D HOOPER
  6.  *
  7.  *   fv source Copyright (c) 1992 - 1998  Chris Hooper
  8.  *
  9.  *   Modification and redistribution is strictly prohibited.
  10.  *   Sale of this software above media cost is prohibited.
  11.  *
  12.  *   Except for above two restrictions, this software may be used for
  13.  *       any purpose, commercial or private.
  14.  *
  15.  *   Disclaimer:  This product is fit for no use, foreign or domestic.
  16.  *                Use implies knowledge you intend to destroy something.
  17.  */
  18.  
  19. #define VERSION "@(#)fv  2.20  19-Jan-98  cdh"
  20.  
  21. #ifdef OS9
  22. _asm("_sysedit: equ 220");
  23. #endif
  24.  
  25. #include <stdio.h>
  26. #include <curses.h>
  27. #include <string.h>
  28. #if !defined(_OS9000) && !defined(_OSK)
  29. #    include <sys/types.h>
  30. #endif
  31. #include "main.h"
  32. #if !defined(Amiga) && !defined(OS9) && !defined(FreeBSD)
  33. #    include <malloc.h>
  34. #    include <unistd.h>
  35. #    include <ctype.h>
  36. #endif
  37. #ifdef Linux
  38. #    include    <sys/ioctl.h>
  39. #endif
  40. #include <signal.h>
  41. #include "edit.h"
  42. #include "screen.h"
  43. #include "io.h"
  44.  
  45. #ifdef Dynix
  46. #    include <sys/types.h>
  47. #endif
  48.  
  49. #if defined(NetBSD) || defined(Linux) || defined(__FreeBSD__)
  50. #    define _cury cury
  51. #    define _curx curx
  52. #endif
  53.  
  54. #ifdef OS9
  55. #    define _cury w_wrow
  56. #    define _curx w_wcol
  57. char *strdup(char *str);
  58. #endif
  59.  
  60. #ifdef LINT
  61. #    include "lint.h"
  62. #endif
  63.  
  64. #define WDISMAX        4
  65. #define KBUFMAX      1024
  66. #define HIGH_BUF_SIZE    65536
  67.  
  68. uchar   *buffer;                /* character pointer into display buffer */
  69. ulong   *ibuffer;               /* integer pointer into display buffer */
  70. char    *filename[256];         /* name of files currently being edited */
  71. char    kbuffer[KBUFMAX];       /* storage area for "automatic" keystrokes */
  72. char    out_string[512];        /* output buffering scratch space */ 
  73. char    *version         = VERSION; /* program version string */
  74. int     SWAPBYTES        = 0;   /* both display-only displacement */
  75. int     Swapbytes        = 0;   /* character cursor displacement */
  76. int     Zmode            = 1;   /* cycle for display character for nil */
  77. int     addis            = 0;   /* 1=address display mode on */
  78. int     alignment        = 1;   /* start out with single character {1,2,4,8} */
  79. int     buf_size         = 0;   /* size of display buffer */
  80. int     chdis            = 1;   /* 1=character display mode on */
  81. int     cpline           = 0;   /* number of characters (bytes) per line */
  82. int     divisor          = 0;   /* address display divisor/modulus for bottom */
  83. int     divisor2         = 0;   /* address display divisor/modulus for left */
  84. int     divmod           = 0;   /* toggle (divide or modulus) for bottom */
  85. int     divmod2          = 0;   /* toggle (divide or modulus) for left */
  86. int     filenames        = 0;   /* number of files in buffer */
  87. int     filenum          = 0;   /* number of file currently being edited */
  88. int     force_ronly      = 0;   /* 1=force file read-only */
  89. int     force_write      = 0;   /* 1=force file write mode */
  90. int     global_direction = 0;   /* direction of last search (o=forward) */
  91. int     global_num       = 0;   /* number of bytes last searched against */
  92. int     global_special[MAXLEN]; /* wildcard positions for search */
  93. int     global_type      = 0;   /* type of last search (hex or character) */
  94. int     kbuffer_size     = 0;   /* number of buffered keystrokes */
  95. int     max_buf_size     = 0;   /* maximum size of display buffer */
  96. int     mode             = STRING; /* display/search mode (words or string) */
  97. int     noscreen         = 0;   /* turn off all screen stuff */
  98. int     ronly            = 0;   /* 1=file is read-only */
  99. int     prompting        = 0;   /* flag for interrupt handler of search */
  100. int     swapbytes        = 0;   /* word cursor displacement */
  101. int     swapmode         = 0;   /* cycle for which of above three is active */
  102. int     view_address     = 0;   /* file address at top left corner of screen */
  103. int     wdis             = 1;   /* 1=word display mode on */
  104. int     wdismode         = 0;   /* word display mode, 0=hex, 1=dec, etc */
  105. int     wpline           = 0;   /* number of (4 byte) words per line */
  106. int     wref             = 0;   /* refresh window because of motion or change */
  107. int     zmode            = 1;   /* cycle for display chara of non-printable */
  108. int     daddr            = -1;  /* current buffered address */
  109. int     dirty            = 0;   /* buffer has dirty data */
  110. uchar   global_search[MAXLEN];  /* last search data */
  111. ulong   cursor_address   = 0;   /* current cursor position in file */
  112. ulong   last_viewed      = 0;   /* last address relocated from */
  113. ulong   fend             = 0;   /* size of file in bytes */
  114.  
  115. extern    ulong inbuf_size;
  116.  
  117. void sigint();
  118. #ifndef AMIGA
  119. void sigquit();
  120. #ifndef HPUX
  121. void sigwinch();
  122. #endif
  123. #endif
  124.  
  125. static void print_usage();
  126. static void kbuffer_append();
  127. static int  parse_string();
  128.  
  129. extern char *getenv();
  130.  
  131.  
  132. #ifdef Amiga
  133. int main(argc, argv)
  134. #else
  135. void main(argc, argv)
  136. #endif
  137. int argc;
  138. char *argv[];
  139. {
  140.     int    index = 0;
  141.     char    *ptr;
  142.  
  143.     while (*version != ' ')
  144.         version++;
  145.  
  146.     if ((ptr = getenv("FVINIT")) != NULL)
  147.         kbuffer_append(ptr);
  148.  
  149.     for (index = 1; index < argc; index++)
  150.         if (*(ptr = argv[index]) == '-')
  151.         for (ptr++; *ptr != '\0'; ptr++)
  152.             switch (*ptr) {
  153. #ifdef EDIT_MEMORY
  154.             case 'a':    /* access memory */
  155.                 index++;
  156.                 if ((index < argc) && isdigit(*argv[index])) {
  157.                     out_string[0] = '<';
  158.                     strcpy(out_string + 1, argv[index]);
  159.                     strcat(out_string, ">");
  160.                 filename[filenames++] = strdup(out_string);
  161.                 } else {
  162.                 fprintf(stderr, "No address for -a given\n");
  163.                 print_usage(argv[0], 0);
  164.                 exit(1);
  165.                 }
  166.                 break;
  167. #endif
  168.             case 'A':
  169.                 for (index = 0; index < 24; index++)
  170. #ifdef LITTLE_ENDIAN
  171.                     putchar(((char *) file_sz)[index ^ 3] ^ 64);
  172. #else
  173.                     putchar(((char *) file_sz)[index] ^ 64);
  174. #endif
  175.                 break;
  176.             case 'h':
  177.             case '?':
  178.             case '/':
  179.                 print_usage(argv[0], 0);
  180.                 exit(0);
  181.             case 'k':    /* buffer keystrokes */
  182.                 index++;
  183.                 if (index < argc)
  184.                 kbuffer_append(argv[index]);
  185.                 else {
  186.                 fprintf(stderr, "No command for -k given\n");
  187.                 print_usage(argv[0], 0);
  188.                 exit(1);
  189.                 }
  190.                 break;
  191.             case 'r':    /* force read-only */
  192.                 force_ronly = !force_ronly;
  193.                 break;
  194.             case 's':    /* turn off screen */
  195.                 noscreen = !noscreen;
  196.                 break;
  197.             case 'v':    /* version */
  198.                 print_usage(argv[0], 1);
  199.                 printf("%s\n", version);
  200.                 exit(0);
  201.                 break;
  202.             case 'w':    /* force write mode */
  203.                 force_write = !force_write;
  204.                 break;
  205.             default: 
  206.                 fprintf(stderr, "Unknown parameter -%s\n", ptr);
  207.                 print_usage(argv[0], 0);
  208.                 exit(1);
  209.             }
  210.         else
  211.         filename[filenames++] = ptr;
  212.  
  213.  
  214.     if (filenames == 0) {
  215.         fprintf(stderr, "No filename specified!  ");
  216.         print_usage(argv[0], 0);
  217.         exit(1);
  218.     }
  219.  
  220.     for (index = 0; index < filenames; index++)
  221.         if (open_file(index))
  222.             break;
  223.  
  224.     if (index < filenames)
  225.         filenum = index;
  226.     else
  227.         exit(1);
  228.  
  229.  
  230.     signal(SIGINT, sigint);
  231. #if !defined(AMIGA) && !defined(Win32)
  232.     signal(SIGQUIT, sigint);
  233. #if !defined(OS9) && !defined(HPUX)
  234.     if (!noscreen)
  235.         signal(SIGWINCH, sigwinch);
  236. #endif /* !OS9 */
  237. #endif /* !Amiga */
  238.  
  239.     assign_curses();
  240.     init();
  241.  
  242.     if (noscreen)
  243.         assign_dummy();
  244.  
  245.     if (fend < HIGH_BUF_SIZE)
  246.         max_buf_size = fend;
  247.  
  248.     if (max_buf_size < HIGH_BUF_SIZE)
  249.         max_buf_size = HIGH_BUF_SIZE;
  250.  
  251.     ibuffer = (ulong *) malloc(max_buf_size + MAXLEN);
  252.     if (ibuffer == NULL)
  253.         error_exit("main: malloc failed");
  254.  
  255.     buffer = (uchar *) ibuffer;
  256.  
  257.     if (!kbuffer_size)
  258.         status_filename();
  259.     else
  260.         wref = 1;
  261.  
  262.     refresh_buffer(1);
  263.  
  264.     if (!noscreen)
  265.         show_addr(view_address);
  266.  
  267.     edit_file();
  268.     close_file();
  269.  
  270.     de_init();
  271.     exit(0);
  272. }
  273.  
  274. void error_exit(str)
  275. char *str;
  276. {
  277.     de_init();
  278.     if (str)
  279.         fprintf(stderr, str);
  280.     exit(1);
  281. }
  282.  
  283. ulong file_sz[] =
  284. {0x03081209,0x13140f10,0x08051260,0x046e6008,0x0f0f1005,0x124a4040};
  285.  
  286. /************************************************************************/
  287. /*                                    */
  288. /*               Editor state machine                */
  289. /*                                    */
  290. /************************************************************************/
  291.  
  292. int edit_file()
  293. {
  294.     int ch = ' ';    /* input character */
  295.     int looptime = 1;    /* default number of times to execute operation */
  296.     int rollover = 1;    /* if non-zero digit entered previously */
  297.     int cref = 0;    /* refresh display because of cursor motion */
  298.     int temp;        /* temp calculation */
  299.     int temp2;        /* temp calculation */
  300.     int temp3;        /* temp calculation */
  301.     int addr;
  302.     int addr2;
  303.     int running = 1;    /* 0=terminating */
  304.  
  305.     update_cursor(ON);
  306.     if (!kbuffer_size)
  307.         xrefresh(main_window);
  308.     status_mode();
  309.  
  310.     while (running) {
  311.     ch = get_key();
  312.     if (((ch >= '1') && (ch <= '9')) ||
  313.         ((ch == '0') && (rollover == 0))) {
  314.         if (rollover)
  315.         looptime = ch - '0';
  316.         else
  317.         looptime = looptime * 10 + ch - '0';
  318.         rollover = 0;
  319.     } else {
  320.         if (rollover)
  321.         looptime = 1;
  322.  
  323.         while (looptime-- > 0)
  324.         switch (ch) {
  325.                 case 'a':    /* toggle address display */
  326.                 wref    = 1;
  327.                 addis = !addis;
  328.  
  329.                 wpline = (COLS - addis * 10) /
  330.                      (9 * wdis + chdis * 4);
  331.             cpline = wpline << 2;
  332.                 buf_size = (LINES - 1) * cpline;
  333.  
  334.                 if ((cursor_address - view_address) >= buf_size) {
  335.                     cursor_address  = view_address + buf_size - 1;
  336.                 ALIGN(cursor_address);
  337.                 }
  338.  
  339.                 xmove(main_window, 0, 0);
  340.                 xclrtobot(main_window);
  341.                 break;
  342.                 case 'A':    /* append bis cursor von mark to a file */
  343.             looptime = 0;
  344.                 write_mark(cursor_address, 1);
  345.                 wref = 1;
  346.                 break;
  347.                 case 'b':
  348. #ifndef EMACS_FEEL
  349.                 case 2:    /* ^B  back one page */
  350. #endif
  351. #ifdef KEY_SR
  352.             case KEY_SR:
  353. #endif
  354.                 last_viewed   = view_address;
  355.                 view_address -= buf_size;
  356.             VALIGN(view_address);
  357.                 if (view_address < 0)
  358.                     view_address = 0;
  359.                 if (cursor_address >= view_address + inbuf_size) {
  360.                 cursor_address -= buf_size;
  361.                 ALIGN(cursor_address);
  362.                 }
  363.                 wref    = 1;
  364.                 break;
  365.                 case 'c':    /* toggle character display */
  366.                 wref    = 1;
  367.                 chdis    = !chdis;
  368.                 temp    = wpline;
  369.                 if (chdis == 0)
  370.                     wdis = 1;
  371.  
  372.                 wpline = (COLS - addis * 10) /
  373.                      (9 * wdis + chdis * 4);
  374.             cpline = wpline << 2;
  375.                 buf_size = (LINES - 1) * cpline;
  376.  
  377.                 if (cursor_address >= view_address + inbuf_size) {
  378.                     cursor_address  = view_address + buf_size - 1;
  379.                 ALIGN(cursor_address);
  380.                 }
  381.                 xmove(main_window, 0, 0);
  382.                 xclrtobot(main_window);
  383.                 break;
  384.             /* ^C taken for SIGINT and 'q' below */
  385.                 case 'C':        /* copy bis cursor von mark to file */
  386.             looptime = 0;
  387.                 write_mark(cursor_address, 0);
  388.                 wref = 1;
  389.                 break;
  390.                 case 4:    /* ^D  down one half page */
  391.                 case 'd':
  392.                 if (view_address < fend - buf_size / 2) {
  393.                     last_viewed   = view_address;
  394.                     view_address += buf_size / 2;
  395.                     VALIGN(view_address);
  396.                     wref          = 1;
  397.                     if (cursor_address < view_address) {
  398.                         cursor_address += buf_size / 2;
  399.                 ALIGN(cursor_address);
  400.                 }
  401.                 }
  402.                 break;
  403.                 case 'D':    /* delete physical area */
  404.                 break;
  405.                 case 'f':
  406. #ifndef EMACS_FEEL
  407.                 case 6:    /* ^F  forward one page */
  408. #endif
  409. #ifdef KEY_SF
  410.             case KEY_SF:
  411. #endif
  412.                 if (view_address < fend - buf_size) {
  413.                     last_viewed   = view_address;
  414.                     view_address += buf_size;
  415.                 VALIGN(view_address);
  416.                     wref          = 1;
  417.                     if (cursor_address < view_address) {
  418.                 cursor_address += buf_size;
  419.                 ALIGN(cursor_address);
  420.                 }
  421.                 }
  422.                 break;
  423.                 case 'F':    /* select new file to edit */
  424. #ifdef KEY_OPEN
  425.             case KEY_OPEN:
  426. #endif
  427.             temp = select_file();
  428.             if (temp != filenum) {
  429.                 if (save_changes(1))
  430.                 break;
  431.                 close_file();
  432.                 view_address = 0;
  433.                 cursor_address = 0;
  434.                 daddr = -1;
  435.                 wref = 1;
  436.                 xmove(status_window, 0, 0);
  437.                 xclrtoeol(status_window);
  438.                 if (open_file(temp))
  439.                     filenum = temp;
  440.                 else if (open_file(filenum) == 0) {
  441.                     sprintf(out_string, "cannot reopen %s!\n",
  442.                                filename[filenum]);
  443.                     error_exit(out_string);
  444.                 }
  445.             } else {
  446.                 xmove(status_window, 0, 0);
  447.                 xclrtoeol(status_window);
  448.             }
  449.                 status_range(view_address, view_address + buf_size);
  450.             status_filename();
  451.             status_mode();
  452.                 break;
  453.                 case 'g':    /* go (jump) to address */
  454.             looptime = 0;
  455.                 temp = get_jump(view_address);
  456.             if (temp == -1) {
  457.                     status_mode();
  458.                 break;
  459.             }
  460.             temp <<= divisor;
  461.             ALIGN(temp);
  462.             extend_end(temp);
  463.                 if ((temp >= view_address) &&
  464.                     (temp <= view_address + inbuf_size)) {
  465.                     update_cursor(OFF);
  466.                     cref            = 1;
  467.                     cursor_address  = temp;
  468.                 } else if ((view_address != temp) &&
  469.                        (temp >= 0) && (temp <= fend)) {
  470.                     wref          = 1;
  471.                     last_viewed    = view_address;
  472.                     view_address   = temp;
  473.                     cursor_address = temp;
  474.                 }
  475.                 status_mode();
  476.                 break;
  477.             case 'G':    /* go to bottom of file */
  478.             /* eventually let user enter address below and this
  479.                would then let them Go to that address? */
  480.                 update_cursor(OFF);
  481.  
  482.             if (rollover == 0) {    /* jump to addr */
  483.                 cursor_address = ALIGNED(looptime + 1);
  484.                 if (cursor_address > fend - 1) {
  485.                 wref = 1;
  486.                 cursor_address = ALIGNED(fend - 1);
  487.                 }
  488.                 if ((cursor_address < view_address) ||
  489.                     (cursor_address > ALIGNED(view_address +
  490.                                               buf_size - 1))) {
  491.                 wref = 1;
  492.                 view_address = ALIGNED((cursor_address -
  493.                                         buf_size / 2) & ~3);
  494.                 } else
  495.                 cref = 1;
  496.             } else {        /* jump to end of file */
  497.                 if (cursor_address == ALIGNED(fend - 1))
  498.                 fend = file_end();
  499.                 cursor_address = ALIGNED(fend - 1);
  500.                 temp = fend - buf_size + alignment - 1;
  501.                 ALIGN(temp);
  502.                 if (view_address < temp) {
  503.                 wref        = 1;
  504.                 last_viewed  = view_address;
  505.                 view_address = temp;
  506.                 } else
  507.                 cref = 1;
  508.             }
  509.  
  510.             looptime = 0;
  511.                 break;
  512.                 case 7:    /* ^G  display current filename + cursor addr */
  513.                 status_filename();
  514.                 status_mode();
  515.                 break;
  516.                 case 'h':
  517. #ifdef EMACS_FEEL
  518.                 case 2:    /* ^B  back one page */
  519. #endif
  520. #ifdef KEY_LEFT
  521.             case KEY_LEFT:
  522. #endif
  523.                 update_cursor(OFF);
  524.                 cref = 1;
  525.  
  526.                 if (cursor_address >= alignment)
  527.                     cursor_address -= alignment;
  528.                 else if (cursor_address > 0)
  529.                 cursor_address = 0;
  530.  
  531.                 if (cursor_address < view_address) {
  532.                     wref         = 1;
  533.                     last_viewed   = view_address;
  534.                     view_address -= buf_size / 2;
  535.                 VALIGN(view_address);
  536.                     if (view_address < 0)
  537.                 view_address = 0;
  538.                 }
  539.                 break;
  540.                 case 'H':    /* move display (not cursor) left */
  541.                 last_viewed   = view_address;
  542.                 view_address += alignment;
  543. #ifdef ALIGN_VIEW
  544.                 if (view_address > fend - alignment) {
  545.                     view_address  = fend - 1;
  546.                 ALIGN(view_address);
  547.                 }
  548. #endif
  549.                 wref = 1;
  550.                 if (cursor_address < view_address)
  551.                     cursor_address = view_address;
  552.                 break;
  553.                 case 8:    /* ^H  Give simple help */
  554. #ifdef KEY_HELP
  555.             case KEY_HELP:
  556. #endif
  557.                 looptime = 0;
  558.                 help_me(0);
  559.                 xtouchwin(main_window);
  560.                 xrefresh(main_window);
  561.                 break;
  562.                 case 'I':    /* insert physical area */
  563.                 break;
  564.                 case 9:    /* ^I  toggle hex/string edit mode */
  565.                 mode = !mode;
  566.                 cref = 1;
  567.                 status_mode();
  568.                 break;
  569.                 case 'j':    /* move cursor down one line */
  570.                 case 14:    /* ^N - for Emacs users */
  571. #ifdef KEY_DOWN
  572.             case KEY_DOWN:
  573. #endif
  574.                 update_cursor(OFF);
  575.                 cref = 1;
  576.                 if (cursor_address < (fend - cpline)) {
  577.                     cursor_address += cpline;
  578.                     if (cursor_address >= view_address + buf_size) {
  579.                     last_viewed   = view_address;
  580.                     view_address += buf_size / 2;
  581. #ifdef ALIGN_VIEW
  582.                 ALIGN(view_address);
  583. #endif
  584.                     wref         = 1;
  585.                     if (view_address > fend) {
  586.                         view_address = fend - 1;
  587. #ifdef ALIGN_VIEW
  588.                     ALIGN(view_address);
  589. #endif
  590.                     }
  591.                     }
  592.                 }
  593.                 break;
  594.                 case 'J':    /* move display (not cursor) down */
  595.                 update_cursor(OFF);
  596.                 if (view_address > 0) {
  597.                     last_viewed = view_address;
  598.                     view_address -= cpline;
  599.                     if (view_address < 0)
  600.                     view_address = 0;
  601.                     if (cursor_address >= view_address + inbuf_size + cpline)
  602.                     cursor_address -= cpline;
  603.                 }
  604.                 wref  = 1;
  605.                 break;
  606.                 case 'k':    /* move cursor up one line */
  607.                 case 16:    /* ^P - for Emacs users */
  608. #ifdef KEY_UP
  609.             case KEY_UP:
  610. #endif
  611.                 update_cursor(OFF);
  612.                 cref = 1;
  613.  
  614.                 if (cursor_address >= cpline)
  615.                     cursor_address -= cpline;
  616.  
  617.                 if (cursor_address < view_address) {
  618.                     wref         = 1;
  619.                     last_viewed   = view_address;
  620.                     view_address -= buf_size / 2;
  621. #ifdef ALIGN_VIEW
  622.                 ALIGN(view_address);
  623. #endif
  624.                     if (view_address < 0)
  625.                 view_address = 0;
  626.                 }
  627.                 break;
  628.                 case 'K':    /* move display (not cursor) up */
  629.                 update_cursor(OFF);
  630.                 if (view_address < fend - cpline) {
  631.                     last_viewed   = view_address;
  632.                     view_address += cpline;
  633.                     if (cursor_address < view_address)
  634.                         cursor_address += cpline;
  635.                 }
  636.                 wref  = 1;
  637.                 break;
  638.                 case 'l':    /* move cursor right */
  639. #ifdef EMACS_FEEL
  640.                 case 6:    /* ^F */
  641. #endif
  642. #ifdef KEY_RIGHT
  643.             case KEY_RIGHT:
  644. #endif
  645.                 update_cursor(OFF);
  646.                 cref = 1;
  647.                 if (cursor_address < (fend - alignment)) {
  648.                     cursor_address += alignment;
  649.                     if (cursor_address >= (view_address + buf_size)) {
  650.                     wref         = 1;
  651.                     last_viewed   = view_address;
  652.                     view_address += buf_size / 2;
  653. #ifdef ALIGN_VIEW
  654.                 ALIGN(view_address);
  655. #endif
  656.                     if (view_address > fend)
  657.                         view_address = fend - 1;
  658.                     }
  659.                 }
  660.                 break;
  661.                 case 'L':        /* move display (not cursor) right */
  662.                 last_viewed   = view_address;
  663.                 view_address -= alignment;
  664.                 if (view_address < 0)
  665.                     view_address = 0;
  666.                 wref = 1;
  667.                 if (cursor_address >= view_address + inbuf_size + alignment) {
  668.                     cursor_address = view_address + inbuf_size - 1;
  669.                 ALIGN(cursor_address);
  670.                 }
  671.                 break;
  672.                 case 12:        /* ^L  redraw screen */
  673. #ifdef KEY_REFRESH
  674.                 case KEY_REFRESH:
  675. #endif
  676. #ifdef KEY_CLEAR
  677.                 case KEY_CLEAR:
  678. #endif
  679.             looptime = 0;
  680.                 wref = 1;
  681.                 daddr = -1;
  682.             if (noscreen)
  683.                 break;
  684.  
  685.                 xclear(stdscr);
  686.             xmove(stdscr, 0, 0);
  687.             xclrtobot(stdscr);
  688.                 xtouchwin(main_window);
  689.                 xtouchwin(status_window);
  690.  
  691.                 xrefresh(stdscr);
  692.  
  693.                 break;
  694.                 case 'm':    /* set mark */
  695. #ifdef KEY_MARK
  696.             case KEY_MARK:
  697. #endif
  698.                 set_mark(cursor_address);
  699.                 break;
  700.                 case 'M':    /* move to middle of screen */
  701.                 update_cursor(OFF);
  702.             cursor_address  = view_address + buf_size / 2;
  703.             ALIGN(cursor_address);
  704.             cref = 1;
  705.                 break;
  706.                 case '.':    /* repeat last edit command - must precede ^M */
  707. #ifdef KEY_REDO
  708.             case KEY_REDO:
  709. #endif
  710.             if (load_ksbuf_from_hist())
  711.                 case 13:    /* ^M  start edit mode */
  712.                 case 10:    /* ^J  start edit mode */
  713.             looptime = 0;
  714.                 addr  = cursor_address - view_address;
  715.                 addr2 = addr >> 2;
  716.                 temp  = ibuffer[addr2];
  717.                 temp2 = ibuffer[addr2 + 1];
  718.                 temp3 = ibuffer[addr2 + 2];
  719.             update_cursor(OFF);
  720. #if !defined(Dynix) && !defined(Linux) && !defined(FreeBSD) && !defined(HPUX)
  721.             if (!noscreen)
  722.                 raw();
  723. #endif
  724.                 prompting = 1;
  725.                 if (mode == STRING)
  726.                     edit_mem_string(addr);
  727.                 else
  728.                     edit_mem_base(addr, wdismode);
  729.                 prompting = 0;
  730. #if !defined(Dynix) && !defined(Linux) && !defined(FreeBSD) && !defined(HPUX)
  731.             if (!noscreen) {
  732.                 noraw();
  733. #    ifdef Solaris2
  734.                 cbreak();
  735. #    endif
  736.             }
  737. #endif
  738.                 status_mode();
  739.                 if ((temp  != ibuffer[addr2]) ||
  740.                     (temp2 != ibuffer[addr2 + 1]) ||
  741.                     (temp3 != ibuffer[addr2 + 2]))
  742.                     dirty = 1;
  743.                 wref = 1;
  744.                 break;
  745.                 case 'N':    /* switch search direction and re-search */
  746. #ifdef KEY_PREVIOUS
  747.             case KEY_PREVIOUS:
  748. #endif
  749.                 global_direction = !global_direction;
  750.                 case 'n':    /* search again for same thing */
  751. #ifdef KEY_NEXT
  752.             case KEY_NEXT:
  753. #endif
  754.                 if (save_changes(1))
  755.                 break;
  756.                 wref = 1;
  757.                 update_cursor(OFF);
  758.                 prompting = 1;
  759.                 cursor_address = generic_search(cursor_address);
  760.             ALIGN(cursor_address);
  761.                 prompting = 0;
  762.                 if ((cursor_address < view_address) ||
  763.                     (cursor_address >= view_address + inbuf_size)) {
  764.                     last_viewed = view_address;
  765.                     view_address = cursor_address;
  766.                     status_mode();
  767.                 }
  768.                 status_mode();
  769.                 daddr = -1;
  770.                 break;
  771.                 case 'o':    /* rotate display character for non-printable */
  772.                 if (save_changes(1))
  773.                 break;
  774.                 wref = 1;
  775.                 zmode++;
  776.                 zmode = zmode % 12;
  777.                 init_ascii();
  778.                 break;
  779.                 case 'O':    /* rotate display character for nil */
  780.                 if (save_changes(1))
  781.                 break;
  782.                 wref = 1;
  783.                 Zmode++;
  784.                 Zmode = Zmode % 12;
  785.                 init_ascii();
  786.                 break;
  787.             /* q and Q taken for exit below */
  788.                 case 'r':    /* reread/redisplay file */
  789.                 daddr = -1;
  790.                 wref = 1;
  791.                 break;
  792.                 case 'R':    /* change Read-only mode */
  793.             ronly = !ronly;
  794.             status_mode();
  795.                 break;
  796.                 case 's':    /* cycle byte swapping off, word, long, quad */
  797.             swapbytes |= Swapbytes | SWAPBYTES;
  798.             swapbytes += swapbytes + 1;
  799.             if (swapbytes == 15)
  800.                 swapbytes = 0;
  801.             if (swapmode == 1) {
  802.                 Swapbytes = swapbytes;
  803.                 swapbytes = 0;
  804.             } else if (swapmode == 2) {
  805.                 SWAPBYTES = swapbytes;
  806.                 swapbytes = 0;
  807.             }
  808.                 wref = 1;
  809.                 status_mode();
  810.                 break;
  811.                 case 'S':    /* toggle word or character display swapping */
  812.             swapmode = (swapmode + 1) % 3;
  813.             switch (swapmode) {
  814.                 case 0:
  815.                 swapbytes = SWAPBYTES;
  816.                 Swapbytes = 0;
  817.                 SWAPBYTES = 0;
  818.                 break;
  819.                 case 1:
  820.                 Swapbytes = swapbytes;
  821.                 swapbytes = 0;
  822.                 SWAPBYTES = 0;
  823.                 break;
  824.                 case 2:
  825.                 SWAPBYTES = Swapbytes;
  826.                 swapbytes = 0;
  827.                 Swapbytes = 0;
  828.                 break;
  829.             }
  830.                 wref = 1;
  831.                 status_mode();
  832.                 break;
  833.                 case 't':    /* toggle hex or decimal word display */
  834.             if (wdismode != 0)
  835.                 wdismode = -1;
  836.                 case 'T':    /* cycle word display hex,dec,float,double */
  837.                 wdismode = (wdismode + 1) % WDISMAX;
  838.                 switch (wdismode) {
  839.                     case 1:
  840.                     case 2:
  841.                     if (alignment < 4)
  842.                         alignment = 4;
  843.                     break;
  844.                     case 3:
  845.                 alignment = 8;
  846.                 }
  847.             ALIGN(cursor_address);
  848.             VALIGN(view_address);
  849.                 wref = 1;
  850.                 status_mode();
  851.                 break;
  852.                 case 21:    /* ^U  up one half page */
  853.                 case 'u':
  854.                 if (view_address > 0) {
  855.                     wref          = 1;
  856.                     last_viewed   = view_address;
  857.                     view_address -= buf_size / 2;
  858.                 VALIGN(view_address);
  859.                     if (view_address < 0)
  860.                         view_address = 0;
  861.                     if (cursor_address >= view_address + inbuf_size) {
  862. /*                        cursor_address  = view_address + inbuf_size - 1; */
  863.                         cursor_address -= buf_size / 2;
  864.                     ALIGN(cursor_address);
  865.                     }
  866.                 }
  867.                 break;
  868.                 case 'w':    /* toggle word display */
  869.                 wref = 1;
  870.                 wdis = !wdis;
  871.                 if (wdis == 0)
  872.                     chdis = 1;
  873.  
  874.                 wpline = (COLS - addis * 10) / (9 * wdis + chdis * 4);
  875.             cpline = wpline << 2;
  876.                 buf_size = (LINES - 1) * cpline;
  877.  
  878.                 if (cursor_address >= view_address + buf_size) {
  879.                     cursor_address  = view_address + buf_size - 1;
  880.                     ALIGN(cursor_address);
  881.                 }
  882.  
  883.                 xmove(main_window, 0, 0);
  884.                 xclrtobot(main_window);
  885.                 break;
  886.                 case 23:    /* ^W  write changes */
  887.                 case 'W':
  888. #ifdef KEY_SAVE
  889.             case KEY_SAVE:
  890. #endif
  891.             looptime = 0;
  892.                 if (save_changes(1))
  893.                 break;
  894.                 wref = 1;
  895.                 break;
  896. #ifndef EMACS_FEEL
  897.                 case 24:    /* ^X   exit program */
  898. #endif
  899.                 case 'q':
  900.                 case 'x':
  901. #ifdef KEY_EXIT
  902.             case KEY_EXIT:
  903. #endif
  904.             looptime = 0;
  905.                 if (save_changes(1))
  906.                 break;
  907.                 running = 0;
  908.                 break;
  909.                 case 3:    /* ^C  exit immediately - no save */
  910.                 case 'Q':
  911. #ifdef KEY_SEXIT
  912.             case KEY_SEXIT:
  913. #endif
  914.             dirty = 0;
  915.             looptime = 0;
  916.                 running = 0;
  917.                 break;
  918.                 case 'z':    /* relocate display, keeping cursor on addr */
  919.             ch = get_key();
  920.             switch (ch) {
  921.                 case '.':    /* center current line */
  922.                 temp = (cursor_address - buf_size / 2);
  923.                 ALIGN(temp);
  924.                 if (temp < 0)
  925.                     temp = 0;
  926.                 break;
  927.                 case '-':    /* line to bottom of screen */
  928.                 temp = cursor_address + cpline - buf_size;
  929.                 ALIGN(temp);
  930.                 if (temp < 0)
  931.                     temp = 0;
  932.                 break;
  933.                 case '+':    /* bottom line to top of screen */
  934.                 temp  = view_address + buf_size - cpline;
  935.                 if (temp >= fend)
  936.                     temp = fend - 1;
  937.                 ALIGN(temp);
  938.                 if (cursor_address < temp)
  939.                     cursor_address = temp;
  940.                 break;
  941.                 case 10:    /* ^J  line to top of screen */
  942.                 case 13:    /* ^M */
  943.                 temp = cursor_address;
  944.                 break;
  945.                 default:    /* unknown, stay there */
  946.                 temp = view_address;
  947.                 break;
  948.             }
  949.             if (view_address != temp) {
  950.                 last_viewed = view_address;
  951.                 view_address = temp;
  952.                 wref = 1;
  953.             }
  954.                 break;
  955.                 case 'Z':    /* save/exit if second Z received */
  956.             ch = get_key();
  957.             if (ch == 'Z') {
  958.                 looptime = 0;
  959.                 if (save_changes(0))
  960.                 break;
  961.                 running = 0;
  962.             }
  963.                 break;
  964. #ifdef ZERO_START
  965.                 case '0':    /* jump to start of file */
  966.                 update_cursor(OFF);
  967.                 if (view_address > 0) {
  968.                     last_viewed  = view_address;
  969.                     view_address = 0;
  970.                     wref        = 1;
  971.                     if (cursor_address >= view_address + inbuf_size) {
  972.                         cursor_address  = view_address + inbuf_size - 1;
  973.                 ALIGN(cursor_address);
  974.                     }
  975.                 } else {
  976.                     cursor_address = 0;
  977.                     cref    = 1;
  978.                 }
  979.                 break;
  980. #endif
  981.                 case '/':    /* search forward */
  982. #ifdef KEY_FIND
  983.             case KEY_FIND:
  984. #endif
  985.             global_direction = -1;
  986.                 case '?':    /* search backward */
  987. #ifdef KEY_SFIND
  988.             case KEY_SFIND:
  989. #endif
  990.             global_direction++;
  991.  
  992.                 if (save_changes(1))
  993.                 break;
  994.                 wref = 1;
  995.                 update_cursor(OFF);
  996.  
  997.             prompting = 1;
  998.  
  999. /*            global_direction = (ch == '?') ? 1 : 0; */
  1000. #if !defined(Dynix) && !defined(Linux) && !defined(FreeBSD) && !defined(HPUX)
  1001.             if (!noscreen)
  1002.                 raw();
  1003. #endif
  1004.                 if (mode == STRING)
  1005.                     cursor_address = find_str(cursor_address);
  1006.                 else
  1007.                     cursor_address = find_hex(cursor_address);
  1008.  
  1009.             prompting = 0;
  1010. #if !defined(Dynix) && !defined(Linux) && !defined(FreeBSD) && !defined(HPUX)
  1011.             if (!noscreen) {
  1012.                 noraw();
  1013. #    if defined(Solaris2)
  1014.                 cbreak();
  1015. #    endif
  1016.             }
  1017. #endif
  1018.  
  1019.                 ALIGN(cursor_address);
  1020.  
  1021.                 if ((cursor_address < view_address) ||
  1022.                     (cursor_address >= view_address + inbuf_size)) {
  1023.                     last_viewed = view_address;
  1024.                     view_address = cursor_address;
  1025.                 }
  1026.                 status_mode();
  1027.             wref = 1;
  1028.                 daddr = -1;
  1029.             if (looptime)
  1030.                 ch = 'n';
  1031.                 break;
  1032.                 case '^':    /* go to beginning of current display row */
  1033. #ifndef ZERO_START
  1034.                 case '0':
  1035. #endif
  1036. #ifdef KEY_SLEFT
  1037.             case KEY_SLEFT:
  1038. #endif
  1039.             update_cursor(OFF);
  1040.             cursor_address = view_address +
  1041.                      ((cursor_address - view_address) /
  1042.                       cpline) * cpline;
  1043.             ALIGN(cursor_address);
  1044.             cref = 1;
  1045.                 break;
  1046.                 case '$':    /* go to end of current display row */
  1047. #ifdef KEY_SRIGHT
  1048.             case KEY_SRIGHT:
  1049. #endif
  1050.             update_cursor(OFF);
  1051.             cursor_address = view_address +
  1052.                      ((cursor_address - view_address) /
  1053.                       cpline + 1) * cpline - 1;
  1054.             ALIGN(cursor_address);
  1055.             cref = 1;
  1056.                 break;
  1057.                 case '+':    /* increase number of columns in display */
  1058.                 case '=':
  1059.                 wref = 1;
  1060.                 wpline++;
  1061.                 if (wpline > (COLS - addis * 10)/(9 * wdis + chdis * 4))
  1062.                     wpline--;
  1063.             else
  1064.                 cpline += 4;
  1065.                 buf_size = (LINES - 1) * cpline;
  1066.  
  1067.                 break;
  1068.                 case '-':    /* decrease number of columns in display */
  1069.                 case '_':
  1070.                 wref = 1;
  1071.                 wpline--;
  1072.                 if (wpline < 1)
  1073.                     wpline++;
  1074.             else
  1075.                 cpline -= 4;
  1076.             cpline = wpline << 2;
  1077.                 buf_size = (LINES - 1) * cpline;
  1078.  
  1079.                 if (cursor_address >= view_address + buf_size) {
  1080.                     cursor_address  = view_address + buf_size - 1;
  1081.                     ALIGN(cursor_address);
  1082.                 }
  1083.  
  1084.                 xmove(main_window, 0, 0);
  1085.                 xclrtobot(main_window);
  1086.                 break;
  1087.                 case '\'':    /* jump to address of mark */
  1088.                 case '`':
  1089.             looptime = 0;
  1090.                 if ((temp = get_mark(-1)) != -1) {
  1091.                 ALIGN(temp);
  1092.                 last_viewed = cursor_address;
  1093.                     if ((temp > view_address + inbuf_size - 1) ||
  1094.                     (temp < view_address)) {
  1095.                     view_address   = temp;
  1096.                     cursor_address = temp;
  1097.                     wref          = 1;
  1098.                     } else {
  1099.                     update_cursor(OFF);
  1100.                     cursor_address = temp;
  1101.                     cref           = 1;
  1102.                     }
  1103.             }
  1104.                 break;
  1105.                 case ')':    /* cursor to bottom right corner of display */
  1106. #ifdef KEY_END
  1107.             case KEY_END:
  1108. #endif
  1109.                 update_cursor(OFF);
  1110.                 cursor_address  = view_address + inbuf_size - 1;
  1111.                 ALIGN(cursor_address);
  1112.                 cref = 1;
  1113.                 break;
  1114.                 case '(':    /* cursor to top left corner of display */
  1115. #ifdef KEY_HOME
  1116.             case KEY_HOME:
  1117. #endif
  1118.                 update_cursor(OFF);
  1119.                 cursor_address = view_address;
  1120.                 cref = 1;
  1121.                 break;
  1122.                 case '<':    /* increase alignment (cursor size) */
  1123.                 update_cursor(OFF);
  1124.                 alignment <<= 1;
  1125.                 if (alignment > 8)
  1126.                     alignment = 1;
  1127.                 status_mode();
  1128.                 cref = 1;
  1129.             ALIGN(cursor_address);
  1130.             if (cursor_address < view_address)
  1131.                 cursor_address += alignment;
  1132. #ifdef ALIGN_VIEW
  1133.             if (view_address & (alignment - 1)) {
  1134.                 ALIGN(view_address);
  1135.                 wref = 1;
  1136.             }
  1137. #endif
  1138.                 break;
  1139.                 case '>':    /* decrease alignment (cursor size) */
  1140.                 update_cursor(OFF);
  1141.                 alignment >>= 1;
  1142.                 if (alignment == 0)
  1143.                     alignment = 8;
  1144.                 status_mode();
  1145.                 cref = 1;
  1146.             ALIGN(cursor_address);
  1147. #ifdef ALIGN_VIEW
  1148.             if (view_address & (alignment - 1)) {
  1149.                 ALIGN(view_address);
  1150.                 wref = 1;
  1151.             }
  1152. #endif
  1153.                 break;
  1154.                 case '[':    /* double address display divisor -- bottom */
  1155.                 divisor++;
  1156.                 if (divisor > 29)
  1157.                     divisor = 29;
  1158.                 status_range(view_address, view_address + buf_size);
  1159.                 break;
  1160.                 case ']':    /* halve address display divisor -- bottom */
  1161.                 divisor--;
  1162.                 if (divisor < 0)
  1163.                     divisor = 0;
  1164.                 status_range(view_address, view_address + buf_size);
  1165.                 break;
  1166.                 case '{':    /* double address display divisor - left */
  1167.                 divisor2++;
  1168.                 if (divisor2 > 29)
  1169.                     divisor2 = 29;
  1170.                 status_range(view_address, view_address + buf_size);
  1171.                 wref = 1;
  1172.                 break;
  1173.                 case '}':    /* halve address display divisor - left */
  1174.                 divisor2--;
  1175.                 if (divisor2 < 0)
  1176.                     divisor2 = 0;
  1177.                 status_range(view_address, view_address + buf_size);
  1178.                 wref = 1;
  1179.                 break;
  1180.                 case '"':    /* toggle div or mod for bottom address disp */
  1181.                 divmod = !divmod;
  1182.                 status_range(view_address, view_address + buf_size);
  1183.                 break;
  1184.                 case '~':    /* toggle div or mod for left address disp */
  1185.                 divmod2 = !divmod2;
  1186.                 wref = 1;
  1187.                 break;
  1188. #ifdef COLON_MODE
  1189.             case ':':    /* enter colon command mode prompt */
  1190.             temp = colon_mode();
  1191.             if (temp == -1)
  1192.                 running = 0;
  1193.             else {
  1194.                 if (temp == 1) {
  1195.                 wref = 1;
  1196.                     status_filename();
  1197.                 }
  1198.                 status_range(view_address, view_address + buf_size);
  1199.                 status_mode();
  1200.             }
  1201.                 break;
  1202. #endif
  1203.             }
  1204.     if (kbuffer_size) {
  1205.         if (wref) {
  1206.         refresh_buffer(1);
  1207.         if (cursor_address < view_address)
  1208.             cursor_address = view_address;
  1209.         else if (cursor_address >= view_address + buf_size) {
  1210.              cursor_address  = view_address + buf_size - 1;
  1211.              ALIGN(cursor_address);
  1212.         }
  1213.         }
  1214.     } else
  1215.         if (wref | cref) {
  1216.             if (wref) {
  1217.             if (refresh_buffer(0)) {
  1218.                     view_address = last_viewed;
  1219.             refresh_buffer(1);
  1220.             }
  1221.             if (cursor_address < view_address)
  1222.                 cursor_address = view_address;
  1223.             else if (cursor_address >= view_address + buf_size) {
  1224.                     cursor_address  = view_address + buf_size - 1;
  1225.                     ALIGN(cursor_address);
  1226.                 }
  1227.             if (!noscreen)
  1228.                     show_addr(view_address);
  1229.             }
  1230.         
  1231.         if (!noscreen) {
  1232.             update_cursor(ON);
  1233. #ifndef Win32
  1234. #ifdef AMIGA
  1235.                 temp  = main_window->_maxy - 1;
  1236.                 temp2 = main_window->_maxx - 1;
  1237. #else
  1238.                 temp  = main_window->_cury;
  1239.                 temp2 = main_window->_curx - 1;
  1240. #endif
  1241.                 xmove(main_window, temp, temp2);
  1242.                 ch = winch(main_window);
  1243.                 xaddch(main_window, ch);
  1244. #endif
  1245.  
  1246.                 xmove(main_window, temp, temp2);
  1247.             xrefresh(main_window);
  1248.             if (wref)
  1249.                 xrefresh(main_window);
  1250.         }
  1251.         wref = 0;
  1252.         cref = 0;
  1253.         }
  1254.         rollover = 1;
  1255.     }
  1256.     }
  1257.  
  1258.     save_changes(1);
  1259.  
  1260.     if (!noscreen) {
  1261.     update_cursor(OFF);
  1262.     xrefresh(main_window);
  1263.     xstandend(main_window);
  1264.  
  1265.     xmove(status_window, 0, COLS - 10);
  1266.     xclrtoeol(status_window);
  1267.     }
  1268.     return(running);
  1269. }
  1270.  
  1271.  
  1272. static void kbuffer_append(str)
  1273. register char *str;
  1274. {
  1275.     char ch;
  1276.     register char *ptr;
  1277.     int len;
  1278.  
  1279.     len = parse_string(str);
  1280.  
  1281.     if (kbuffer_size + len > KBUFMAX) {
  1282.         de_init();
  1283.         fprintf(stderr, "key buffer overflow\n");
  1284.         exit(1);
  1285.     }
  1286.  
  1287.     ptr = kbuffer + kbuffer_size + len;
  1288.     kbuffer_size += len;
  1289.  
  1290.     while ((ch = *str++) != '\0')
  1291.         *--ptr = ch;
  1292. }
  1293.  
  1294. int get_key()
  1295. {
  1296.     if (kbuffer_size)
  1297.         return(kbuffer[--kbuffer_size]);
  1298.  
  1299. #ifdef OS9
  1300.     {
  1301.         int ch = xgetch(main_window) & 255;
  1302.  
  1303.         if (ch == 0xff)
  1304.             return(ESC);
  1305.         else
  1306.             return(ch);
  1307.     }
  1308. #else
  1309.     return(xgetch(main_window));
  1310. #endif
  1311.  
  1312. }
  1313.  
  1314.  
  1315. void unget_key(ch)
  1316. char ch;
  1317. {
  1318.     kbuffer[kbuffer_size++] = ch;
  1319. }
  1320.  
  1321. #define LINE(text) fprintf(stderr, text, len, "")
  1322.  
  1323.  
  1324. static void print_usage(progname, just_name)
  1325. char *progname;
  1326. int just_name;
  1327. {
  1328.     int len;
  1329.     char *program;
  1330.  
  1331.     for (program = progname; *program != '\0'; program++);
  1332.     for (--program; program > progname; program--)
  1333.         if ((*program == '/') || (*program == '\\')) {
  1334.         program++;
  1335.         break;
  1336.         }
  1337.  
  1338.     if (just_name) {
  1339.         printf("%s", program);
  1340.         return;
  1341.     }
  1342.  
  1343.     len = strlen(program);
  1344.  
  1345.     fprintf(stderr, "Usage is:\n%s [ -hrsvw ] %s%sfilename [ filename(s) ... ]\n",
  1346.             program,
  1347. #ifdef EDIT_MEMORY
  1348.             "[ -a RANGE ] ",
  1349. #else
  1350.             "",
  1351. #endif
  1352.             "[ -k STRING ] ");
  1353.  
  1354. #ifdef EDIT_MEMORY
  1355.     LINE("%*s -a = edit memory at ADDRESS[-ENDADDR or :SIZE]\n");
  1356. #endif
  1357.     LINE("%*s -h = display this help information\n");
  1358.     LINE("%*s -k = specify initial keystrokes to perform\n");
  1359.     LINE("%*s -r = force read only mode\n");
  1360.     LINE("%*s -s = perform editing with no screen\n");
  1361.     LINE("%*s -v = print version\n");
  1362.     LINE("%*s -w = force read / write mode\n");
  1363.     fprintf(stderr, "\n  Environment FVINIT specifies startup keystrokes.\n");
  1364.  
  1365.     fprintf(stderr, "\n%s\n       ", version);
  1366. #if defined(Amiga)
  1367.     fprintf(stderr, " Amiga");
  1368. #elif defined(Win32)
  1369.     fprintf(stderr, " Win32");
  1370. #elif defined(Dynix)
  1371.     fprintf(stderr, " Dynix");
  1372. #elif defined(Linux)
  1373.     fprintf(stderr, " Linux");
  1374. #elif defined(NetBSD)
  1375.     fprintf(stderr, " NetBSD");
  1376. #elif defined(FreeBSD)
  1377.     fprintf(stderr, " FreeBSD");
  1378. #elif defined(HPUX)
  1379.     fprintf(stderr, " HPUX");
  1380. #elif defined(OS9)
  1381. #    if defined _OS9000
  1382.     fprintf(stderr, " OS-9000");
  1383. #    else
  1384.     fprintf(stderr, " OS-9");
  1385. #    endif
  1386. #elif defined(SunOS)
  1387.     fprintf(stderr, " SunOS");
  1388. #elif defined(unix)
  1389.     fprintf(stderr, " UNIX");
  1390. #else
  1391.     fprintf(stderr, " Unknown host");
  1392. #endif
  1393.  
  1394. #if defined(STRICT_VI)
  1395.     fprintf(stderr, " Strict_VI");
  1396. #endif
  1397.  
  1398. #if defined(ZERO_START)
  1399.     fprintf(stderr, " Zero_Start");
  1400. #endif
  1401.  
  1402. #if defined(EMACS_FEEL)
  1403.     fprintf(stderr, " Emacs_Feel");
  1404. #endif
  1405.  
  1406. #if defined(ALIGN_VIEW)
  1407.     fprintf(stderr, " Align_View");
  1408. #endif
  1409.  
  1410. #if defined(SHOW_EXTASCII)
  1411.     fprintf(stderr, " Show_ExtASCII");
  1412. #endif
  1413.  
  1414. #if defined(EDIT_MEMORY)
  1415.     fprintf(stderr, " Edit_Memory");
  1416. #endif
  1417.  
  1418. #if defined(COLON_MODE)
  1419.     fprintf(stderr, " Colon_Mode");
  1420. #endif
  1421.  
  1422. #if defined(HUGE_BUFFER)
  1423.     fprintf(stderr, " Huge_Buffer");
  1424. #endif
  1425.  
  1426. #if defined(COLOR_CURSES)
  1427.     fprintf(stderr, " Color_Curses");
  1428. #endif
  1429.  
  1430. #if defined(DEBUG)
  1431.     fprintf(stderr, " Debug");
  1432. #endif
  1433.     fprintf(stderr, "\n");
  1434.  
  1435.     exit(1);
  1436. }
  1437.  
  1438.  
  1439. void sigint()            /* catch ^C */
  1440. {
  1441.     if (prompting) {
  1442.         stopping = 1;
  1443. #if defined(Solaris2) || defined(OS9)
  1444.         signal(SIGINT, (void (*)(int)) sigint);
  1445. #endif
  1446. #ifdef OS9
  1447.         get_key();
  1448. #endif
  1449.         return;
  1450.     }
  1451.  
  1452.     de_init();
  1453.     exit(0);
  1454. }
  1455.  
  1456. #if !defined(AMIGA) && !defined(Win32)
  1457. void sigquit()            /* catch ^\ */
  1458. {
  1459.     de_init();
  1460.     exit(0);
  1461. }
  1462.  
  1463. #if !defined(OS9) && !defined(HPUX)
  1464. void sigwinch()            /* catch window size changes */
  1465. {
  1466.     struct winsize buf;
  1467.  
  1468.     if (noscreen)
  1469.         return;
  1470.  
  1471.     de_init();
  1472.  
  1473.     ioctl(1, TIOCGWINSZ, &buf);
  1474.     COLS  = buf.ws_col;
  1475.     LINES = buf.ws_row;
  1476.  
  1477.     init();
  1478.  
  1479.     status_filename();
  1480.     last_viewed = view_address;
  1481.  
  1482.     refresh_buffer(0);
  1483.     show_addr(view_address);
  1484.     if (cursor_address >= view_address + buf_size) {
  1485.         cursor_address  = view_address + inbuf_size - 1;
  1486.         ALIGN(cursor_address);
  1487.     }
  1488.     update_cursor(ON);
  1489.     xrefresh(main_window);
  1490.     status_mode();
  1491. #ifdef Solaris2
  1492.     signal(SIGWINCH, (void (*)(int)) sigwinch);
  1493. #endif
  1494. }
  1495. #endif  /* !OS9 */
  1496. #endif    /* !AMIGA */
  1497.  
  1498.  
  1499. #ifndef isoctal
  1500. #define isoctal(x) ((x >= '0') && (x <= '7'))
  1501. #endif
  1502.  
  1503. static int parse_string(str)
  1504. char *str;
  1505. {
  1506.     char ch;
  1507.     register char *nstr;
  1508.     register char *ostr;
  1509.  
  1510.     ostr = str;
  1511.     nstr = str;
  1512.  
  1513.     while ((ch = *ostr++) != '\0')
  1514.         if (ch != '\\')
  1515.             *nstr++ = ch;    
  1516.         else
  1517.         if (isoctal(*ostr)) {
  1518.             ch = (*ostr++ - '0');
  1519.             if (isoctal(*ostr)) {
  1520.             ch <<= 3;
  1521.             ch += (*ostr++ - '0');
  1522.             if (isoctal(*ostr)) {
  1523.                 ch <<= 3;
  1524.                 ch += (*ostr++ - '0');
  1525.             }
  1526.             }
  1527.             *nstr++ = ch;
  1528.         } else
  1529.             switch ((ch = *ostr++)) {
  1530.             case '\0':
  1531.                 ostr--;
  1532.                 break;
  1533.             case 't':
  1534.                 *nstr++ = '\t';
  1535.                 break;
  1536.             case 'n':
  1537.                 *nstr++ = '\n';
  1538.                 break;
  1539.             case 'r':
  1540.                 *nstr++ = '\r';
  1541.                 break;
  1542.             case 'b':
  1543.                 *nstr++ = '\b';
  1544.                 break;
  1545.             default:
  1546.                 *nstr++ = ch;
  1547.                 break;
  1548.             }
  1549.  
  1550.     *nstr = '\0';
  1551.  
  1552.     return(nstr - str);
  1553. }
  1554.  
  1555. #ifdef OS9
  1556. char *strdup(char *str)
  1557. {
  1558.     int   len;
  1559.     char *newstr;
  1560.  
  1561.     len = strlen(str) + 1;
  1562.     if ((newstr = (char *) malloc(len)) == NULL)
  1563.         return(NULL);
  1564.  
  1565.     return(memcpy(newstr, str, len));
  1566. }
  1567. #endif
  1568.