home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / VILE327.ZIP / VILE327.TAR / vile3.27 / insert.c < prev    next >
C/C++ Source or Header  |  1992-12-14  |  16KB  |  809 lines

  1. /* 
  2.  *
  3.  *    insert.c
  4.  *
  5.  * Do various types of character insertion, including most of insert mode.
  6.  *
  7.  * Most code probably by Dan Lawrence or Dave Conroy for MicroEMACS
  8.  * Extensions for vile by Paul Fox
  9.  *
  10.  *    $Log: insert.c,v $
  11.  * Revision 1.9  1992/12/04  09:25:03  foxharp
  12.  * deleted unused assigns
  13.  *
  14.  * Revision 1.8  1992/12/02  09:13:16  foxharp
  15.  * changes for "c-shiftwidth"
  16.  *
  17.  * Revision 1.7  1992/11/30  23:06:03  foxharp
  18.  * firstchar/lastchar now return -1 for no non-white chars in line
  19.  *
  20.  * Revision 1.6  1992/11/19  09:08:49  foxharp
  21.  * experiment -- cause further indent on lines following lines that end
  22.  * in a ':' when in c-mode, so we indent after labels, case xxx:, and default:
  23.  *
  24.  * Revision 1.5  1992/08/06  23:53:51  foxharp
  25.  * autoindent now goes by shiftwidth, instead of tabstop
  26.  *
  27.  * Revision 1.4  1992/07/15  23:23:46  foxharp
  28.  * made '80i-ESC' work
  29.  *
  30.  * Revision 1.3  1992/07/04  14:34:52  foxharp
  31.  * added ability to call SPEC-key bound functions (motion only) during
  32.  * insert mode, on the assumption that you don't _really_ want to insert
  33.  * function keys into your buffer.
  34.  *
  35.  * Revision 1.2  1992/06/01  20:37:31  foxharp
  36.  * added tabinsert
  37.  * mode
  38.  *
  39.  * Revision 1.1  1992/05/29  09:38:33  foxharp
  40.  * Initial revision
  41.  *
  42.  *
  43.  *
  44.  */
  45.  
  46. #include    <stdio.h>
  47. #include    "estruct.h"
  48. #include    "edef.h"
  49. #if UNIX
  50. #include    <signal.h>
  51. #endif
  52.  
  53. /* open lines up before this one */
  54. int
  55. openup(f,n)
  56. int f,n;
  57. {
  58.     register int s;
  59.  
  60.     if (!f) n = 1;
  61.     if (n < 0) return (FALSE);
  62.     if (n == 0) return ins(FALSE);
  63.  
  64.     gotobol(TRUE,1);
  65.  
  66.     /* if we are in C mode and this is a default <NL> */
  67.     if (n == 1 && (b_val(curbp,MDCMOD) || b_val(curbp,MDAIND)) &&
  68.                         !is_header_line(DOT,curbp)) {
  69.         s = indented_newline_above(b_val(curbp, MDCMOD));
  70.         if (s != TRUE) return (s);
  71.  
  72.         return(ins(FALSE));
  73.     }
  74.     s = lnewline();
  75.     if (s != TRUE) return s;
  76.  
  77.     s = backline(TRUE,1);        /* back to the blank line */
  78.     if (s != TRUE) return s;
  79.  
  80.     if ( n > 1) {
  81.         s = openlines(n-1);
  82.         if (s != TRUE) return s;
  83.         s = backline(TRUE, 1);    /* backup over the first one */
  84.         if (s != TRUE) return s;
  85.     }
  86.  
  87.     return(ins(FALSE));
  88. }
  89.  
  90. /* open lines up after this one */
  91. int
  92. opendown(f,n)
  93. int f,n;
  94. {
  95.     register int    s;
  96.  
  97.     if (!f) n = 1;
  98.     if (n < 0) return (FALSE);
  99.     if (n == 0) return ins(FALSE);
  100.  
  101.     s = openlines(n);
  102.     if (s != TRUE)
  103.         return (s);
  104.  
  105.     return(ins(FALSE));
  106. }
  107.  
  108. /*
  109.  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  110.  * and then back up over them.
  111.  */
  112. int
  113. openlines(n)
  114. int n;
  115. {
  116.     register int i = n;            /* Insert newlines. */
  117.     register int s = TRUE;
  118.     while (i-- && s==TRUE) {
  119.         gotoeol(FALSE,1);
  120.         s = newline(TRUE,1);
  121.     }
  122.     if (s == TRUE && n)            /* Then back up overtop */
  123.         backline(TRUE, n-1);    /* of them all.         */
  124.  
  125.     curgoal = -1;
  126.  
  127.     return s;
  128. }
  129.  
  130. /*
  131.  * Go into insert mode.  I guess this isn't emacs anymore...
  132.  */
  133. /* ARGSUSED */
  134. int
  135. insert(f, n)
  136. int f,n;
  137. {
  138.     int s;
  139.  
  140.     if (!f || n < 0) n = 1;
  141.  
  142.     s = ins(FALSE);
  143.  
  144.     while (s && --n)
  145.         s = ins(TRUE);
  146.  
  147.     update(FALSE);
  148.     return s;
  149. }
  150.  
  151. /* ARGSUSED */
  152. int
  153. insertbol(f, n)
  154. int f,n;
  155. {
  156.     int s;
  157.     firstnonwhite(f,n);
  158.  
  159.     if (!f || n < 0) n = 1;
  160.  
  161.     s = ins(FALSE);
  162.  
  163.     while (s && --n)
  164.         s = ins(TRUE);
  165.  
  166.     return s;
  167. }
  168.  
  169. /* ARGSUSED */
  170. int
  171. append(f, n)
  172. int f,n;
  173. {
  174.     int s;
  175.  
  176.     if (! is_header_line(DOT,curbp) && !is_at_end_of_line(DOT))
  177.         forwchar(TRUE,1); /* END OF LINE HACK */
  178.  
  179.     if (!f || n < 0) n = 1;
  180.  
  181.     s = ins(FALSE);
  182.  
  183.     while (s && --n)
  184.         s = ins(TRUE);
  185.  
  186.     return s;
  187. }
  188.  
  189. /* ARGSUSED */
  190. int
  191. appendeol(f, n)
  192. int f,n;
  193. {
  194.     int s;
  195.     if (!is_header_line(DOT,curbp))
  196.         gotoeol(FALSE,0);
  197.  
  198.     if (!f || n < 0) n = 1;
  199.  
  200.     s = ins(FALSE);
  201.  
  202.     while (s && --n)
  203.         s = ins(TRUE);
  204.  
  205.     return s;
  206. }
  207.  
  208. /* ARGSUSED */
  209. int
  210. overwrite(f, n)
  211. int f,n;
  212. {
  213.     int s;
  214.     insertmode = OVERWRITE;
  215.     if (b_val(curbp, MDSHOWMODE))
  216.         curwp->w_flag |= WFMODE;
  217.  
  218.     if (!f || n < 0) n = 1;
  219.  
  220.     s = ins(FALSE);
  221.  
  222.     while (s && --n)
  223.         s = ins(TRUE);
  224.  
  225.     return s;
  226. }
  227.  
  228. int
  229. replacechar(f, n)
  230. int f,n;
  231. {
  232.     register int    s;
  233.     register int    c;
  234.  
  235.     if (!f && llength(DOT.l) == 0)
  236.         return FALSE;
  237.  
  238.     insertmode = REPLACECHAR;  /* need to fool the SPEC prefix code */
  239.     if (b_val(curbp, MDSHOWMODE))
  240.         curwp->w_flag |= WFMODE;
  241.     update(FALSE);
  242.     c = kbd_key();
  243.     insertmode = FALSE;
  244.     curwp->w_flag |= WFMODE;
  245.  
  246.     if (n < 0)
  247.         return FALSE;
  248.     if (n == 0)
  249.         return TRUE;
  250.     if (c == abortc)
  251.         return FALSE;
  252.  
  253.     ldelete((long)n,FALSE);
  254.     if (c == quotec) {
  255.         return(quote(f,n));
  256.     }
  257.     c = kcod2key(c);
  258.     if (c == '\n' || c == '\r') {
  259.         do {
  260.             s = lnewline();
  261.         } while (s==TRUE && --n);
  262.         return s;
  263.     } else if (isbackspace(c))
  264.         s = TRUE;
  265.     else
  266.         s = linsert(n, c);
  267.     if (s == TRUE)
  268.         s = backchar(FALSE,1);
  269.     return s;
  270. }
  271.  
  272. /* grunt routine for insert mode */
  273. int
  274. ins(playback)
  275. int playback;
  276. {
  277.     register int status;
  278.     int f,n;
  279.     int (*execfunc)();        /* ptr to function to execute */
  280.     int    c;        /* command character */
  281.     int newlineyet = FALSE; /* are we on the line we started on? */
  282.     int startoff = DOT.o;    /* starting offset on that line */
  283.     static char insbuff[256];
  284.     char *iptr = insbuff;
  285.  
  286.     if (insertmode == FALSE) {
  287.         insertmode = INSERT;
  288.         if (b_val(curbp, MDSHOWMODE))
  289.             curwp->w_flag |= WFMODE;
  290.     }
  291.  
  292.     /* get the next command from the keyboard */
  293.     while(1) {
  294.  
  295.         f = FALSE;
  296.         n = 1;
  297.  
  298.         if (playback) {
  299.             c = *iptr++;
  300.         } else {
  301.             update(FALSE);
  302.             c = kbd_key();
  303.             if (iptr - insbuff < 255)
  304.                 *iptr++ = c;
  305.             else
  306.                 insbuff[255] = abortc;
  307.         }
  308.  
  309.         if (c == abortc ) {
  310.              /* an unfortunate Vi-ism that ensures one 
  311.                 can always type "ESC a" if you're not sure 
  312.                 you're in insert mode. */
  313.             if (DOT.o != 0)
  314.                 backchar(TRUE,1);
  315.             if (autoindented >= 0) {
  316.                 trimline();
  317.                 autoindented = -1;
  318.             }
  319.             insertmode = FALSE;
  320.             if (b_val(curbp, MDSHOWMODE))
  321.                 curwp->w_flag |= WFMODE;
  322.             return (TRUE);
  323.         } else if (c == -abortc ) {
  324.             /* we use the negative to suppress that
  325.                 junk, for the benefit of SPEC keys */
  326.             insertmode = FALSE;
  327.             if (b_val(curbp, MDSHOWMODE))
  328.                 curwp->w_flag |= WFMODE;
  329.             return (TRUE);
  330.         }
  331.  
  332.         if (c & SPEC) {
  333.             CMDFUNC *cfp;
  334.             cfp = kcod2fnc(c);
  335.             if (!cfp || ((cfp->c_flags & MOTION|REDO|UNDO)
  336.                         != MOTION)) {
  337.                 startoff = 0;
  338.                 curgoal = getccol(FALSE);
  339.                 execute(cfp,FALSE,1);
  340.             }
  341.             continue;
  342.         }
  343.  
  344.         execfunc = NULL;
  345.         if (c == quotec) {
  346.             execfunc = quote;
  347.         } else {
  348.             /*
  349.              * If a space was typed, fill column is defined, the
  350.              * argument is non- negative, wrap mode is enabled, and
  351.              * we are now past fill column, perform word wrap. 
  352.              */
  353.             if (isspace(c) && b_val(curwp->w_bufp,MDWRAP) &&
  354.                 b_val(curbp,VAL_FILL) > 0 && n >= 0 &&
  355.                 getccol(FALSE) > b_val(curbp,VAL_FILL)) {
  356.                 wrapword(FALSE,1);
  357.                 newlineyet = TRUE;
  358.             }
  359.  
  360.             if ( c ==  '\t') { /* tab */
  361.                 execfunc = tab;
  362.                 autoindented = -1;
  363.             } else if (c ==  tocntrl('J') ||
  364.                 c ==  tocntrl('M')) { /* CR and NL */
  365.                 execfunc = newline;
  366.                 if (autoindented >= 0) {
  367.                     trimline();
  368.                     autoindented = -1;
  369.                 }
  370.                 newlineyet = TRUE;
  371.             } else if ( isbackspace(c) ||
  372.                     c == tocntrl('D') || 
  373.                     c == killc ||
  374.                     c == wkillc) { /* ^U and ^W */
  375.                 /* how far can we back up? */
  376.                 register int backlimit;
  377.                 /* have we backed thru a "word" yet? */
  378.                 int saw_word = FALSE;
  379.                 if ((c == tocntrl('D') && autoindented >=0) ||
  380.                     newlineyet || !b_val(curbp,MDBACKLIMIT))
  381.                     backlimit = 0;
  382.                 else
  383.                     backlimit = startoff;
  384.                 execfunc = nullproc;
  385.                 if (c == tocntrl('D')) {
  386.                     int goal;
  387.                     int col;
  388.                     int sw = curswval;
  389.                     col = getccol(FALSE);
  390.                     if (col > 0)
  391.                         goal = ((col-1)/sw)*sw;
  392.                     else
  393.                         goal = 0;
  394.                     while (col > goal &&
  395.                         DOT.o > backlimit) {
  396.                         backspace();
  397.                         col = getccol(FALSE);
  398.                     }
  399.                     if (col < goal)
  400.                         linsert(goal - col,' ');
  401.                 } else while (DOT.o > backlimit) {
  402.                     if (c == wkillc) {
  403.                         if (isspace(
  404.                             lgetc(DOT.l,DOT.o-1))) {
  405.                             if (saw_word)
  406.                                 break;
  407.                         } else {
  408.                             saw_word = TRUE;
  409.                         }
  410.                     }
  411.                     backspace();
  412.                     autoindented--;
  413.                     if (isbackspace(c) ||
  414.                         c == tocntrl('D'))
  415.                         break;
  416.                 }
  417.             } else if ( c ==  tocntrl('T')) { /* ^T */
  418.                 execfunc = shiftwidth;
  419.  
  420. #if UNIX && defined(SIGTSTP)    /* job control, ^Z */
  421.             } else if (c == suspc) {
  422.                 execfunc = bktoshell;
  423.  
  424. #endif
  425.             } else if (c == startc ||
  426.                     c == stopc) {  /* ^Q and ^S */
  427.                 execfunc = nullproc;
  428.             }
  429.         }
  430.  
  431.         if (execfunc != NULL) {
  432.             status     = (*execfunc)(f, n);
  433.             if (status != TRUE) {
  434.                 insertmode = FALSE;
  435.                 if (b_val(curbp, MDSHOWMODE))
  436.                     curwp->w_flag |= WFMODE;
  437.                 return (status);
  438.             }
  439.             continue;
  440.         }
  441.  
  442.             
  443.         /* make it a real character again */
  444.         c = kcod2key(c);
  445.  
  446.         /* if we are in overwrite mode, not at eol,
  447.            and next char is not a tab or we are at a tab stop,
  448.            delete a char forword            */
  449.         if (insertmode == OVERWRITE &&
  450.                 DOT.o < llength(DOT.l) &&
  451.                 (char_at(DOT) != '\t' ||
  452.                     (DOT.o) % curtabval == curtabval-1)) {
  453.             autoindented = -1;
  454.             ldelete(1L, FALSE);
  455.         }
  456.  
  457.         /* do the appropriate insertion */
  458.         if ((c == RBRACE) && b_val(curbp, MDCMOD)) {
  459.             status = insbrace(n, c);
  460.         } else if (c == '#' && b_val(curbp, MDCMOD)) {
  461.             status = inspound();
  462.         } else {
  463.             autoindented = -1;
  464.             status = linsert(n, c);
  465.         }
  466.  
  467. #if CFENCE
  468.         /* check for CMODE fence matching */
  469.         if ((c == RBRACE || c == ')' || c == ']') && 
  470.                         b_val(curbp, MDSHOWMAT))
  471.             fmatch(c);
  472. #endif
  473.  
  474.         /* check auto-save mode */
  475.         if (b_val(curbp, MDASAVE))
  476.             if (--curbp->b_acount <= 0) {
  477.                 /* and save the file if needed */
  478.                 upscreen(FALSE, 0);
  479.                 filesave(FALSE, 0);
  480.                 curbp->b_acount = b_val(curbp,VAL_ASAVECNT);
  481.             }
  482.  
  483.         if (status != TRUE) {
  484.             insertmode = FALSE;
  485.             if (b_val(curbp, MDSHOWMODE))
  486.                 curwp->w_flag |= WFMODE;
  487.             return (status);
  488.         }
  489.     }
  490. }
  491.  
  492. int
  493. backspace()
  494. {
  495.     register int    s;
  496.  
  497.     if ((s=backchar(TRUE, 1)) == TRUE)
  498.         s = ldelete(1L, FALSE);
  499.     return (s);
  500. }
  501.  
  502. /*
  503.  * Insert a newline. If we are in CMODE, do automatic
  504.  * indentation as specified.
  505.  */
  506. int
  507. newline(f, n)
  508. int f,n;
  509. {
  510.     register int    s;
  511.  
  512.     if (!f)
  513.         n = 1;
  514.     else if (n < 0)
  515.         return (FALSE);
  516.  
  517. #if LATER    /* already done for autoindented != 0 in ins() */
  518.     if (b_val(curbp, MDTRIM))
  519.         trimline();
  520. #endif
  521.         
  522.     /* if we are in C or auto-indent modes and this is a default <NL> */
  523.     if (n == 1 && (b_val(curbp,MDCMOD) || b_val(curbp,MDAIND)) &&
  524.                         !is_header_line(DOT,curbp))
  525.         return indented_newline(b_val(curbp, MDCMOD));
  526.  
  527.     /*
  528.      * If a newline was typed, fill column is defined, the argument is non-
  529.      * negative, wrap mode is enabled, and we are now past fill column,
  530.      * perform word wrap.
  531.      */
  532.     if (b_val(curwp->w_bufp, MDWRAP) && b_val(curbp,VAL_FILL)> 0 &&
  533.                 getccol(FALSE) > b_val(curbp,VAL_FILL))
  534.         wrapword(FALSE,1);
  535.  
  536.     /* insert some lines */
  537.     while (n--) {
  538.         if ((s=lnewline()) != TRUE)
  539.             return (s);
  540.         curwp->w_flag |= WFINS;
  541.     }
  542.     return (TRUE);
  543. }
  544.  
  545. /* insert a newline and indentation for C */
  546. int
  547. indented_newline(cmode)
  548. int cmode;
  549. {
  550.     register int indentwas; /* indent to reproduce */
  551.     int bracef; /* was there a brace at the end of line? */
  552.         
  553.     indentwas = previndent(&bracef);
  554.  
  555.     if (lnewline() == FALSE)
  556.         return FALSE;
  557.     if (cmode && bracef)
  558.         indentwas = nextsw(indentwas);
  559.     if (doindent(indentwas) != TRUE)
  560.         return FALSE;
  561.     return TRUE;
  562. }
  563.  
  564. /* insert a newline and indentation for autoindent */
  565. int
  566. indented_newline_above(cmode)
  567. int cmode;
  568. {
  569.     register int indentwas;    /* indent to reproduce */
  570.     int bracef; /* was there a brace at the beginning of line? */
  571.     
  572.     indentwas = nextindent(&bracef);
  573.     if (lnewline() == FALSE)
  574.         return FALSE;
  575.     if (backline(TRUE,1) == FALSE)
  576.         return FALSE;
  577.     if (cmode && bracef)
  578.         indentwas = nextsw(indentwas);
  579.     if (doindent(indentwas) != TRUE)
  580.         return FALSE;
  581.     return TRUE;
  582. }
  583. /* get the indent of the last previous non-blank line.    also, if arg
  584.     is non-null, check if line ended in a brace */
  585. int
  586. previndent(bracefp)
  587. int *bracefp;
  588. {
  589.     int ind;
  590.         
  591.     MK = DOT;
  592.         
  593.     if (backword(FALSE,1) == FALSE) {
  594.         if (bracefp) *bracefp = FALSE;
  595.         gomark(FALSE,1);
  596.         return 0;
  597.     }
  598.     ind = indentlen(DOT.l);
  599.     if (bracefp) {
  600.         int lc = lastchar(DOT.l);
  601.         *bracefp = (lc >= 0 &&
  602.             (lgetc(DOT.l,lc) == LBRACE ||
  603.              lgetc(DOT.l,lc) == ':') );
  604.     }
  605.             
  606.     gomark(FALSE,1);
  607.         
  608.     return ind;
  609. }
  610.  
  611. /* get the indent of the next non-blank line.    also, if arg
  612.     is non-null, check if line starts in a brace */
  613. int
  614. nextindent(bracefp)
  615. int *bracefp;
  616. {
  617.     int ind;
  618.         
  619.     MK = DOT;
  620.         
  621.     if (forwword(FALSE,1) == FALSE) {
  622.         if (bracefp) *bracefp = FALSE;
  623.         gomark(FALSE,1);
  624.         return 0;
  625.     }
  626.     ind = indentlen(DOT.l);
  627.     if (bracefp) {
  628.         int fc = firstchar(DOT.l);
  629.         *bracefp = (fc >= 0 && lgetc(DOT.l,fc) == RBRACE);
  630.     }
  631.             
  632.     gomark(FALSE,1);
  633.         
  634.     return ind;
  635. }
  636.  
  637. int
  638. doindent(ind)
  639. int ind;
  640. {
  641.     int i;
  642.     /* if no indent was asked for, we're done */
  643.     if (ind <= 0)
  644.         return TRUE;
  645.     autoindented = 0;
  646.     /* first clean up existing leading whitespace */
  647.     i = firstchar(DOT.l);
  648.     if (i > 0)
  649.         ldelete((long)i,FALSE);
  650.     if ((i=ind/curtabval)!=0) {
  651.         autoindented += i;
  652.         if (tab(TRUE,i) == FALSE)
  653.             return FALSE;
  654.     }
  655.     if ((i=ind%curtabval) != 0) {
  656.         autoindented += i;
  657.         if (linsert(i,    ' ') == FALSE)
  658.             return FALSE;
  659.     }
  660.     if (!autoindented)
  661.         autoindented = -1;
  662.         
  663.     return TRUE;
  664. }
  665.  
  666. /* return the column indent of the specified line */
  667. int
  668. indentlen(lp)
  669. LINE *lp;
  670. {
  671.     register int ind, i, c;
  672.     ind = 0;
  673.     for (i=0; i<llength(lp); ++i) {
  674.         c = lgetc(lp, i);
  675.         if (!isspace(c))
  676.             break;
  677.         if (c == '\t')
  678.             ind = nextab(ind);
  679.         else
  680.             ++ind;
  681.     }
  682.     return ind;
  683. }
  684.  
  685.  
  686. int
  687. insbrace(n, c)    /* insert a brace into the text here...we are in CMODE */
  688. int n;    /* repeat count */
  689. int c;    /* brace to insert (always { for now) */
  690. {
  691.  
  692. #if ! CFENCE
  693.     /* wouldn't want to back up from here, but fences might take us 
  694.         forward */
  695.     /* if we are at the beginning of the line, no go */
  696.     if (DOT.o == 0)
  697.         return(linsert(n,c));
  698. #endif
  699.  
  700.     if (autoindented >= 0) {
  701.         trimline();
  702.     }
  703.     else {
  704.         return linsert(n,c);
  705.     }
  706. #if ! CFENCE /* no fences?    then put brace one tab in from previous line */
  707.     doindent(((previndent(NULL)-1) / curtabval) * curtabval);
  708. #else /* line up brace with the line containing its match */
  709.     doindent(fmatchindent());
  710. #endif
  711.     autoindented = -1;
  712.  
  713.     /* and insert the required brace(s) */
  714.     return(linsert(n, c));
  715. }
  716.  
  717. int
  718. inspound()    /* insert a # into the text here...we are in CMODE */
  719. {
  720.  
  721.     /* if we are at the beginning of the line, no go */
  722.     if (DOT.o == 0)
  723.         return(linsert(1,'#'));
  724.  
  725.     if (autoindented > 0) { /* must all be whitespace before us */
  726.         DOT.o = 0;
  727.         ldelete((long)autoindented,FALSE);
  728.     }
  729.     autoindented = -1;
  730.  
  731.     /* and insert the required pound */
  732.     return(linsert(1, '#'));
  733. }
  734.  
  735. /* insert a tab into the file */
  736. /* ARGSUSED */
  737. int
  738. tab(f, n)
  739. int f,n;
  740. {
  741.     int ccol;
  742.     if (!f) n = 1;
  743.     if (n <= 0)
  744.         return FALSE;
  745.  
  746.     if (b_val(curbp,MDTABINSERT))
  747.         return linsert(n, '\t');
  748.  
  749.     ccol = getccol(FALSE);
  750.     return linsert((nextab(ccol) - ccol) + (n-1)*curtabval,' ');
  751. }
  752.  
  753. int
  754. shiftwidth()
  755. {
  756.     int s;
  757.     int fc;
  758.     fc = firstchar(DOT.l);
  759.     if (fc >= 0 && fc < DOT.o) {
  760.         s = linsert(curswval, ' ');
  761.         /* should entab mult ^T inserts */
  762.         return s;
  763.     }
  764.     detabline(TRUE);
  765.     s = curswval - (getccol(FALSE) % curswval);
  766.     if (s)
  767.         linsert(s, ' ');
  768.     if (b_val(curbp,MDTABINSERT))
  769.                 entabline(TRUE);
  770.     if (autoindented >= 0) {
  771.         fc = firstchar(DOT.l);
  772.         if (fc >= 0)
  773.             autoindented = fc;
  774.         else /* all white */
  775.             autoindented = llength(DOT.l);
  776.     }
  777.     return TRUE;
  778. }
  779.  
  780. /*
  781.  * Quote the next character, and insert it into the buffer. All the characters
  782.  * are taken literally, with the exception of the newline, which always has
  783.  * its line splitting meaning. The character is always read, even if it is
  784.  * inserted 0 times, for regularity.
  785.  */
  786. int
  787. quote(f, n)
  788. int f,n;
  789. {
  790.     register int    s;
  791.     register int    c;
  792.  
  793.     c = tgetc();
  794.     if (!f)
  795.         n = 1;
  796.     if (n < 0)
  797.         return FALSE;
  798.     if (n == 0)
  799.         return TRUE;
  800.     if (c == '\n') {
  801.         do {
  802.             s = lnewline();
  803.         } while (s==TRUE && --n);
  804.         return s;
  805.     }
  806.     return linsert(n, c);
  807. }
  808.  
  809.