home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / jove4.9 / part03 / delete.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-25  |  6.4 KB  |  309 lines

  1. /***************************************************************************
  2.  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
  3.  * is 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.  
  12. /* Assumes that either line1 or line2 is actual the current line, so it can
  13.    put its result into linebuf. */
  14.  
  15. void
  16. patchup(line1, char1, line2, char2)
  17. Line    *line1,
  18.     *line2;
  19. register int    char1,
  20.         char2;
  21. {
  22.     if (line1 != line2)
  23.         ChkWindows(line1, line2);
  24.     DotTo(line1, char1);
  25.     modify();
  26.     linecopy(linebuf, curchar, lcontents(line2) + char2);
  27.  
  28.     /* The following is a redisplay optimization. */
  29.     if (line1 != line2 && (char1 == 0 && char2 == 0))
  30.         line1->l_dline = line2->l_dline;
  31.  
  32.     DFixMarks(line1, char1, line2, char2);
  33.     makedirty(curline);
  34. }
  35.  
  36. /* Deletes the region by unlinking the lines in the middle,
  37.    and patching things up.  The unlinked lines are still in
  38.    order.  */
  39.  
  40. Line *
  41. reg_delete(line1, char1, line2, char2)
  42. Line    *line1,
  43.     *line2;
  44. {
  45.     register Line    *retline;
  46.  
  47.     if ((line1 == line2 && char1 == char2) || line2 == 0)
  48.         complain((char *) 0);
  49.     (void) fixorder(&line1, &char1, &line2, &char2);
  50.  
  51.     retline = nbufline();    /* New buffer line */
  52.  
  53.     (void) ltobuf(line1, genbuf);
  54.     if (line1 == line2)
  55.         genbuf[char2] = '\0';
  56.  
  57.     retline->l_prev = 0;
  58.     retline->l_dline = putline(&genbuf[char1]);
  59.     patchup(line1, char1, line2, char2);
  60.  
  61.     if (line1 == line2)
  62.         retline->l_next = 0;
  63.     else {
  64.         retline->l_next = line1->l_next;
  65.         (void) ltobuf(line2, genbuf);
  66.         genbuf[char2] = '\0';
  67.         line2->l_dline = putline(genbuf);
  68.         /* Shorten this line */
  69.     }
  70.  
  71.     if (line1 != line2) {
  72.         line1->l_next = line2->l_next;
  73.         if (line1->l_next)
  74.             line1->l_next->l_prev = line1;
  75.         else
  76.             curbuf->b_last = line1;
  77.         line2->l_next = 0;
  78.     }
  79.  
  80.     return retline;
  81. }
  82.  
  83. void
  84. lremove(line1, line2)
  85. register Line    *line1,
  86.         *line2;
  87. {
  88.     Line    *next = line1->l_next;
  89.  
  90.     if (line1 == line2)
  91.         return;
  92.     line1->l_next = line2->l_next;
  93.     if (line1->l_next)
  94.         line1->l_next->l_prev = line1;
  95.     else
  96.         curbuf->b_last = line1;
  97.     lfreereg(next, line2);    /* Put region at end of free line list. */
  98. }
  99.  
  100. /* Delete character forward */
  101.  
  102. void
  103. DelNChar()
  104. {
  105.     del_char(FORWARD, arg_value());
  106. }
  107.  
  108. /* Delete character backward */
  109.  
  110. void
  111. DelPChar()
  112. {
  113.     if (MinorMode(OverWrite)) {
  114.         int    count = min(arg_value(), curchar);
  115.  
  116.         b_char(count);
  117.  
  118.         /* overwrite with spaces */
  119.         set_arg_value(count);
  120.         LastKeyStruck = ' ';
  121.         SelfInsert();
  122.  
  123.         b_char(count);
  124.     } else        
  125.         del_char(BACKWARD, arg_value());
  126. }
  127.  
  128. /* Delete some characters.  If deleting forward then call for_char
  129.    to the final position otherwise call back_char.  Then delete the
  130.    region between the two with patchup(). */
  131.  
  132. void
  133. del_char(dir, num)
  134. {
  135.     Bufpos    before,
  136.         after;
  137.     int    killp = (abs(num) > 1);
  138.  
  139.     DOTsave(&before);
  140.     if (dir == FORWARD) f_char(num);
  141.         else b_char(num);
  142.     if (before.p_line == curline && before.p_char == curchar)
  143.         complain((char *) 0);
  144.     if (killp)
  145.         reg_kill(before.p_line, before.p_char, 1);
  146.     else {
  147.         DOTsave(&after);
  148.         (void) fixorder(&before.p_line, &before.p_char, &after.p_line, &after.p_char);
  149.         patchup(before.p_line, before.p_char, after.p_line, after.p_char);
  150.         lremove(before.p_line, after.p_line);
  151.     }
  152. }
  153.  
  154. /* This kills a region between point, and line1/char1 and puts it on
  155.    the kill-ring.  If the last command was one of the kill commands,
  156.    the region is appended (prepended if backwards) to the last entry.  */
  157.  
  158. int    killptr = 0;
  159. Line    *killbuf[NUMKILLS];
  160.  
  161. void
  162. reg_kill(line2, char2, dot_moved)
  163. Line    *line2;
  164. {
  165.     Line    *nl,
  166.         *line1 = curline;
  167.     int    char1 = curchar;
  168.     int    backwards;
  169.  
  170.     backwards = !fixorder(&line1, &char1, &line2, &char2);
  171.     /* This is a kludge!  But it possible for commands that don't
  172.        know which direction they are deleting in (e.g., delete
  173.        previous word could have been called with a negative argument
  174.        in which case, it wouldn't know that it really deleted
  175.        forward. */
  176.  
  177.     if (!dot_moved)
  178.         backwards = !backwards;
  179.  
  180.     DotTo(line1, char1);
  181.  
  182.     nl = reg_delete(line1, char1, line2, char2);
  183.  
  184.     if (last_cmd != KILLCMD) {
  185.         killptr = ((killptr + 1) % NUMKILLS);
  186.         lfreelist(killbuf[killptr]);
  187.         killbuf[killptr] = nl;
  188.     } else {
  189.         Line    *lastln = lastline(nl);
  190.  
  191.         if (backwards)
  192.             (void) DoYank(nl, 0, lastln, length(lastln), killbuf[killptr], 0, (Buffer *) 0);
  193.         else {
  194.             Line    *olastln = lastline(killbuf[killptr]);
  195.  
  196.             (void) DoYank(nl, 0, lastln, length(lastln), olastln, length(olastln), (Buffer *) 0);
  197.         }
  198.     }
  199.     this_cmd = KILLCMD;
  200. }
  201.  
  202. void
  203. DelReg()
  204. {
  205.     register Mark    *mp = CurMark();
  206.  
  207.     reg_kill(mp->m_line, mp->m_char, 0);
  208. }
  209.  
  210. /* Save a region.  A pretend kill. */
  211.  
  212. void
  213. CopyRegion()
  214. {
  215.     register Line    *nl;
  216.     register Mark    *mp;
  217.     register int    status;
  218.  
  219.     mp = CurMark();
  220.     if (mp->m_line == curline && mp->m_char == curchar)
  221.         complain((char *) 0);
  222.  
  223.     killptr = ((killptr + 1) % NUMKILLS);
  224.     if (killbuf[killptr])
  225.         lfreelist(killbuf[killptr]);
  226.     nl = killbuf[killptr] = nbufline();
  227.     SavLine(nl, NullStr);
  228.     nl->l_next = nl->l_prev = 0;
  229.  
  230.     status = inorder(mp->m_line, mp->m_char, curline, curchar);
  231.     if (status == -1)
  232.         return;
  233.  
  234.     if (status)
  235.         (void) DoYank(mp->m_line, mp->m_char, curline, curchar,
  236.                 nl, 0, (Buffer *) 0);
  237.     else
  238.         (void) DoYank(curline, curchar, mp->m_line, mp->m_char,
  239.                 nl, 0, (Buffer *) 0);
  240. }
  241.  
  242. void
  243. DelWtSpace()
  244. {
  245.     register char    *ep = &linebuf[curchar],
  246.             *sp = &linebuf[curchar];
  247.  
  248.     while (*ep == ' ' || *ep == '\t')
  249.         ep += 1;
  250.     while (sp > linebuf && *(sp - 1) == ' ' || *(sp - 1) == '\t')
  251.         sp -= 1;
  252.     if (sp != ep) {
  253.         curchar = sp - linebuf;
  254.         DFixMarks(curline, curchar, curline, curchar + (ep - sp));
  255.         strcpy(sp, ep);
  256.         makedirty(curline);
  257.         modify();
  258.     }
  259. }
  260.  
  261. void
  262. DelBlnkLines()
  263. {
  264.     register Mark    *dot;
  265.     int    all;
  266.  
  267.     if (!blnkp(&linebuf[curchar]))
  268.         return;
  269.     dot = MakeMark(curline, curchar, M_FLOATER);
  270.     all = !blnkp(linebuf);
  271.     while (blnkp(linebuf) && curline->l_prev)
  272.         SetLine(curline->l_prev);
  273.     all |= (firstp(curline));
  274.     Eol();
  275.     DelWtSpace();
  276.     line_move(FORWARD, 1, NO);
  277.     while (blnkp(linebuf) && !eobp()) {
  278.         DelWtSpace();
  279.         del_char(FORWARD, 1);
  280.     }
  281.     if (!all && !eobp())
  282.         open_lines(1);
  283.     ToMark(dot);
  284.     DelMark(dot);
  285. }
  286.  
  287. void
  288. DelNWord()
  289. {
  290.     dword(1);
  291. }
  292.  
  293. void
  294. DelPWord()
  295. {
  296.     dword(0);
  297. }
  298.  
  299. void
  300. dword(forward)
  301. {
  302.     Bufpos    savedot;
  303.  
  304.     DOTsave(&savedot);
  305.     if(forward)  ForWord();
  306.         else BackWord();
  307.     reg_kill(savedot.p_line, savedot.p_char, 1);
  308. }
  309.