home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume7 / rvi / part3 / rv_insert.c next >
Encoding:
C/C++ Source or Header  |  1989-04-09  |  9.8 KB  |  501 lines

  1. #include "rv.h"
  2. #include <ctype.h>
  3.  
  4. #define ALLOC_LEN  64  /* Size of reallocation chunk */
  5.  
  6. boolean replace_flag;        /* TRUE if R command */
  7. boolean superquote;        /* Set by rv_getchar if char is quoted by ^V */
  8. extern INT autoindent;        /* Physical autoindent, if opened_line */
  9.  
  10.        char *fake_input;    /* Set this to fake text into rv_getchar */
  11. static char fake_buf[512];    /* Buffer for faked characters */
  12. extern char *realloc();
  13.  
  14.  
  15. void
  16. insert()
  17. /*
  18.  * Insert input at the current cursor position, replacing
  19.  * text up to lastcol.  If lastcol < cursor, no text replaced.
  20.  */
  21. {
  22.     register struct sc_screen *sc;
  23.     register struct li_line   *line;
  24.     boolean    quick_append;
  25.     INT    i;
  26.     char    *s, *indentbuf;
  27.     void    fake_chars();
  28.  
  29.     file.fi_modified = TRUE;
  30.     /*
  31.      * sc_firstcol = first column of insertion. Fixed.
  32.      * sc_lastcol  = last column of insertion.  Grows.
  33.      * sc_column   = current cursor position
  34.      */
  35.  
  36. nextinsert:
  37.     input_mode = TRUE;
  38.     quick_append = FALSE;
  39.     indentbuf = NULL;
  40.     save_Undo();
  41.     sc = &screen;
  42.     line = sc->sc_curline;
  43.  
  44.     if (!opened_line) {
  45.         /*
  46.          * Remember insertion for later undo
  47.          */
  48.         undo.un_firstline = sc->sc_firstline;
  49.         undo.un_lastline = sc->sc_lastline;
  50.         undo.un_validcol = TRUE;
  51.         undo.un_firstcol = sc->sc_firstcol;
  52.         undo.un_inserted = TRUE;
  53.         /*
  54.          * Save overwritten text for later undo
  55.          */
  56.         yank_cmd = ' ';
  57.         if (sc->sc_lastcol >= sc->sc_column) {
  58.             yank();
  59.             undo.un_deleted = TRUE;
  60.         }
  61.     } else if (autoindent > 0) {
  62.         /*
  63.          * Fake autoindented tabs and spaces into line
  64.          */
  65.         fake_input = fake_buf;
  66.         indentbuf = xalloc(autoindent+1);
  67.         i = autoindent / set_tabstops;
  68.         if (set_fortran)
  69.             fake_chars(' ', i * set_tabstops);
  70.         else
  71.             fake_chars('\t', i);
  72.         i = autoindent % set_tabstops;
  73.         fake_chars(' ', i);
  74.         fake_input = fake_buf;
  75.         strcpy(indentbuf, fake_input);
  76.     }
  77.  
  78.     if (sc->sc_lastcol >= sc->sc_column)
  79.         /*
  80.          * Append '$' to end of replaced text
  81.          */
  82.         line->li_text[sc->sc_lastcol] = '$';
  83.  
  84.     line->li_text = realloc(line->li_text, line->li_width + ALLOC_LEN + 1);
  85.  
  86.     /*
  87.      * Get and process input chars
  88.      */
  89.     for (;;) {
  90.         INT    ch;
  91.  
  92.         /*
  93.          * Redisplay line
  94.          * Append is a fast special case
  95.          */
  96.         if (quick_append)
  97.             quick_append = FALSE;
  98.         else {
  99.             redraw_curline(line->li_text);
  100.             move_cursor(sc->sc_lineno, sc->sc_column);
  101.         }
  102.  
  103.         ch = rv_getchar();
  104.         if (superquote) /* If quoted with ^V, skip all processing */
  105.             goto addchar;
  106.  
  107.         if (ch == erasechar() || ch == '\b') {
  108.             /*
  109.              * Delete a character if not blackslashed
  110.              */
  111.             if (sc->sc_column == sc->sc_firstcol) {
  112.                 flash();
  113.                 continue;
  114.             }
  115.             if (line->li_text[sc->sc_column-1] == '\\')
  116.                 line->li_text[sc->sc_column-1] = ch;
  117.             else
  118.                 sc->sc_column--;
  119.             continue;
  120.         }
  121.  
  122.         if (ch == killchar() || ch == CTRL(X)) {
  123.             /*
  124.              * Delete line if not backslashed
  125.              */
  126.             if (sc->sc_column == sc->sc_firstcol) {
  127.                 /*
  128.                  * Already at first column, error
  129.                  */
  130.                 flash();
  131.                 continue;
  132.             }
  133.             if (line->li_text[sc->sc_column-1] == '\\')
  134.                 line->li_text[sc->sc_column-1] = ch;
  135.             else
  136.                 sc->sc_column = sc->sc_firstcol;
  137.             continue;
  138.         }
  139.  
  140.         switch (ch) {
  141. case CTRL([):
  142. case '\n':
  143. case '\r':
  144.         /*
  145.          * Escape or newline - end insert
  146.          */
  147.         if (replace_flag) {
  148.             /*
  149.              * Clean up replace mode
  150.              */
  151.             if (sc->sc_column <= sc->sc_lastcol) {
  152.                 register i;
  153.                 /*
  154.                  * Replace backspaced chars from undo buffer
  155.                  */
  156.                 for (i=sc->sc_column; i <= sc->sc_lastcol; ++i)
  157.                     if (i < sc->sc_origline.li_width)
  158.                         line->li_text[i] =
  159.                             sc->sc_origline.li_text[i];
  160.             }
  161.             /*
  162.              * Chop off backspaced chars at end of line
  163.              */
  164.             if (sc->sc_lastcol == line->li_width-1 &&
  165.                     sc->sc_lastcol >= 0) {
  166.                 line->li_width = sc->sc_column;
  167.                 line->li_text[line->li_width] = '\0';
  168.             }
  169.         } else { /* insert mode */
  170.             if (sc->sc_lastcol >= sc->sc_column) {
  171.                 register char    *s, *s2;
  172.                 /*
  173.                  * Close up backspaced text
  174.                  */
  175.                 s  = &line->li_text[sc->sc_column];
  176.                 s2 = &line->li_text[sc->sc_lastcol+1];
  177.                 while (*s++ = *s2++)
  178.                     ;
  179.                 line->li_width = strlen(line->li_text);
  180.             }
  181.         }
  182.  
  183.         /*
  184.          * Collapse autoindent if line not altered by user
  185.          */
  186.         if (opened_line && autoindent > 0 && indentbuf &&
  187.                 strcmp(indentbuf, line->li_text) == 0) {
  188.             redraw_curline("");
  189.             sc->sc_column = 0;
  190.             i = autoindent;
  191.         } else {
  192.             redraw_curline(line->li_text);
  193.             i = 0;
  194.         }
  195.         if (indentbuf)
  196.             free(indentbuf);
  197.  
  198.         if (ch == CTRL([)) {
  199.             input_mode = FALSE;
  200.             replace_flag = FALSE;
  201.             if (sc->sc_column > 0)
  202.                 sc->sc_column--;
  203.             move_cursor(sc->sc_lineno, sc->sc_column);
  204.             if (sc->sc_lastcol < sc->sc_firstcol) {
  205.                 if (!opened_line)
  206.                     undo.un_inserted = FALSE;
  207.             } else
  208.                 undo.un_lastcol = sc->sc_column;
  209.             return;
  210.         } else {
  211.             register char *s, *s2;
  212.             /*
  213.              * Continue input on new line
  214.              */
  215.             s = s2 = &line->li_text[sc->sc_column];
  216.             toss_undo();
  217.             openline(1);
  218.             if (i != 0)
  219.                 autoindent = i;
  220.             if (*s != '\0') { /* if not at end of line */
  221.                 /*
  222.                  * Split line
  223.                  */
  224.                 undo.un_validcol = TRUE;
  225.                 undo.un_firstcol = 0;
  226.                 if (set_autoindent)
  227.                     while (isspace(*s))
  228.                         ++s;
  229.                 redraw_curline(s);
  230.                 xmit_curline();
  231.                 *s2 = '\0';
  232.                 sc->sc_lineno--;
  233.                 sc->sc_curline--;
  234.                 redraw_curline(sc->sc_curline->li_text);
  235.                 save_Undo();
  236.                 xmit_curline();
  237.                 move_cursor(sc->sc_lineno+1, 0);
  238.                 save_Undo();
  239.             }
  240.             goto nextinsert; /* quick recursion */
  241.         }
  242.         break;
  243.  
  244. case CTRL(W):
  245.         /*
  246.          * Control-W - backspace 1 word
  247.          */
  248.         /* Implementation deferred */
  249.         continue;
  250.  
  251. case '\t':
  252.         /*
  253.          * Tab
  254.          */
  255.         if (set_fortran) {
  256.             /*
  257.              * Fortran source.  Expand tab to spaces
  258.              */
  259.             if (sc->sc_column < 6) {
  260.                 /*
  261.                  * First tab in fortran program, expand
  262.                  * to six spaces
  263.                  */
  264.                 fake_input = fake_buf;
  265.                 fake_chars(' ', 6-sc->sc_column);
  266.                 fake_input = fake_buf;
  267.                 continue;
  268.             }
  269.             /*
  270.              * Expand other tabs to shiftwidth spaces
  271.              */
  272.             i = set_shiftwidth - (sc->sc_column % set_shiftwidth);
  273.             fake_input = fake_buf;
  274.             fake_chars(' ', i);
  275.             fake_input = fake_buf;
  276.             continue;
  277.         }
  278.         break;
  279.  
  280.  
  281. case CTRL(D):
  282.         /*
  283.          * Backtab
  284.          */
  285.         if (sc->sc_column == sc->sc_firstcol) {
  286.             flash();
  287.             continue;
  288.         }
  289.         i = screen_column(line->li_text, sc->sc_column);
  290.         i -= i % set_shiftwidth == 0 ?
  291.             set_shiftwidth : i % set_shiftwidth;
  292.         i = file_column(line->li_text, i);
  293.         if (set_fortran && i < 6 && sc->sc_column > 6)
  294.             i = 6;
  295.         fake_input = fake_buf;
  296.         fake_chars('\b', sc->sc_column - i);
  297.         fake_input = fake_buf;
  298.         continue;
  299.  
  300.         } /* End switch */
  301.  
  302.         
  303.  
  304.         /*
  305.          * Add character to line
  306.          */
  307.  
  308. addchar:
  309.         /*
  310.          * Check if line needs expansion
  311.          */
  312.         if (sc->sc_lastcol < sc->sc_column) {
  313.             if (!replace_flag || sc->sc_column >= line->li_width) {
  314.                 register  char *s, *s2;
  315.                 /*
  316.                  * Expand line 1 character
  317.                  */
  318.                 line->li_width++;
  319.                 /*
  320.                  * Expand line in chunks of ALLOC_LEN
  321.                  */
  322.                 if (line->li_width % ALLOC_LEN == 0)
  323.                     line->li_text = realloc(line->li_text,
  324.                         line->li_width + ALLOC_LEN+1);
  325.  
  326.                 if (sc->sc_column == line->li_width-1 && 
  327.                     ch >= '@' && CURCOLUMN > 0) {
  328.                     /*
  329.                      * Fast special case - add char at
  330.                      * eol.  No control chars, no char, 
  331.                      * shifting, and no line shifting
  332.                      * required.
  333.                      */
  334.                     quick_append = TRUE;
  335.                     addch(ch);
  336.                     line->li_text[line->li_width] = '\0';
  337. #ifndef USG
  338.                     /*
  339.                      * KLUDGE - Handle VT100 brain damage
  340.                      * until Berkeley fixes up curses to 
  341.                      * handle it.
  342.                      */
  343.                     if (XN && CURCOLUMN==0) {
  344.                         addch(' ');
  345.                         refresh();
  346.                         addch('\b');
  347.                     }
  348. #endif
  349.                 } else {
  350.                     /*
  351.                      * Slide text beyond insert right
  352.                      */
  353.                     s  = &line->li_text[line->li_width-1];
  354.                     s2 = &line->li_text[sc->sc_column];
  355.                     while (s >= s2) {
  356.                         *(s+1) = *s;
  357.                         --s;
  358.                     }
  359.                 }
  360.             }
  361.             sc->sc_lastcol++;
  362.             if (sc->sc_lastcol < sc->sc_firstcol)
  363.                 sc->sc_lastcol = sc->sc_firstcol;
  364.         }
  365.  
  366.         /*
  367.          * Insert character
  368.          */
  369.         line->li_text[sc->sc_column++] = ch;
  370.     }
  371. }
  372.  
  373.  
  374. INT
  375. rv_getchar()
  376. /*
  377.  * Get a character from the keyboard.  
  378.  * Parse ^V as a super quote.
  379.  */
  380. {
  381.     INT ch;
  382.  
  383.     superquote = FALSE;
  384.     /*
  385.      * Check for fake input
  386.      */
  387.     if (fake_input && *fake_input != '\0')
  388.         return(*fake_input++);
  389.  
  390.     refresh();
  391.     while ((ch = getch()) == '\0') /* null is verboten */
  392.         ;
  393.     if (ch == CTRL(V)) {
  394.         raw(); /* Allow ^S, ^Q and interrupt keys */
  395.         insch('^');
  396.         /*
  397.          * Get raw character, null is verboten.
  398.          */
  399.         refresh();
  400.         while ((ch = getch()) == '\0')
  401.             ;
  402.         noraw();
  403. #ifdef USG
  404.         cbreak();
  405. #else
  406.         crmode();
  407. #endif !USG
  408.         superquote = (ch != '\n');
  409.     }
  410.     if (ch == ERR || ch == EOF)
  411.         quit();
  412.     return(ch);
  413. }
  414.  
  415.  
  416. void
  417. dup_insert(count)
  418. /*
  419.  * Duplicate the text found between firstcol and column
  420.  */
  421. INT count;
  422. {
  423.     register struct sc_screen *sc;
  424.     register struct li_line   *line;
  425.     register char    *buf, *s, *s1, *s2;
  426.  
  427.     sc = &screen;
  428.     line = sc->sc_curline;
  429.  
  430.     /*
  431.      * Make sure duplicatable section exists
  432.      */
  433.     if (count <= 1 || sc->sc_column  < sc->sc_firstcol
  434.                || sc->sc_lastcol < sc->sc_firstcol)
  435.         return;
  436.  
  437.     sc->sc_column++;
  438.     /*
  439.      * Get buffer space
  440.      */
  441.     buf = xalloc(strlen(line->li_text)+1 + (sc->sc_column -
  442.                          sc->sc_firstcol) * count);
  443.     /*
  444.      * Copy text up to duplicatable section
  445.      */
  446.     s = buf;
  447.     s1 = line->li_text;
  448.     s2 = &line->li_text[sc->sc_column];
  449.     while (s1 < s2)
  450.         *s++ = *s1++;
  451.  
  452.     /*
  453.      * Duplicate section
  454.      */
  455.     while (--count > 0) {
  456.         s1 = &line->li_text[sc->sc_firstcol];
  457.         while (s1 < s2)
  458.             *s++ = *s1++;
  459.     }
  460.  
  461.     /*
  462.      * Position cursor at last character of last duplicated section
  463.      */
  464.     sc->sc_column = (s - buf) - 1;
  465.  
  466.     /*
  467.      * Set up for undo
  468.      */
  469.     if (!opened_line) {
  470.         undo.un_inserted = TRUE;
  471.         undo.un_validcol = TRUE;
  472.         undo.un_firstline = undo.un_lastline = sc->sc_lineno;
  473.         undo.un_firstcol = sc->sc_firstcol;
  474.         undo.un_lastcol = sc->sc_column;
  475.     }
  476.  
  477.     /*
  478.      * Copy remainder of line
  479.      */
  480.     while (*s++ = *s2++)
  481.         ;
  482.     redraw_curline(buf);
  483.     free(buf);
  484.     move_cursor(sc->sc_lineno, sc->sc_column);
  485. }
  486.  
  487.  
  488. void
  489. fake_chars(ch, count)
  490. char ch;
  491. register INT count;
  492. {
  493.     register char *s;
  494.  
  495.     s = fake_input;
  496.     for (; count > 0; --count)
  497.         *s++ = ch;
  498.     *s = '\0';
  499.     fake_input = s;
  500. }
  501.