home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 2 / MECOMP-CD-II.iso / amiga / tools / workbench / fv-220 / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-17  |  19.9 KB  |  815 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. #include <stdio.h>
  20. #include <curses.h>
  21. #include <string.h>
  22. #include "main.h"
  23. #if !defined(Amiga) && !defined(OS9) && !defined(FreeBSD)
  24. #    include <malloc.h>
  25. #endif
  26. #include "screen.h"
  27. #include "edit.h"
  28.  
  29. #ifdef NetBSD
  30. #    include <sys/ttycom.h>
  31. #endif
  32.  
  33. #ifdef Dynix
  34. #    include <sys/types.h>
  35. #endif
  36.  
  37. #ifdef LINT
  38. #    include "lint.h"
  39. #endif
  40.  
  41. char *NONWORD = ",<.>/?;:'`~[{]}=+-\\|!@#$%^&*() \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032";
  42.  
  43. #define MARKS   64
  44. extern    int    generic_search();
  45.  
  46. STATIC    void    light_string();
  47. STATIC    int    eget_key();
  48.  
  49. #define KSHISTMAX 256
  50. static    char    kshist[KSHISTMAX];
  51. static    int     kshistsize = 0;
  52.  
  53. #define KSFULLHISTMAX 1024
  54. static    char    ksfullhist[KSFULLHISTMAX];
  55. static    int     ksfullhistsize = 0;
  56.  
  57. #define KSBUFMAX 1024
  58. char    ksbuf[KSBUFMAX];
  59. int     ksbufsize = 0;
  60.  
  61.  
  62. int edit_mem_base(addr, base)
  63. int addr;
  64. int base;
  65. {
  66.     uchar    *origbuf;
  67.     int    ch = ' ';
  68.     int    cur = addr;
  69.     int    row = 0;
  70.     int    col = 0;
  71.     int    icur;
  72.     int    mrow, mcol;
  73.     int    value;
  74.  
  75.     stopping = 0;
  76.  
  77. #ifdef Amiga
  78.     leaveok(main_window, FALSE);
  79. #endif
  80.     xmove(status_window,  0, 20);
  81.     xaddstr(status_window, "hex editing..");
  82.     xclrtoeol(status_window);
  83.     xrefresh(status_window);
  84.  
  85.     origbuf = (uchar *) malloc(buf_size);
  86.     if (origbuf == NULL)
  87.         error_exit("edit_mem_base: malloc failed");
  88.  
  89.     memcpy(origbuf, buffer, buf_size);
  90.  
  91.     mcol = 2 * cpline - 1;
  92.     mrow = buf_size / cpline - 1;
  93.  
  94.     col = 2 * (addr % cpline);
  95.     row = addr / cpline;
  96.  
  97.     /* stop on ^M ^J ^D or ^C */
  98.     while ((ch != 13) && (ch != 10) && (ch != 4) && !stopping) {
  99.         cur = row * cpline + col / 2;
  100. #ifdef Amiga
  101.         xstandout(main_window);
  102.         light_string(cur, 0, 1);
  103. #endif
  104.         icur = cur ^ swapbytes;
  105.  
  106.         xmove(main_window, icur / cpline, 10 * addis +
  107.           (icur % cpline) * 2 + ((icur % cpline) >> 2) + (col & 1));
  108.         xrefresh(main_window);
  109.         ch = get_key();
  110. #ifdef Amiga
  111.         light_string(cur, 0, 1);
  112. #endif
  113.         switch (ch) {
  114.         case 8:        /* ^H  back */
  115.         case 127:
  116.         case 'h':
  117.         case 2:     /* ^B */
  118. #ifdef KEY_LEFT
  119.         case KEY_LEFT:
  120. #endif
  121.             if (col)
  122.             col--;
  123.             else if (row) {
  124.             row--;
  125.             col = mcol;
  126.             }
  127.             break;
  128.         case 'j':    /* down one row */
  129. #ifdef KEY_DOWN
  130.         case KEY_DOWN:
  131. #endif
  132.             if (row < mrow)
  133.             row++;
  134.             break;
  135.         case 'k':    /* up one row */
  136. #ifdef KEY_UP
  137.         case KEY_UP:
  138. #endif
  139.             if (row > 0)
  140.             row--;
  141.             break;
  142.         case 'l':    /* right one column */
  143.         case 6:     /* ^F */
  144. /*        case ' ':    commented out so paste of xxxx xxxx works */
  145. #ifdef KEY_RIGHT
  146.         case KEY_RIGHT:
  147. #endif
  148.             if (col < mcol)
  149.             col++;
  150.             else {
  151.             if (row < mrow) {
  152.                 row++;
  153.                 col = 0;
  154.             }
  155.             }
  156.             break;
  157.         case '^':    /* back to start */
  158.             col = 2 * (addr % cpline);
  159.             row = addr / cpline;
  160.             break;
  161. #ifndef EMACS_FEEL
  162.         case 24:    /* ^X  quit */
  163. #endif
  164.         case 3:        /* ^C */
  165.         case 'q':
  166.         case 'Q':
  167.             memcpy(buffer, origbuf, buf_size);
  168.             ch = 4;
  169.             break;
  170.         case '?':
  171.         case 'H':
  172. #ifdef KEY_HELP
  173.         case KEY_HELP:
  174. #endif
  175.             help_me(1);
  176.             xtouchwin(main_window);
  177.             xrefresh(main_window);
  178.             break;
  179.         default:    /* guess it is hex */
  180.             value = -1;
  181.             if ((ch >= '0') && (ch <= '9'))
  182.             value = ch - '0';
  183.             else if ((ch >= 'a') && (ch <= 'f'))
  184.             value = ch - 'a' + 10;
  185.             else if ((ch >= 'A') && (ch <= 'F')) {
  186.             value = ch - 'A' + 10;
  187.             ch += 'a' - 'A';
  188.             } else
  189.             break;
  190.  
  191.             cur = row * cpline + col / 2;
  192.             if (col & 1)        /* odd position */
  193.                 buffer[cur ^ SWAPBYTES] =
  194.                 (buffer[cur ^ SWAPBYTES] & 0xf0) | value;
  195.             else
  196.                 buffer[cur ^ SWAPBYTES] =
  197.                 (buffer[cur ^ SWAPBYTES] & 0x0f) | (value << 4);
  198.  
  199.             /* update in character area */
  200.             icur = cur ^ Swapbytes;
  201.             xmove(main_window, icur / cpline,
  202.                   10 * addis + wpline * 9 + (icur % cpline));
  203. #ifdef CHAR_COLOR
  204.             wattron(main_window, CHAR_COLOR);
  205. #endif
  206.             xaddch_filt(buffer[cur ^ SWAPBYTES]);
  207.  
  208.             /* update in word area */
  209.             icur = cur ^ swapbytes;
  210.             xmove(main_window, icur / cpline, 10 * addis +
  211.                   (icur % cpline) * 2 + ((icur % cpline) >> 2) +
  212.                   (col & 1));
  213. #ifdef WORD_COLOR
  214.             wattron(main_window, WORD_COLOR);
  215. #endif
  216.             xaddch(main_window, ch);
  217.  
  218.             if (col < mcol)
  219.                 col++;
  220.             else if (row < mrow) {
  221.                 row++;
  222.                 col = 0;
  223.             }
  224. #ifdef NO_COLOR
  225.             wattrset(main_window, 0);
  226. #endif
  227.         }
  228.     }
  229. #ifdef Amiga
  230.     leaveok(main_window, TRUE);
  231. #endif
  232.     xmove(status_window, 0, 20);
  233.     xclrtoeol(status_window);
  234.     xrefresh(status_window);
  235.     return(0);
  236. }
  237.  
  238.  
  239.  
  240. int edit_mem_string(addr)
  241. int addr;
  242. {
  243.     uchar    *origbuf;
  244.     uchar    *prevstr;
  245.     uchar    *prevstr2;
  246.     uchar    *prevstrtemp;
  247.     int    strsize;
  248.     int    strpsize;
  249.     int    cur;
  250.     int    index;
  251.     uchar    temp;
  252.     uchar    temp2;
  253.     int    old_alignment;
  254.     int    emode = 1;   /* esc mode */
  255.     int    amode = 0;   /* append mode */
  256.     int    rollover = 1;
  257.     int    looptime = 1;
  258.     int    ch = '\0';
  259.     int    ch2;
  260.     int    fixed_x_offset;
  261.     int    icur;
  262.  
  263.     stopping = 0;
  264.  
  265.     ksfullhistsize = 0;
  266.     old_alignment = alignment;
  267.     cur = addr;
  268.     for (cur = addr; ((cur < buf_size - 1) && buffer[cur ^ SWAPBYTES]); cur++);
  269.     strsize = cur - addr;
  270.     strpsize = strsize + 32;
  271.     origbuf = (uchar *) malloc(strpsize);
  272.     prevstr = (uchar *) malloc(strpsize);
  273.     prevstr2 = (uchar *) malloc(strpsize);
  274.     if ((origbuf == NULL) ||
  275.         (prevstr == NULL) ||
  276.         (prevstr2 == NULL))
  277.         error_exit("edit_mem_string: malloc failed");
  278.     memcpy(origbuf, buffer + addr, strpsize);
  279.     memcpy(prevstr, buffer + addr, strpsize);
  280.     memcpy(prevstr2, buffer + addr, strpsize);
  281.  
  282.  
  283.     xmove(status_window,  0, 20);
  284.     if (mode)
  285.         xaddstr(status_window, "string editing..");
  286.     else
  287.         xaddstr(status_window, "hex editing..");
  288.     xclrtoeol(status_window);
  289.     xrefresh(status_window);
  290.  
  291.     fixed_x_offset = addis * 10 + wpline * 9 * wdis;
  292.  
  293.     cur = addr;
  294.     do {            /* ^D - ends editing session */
  295.  
  296.         light_string(addr, 1, strsize);
  297.         light_string(addr + strsize, 0, strpsize - strsize);
  298.  
  299.         icur = cur ^ Swapbytes;
  300. #ifdef Amiga
  301.         light_string(cur, 2, 1);
  302. #endif
  303.         xmove(main_window, icur / cpline, fixed_x_offset + icur % cpline);
  304.  
  305.         xrefresh(main_window);
  306.  
  307.         ch = eget_key();
  308.  
  309.         if (emode)
  310.         if (strchr("~aAcCdDiIrRsx", ch))    /* edit cmds */
  311.             if (looptime > 1) {
  312.             sprintf(kshist, "%d%c", looptime, ch);
  313.             kshistsize = strlen(kshist);
  314.             } else {
  315.             kshist[0] = ch;
  316.             kshistsize = 1;
  317.             }
  318.         else if (strchr("?/.0^befG$\010\177hjkl uUtTw\012\015\030q\004\033", ch))
  319.             kshistsize--;            /* motion cmd */
  320.  
  321.         switch (ch) {    /* FOLLOWING WORK IN BOTH EDIT OR INSERT MODE */
  322. #ifndef EMACS_FEEL
  323.         case 24:    /* ^X  abort editing - must precede ^D */
  324.             memcpy(buffer + addr, origbuf, strpsize);
  325. #endif
  326.         case 4:        /* ^D - done editing */
  327.         case 10:    /* ^R */
  328.         case 13:    /* ^M */
  329.             ch = 4;    /* ^D */
  330.             break;
  331.         case ESC:    /* 27  return to command mode */
  332.             if (!emode && amode)
  333.             if (cur > addr)
  334.                 cur--;
  335.             looptime = 1;
  336.             rollover = 1;
  337.             emode = 1;
  338.             break;
  339.         case 8:        /* ^H delete character to left (or crsr left) */
  340.         case 127:    /* ^? */
  341.             if (looptime < 1)
  342.             looptime = 1;
  343.             if (emode) {
  344.             if (cur > addr)
  345.                 cur--;
  346.             break;
  347.             }
  348.             memcpy(prevstr, buffer + addr, strpsize);
  349.             if (cur > addr) {
  350.             cur--;
  351.             for (index = cur; index <= addr + strsize - looptime;
  352.                  index++)
  353.                 buffer[index ^ SWAPBYTES] =
  354.                 buffer[(index + looptime) ^ SWAPBYTES];
  355.             for (; index <= addr + strsize; index++)
  356.                 buffer[index ^ SWAPBYTES] = '\0';
  357.             }
  358.             break;
  359.         default:
  360.             if (emode)    /* EDIT MODE COMMAND */
  361.             if (((ch >= '1') && (ch <= '9')) ||
  362.                 ((ch == '0') && (rollover == 0))) {
  363.                 if (rollover)
  364.                 looptime = ch - '0';
  365.                 else
  366.                 looptime = looptime * 10 + ch - '0';
  367.                 rollover = 0;
  368.             } else {
  369.                 if (rollover)
  370.                 looptime = 1;
  371.                 else
  372.                 rollover = 1;
  373.  
  374.                 switch (ch) {
  375. #ifdef DEBUG
  376.                 case '?':
  377.                 printf("___%.*s___", kshistsize, kshist);
  378.                 break;
  379.                 case '/':
  380.                 printf("___%.*s___", ksbufsize, ksbuf);
  381.                 break;
  382. #endif
  383.                 case '.':
  384.                 while ((looptime--) &&
  385.                        (ksbufsize + kshistsize < 1023))
  386.                     for (index = kshistsize; index;)
  387.                     ksbuf[ksbufsize++] = kshist[--index];
  388.                 break;
  389.                 case '~':
  390.                 while (looptime--) {
  391.                     if (buffer[cur ^ SWAPBYTES] & 64)
  392.                     buffer[cur ^ SWAPBYTES] ^= 32;
  393.                     if (cur + 1 < addr + strpsize)
  394.                     cur++;
  395.                 }
  396.                 break;
  397.                 case '0':    /* beginning of line */
  398.                 cur = addr;
  399.                 break;
  400.                 case '^':    /* beginning of text */
  401.                 cur = addr;
  402.                 while ((cur == ' ') || (cur == '\t'))
  403.                     cur++;
  404.                 if (cur > addr + strpsize)
  405.                     cur = addr;
  406.                 break;
  407.                 case 'A':    /* append at end - must precede 'a' */
  408.                 cur = addr + strsize - 1;
  409.                 case 'a':    /* append after cursor */
  410.                 memcpy(prevstr, buffer + addr, strpsize);
  411.                 amode = 1;
  412.                 emode = 0;
  413.                 if (cur + 1 < addr + strpsize)
  414.                     cur++;
  415.                 break;
  416.                 case 'b':    /* back a single word */
  417.                 while (looptime--) {
  418.                     index = cur - 1;
  419.                     for (; index >= addr; index--)
  420.                     if (!strchr(NONWORD, buffer[index ^ SWAPBYTES]))
  421.                         break;
  422.                     for (; index >= addr; index--)
  423.                     if (strchr(NONWORD, buffer[index ^ SWAPBYTES]))
  424.                         break;
  425.                     else
  426.                         cur = index;
  427.                 }
  428.                 break;
  429.                 case 'c':    /* change (range) - must precede 'd' */
  430.                 emode = 0;
  431.                 case 'd':    /* delete (range) */
  432.                 memcpy(prevstr, buffer + addr, strpsize);
  433.                 ch2 = eget_key();
  434.  
  435.                 if (ch2 == 'w') {    /* word */
  436.                     while (looptime--) {
  437.                     if (strchr(NONWORD, buffer[cur ^ SWAPBYTES]))
  438.                         index = cur + 1;
  439.                     else
  440.                     for (index = cur + 1;
  441.                          index < addr + strsize; index++)
  442.                         if (strchr(NONWORD, buffer[index ^ SWAPBYTES]))
  443.                         break;
  444.                         temp = index - cur;
  445.                         if ((buffer[index ^ SWAPBYTES] == ' ') &&
  446.                         (ch == 'd'))
  447.                         temp++;
  448.                         for (index = cur; index <= (int)
  449.                          (addr + strsize - temp); index++)
  450.                         buffer[index ^ SWAPBYTES] = buffer[(index + temp) ^ SWAPBYTES];
  451.                         for (; index <= addr + strsize; index++)
  452.                         buffer[index ^ SWAPBYTES] = '\0';
  453.                     }
  454.                 } else if (ch2 == 't') {  /* to character */
  455.                     ch2 = eget_key();
  456.                     while (looptime--)
  457.                     for (index = cur + 1;
  458.                      index < addr + strsize; index++)
  459.                     if (buffer[index ^ SWAPBYTES] == ch2) {
  460.                         temp = index - cur;
  461.                         for (index = cur; index <= (int)(addr + strsize - temp); index++)
  462.                         buffer[index ^ SWAPBYTES] = buffer[(index + temp) ^ SWAPBYTES];
  463.                         for (; index <= addr + strsize; index++)
  464.                         buffer[index ^ SWAPBYTES] = '\0';
  465.                         break;
  466.                     }
  467.                 } else if (ch2 == 'f') {  /* including char. */
  468.                     ch2 = eget_key();
  469.                     while (looptime--)
  470.                     for (index = cur + 1;
  471.                          index < addr + strsize; index++)
  472.                     if (buffer[index ^ SWAPBYTES] == ch2) {
  473.                         temp = index - cur + 1;
  474.                         for (index = cur; index <= (addr +
  475.                                    strsize - temp); index++)
  476.                         buffer[index ^ SWAPBYTES] =
  477.                                        buffer[(index + temp) ^ SWAPBYTES];
  478.                         for (; index <= addr + strsize;
  479.                                                     index++)
  480.                         buffer[index ^ SWAPBYTES] = '\0';
  481.                         break;
  482.                     }
  483.                 } else if ((ch2 == '0') ||  /* start of line */
  484.                            (ch2 == '^')) {
  485.                     if (cur != addr) {
  486.                         temp = strsize - cur + addr;
  487.                         memcpy(buffer + addr,
  488.                                buffer + cur, temp);
  489.                         memset(buffer + addr + temp,
  490.                                0, cur - addr);
  491.                         cur = addr;
  492.                     }
  493.                 } else if (ch2 == '$')    /* rest of line */
  494.                     goto delete_line;
  495.                 break;
  496.                 case 'C':    /* change line - must precede 'D' */
  497.                 emode = 0;
  498.                 amode = 1;
  499.                 case 'D':    /* delete line - must follow 'C' */
  500.                 delete_line:
  501.                 memcpy(prevstr, buffer + addr, strpsize);
  502.                 for (index = cur; index <= addr + strsize; index++)
  503.                     buffer[index ^ SWAPBYTES] = '\0';
  504.                 break;
  505.                 case 'e':    /* go to end of current word */
  506.                 while (looptime--) {
  507.                     index = cur + 1;
  508.                     for (; index < addr + strpsize; index++)
  509.                     if (!strchr(NONWORD, buffer[index ^ SWAPBYTES]))
  510.                         break;
  511.                     for (; index < addr + strpsize; index++)
  512.                     if (strchr(NONWORD, buffer[index ^ SWAPBYTES]))
  513.                         break;
  514.                     else
  515.                         cur = index;
  516.                 }
  517.                 break;
  518.                 case 'f':    /* go to specific character */
  519.                 ch2 = eget_key();
  520.                 while (looptime--)
  521.                     for (index = cur + 1;
  522.                      index < addr + strsize; index++)
  523.                     if (buffer[index ^ SWAPBYTES] == ch2) {
  524.                         cur = index;
  525.                         break;
  526.                     }
  527.                 break;
  528.                 case 'I':    /* insert at start - must precede 'i' */
  529.                 cur = addr;
  530.                 case 'i':    /* insert at cursor position */
  531.                 memcpy(prevstr, buffer + addr, strpsize);
  532.                 emode = 0;
  533.                 break;
  534.                 case 'G':    /* go to end of string */
  535.                 case '$':
  536.                 cur = addr + strsize - 1;
  537.                 break;
  538.                 case 8:    /* ^H - go left one character */
  539.                 case 127:    /* ^? */
  540.                 case 'h':
  541.                 case 2:     /* ^B */
  542. #ifdef KEY_LEFT
  543.                 case KEY_LEFT:
  544. #endif
  545.                 while (looptime--)
  546.                     if (cur > addr)
  547.                     cur--;
  548.                 break;
  549.                 case 'j':    /* go down one row */
  550. #ifdef KEY_DOWN
  551.                 case KEY_DOWN:
  552. #endif
  553.                 while (looptime--)
  554.                     if (cur + cpline< addr + strpsize)
  555.                     cur += cpline;
  556.                 break;
  557.                 case 'k':    /* go up one row */
  558. #ifdef KEY_UP
  559.                 case KEY_UP:
  560. #endif
  561.                 while (looptime--)
  562.                     if (cur - cpline >= addr)
  563.                     cur -= cpline;
  564.                 break;
  565.                 case 'l':    /* go right one character */
  566.                 case ' ':
  567.                 case 6:     /* ^F */
  568. #ifdef KEY_RIGHT
  569.                 case KEY_RIGHT:
  570. #endif
  571.                 while (looptime--)
  572.                     if (cur + 1 < addr + strpsize)
  573.                     cur++;
  574.                 break;
  575.                 case 'q':    /* terminate edit - no change */
  576.                 case 3:    /* ^C */
  577. #ifndef EMACS_FEEL
  578.                 case 24:    /* ^X */
  579. #endif
  580.                 memcpy(buffer + addr, origbuf, strpsize);
  581.                 ch = '\004';
  582.                 break;
  583.                 case 'r':    /* replace character */
  584.                 memcpy(prevstr, buffer + addr, strpsize);
  585.                 while (looptime--)
  586.                     if (cur < addr + strpsize) {
  587.                     ch2 = eget_key();
  588.                     buffer[cur ^ SWAPBYTES] = ch2;
  589.                         light_string(addr, 1, strsize);
  590.                         light_string(addr + strsize, 0,
  591.                              strpsize - strsize);
  592.                     cur++;
  593.                         icur = cur ^ Swapbytes;
  594.                         xmove(main_window, icur / cpline,
  595.                           fixed_x_offset + icur % cpline);
  596.                         xrefresh(main_window);
  597.                     }
  598.                 break;
  599.                 case 'R':    /* overstrike mode */
  600.                 memcpy(prevstr, buffer + addr, strpsize);
  601.                 ch2 = eget_key();
  602.                 while (ch2 != ESC) {
  603.                     if ((ch2 == 8) || (ch2 == 127)) {
  604.                     if (cur > addr)
  605.                         cur--;
  606.                     } else {
  607.                     if (cur < addr + strpsize) {
  608.                         buffer[cur ^ SWAPBYTES] = ch2;
  609.                     } else
  610.                         break;
  611.                     cur++;
  612.                     }
  613.                     light_string(addr, 1, strsize);
  614.                     light_string(addr + strsize, 0,
  615.                          strpsize - strsize);
  616.                     icur = cur ^ Swapbytes;
  617.                     xmove(main_window, icur / cpline,
  618.                       fixed_x_offset + icur % cpline);
  619.                     xrefresh(main_window);
  620.  
  621.                     ch2 = eget_key();
  622.                 }
  623.                 break;
  624.                 case 's':    /* substitute string for character */
  625.                 memcpy(prevstr, buffer + addr, strpsize);
  626.                 for (index = cur; index <= addr+strsize-looptime; index++)
  627.                     buffer[index ^ SWAPBYTES] = buffer[(index + looptime) ^ SWAPBYTES];
  628.                 for (; index <= addr + strsize; index++)
  629.                     buffer[index ^ SWAPBYTES] = '\0';
  630.                 emode = 0;
  631.                 break;
  632.                 case 't':    /* move forward just before character */
  633.                 case 'T':
  634.                 ch2 = eget_key();
  635.                 while (looptime--)
  636.                     for (index = cur + 1;
  637.                      index < addr + strsize; index++)
  638.                     if (buffer[index ^ SWAPBYTES] == ch2) {
  639.                         cur = index - 1;
  640.                         break;
  641.                     }
  642.                 break;
  643.                 case 'u':    /* undo last edit */
  644.                 memcpy(prevstr2, buffer + addr, strpsize);
  645.                 memcpy(buffer + addr, prevstr, strpsize);
  646.                 prevstrtemp = prevstr;
  647.                 prevstr = prevstr2;
  648.                 prevstr2 = prevstrtemp;
  649.                 break;
  650.                 case 'U':    /* Undo all edits */
  651.                 memcpy(prevstr, buffer + addr, strpsize);
  652.                 memcpy(buffer + addr, origbuf, strpsize);
  653.                 break;
  654.                 case 'w':    /* move forward to next word */
  655.                 while (looptime--)
  656.                     for (index = cur + 1; index < addr + strpsize;index++)
  657.                     if (strchr(NONWORD, buffer[index ^ SWAPBYTES])) {
  658.                         for (index++; index < addr + strpsize;index++)
  659.                         if (!strchr(NONWORD, buffer[index ^ SWAPBYTES])) {
  660.                             cur = index;
  661.                             break;
  662.                         }
  663.                         break;
  664.                     }
  665.                 break;
  666.                 case 'x':    /* delete character */
  667.                 memcpy(prevstr, buffer + addr, strpsize);
  668.                 for (index = cur; index <= addr+strsize-looptime; index++)
  669.                     buffer[index ^ SWAPBYTES] = buffer[(index + looptime) ^ SWAPBYTES];
  670.                 for (; index <= addr + strsize; index++)
  671.                     buffer[index ^ SWAPBYTES] = '\0';
  672.                 break;
  673.                 case '?':    /* help me */
  674. #ifdef KEY_HELP
  675.                 case KEY_HELP:
  676. #endif
  677.                 help_me(2);
  678.                 xtouchwin(main_window);
  679.                 xrefresh(main_window);
  680.                 break;
  681.                 }
  682.             }
  683.             else {   /* INSERT MODE (CHARACTER) */
  684.                 if (ch == 22)  /* ^V - insert verbose next character */
  685.                 temp = eget_key();
  686.             else
  687.                 temp = ch;
  688.             for (index = cur; index < addr + strsize; index++) {
  689.                 temp2 = buffer[index ^ SWAPBYTES];
  690.                 buffer[index ^ SWAPBYTES] = temp;
  691.                 temp = temp2;
  692.             }
  693.             if ((index == cur) && (index < addr + strpsize)) {
  694.                 buffer[index ^ SWAPBYTES] = temp;  /* already at end of buffer, add more */
  695.             }
  696.             if (cur + 1 < addr + strpsize)
  697.                 cur++;
  698.             }
  699.         }
  700.     } while ((ch != 4) && !stopping);    /* ^D or ^C - end editing session */
  701.     light_string(addr, 0, strsize);
  702.  
  703.     alignment = old_alignment;
  704.     xmove(status_window,  0, 20);
  705.     xclrtoeol(status_window);
  706.     xrefresh(status_window);
  707.  
  708.     free(origbuf);
  709.     free(prevstr);
  710.  
  711.     return(0);
  712. }
  713.  
  714.  
  715. STATIC void light_string(addr, hi, strsize)
  716. int addr;
  717. int hi;
  718. int strsize;
  719. {
  720.     int cur;
  721.     int icur;
  722.  
  723.     if (hi > 0)
  724.         xstandout(main_window);
  725.  
  726.     if (chdis) {
  727. #if defined(CRSR_COLOR) || defined(WORD_COLOR) || defined(CHAR_COLOR)
  728.         if (!noscreen)
  729.         if (hi == 2)
  730.             wattron(main_window, CRSR_COLOR);
  731.         else if (hi)
  732.             wattron(main_window, WORD_COLOR);
  733.         else
  734.             wattron(main_window, CHAR_COLOR);
  735. #endif
  736.         cur = addr;
  737.         while ((cur < buf_size - 1) && ((cur - addr) < strsize)) {
  738.         icur = cur ^ Swapbytes;
  739.         xmove(main_window, icur / cpline,
  740.               addis * 10 + wpline * 9 * wdis +
  741.               (icur % cpline));
  742.         xaddch_filt(buffer[cur ^ SWAPBYTES]);
  743.         cur++;
  744.         }
  745.     }
  746.  
  747.     if (wdis) {
  748. #if defined(CRSR_COLOR) || defined(WORD_COLOR) || defined(CHAR_COLOR)
  749.         if (!noscreen)
  750.         if (hi == 2)
  751.             wattron(main_window, CRSR_COLOR);
  752.         else if (hi)
  753.             wattron(main_window, CHAR_COLOR);
  754.         else
  755.             wattron(main_window, WORD_COLOR);
  756. #endif
  757.         cur = addr;
  758.         while ((cur < buf_size - 1) && ((cur - addr) < strsize)) {
  759.         icur = cur ^ swapbytes;
  760.         xmove(main_window, icur / cpline,
  761.               addis * 10 + ((icur >> 2) % wpline) * 9 +
  762.               (icur & 3) * 2);
  763.         xaddch(main_window, hex[buffer[cur ^ SWAPBYTES] >> 4]);
  764.         xaddch(main_window, hex[buffer[cur ^ SWAPBYTES] & 15]);
  765.         cur++;
  766.         }
  767.     }
  768.  
  769.     if (hi > 0)
  770.         xstandend(main_window);
  771.  
  772. #ifdef NO_COLOR
  773.     if (!noscreen)
  774.         wattrset(main_window, 0);
  775. #endif
  776. }
  777.  
  778.  
  779. STATIC int eget_key()
  780. {
  781.     int ch;
  782.  
  783.     if (ksbufsize)
  784.     ch = ksbuf[--ksbufsize];
  785.     else
  786.     ch = get_key();
  787.  
  788.     if (ch != '.')
  789.     ksfullhist[ksfullhistsize++] = ch;
  790.     kshist[kshistsize++] = ch;
  791.  
  792.     return(ch);
  793. }
  794.  
  795. int load_ksbuf_from_hist()
  796. {
  797.     int index;
  798.  
  799.     if (kshistsize == 0)
  800.     return(1);
  801.  
  802.     ksbufsize = 0;
  803.  
  804. #ifdef NOT
  805.     /* following is not needed because buffer contains exit keystrokes */
  806.     ksbuf[ksbufsize++] = 4;         /* ^D */
  807.     ksbuf[ksbufsize++] = 27;        /* ESC */
  808. #endif
  809.  
  810.     for (index = ksfullhistsize; index && (ksfullhistsize < KSBUFMAX - 1); )
  811.     ksbuf[ksbufsize++] = ksfullhist[--index];
  812.  
  813.     return(0);
  814. }
  815.