home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / STVI369G.ZIP / MISCCMDS.C < prev    next >
C/C++ Source or Header  |  1990-05-01  |  10KB  |  443 lines

  1. /* $Header: /nw/tony/src/stevie/src/RCS/misccmds.c,v 1.14 89/08/06 09:50:17 tony Exp $
  2.  *
  3.  * Various routines to perform specific editing operations or return
  4.  * useful information about the file.
  5.  */
  6.  
  7. #include "stevie.h"
  8.  
  9. static    void    openfwd(), openbwd();
  10.  
  11. extern    bool_t    did_ai;
  12.  
  13. /*
  14.  * opencmd
  15.  *
  16.  * Add a blank line above or below the current line.
  17.  */
  18.  
  19. void
  20. opencmd(dir, can_ai)
  21. int    dir;
  22. int    can_ai;            /* if true, consider auto-indent */
  23. {
  24.     if (dir == FORWARD)
  25.         openfwd(can_ai);
  26.     else
  27.         openbwd(can_ai);
  28. }
  29.  
  30. static void
  31. openfwd(can_ai)
  32. int    can_ai;
  33. {
  34.     register LINE    *l;
  35.     LPTR    *next;
  36.     register char    *s;    /* string to be moved to new line, if any */
  37.     int    newindex = 0;    /* index of the cursor on the new line */
  38.  
  39.     /*
  40.      * If we're in insert mode, we need to move the remainder of the
  41.      * current line onto the new line. Otherwise the new line is left
  42.      * blank.
  43.      */
  44.     if (State == INSERT || State == REPLACE)
  45.         s = &Curschar->linep->s[Curschar->index];
  46.     else
  47.         s = "";
  48.  
  49.     if ((next = nextline(Curschar)) == NULL)    /* open on last line */
  50.         next = Fileend;
  51.  
  52.     /*
  53.      * By asking for as much space as the prior line had we make sure
  54.      * that we'll have enough space for any auto-indenting.
  55.      */
  56.     if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
  57.         return;
  58.  
  59.     if (*s != NUL)
  60.         strcpy(l->s, s);        /* copy string to new line */
  61.  
  62.     else if (can_ai && P(P_AI) && !anyinput()) {
  63.         char    *p;
  64.  
  65.         /*
  66.          * Copy prior line, and truncate after white space
  67.          */
  68.         strcpy(l->s, Curschar->linep->s);
  69.  
  70.         for (p = l->s; *p == ' ' || *p == TAB ;p++)
  71.             ;
  72.         *p = NUL;
  73.         newindex = p - l->s;
  74.  
  75.         /*
  76.          * If we just did an auto-indent, then we didn't type
  77.          * anything on the prior line, and it should be truncated.
  78.          */
  79.         if (did_ai)
  80.             Curschar->linep->s[0] = NUL;
  81.  
  82.         did_ai = TRUE;
  83.     }
  84.  
  85.     /* truncate current line at cursor */
  86.     if (State == INSERT || State == REPLACE)
  87.         *s = NUL;
  88.             
  89.  
  90.     Curschar->linep->next = l;    /* link neighbors to new line */
  91.     next->linep->prev = l;
  92.  
  93.     l->prev = Curschar->linep;    /* link new line to neighbors */
  94.     l->next = next->linep;
  95.  
  96.     if (next == Fileend)            /* new line at end */
  97.         l->num = Curschar->linep->num + LINEINC;
  98.  
  99.     else if ((l->prev->num) + 1 == l->next->num)    /* no gap, renumber */
  100.         renum();
  101.  
  102.     else {                    /* stick it in the middle */
  103.         unsigned long    lnum;
  104.         lnum = ((long)l->prev->num + (long)l->next->num) / 2;
  105.         l->num = lnum;
  106.     }
  107.  
  108.     /*
  109.      * Get the cursor to the start of the line, so that 'Cursrow'
  110.      * gets set to the right physical line number for the stuff
  111.      * that follows...
  112.      */
  113.     Curschar->index = 0;
  114.     cursupdate();
  115.  
  116.     /*
  117.      * If we're doing an open on the last logical line, then
  118.      * go ahead and scroll the screen up. Otherwise, just insert
  119.      * a blank line at the right place. We use calls to plines()
  120.      * in case the cursor is resting on a long line.
  121.      */
  122.     if (Cursrow + plines(Curschar) == (Rows - 1))
  123.         scrollup(1);
  124.     else
  125.         s_ins(Cursrow+plines(Curschar), 1);
  126.  
  127.     *Curschar = *nextline(Curschar);    /* cursor moves down */
  128.     Curschar->index = newindex;
  129.  
  130.     updatescreen();        /* because Botchar is now invalid... */
  131.  
  132.     cursupdate();        /* update Cursrow before insert */
  133. }
  134.  
  135. static void
  136. openbwd(can_ai)
  137. int    can_ai;
  138. {
  139.     register LINE    *l;
  140.     LINE    *prev;
  141.     int    newindex = 0;
  142.  
  143.     prev = Curschar->linep->prev;
  144.  
  145.     if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL)
  146.         return;
  147.  
  148.     Curschar->linep->prev = l;    /* link neighbors to new line */
  149.     prev->next = l;
  150.  
  151.     l->next = Curschar->linep;    /* link new line to neighbors */
  152.     l->prev = prev;
  153.  
  154.     if (can_ai && P(P_AI) && !anyinput()) {
  155.         char    *p;
  156.  
  157.         /*
  158.          * Copy current line, and truncate after white space
  159.          */
  160.         strcpy(l->s, Curschar->linep->s);
  161.  
  162.         for (p = l->s; *p == ' ' || *p == TAB ;p++)
  163.             ;
  164.         *p = NUL;
  165.         newindex = p - l->s;
  166.  
  167.         did_ai = TRUE;
  168.     }
  169.  
  170.     Curschar->linep = Curschar->linep->prev;
  171.     Curschar->index = newindex;
  172.  
  173.     if (prev == Filetop->linep)        /* new start of file */
  174.         Filemem->linep = l;
  175.  
  176.     renum();    /* keep it simple - we don't do this often */
  177.  
  178.     cursupdate();            /* update Cursrow before insert */
  179.     if (Cursrow != 0)
  180.         s_ins(Cursrow, 1);        /* insert a physical line */
  181.  
  182.     updatescreen();
  183. }
  184.  
  185. int
  186. cntllines(pbegin,pend)
  187. register LPTR    *pbegin, *pend;
  188. {
  189.     register LINE    *lp;
  190.     int    lnum = 1;
  191.  
  192.     for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next)
  193.         lnum++;
  194.  
  195.     return(lnum);
  196. }
  197.  
  198. /*
  199.  * plines(p) - return the number of physical screen lines taken by line 'p'
  200.  */
  201. int
  202. plines(p)
  203. LPTR    *p;
  204. {
  205.     register int    col = 0;
  206.     register char    *s;
  207.  
  208.     s = p->linep->s;
  209.  
  210.     if (*s == NUL)        /* empty line */
  211.         return 1;
  212.  
  213.     for (; *s != NUL ;s++) {
  214.         if ( *s == TAB && !P(P_LS))
  215.             col += P(P_TS) - (col % P(P_TS));
  216.         else
  217.             col += chars[(unsigned)(*s & 0xff)].ch_size;
  218.     }
  219.  
  220.     /*
  221.      * If list mode is on, then the '$' at the end of
  222.      * the line takes up one extra column.
  223.      */
  224.     if (P(P_LS))
  225.         col += 1;
  226.     /*
  227.      * If 'number' mode is on, add another 8.
  228.      */
  229.     if (P(P_NU))
  230.         col += 8;
  231.  
  232.     return ((col + (Columns-1)) / Columns);
  233. }
  234.  
  235. void
  236. fileinfo()
  237. {
  238.     extern    int    numfiles, curfile;
  239.     register long    l1, l2;
  240.  
  241.     if (bufempty()) {
  242.          l1 = 0;
  243.          l2 = 1;            /* don't div by zero */
  244.      } else {
  245.          l1 = cntllines(Filemem, Curschar);
  246.          l2 = cntllines(Filemem, Fileend) - 1;
  247.     }
  248.  
  249.     if (numfiles > 1)
  250.         smsg("\"%s\"%s line %ld of %ld -- %ld %% -- (file %d of %d)",
  251.             (Filename != NULL) ? Filename : "No File",
  252.             Changed ? " [Modified]" : "",
  253.             l1, l2, (l1 * 100)/l2,
  254.             curfile+1, numfiles);
  255.     else
  256.         smsg("\"%s\"%s line %ld of %ld -- %ld %% --",
  257.             (Filename != NULL) ? Filename : "No File",
  258.             Changed ? " [Modified]" : "",
  259.             l1, l2, (l1 * 100)/l2);
  260. }
  261.  
  262. /*
  263.  * gotoline(n) - return a pointer to line 'n'
  264.  *
  265.  * Returns a pointer to the last line of the file if n is zero, or
  266.  * beyond the end of the file.
  267.  */
  268. LPTR *
  269. gotoline(n)
  270. register int    n;
  271. {
  272.     static    LPTR    l;
  273.  
  274.     l.index = 0;
  275.  
  276.     if ( n == 0 )
  277.         l = *prevline(Fileend);
  278.     else {
  279.         LPTR    *p;
  280.  
  281.         for (l = *Filemem; --n > 0 ;l = *p)
  282.             if ((p = nextline(&l)) == NULL)
  283.                 break;
  284.     }
  285.     return &l;
  286. }
  287.  
  288. void
  289. inschar(c)
  290. int    c;
  291. {
  292.     register char    *p, *pend;
  293.  
  294.     /* make room for the new char. */
  295.     if ( ! canincrease(1) )
  296.         return;
  297.  
  298.     if (State != REPLACE) {
  299.         p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
  300.         pend = &Curschar->linep->s[Curschar->index];
  301.  
  302.         for (; p > pend ;p--)
  303.             *p = *(p-1);
  304.  
  305.         *p = c;
  306.  
  307.     } else {    /* replace mode */
  308.         /*
  309.          * Once we reach the end of the line, we are effectively
  310.          * inserting new text, so make sure the string terminator
  311.          * stays out there.
  312.          */
  313.         if (gchar(Curschar) == NUL)
  314.             Curschar->linep->s[Curschar->index+1] = NUL;
  315.         pchar(Curschar, c);
  316.     }
  317.  
  318.     /*
  319.      * If we're in insert mode and showmatch mode is set, then
  320.      * check for right parens and braces. If there isn't a match,
  321.      * then beep. If there is a match AND it's on the screen, then
  322.      * flash to it briefly. If it isn't on the screen, don't do anything.
  323.      */
  324.     if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
  325.         LPTR    *lpos, csave;
  326.  
  327.         if ((lpos = showmatch()) == NULL)    /* no match, so beep */
  328.             beep();
  329.         else if (LINEOF(lpos) >= LINEOF(Topchar)) {
  330.             updatescreen();        /* show the new char first */
  331.             csave = *Curschar;
  332.             *Curschar = *lpos;    /* move to matching char */
  333.             cursupdate();
  334.             windgoto(Cursrow, Curscol);
  335.             pause();        /* brief pause */
  336.             *Curschar = csave;    /* restore cursor position */
  337.             cursupdate();
  338.         }
  339.     }
  340.  
  341.     inc(Curschar);
  342.     CHANGED;
  343. }
  344.  
  345. bool_t
  346. delchar(fixpos)
  347. bool_t    fixpos;        /* if TRUE, fix the cursor position when done */
  348. {
  349.     register int    i;
  350.  
  351.     /* Check for degenerate case; there's nothing in the file. */
  352.     if (bufempty())
  353.         return FALSE;
  354.  
  355.     if (lineempty())    /* can't do anything */
  356.         return FALSE;
  357.  
  358.     /* Delete the char. at Curschar by shifting everything */
  359.     /* in the line down. */
  360.     for ( i=Curschar->index+1; i < Curschar->linep->size ;i++)
  361.         Curschar->linep->s[i-1] = Curschar->linep->s[i];
  362.  
  363.     /* If we just took off the last character of a non-blank line, */
  364.     /* we don't want to end up positioned at the newline. */
  365.     if (fixpos) {
  366.         if (gchar(Curschar)==NUL && Curschar->index>0 && State!=INSERT)
  367.             Curschar->index--;
  368.     }
  369.     CHANGED;
  370.  
  371.     return TRUE;
  372. }
  373.  
  374.  
  375. void
  376. delline(nlines, can_update)
  377. int    nlines;
  378. bool_t    can_update;
  379. {
  380.     register LINE    *p, *q;
  381.     int    doscreen;        /* if true, update the screen */
  382.  
  383.     doscreen = can_update;
  384.     /*
  385.      * There's no point in keeping the screen updated if we're
  386.      * deleting more than a screen's worth of lines.
  387.      */
  388.     if (nlines > (Rows - 1) && can_update) {
  389.         doscreen = FALSE;
  390.         s_del(Cursrow, Rows-1);    /* flaky way to clear rest of screen */
  391.     }
  392.  
  393.     while ( nlines-- > 0 ) {
  394.  
  395.         if (bufempty())            /* nothing to delete */
  396.             break;
  397.  
  398.         if (buf1line()) {        /* just clear the line */
  399.             Curschar->linep->s[0] = NUL;
  400.             Curschar->index = 0;
  401.             break;
  402.         }
  403.  
  404.         p = Curschar->linep->prev;
  405.         q = Curschar->linep->next;
  406.  
  407.         if (p == Filetop->linep) {    /* first line of file so... */
  408.             Filemem->linep = q;    /* adjust start of file */
  409.             Topchar->linep = q;    /* and screen */
  410.         }
  411.         p->next = q;
  412.         q->prev = p;
  413.  
  414.         clrmark(Curschar->linep);    /* clear marks for the line */
  415.  
  416.         /*
  417.          * Delete the correct number of physical lines on the screen
  418.          */
  419.         if (doscreen)
  420.             s_del(Cursrow, plines(Curschar));
  421.  
  422.         /*
  423.          * If deleting the top line on the screen, adjust Topchar
  424.          */
  425.         if (Topchar->linep == Curschar->linep)
  426.             Topchar->linep = q;
  427.  
  428.         free(Curschar->linep->s);
  429.         free((char *) Curschar->linep);
  430.  
  431.         Curschar->linep = q;
  432.         Curschar->index = 0;        /* is this right? */
  433.         CHANGED;
  434.  
  435.         /* If we delete the last line in the file, back up */
  436.         if ( Curschar->linep == Fileend->linep) {
  437.             Curschar->linep = Curschar->linep->prev;
  438.             /* and don't try to delete any more lines */
  439.             break;
  440.         }
  441.     }
  442. }
  443.