home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 331_01 / edit.c < prev    next >
Text File  |  1990-06-14  |  22KB  |  809 lines

  1.  
  2. /*
  3. HEADER:         CUG999.03;
  4. TITLE:          SE (nee E) screen editor
  5. DATE:           5/19-87;
  6.  
  7. DESCRIPTION:    "Text buffer editing routines for se"
  8. VERSION:        1.00;
  9. SYSTEM:         MS-DOS;
  10. FILENAME:       EDIT.C;
  11. SEE-ALSO:       SE.C
  12. AUTHORS:        G. Nigel Gilbert, James W. Haefner, Mel Tearle, G. Osborn;
  13. */
  14.  
  15. /*
  16.      e/qed/ged/se screen editor
  17.  
  18.     (C) G. Nigel Gilbert, MICROLOGY, 1981
  19.            August-December 1981
  20.  
  21.     FUNCTIONS: movechar, moveline, dojump, jumpline,
  22.                movepage, moveword, insertchar, replchar, deletechar,
  23.                deleteword, linedelete, crdelete, crinsert, adjustc, sync
  24.  
  25.  
  26. */
  27.  
  28. /* Earlier versions had the capabiltiy of editing text containing embedded
  29.  * tabs.  In that case the character index into text[] is less in magnitude
  30.  * than cursorx.  Due partly to the addition of new functions, charn and
  31.  * cursorx are used interchangably in this version.  This version converts
  32.  * tabs to spaces at the time the file is read.  The capability of editing
  33.  * tabs might be restored as an option in a future version, but probably a
  34.  * better way is to do an automatic entab at disc write time for those who
  35.  * want tabs.  The only advantage of embedded tabs is that they save disc
  36.  * space.  They mess up everything else.  The keyboard tab key is a cursor
  37.  * positioning command in this version.  It does not store anyting.     g.o.
  38.  */
  39.  
  40. #include <stdio.h>
  41. #include <ctype.h>
  42. #include "ged.h"
  43.  
  44. /* move cursor by 'move' columns to the right return YES unless going off text
  45.  */
  46. movechar(move)
  47. int  move;
  48. {
  49.     int  cp, len, result, j;
  50.  
  51.     cp = charn + move;
  52.     result = YES;
  53.  
  54.     if ( cp < 0 )  {
  55.         if (cline > 1) {
  56.             charn = strlen(getline(cline-1));
  57.             moveline(-1);
  58.         }
  59.     }
  60.  
  61. /* The "cursor right one char" command adds trailing spaces as needed to
  62.  * provide free cursor movement.  New characters would be lost if preceeded
  63.  * by a '\0'.
  64.  */
  65.     else if ( cp > ( len = strlen(text) ) )  {
  66.         if(!trail && move == 1) {
  67.             sync(cp);
  68.             resetcursor();
  69.             return YES;
  70.         }
  71.         else {
  72.             charn = 0;
  73.             result = moveline(1);
  74.             return result;
  75.         }
  76.     }
  77.     else {
  78.         sync(cp);  /* move +/- one on same line */
  79.         resetcursor();
  80.         return result;
  81.     }
  82. }
  83.  
  84. /* calculate line number at the top and bottom of screen.  The lines in that
  85.  * span are read from disc if not already in memory.
  86.  *
  87.  * It is convenient to be able to scroll
  88.  * by page for a few pages then page back to the original line with the
  89.  * cursor returning to its original position.  The program works
  90.  * that way for page scrolls.
  91.  */
  92.  
  93. calp()
  94. {
  95.     if (cursory < topline)
  96.         cursory = topline;
  97.     if ( (cursory - topline) > (cline - 1) )
  98.         cursory = topline + (cline - 1);    /* near bof */
  99.     pfirst = loc(cline + topline - cursory, 0);
  100.     plast = loc(pfirst + SHEIGHT - topline, 0);
  101.     if ( (cursory - topline) > (plast - pfirst) )
  102.         calp(--cursory);  /* neaar eof */
  103.     return;
  104. }
  105.  
  106. /* Move cursor by '+/- move' lines, + is downward.
  107.  * return YES if Ok, NO if going off text.
  108.  *
  109.  * Set 'cursory' to the preferred cursor y value before the call.  The
  110.  * preferred location is not always be used.  There are conditions near
  111.  * beginning and end of file when it cannot be used.  A scroll
  112.  * placing the y cursor in the preferred positiion can be forced to
  113.  * the extent possible by setting plast=-1 before the call.  The
  114.  * preferred value will otherwise not be used if a one-line
  115.  * scroll suffices, or if the new cursor position is already somewhere
  116.  * on the existing display.  The minimization of scrolling is desirable
  117.  * from a speed standpoint.  It also minimizes eye fatigue.
  118.  *
  119.  * The window movement is normally purely vertical, but there are
  120.  * exceptions.  If 'charn' has recently changed then horizontal
  121.  * display motion may result also.  If 'trail' is true then horizontal
  122.  * motion will often result due to the differing line lengths if
  123.  * the lines are long.  To cause horizontal adjstment on the new
  124.  * line, set charn before the call to moveline().  It is unnecessary
  125.  * to call sync().
  126.  *
  127.  * moveline() assumes that the existing physical display is correct and
  128.  * current.  It can't be called to show the result of an editng operation.
  129.  *
  130.  * It is assumed that the scroll function is faster than a
  131.  * rewrite, so scrolling is used when possible.  Good high-level portability
  132.  * could be achieved by writing a low-level scroll function which might
  133.  * actually do a rewrite when the hardware scroll function is missing.
  134.  * The program is being restructured so that all hardware specific
  135.  * display and terminal functions are in term.c.
  136.  */
  137.  
  138. moveline(move)
  139. int move;
  140. {
  141.     int line, i, oldoff, sav, ocline;
  142.  
  143.     puttext();
  144.  
  145.     ocline = cline;
  146.     cline = loc(cline, move);  /* read from disc if necessary */
  147.     move = cline - ocline;
  148.  
  149.     sav = curson(NO);
  150. /* gettext adds trailing spaces if needed for free cursor motion */
  151.     gettext(cline, charn);
  152.     sync(charn);
  153.  
  154.     if (plast < 0)
  155.         pfirst = -1;
  156.     if (pfirst < 0)
  157.         plast = -1;
  158.     oldoff = lastoff;
  159.     lastoff = calcoffset(charn);
  160.  
  161.     if (blocking && ( move != 1  && move != -1) )
  162.         oldoff = -1;    /* force a complete rewrite if reverse field too complex */
  163.  
  164.     if (oldoff == lastoff && cline >= pfirst && cline <= plast ) {
  165. /* the new cursor position is already on the screen */
  166.  
  167.         if (blocking)        /* the vacated line may become unmarked */
  168.             putline(ocline, cursory, NULL);
  169.  
  170.         cursory = (cline - pfirst) + topline;
  171.         calp();
  172.  
  173.         if (blocking)         /* the new line may become marked */
  174.             putline(cline, cursory, NULL);
  175.  
  176.     }
  177. /* scroll down and add one line at top */
  178. /* the old cursor can be anywhere on the screen */
  179.     else if (oldoff == lastoff && cline == pfirst -1) {
  180.         if (blocking)  /* the vacated line may become unmarked */
  181.             putline(ocline, cursory, NULL);
  182.  
  183.         scrolldown(topline);
  184.         cursory = topline;
  185.         putline(cline,topline,text);
  186.         calp();
  187.     }
  188. /* scroll up and add one line at bottom */
  189.     else if (oldoff == lastoff && cline == plast + 1) {
  190.         if (blocking)  /* the vacated line may become unmarked */
  191.             putline(ocline, cursory, NULL);
  192.  
  193.         scrollup(topline);
  194.         cursory = SHEIGHT;
  195.         putline(cline, SHEIGHT, text);
  196.         calp();
  197.     }
  198. /* Vertical screen motion of 0 or  more than 1 line, or horiz scrolling. */
  199. /* This case uses the preferred y cursor position if possible */
  200. /* moves of 0 are used to re-establish valid environment */
  201.     else  {
  202.         calp();
  203.         putpage();
  204.     }
  205.     putlineno(cline);  /* update line and column no. */
  206.     resetpcursor();
  207.     curson(sav);       /* ready to edit */
  208.     return  YES;
  209. }
  210.  
  211. dojump()
  212. {
  213.     int i;
  214.  
  215.     putmess( "[|+|/|-|]|line|, last |C|hange, |E|nd,  prior |J|ump, |M|ark;  |S|et mark");
  216.     scans(ans,2);
  217.     gotoxy(59,0);
  218.     if ( (i = calcjmp()) > 0)
  219.         jumpline(i - cline);
  220.     return;
  221. }
  222. /* calculate jump to new line.
  223.  * interpret the jump to current line (a NOP) as full screen refresh request.
  224.  * Useful for debugging and from a remote location with transmission errors
  225.  * or outages.
  226.  */
  227. calcjmp()
  228. {
  229.     int i, j, k, to;
  230.     char far *jj;
  231.     i = toupper(ans[0]);
  232.     switch (i) {
  233.  
  234.     case '+':
  235.         scans(ans,5);
  236.         to = atoi( ans );
  237.         if ( to == 0) {
  238.             cleareop(0);
  239.             putpage();
  240.         }
  241.         jmpto = cline + to;
  242.         break;
  243.  
  244.     case '-':
  245.         scans(ans,5);
  246.         if ( (to = atoi( ans ) ) )
  247.             jmpto = cline - to;
  248.         break;
  249.  
  250.     case 'C':
  251.         if (lastc < 1) {
  252.             error("No lines have been changed");
  253.             return cline;
  254.         }
  255.         cursory = topline + SHEIGHT/2;
  256.         jmpto = lastc;  /* line last changed/deleted/inserted */
  257.         break;
  258.  
  259.     case 'E':
  260.         jmpto = lastl;
  261.         cursory = SHEIGHT - (SHEIGHT - topline)/4;
  262.         break;
  263.  
  264.     case 'J':
  265.         cursory = topline + SHEIGHT/2;
  266.         return jmpto;
  267.         break;
  268.  
  269.     case 'M':
  270.         if (linem1 == 0) {
  271.             error("No cursor line was marked with S option");
  272.             return cline;
  273.         }
  274.         else {
  275.             cursory = topline + SHEIGHT/2;
  276.             if (linem1 == cline) {
  277.                 if (linem2 > 0)
  278.                     return linem2;
  279.                 else
  280.                     return linem1;
  281.             }
  282.             if (linem2 == cline) {
  283.                 if (linem3 > 0)
  284.                     return linem3;
  285.                 else
  286.                     return linem1;
  287.             }
  288.             return linem1;
  289.         }
  290.         break;
  291.  
  292.     case 'S':
  293.         linem3 = linem2;
  294.         linem2 = linem1;
  295.         linem1 = cline;   /* mark the current line */
  296.         return cline;
  297.         break;
  298.  
  299.  
  300.     case 'W':
  301.         cent();
  302.         return -1;
  303.         break;
  304.  
  305.     default:
  306.         if ( ans[0] < ' ')
  307.             return -1;
  308.  
  309.         if ( i >= '0' && i <= '9' ) {
  310.             scans(ans+1,5);
  311.             if ( to = atoi(ans)  ) {
  312.                 cursory = topline + SHEIGHT/2;
  313.                 jmpto = to;
  314.             }
  315.         }
  316.         else {
  317.             error("Bad parameter");
  318.             return cline;
  319.         }
  320.     }
  321.     return jmpto;
  322. }
  323.  
  324. /* center window on cursor.  */
  325. cent()
  326. {
  327.     int i,j,k;
  328.  
  329.     cursory = topline + (SHEIGHT-topline)/2;
  330.     calp();
  331.     offset = cursorx - SWIDTH/2;
  332.     if (offset < 0)
  333.         offset = 0;
  334. /* in centering, don't move right beyond line ends in order to show as
  335.    much text as possible */
  336.     j = 0;
  337.     for(i = pfirst; i <= plast; i++) {
  338.         if (i == cline && altered)
  339.             k = strlen(text);
  340.         else
  341.             k = strlen(getline(i));
  342.         j = ( ( k > j) ? k : j );
  343.     }
  344.     if (j < (offset + SWIDTH) )
  345.         offset =  j - SWIDTH;
  346.     if (offset < 0)
  347.         offset = 0;
  348.  
  349.     lastoff = -1;
  350.     resetcursor();
  351.  
  352.     return;
  353. }
  354.  
  355. /* move current line by move lines down,
  356.  */
  357. jumpline(move)
  358. int move;
  359. {
  360.  
  361.     puttext();
  362.  
  363. /* the old cursor position is mostly irrevlelant.  The following
  364.  * avoids excessive horizontal scrolling.
  365.  */
  366.     charn = offset + (offset>0);
  367.     moveline( move );
  368.  
  369.     return  YES;
  370. }
  371.  
  372.  
  373. /* move current line by a page down (dir==0) or up (-1)
  374.  */
  375. movepage(dir)
  376. int dir;
  377. {
  378.     int move, i;
  379.  
  380.     puttext();
  381.  
  382.     move = SHEIGHT -topline +1 - PAGEOVERLAP;
  383.     if (dir)
  384.         move = -move;
  385.  
  386. /* the scroll distance is less than the page height, so a move of
  387.  * 'move' downward from the top line would still be on the screen
  388.  * and no scroll would occur.  force a scroll.
  389.  */
  390.     plast = -1;
  391.     moveline(move);  /* use the existing y cursor */
  392.  
  393. /* the screen has been updated.  if the disc file is being used then
  394.  * prepare the page containing the next screen for quick access.  In this
  395.  * way the disc access usually occurs after the operator command rather
  396.  * than before it's completion.
  397.  */
  398.     if (move > 0)
  399.         i = plast + SHEIGHT - PAGEOVERLAP;
  400.     else
  401.         i = pfirst - SHEIGHT + PAGEOVERLAP;
  402.     getline(i);
  403.  
  404.     return;
  405. }
  406.  
  407.  
  408. /* move 1 word to the right (move -ve: left)
  409.  */
  410. moveword(move)
  411. int move;
  412. {
  413.  
  414.     if ( charn + move < 0 )  {
  415.         if (cline > 1) {
  416.             puttext();
  417.             charn = strlen(getline(cline-1));
  418.             moveline(-1);
  419.         }
  420.         else {
  421.             return;
  422.         }
  423.     }
  424.     else if ( charn + move >= strlen(text) )  {
  425.         puttext();
  426.         charn = 0;
  427.         moveline(1);
  428.         if ( inword(text[0]) )
  429.             return;
  430.     }
  431.  
  432.     while (( move<0 || text[charn]) && inword(text[charn]) && (charn += move))
  433.         ;
  434.     while (( move<0 || text[charn]) && !inword(text[charn]) && (charn += move))
  435.         ;
  436.     if ( move < 0  &&  charn )  {
  437.         while ( inword(text[charn])  &&  --charn )
  438.             ;
  439.         if ( charn || !inword(text[charn]) )  charn++;
  440.     }
  441.     sync( charn );
  442.     resetcursor();
  443. }
  444.  
  445. /* replace char at cursor position.
  446.    The last character is at text[LLIM-2].  The latest possible
  447.    '\0' is at text[LLIM-1]
  448.  */
  449. replchar(c)
  450. char c;
  451. {
  452.     if ( charn >= LLIM-1 ) {
  453.         error(" Line would be too long ");
  454.         inbufp = 0;
  455.     }
  456.     else {
  457.         if(text[charn] == '\0')
  458.             text[charn+1] = '\0';
  459.         text[charn] = c;
  460.         altered = YES;
  461.         sync( charn + 1 );
  462.         rewrite( charn-1 );  /* updated charn */
  463.     }
  464.     return;
  465. }
  466.  
  467. /* inserts 'c' at charn, moves cursor up one
  468.  
  469.    The last character is at text[LLIM-2].  The latest possible
  470.    '\0' is at text[LLIM-1]
  471.  */
  472. insertchar(c)
  473. char c;
  474. {
  475.     int  cp;
  476.  
  477.     cp = strlen(text);
  478.     if ( cp >= LLIM)
  479.         cerr(20);
  480.     if ( charn > cp)
  481.         cerr(21);
  482.  
  483. /* prevent line overflow due to trailing spaces */
  484.     if (!trail && text[LLIM-2] == ' ')
  485.         text[LLIM-2] = '\0';
  486.  
  487.     cp += 1;    /* 1 <=  cp  <= LLIM */
  488.     if ( cp >= LLIM ) {
  489.         error(" Line would be too long ");
  490. /* empy the input buffer to prevent multiple error occurrences if the
  491.    key is held down  */
  492.         inbufp = 0;
  493.     }
  494.     else  {
  495.         for ( ; cp > charn; cp-- )
  496.             text[cp] = text[cp-1];
  497.         text[charn] = c;
  498.         altered = YES;
  499.         sync( charn+1 );
  500.         rewrite( charn-1 );   /* updated charn */
  501.     }
  502. }
  503.  
  504.  
  505. /* deletes char before (dir=-1) or at (dir=0) cursor.
  506.  * NOP if charn = 0.
  507.  */
  508. deletechar(dir)
  509. int dir;
  510. {
  511.     char c;
  512.     int  cp;
  513.  
  514.     cp = charn + dir;
  515.     if ( cp < 0 )
  516.         return;
  517.     else if ( text[cp] == '\0' ) {  /* can't be dir = -1 */
  518.         crdelete();  /* case of cline == lastl handeled by crdelete() */
  519.     }
  520.     else  {
  521.         do  {
  522.             c = text[cp] = text[cp+1];
  523.             cp++;
  524.         }
  525.         while(c);
  526.  
  527.         altered = YES;
  528.         sync( charn + dir );
  529.         rewrite( charn );  /* updated charn */
  530.     }
  531. }
  532.  
  533. /* line delete */
  534.  
  535. linedelete()
  536. {
  537.     int i;
  538.  
  539.     puttext();
  540.     if (lastl == 1) {
  541.         altered = YES;
  542.         text[0] = '\0';  /* keep a seed */
  543.         sync(0);
  544.         rewrite(0);
  545.     }
  546.     else {
  547.         scrollup(cursory);      /* always clears bottom line */
  548.         if (loc(plast,1) > plast )
  549.             putline( plast+1, SHEIGHT, NULL );   /* add new line at bottom */
  550. /* The screen is updated.  Now do the slow work */
  551.         i = cline;
  552.         if (cline == lastl) {
  553.             cursory -=1;
  554.             cline -= 1;
  555.             putlineno(cline);
  556.         }
  557.         resetpcursor();
  558.         deltp(i, 1);
  559.         calp();
  560.         gettext(cline, charn);
  561.         sync(charn);
  562.     }
  563. /* do a kludged push on the text buffer.  see pop() */
  564.     stkptr = histptr;
  565.     stkcnt = histcnt;
  566.     return;
  567. }
  568.  
  569.  
  570. /* Concatenate lines.  Following line is appended to the current line
  571.  * at the cursor position.  The cursor position may be beyond the last
  572.  * visible character if !trail.
  573.  */
  574. crdelete()
  575. {
  576.     int  len, err, *t;
  577.     char textb[LLIM];
  578.  
  579.     puttext();
  580.     if (text[0] == 0) {
  581.         linedelete();  /* crdelete would work but linedelete looks better for undo */
  582.     }
  583.     else {
  584.         err = 0;
  585.         if (cline < loc(cline,1))
  586.             strcpy( textb, getline(cline+1) );
  587.         else
  588.             return;   /* cline == lastl */
  589.  
  590. /* have to rewrite first if a right marker will be added */
  591.         if (cursorx - offset == SWIDTH) {
  592.             offset += 1;
  593.             resetcursor();
  594.         }
  595.         len = strlen(text);
  596.         if ( len + strlen(textb) + 1 > LLIM )  {
  597.             textb[(LLIM-1)-len] = '\0';
  598.             error1(" Line too long - cut short ");
  599.             err = 1;
  600.         }
  601.  
  602.         strcat( text, textb );
  603.         altered = YES;
  604.         puttext();
  605.         putline(cline, cursory, text);
  606.         if (cursory < SHEIGHT) {
  607.             scrollup(cursory+1);             /* clears bottom line */
  608.             if (loc(plast,1) > plast )
  609.                 putline( plast+1, SHEIGHT, NULL );   /* add new line at bottom */
  610.         }
  611.         resetcursor();
  612. /* The screen is updated.  Now do the slow work */
  613.         deltp( cline+1, 1 );
  614.         calp();   /* lastl has changed, which can change plast */
  615.  
  616. /* hold off the status line if line truncated */
  617.         while( (err) && chkbuf() == 0)
  618.             ;
  619.     }
  620.     return;
  621. }
  622.  
  623.  
  624. /* deletes up to first occurrence of white space.
  625.  * if no white space then delete to end of line
  626.  * see inword() in ged7.c
  627.  * deletes first space after word as part of the word.
  628.  */
  629. deleteword()
  630. {
  631.     int  pend, cp, in;
  632.     char c;
  633.  
  634.     for ( in = inword( text[pend = charn] );
  635.       ( c = text[pend] )  &&  ( in ? inword(c): !inword(c) );
  636.       pend++ )
  637.             ;
  638.     if (text[pend] == ' ')
  639.         pend++;
  640.     for ( cp = charn; ( text[cp] = text[pend] ); pend++, cp++ )
  641.         ;
  642.     rewrite( charn );
  643.     altered = YES;
  644. }
  645.  
  646.  
  647. /* line break.
  648.  * In mode 0 the portion after the cursor is moved down one line, creating a
  649.  * new line.  The cursor is positioned on the new line unless it was
  650.  * initially in position 0, in which case it remains on the original line
  651.  * in preparation for the entry of a new line.
  652.  * However, if if the cursor is in column 1 of a null line
  653.  * then a new null line is created and the cursor moves
  654.  * down one.  These rules usually accomplish what is wanted with a mimimum
  655.  * of keystrokes.
  656.  *
  657.  * In mode 1 (^N) the cursor always stays on the initial line.  ^N will
  658.  * be used in a future version for sentence push/delete.
  659.  *
  660.  * The injection is done after the screen refresh because it is slow
  661.  * for large documents
  662.  *
  663.  * cursory, cline, and scroll() have to be used with internal consistantly
  664.  * if movline() is not used for linejumps.  calp() must be called if lastl
  665.  * changes due to injection or deletion because cursory and cline have
  666.  * relationships to pfirst and plast.
  667.  */
  668.  
  669. crinsert(mode)
  670. {
  671.     char textb[LLIM], c;
  672.     int  i, iline, charnb, ocharn, ncline, ocline, ch0;
  673.  
  674. /* the next steps produce the best reverse-field appearance with undo */
  675.     if (charn != 0)
  676.         altered = YES;
  677.  
  678.     puttext();
  679.     curson(NO);
  680.     ncline = ocline = cline;
  681.     ocharn = charn;
  682.  
  683.     charnb = 0;
  684.     if (autoin) {
  685.         for ( ; text[charnb] == ' '; charnb++)
  686.             textb[charnb] = ' ';
  687.         if (charnb > charn)
  688.             charnb = 0;
  689.     }
  690.  
  691.     strcpy( &textb[charnb], &text[charn] );  /* can be a null line */
  692.     ch0 = text[0];
  693.     text[charn] = '\0';
  694.  
  695.     if (mode == 0 ) {
  696.         sync(charnb);   /* cursor moves for <ret>, not for ^N
  697. /* horizontal scroll may occur if offset not 0.  may have to rewrite old text first.*/
  698.         if (offset > 0)
  699.             resetcursor();
  700.     }
  701.  
  702.     if (cursory == SHEIGHT) {
  703.         cursory--;
  704.         scrollup(topline); /* make room for the second half of the split line */
  705.     }
  706.     else
  707.         scrolldown(cursory+1); /* make rooom for the second half */
  708.  
  709.     putline(cline, cursory, text);
  710.     putline(cline+1, cursory+1, textb);
  711.     if (mode == 0) {
  712.         if (ocharn == 0 && ch0 != 0)
  713.             i = 0;  /* a convenience feature */
  714.         else
  715.             i = 1;
  716.         ncline += i;
  717.         cline = ncline;   /* for consistancy check in resetcursor() */
  718. /* calp() can't be called until after inject() */
  719.         cursory += i;
  720.         putlineno(ncline);
  721.     }
  722.     sync(charn);
  723.     resetpcursor();
  724.     curson(YES);
  725. /* The screen is updated.  Now do the slow work */
  726.  
  727. /* undo looks better if charn==0 is made a special case */
  728.     if (ocharn == 0) {
  729.         inject (ocline-1, text);
  730.     }
  731.     else {
  732.         cline = ocline;
  733.         altered = YES;
  734.         puttext();              /* left portion of line.  uses 'cline' */
  735.         inject(cline,textb);    /* right portion */
  736.         cline = ncline;
  737.         gettext(cline, charn);         /* get the correct data in text[] */
  738.     }
  739.     calp();           /* lastl has increased */
  740.     return;
  741. }
  742.  
  743.  
  744. /* set cursorx to col. cursor nearest to col. 'x' so that
  745.    cursor isn't in the middle of a tab or off the end of the
  746.    current line  +++ obsolete ?
  747.  */
  748. adjustc(x)
  749. int x;
  750. {
  751.     char c;
  752.  
  753.     for( charn = 0, cursorx = 0;
  754.      cursorx < x  && ( c = text[charn] );
  755.      charn++, cursorx++ )
  756.             if ( c == '\t' )
  757.             cursorx += tabwidth-1-(cursorx % tabwidth);
  758. }
  759.  
  760.  
  761. /* put cursorx and charn onto character 'cp' of current line.
  762.  */
  763.  
  764. sync(cp)
  765. int cp;
  766. {
  767.     int i;
  768.  
  769.     if (cp < 0)
  770.         cp = 0;
  771.     if (cp > (LLIM-1) )
  772.         cp = LLIM-1;   /* last possible '\0' is at text[LLIM-1] */
  773.     pad(cp);
  774.     for( charn = 0, cursorx = 0; charn < cp; cursorx++, charn++ ) {
  775.         if ( text[charn] == '\t' )
  776.             cursorx = cursorx+tabwidth-1-(cursorx % tabwidth);
  777.     }
  778.     return;
  779. }
  780.  
  781. /* Add trailing spaces if needed.
  782.  *
  783.  * When a new line is selected it is extended with spaces if necessary
  784.  * in order for the cursor to stay in its old x position.  The cursor
  785.  * can move anywhere.  The spaces are removed before the line is stored.
  786.  *
  787.  * If trail is TRUE then the spaces are not added because in that case
  788.  * trailing spaces in the input file or those added in editing are
  789.  * permanently retained.  In this mode the cursor can't be moved beyond
  790.  * the rightmost character of a line.
  791.  */
  792. pad(cp)
  793. int cp;
  794. {
  795.     int i;
  796.  
  797.     if( !trail ) {
  798.         i = trim(text);   /* 0  <=  i  <=  LLIM-1  */
  799.         if( cp > i ) {
  800.             for (  ; i < cp; i++)
  801.                 text[i] = ' ';
  802.             text[cp] = '\0';
  803.         }
  804.     }
  805.     return;
  806. }
  807.  
  808.  
  809.