home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / jove-4.16-src.tgz / tar.out / bsd / jove / delete.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  8KB  |  368 lines

  1. /************************************************************************
  2.  * This program is Copyright (C) 1986-1996 by Jonathan Payne.  JOVE is  *
  3.  * provided to you without charge, and with no warranty.  You may give  *
  4.  * away copies of JOVE, including sources, provided that this notice is *
  5.  * included in all the files.                                           *
  6.  ************************************************************************/
  7.  
  8. /* Routines to perform all kinds of deletion.  */
  9.  
  10. #include "jove.h"
  11. #include "jctype.h"
  12. #include "disp.h"
  13. #include "delete.h"
  14. #include "insert.h"
  15. #include "marks.h"
  16. #include "move.h"
  17.  
  18. /* Assumes that either line1 or line2 is actually the current line, so it can
  19.    put its result into linebuf. */
  20.  
  21. private void
  22. patchup(line1, char1, line2, char2)
  23. LinePtr    line1,
  24.     line2;
  25. register int    char1,
  26.         char2;
  27. {
  28.     if (line1 != line2)
  29.         ChkWindows(line1, line2);
  30.     DotTo(line1, char1);
  31.     modify();
  32.     linecopy(linebuf, curchar, lcontents(line2) + char2);
  33.  
  34.     /* The following is a redisplay optimization. */
  35.     if (line1 != line2 && (char1 == 0 && char2 == 0))
  36.         line1->l_dline = line2->l_dline;
  37.  
  38.     DFixMarks(line1, char1, line2, char2);
  39.     makedirty(curline);
  40. }
  41.  
  42. /* Deletes the region by unlinking the lines in the middle,
  43.    and patching things up.  The unlinked lines are still in
  44.    order.  */
  45.  
  46. LinePtr
  47. reg_delete(line1, char1, line2, char2)
  48. LinePtr    line1,
  49.     line2;
  50. int    char1,
  51.     char2;
  52. {
  53.     register LinePtr    retline;
  54.  
  55.     if ((line1 == line2 && char1 == char2) || line2 == NULL)
  56.         complain((char *)NULL);
  57.     (void) fixorder(&line1, &char1, &line2, &char2);
  58.  
  59.     retline = nbufline();    /* New buffer line */
  60.  
  61.     (void) ltobuf(line1, genbuf);
  62.     if (line1 == line2)
  63.         genbuf[char2] = '\0';
  64.  
  65.     retline->l_prev = NULL;
  66.     retline->l_dline = putline(&genbuf[char1]);
  67.     patchup(line1, char1, line2, char2);
  68.  
  69.     if (line1 == line2)
  70.         retline->l_next = NULL;
  71.     else {
  72.         retline->l_next = line1->l_next;
  73.         (void) ltobuf(line2, genbuf);
  74.         genbuf[char2] = '\0';
  75.         line2->l_dline = putline(genbuf);
  76.         /* Shorten this line */
  77.     }
  78.  
  79.     if (line1 != line2) {
  80.         line1->l_next = line2->l_next;
  81.         if (line1->l_next)
  82.             line1->l_next->l_prev = line1;
  83.         else
  84.             curbuf->b_last = line1;
  85.         line2->l_next = NULL;
  86.     }
  87.  
  88.     return retline;
  89. }
  90.  
  91. private void
  92. lremove(line1, line2)
  93. register LinePtr    line1,
  94.         line2;
  95. {
  96.     LinePtr    next = line1->l_next;
  97.  
  98.     if (line1 == line2)
  99.         return;
  100.     line1->l_next = line2->l_next;
  101.     if (line1->l_next)
  102.         line1->l_next->l_prev = line1;
  103.     else
  104.         curbuf->b_last = line1;
  105.     lfreereg(next, line2);    /* Put region at end of free line list. */
  106. }
  107.  
  108. /* delete character forward */
  109.  
  110. void
  111. DelNChar()
  112. {
  113.     del_char(FORWARD, arg_value(), YES);
  114. }
  115.  
  116. /* Delete character backward */
  117.  
  118. void
  119. DelPChar()
  120. {
  121.     if (MinorMode(OverWrite) && !eolp()) {
  122.         /* Overwrite with spaces.
  123.          * Some care is exercised to overwrite tabs reasonably,
  124.          * but control characters displayed as two are not handled.
  125.          */
  126.         int    rightcol = calc_pos(linebuf, curchar);
  127.         int    charcount = min(arg_value(), curchar);
  128.         int    colcount = rightcol - calc_pos(linebuf, curchar-charcount);
  129.  
  130.         b_char(charcount);
  131.         overwrite(' ', colcount);
  132.         b_char(colcount);
  133.     } else {
  134.         del_char(BACKWARD, arg_value(), YES);
  135.     }
  136. }
  137.  
  138. /* Delete some characters.  If deleting forward then call for_char
  139.    to the final position otherwise call back_char.  Then delete the
  140.    region between the two with patchup(). */
  141.  
  142. void
  143. del_char(dir, num, OK_kill)
  144. int    dir,
  145.     num;
  146. bool    OK_kill;
  147. {
  148.     Bufpos    before,
  149.         after;
  150.     bool    killp = (OK_kill && (abs(num) > 1));
  151.  
  152.     DOTsave(&before);
  153.     if (dir == FORWARD)
  154.         f_char(num);
  155.     else
  156.         b_char(num);
  157.     if (before.p_line == curline && before.p_char == curchar)
  158.         complain((char *)NULL);
  159.     if (killp)
  160.         reg_kill(before.p_line, before.p_char, YES);
  161.     else {
  162.         DOTsave(&after);
  163.         (void) fixorder(&before.p_line, &before.p_char, &after.p_line, &after.p_char);
  164.         patchup(before.p_line, before.p_char, after.p_line, after.p_char);
  165.         lremove(before.p_line, after.p_line);
  166.     }
  167. }
  168.  
  169. /* The kill ring.
  170.  * Newest entry is at killptr; second newest is at killptr-1, etc.
  171.  * All empty slots are at the end of the array.
  172.  */
  173.  
  174. LinePtr    killbuf[NUMKILLS];
  175. int    killptr = 0;    /* index of newest entry (if any) */
  176.  
  177. void
  178. DelKillRing()    /* delete newest entry */
  179. {
  180.     int    i;
  181.  
  182.     lfreelist(killbuf[killptr]);    /* free entry */
  183.  
  184.     /* move space to end */
  185.     for (i = killptr; i != NUMKILLS-1; i++)
  186.         killbuf[i] = killbuf[i+1];
  187.     killbuf[i] = NULL;
  188.  
  189.     /* make killptr index predecessor (if any) */
  190.     killptr = (killptr + NUMKILLS - 1) % NUMKILLS;
  191.     while (killbuf[killptr] == NULL && killptr != 0)
  192.         killptr -= 1;
  193. }
  194.  
  195. private void
  196. AddKillRing(text)    /* add a new entry */
  197. LinePtr    text;
  198. {
  199.     if (killbuf[killptr] != NULL) {
  200.         killptr = (killptr +1) % NUMKILLS;
  201.         if (killbuf[NUMKILLS-1] == NULL) {
  202.             /* there is space: move one slot here */
  203.             int    i;
  204.  
  205.             for (i = NUMKILLS-1; i != killptr; i--)
  206.                 killbuf[i] = killbuf[i-1];
  207.         } else {
  208.             /* no free slots: delete oldest element */
  209.             lfreelist(killbuf[killptr]);
  210.         }
  211.     }
  212.     killbuf[killptr] = text;
  213. }
  214.  
  215. /* This kills a region between point, and line1/char1 and puts it on
  216.    the kill-ring.  If the last command was one of the kill commands,
  217.    the region is appended (prepended if backwards) to the last entry.  */
  218.  
  219. void
  220. reg_kill(line2, char2, dot_moved)
  221. LinePtr    line2;
  222. int    char2;
  223. bool    dot_moved;
  224. {
  225.     LinePtr    nl,
  226.         line1 = curline;
  227.     int    char1 = curchar;
  228.     bool    backwards;
  229.  
  230.     backwards = !fixorder(&line1, &char1, &line2, &char2);
  231.     /* This is a kludge!  But it possible for commands that don't
  232.        know which direction they are deleting in (e.g., delete
  233.        previous word could have been called with a negative argument
  234.        in which case, it wouldn't know that it really deleted
  235.        forward. */
  236.  
  237.     if (!dot_moved)
  238.         backwards = !backwards;
  239.  
  240.     DotTo(line1, char1);
  241.  
  242.     nl = reg_delete(line1, char1, line2, char2);
  243.  
  244.     if (last_cmd != KILLCMD) {
  245.         AddKillRing(nl);
  246.     } else {
  247.         LinePtr    lastln = lastline(nl);
  248.  
  249.         if (backwards) {
  250.             (void) DoYank(nl, 0, lastln, length(lastln), killbuf[killptr], 0, (Buffer *)NULL);
  251.         } else {
  252.             LinePtr    olastln = lastline(killbuf[killptr]);
  253.  
  254.             (void) DoYank(nl, 0, lastln, length(lastln), olastln, length(olastln), (Buffer *)NULL);
  255.         }
  256.     }
  257.     this_cmd = KILLCMD;
  258. }
  259.  
  260. void
  261. DelReg()
  262. {
  263.     register Mark    *mp = CurMark();
  264.  
  265.     reg_kill(mp->m_line, mp->m_char, NO);
  266. }
  267.  
  268. /* Save a region.  A pretend kill. */
  269.  
  270. void
  271. CopyRegion()
  272. {
  273.     register LinePtr    nl;
  274.     register Mark    *mp;
  275.     register int    status;
  276.  
  277.     mp = CurMark();
  278.     if (mp->m_line == curline && mp->m_char == curchar)
  279.         complain((char *)NULL);
  280.  
  281.     nl = nbufline();
  282.     AddKillRing(nl);
  283.     SavLine(nl, NullStr);
  284.     nl->l_next = nl->l_prev = NULL;
  285.  
  286.     status = inorder(mp->m_line, mp->m_char, curline, curchar);
  287.     if (status == -1)
  288.         return;
  289.  
  290.     if (status)
  291.         (void) DoYank(mp->m_line, mp->m_char, curline, curchar,
  292.                 nl, 0, (Buffer *)NULL);
  293.     else
  294.         (void) DoYank(curline, curchar, mp->m_line, mp->m_char,
  295.                 nl, 0, (Buffer *)NULL);
  296. }
  297.  
  298. void
  299. DelWtSpace()
  300. {
  301.     register char    *ep = &linebuf[curchar],
  302.             *sp = &linebuf[curchar];
  303.  
  304.     while (jiswhite(*ep))
  305.         ep += 1;
  306.     while (sp > linebuf && jiswhite(sp[-1]))
  307.         sp -= 1;
  308.     if (sp != ep) {
  309.         curchar = sp - linebuf;
  310.         DFixMarks(curline, curchar, curline, curchar + (ep - sp));
  311.         strcpy(sp, ep);
  312.         makedirty(curline);
  313.         modify();
  314.     }
  315. }
  316.  
  317. void
  318. DelBlnkLines()
  319. {
  320.     register Mark    *dot;
  321.     bool    all;
  322.  
  323.     if (!blnkp(&linebuf[curchar]))
  324.         return;
  325.     dot = MakeMark(curline, curchar);
  326.     all = !blnkp(linebuf);
  327.     while (blnkp(linebuf) && curline->l_prev)
  328.         SetLine(curline->l_prev);
  329.     all |= firstp(curline);
  330.     Eol();
  331.     DelWtSpace();
  332.     line_move(FORWARD, 1, NO);
  333.     while (blnkp(linebuf) && !eobp()) {
  334.         DelWtSpace();
  335.         del_char(FORWARD, 1, NO);
  336.     }
  337.     if (!all && !eobp())
  338.         open_lines(1);
  339.     ToMark(dot);
  340.     DelMark(dot);
  341. }
  342.  
  343. private void
  344. dword(forward)
  345. bool    forward;
  346. {
  347.     Bufpos    savedot;
  348.  
  349.     DOTsave(&savedot);
  350.     if (forward)
  351.         ForWord();
  352.     else
  353.         BackWord();
  354.     reg_kill(savedot.p_line, savedot.p_char, YES);
  355. }
  356.  
  357. void
  358. DelNWord()
  359. {
  360.     dword(YES);
  361. }
  362.  
  363. void
  364. DelPWord()
  365. {
  366.     dword(NO);
  367. }
  368.