home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d1xx / d166 / stevie.lha / Stevie / source / misccmds.c < prev    next >
C/C++ Source or Header  |  1988-11-22  |  9KB  |  413 lines

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