/* Jonathan Payne at Lincoln-Sudbury Regional High School 5-25-83 jove_delete.c Routines to perform deletion. The word delete and line delete use the same routine as "delete-to-killbuffer". Character delete uses some of the same stuff, but doesn't save the text in the kill-buffer. */ #include "jove.h" int diffnum = 0; /* Returns whether line1 char1 is before line2 char2 in the buffer. Also sets `diffnum' to the number of lines between the two for redisplay purposes. */ inorder(line1, char1, line2, char2) LINE *line1, *line2; { register int i = 1; register LINE *lp = curbuf->b_zero; int f1, f2; diffnum = f1 = f2 = 0; if (line1 == line2) return char1 < char2; while (lp && (!f1 || !f2)) { if (lp == line1) f1 = i; else if (lp == line2) f2 = i; lp = lp->l_next; ++i; } diffnum = abs(f1 - f2); if (f1 == 0 || f2 == 0) return -1; return f1 < f2; } /* Use this when you just want to look at a line without changing anything. It'll return linebuf if it is the current line of the current buffer (no copying). */ char * getcptr(line, buf) LINE *line; char *buf; { if (line == curline) return linebuf; else { ignore(getline(line->l_dline, buf)); return buf; } } /* Use this when ggetcptr is not appropiate */ char * getright(line, buf) LINE *line; char *buf; { if (line == curline) { if (buf != linebuf) strcpy(buf, linebuf); } else ignore(getline(line->l_dline, buf)); return buf; } /* Assumes that either line1 or line2 is actual the current line, so it can put its result into linebuf. */ patchup(line1, char1, line2, char2) register LINE *line1, *line2; { char line2buf[LBSIZE]; register char *twoptr; if (line1 != line2) KludgeWindows(line1, line2); SetModified(curbuf); if (line2 == curline) { /* So we don't need to getline it */ if (line1 == curline) twoptr = linebuf; else { strcpy(line2buf, linebuf); twoptr = line2buf; } SetLine(line1); /* Line1 now in linebuf */ } else twoptr = getright(line2, line2buf); curchar = char1; linecopy(linebuf, curchar, twoptr + char2); DFixMarks(line1, char1, line2, char2); makedirty(curline); } /* Deletes the region by unlinking the lines in the middle, and patching things up. The unlinked lines are still in order. */ LINE * reg_delete(line1, char1, line2, char2) LINE *line1, *line2; { LINE *retline; if ((line1 == line2 && char1 == char2) || line2 == 0) complain((char *) 0); fixorder(&line1, &char1, &line2, &char2); retline = nbufline(); /* New buffer line */ ignore(getright(line1, genbuf)); if (line1 == line2) genbuf[char2] = '\0'; retline->l_prev = 0; retline->l_dline = putline(&genbuf[char1]); patchup(line1, char1, line2, char2); if (line1 == line2) retline->l_next = 0; else { retline->l_next = line1->l_next; ignore(getright(line2, genbuf)); genbuf[char2] = '\0'; line2->l_dline = putline(genbuf); /* Shorten this line */ } if (line1 != line2) { line1->l_next = line2->l_next; if (line1->l_next) line1->l_next->l_prev = line1; else curbuf->b_dol = line1; line2->l_next = 0; } return retline; } lremove(line1, line2) register LINE *line1, *line2; { LINE *next = line1->l_next; if (line1 == line2) return; line1->l_next = line2->l_next; if (line1->l_next) line1->l_next->l_prev = line1; else curbuf->b_dol = line1; lfreereg(next, line2); /* Put region at end of free line list */ } /* Delete character forward */ DelNChar() { del_char(1); } /* Delete character backward */ DelPChar() { del_char(0); } /* Delete some characters. If deleting `forward' then call for_char * to the final position otherwise call back_char. Then delete the * region between the two with patchup(). */ del_char(forward) { BUFLOC newdot, pt; if (forward) { DOTsave(&newdot); ForChar(); DOTsave(&pt); } else { DOTsave(&pt); BackChar(); DOTsave(&newdot); /* New dot will be back here */ } /* Patchup puts the result in linebuf, which is fine with us */ patchup(newdot.p_line, newdot.p_char, pt.p_line, pt.p_char); lremove(newdot.p_line, pt.p_line); } /* This kills a region and puts it on the kill-ring. If the last command was one of the kill commands, the region is appended (prepended if backwards) to the last entry. */ reg_kill(line1, char1, line2, char2, backwards) LINE *line1, *line2; { LINE *nl, *ol; char buf[LBSIZE]; fixorder(&line1, &char1, &line2, &char2); DotTo(line1, char1); nl = reg_delete(line1, char1, line2, char2); if (last_cmd != KILLCMD) { killptr = ((killptr + 1) % NUMKILLS); lfreelist(killbuf[killptr]); killbuf[killptr] = nl; } else { /* Last cmd was a KILLCMD so merge the kills */ if (backwards) { LINE *fl, *lastln; fl = killbuf[killptr]; lastln = lastline(nl); ignore(getright(lastln, buf)); ignore(getright(fl, genbuf)); linecopy(buf, strlen(buf), genbuf); lastln->l_dline = putline(buf); killbuf[killptr] = nl; lastln->l_next = fl->l_next; } else { ol = lastline(killbuf[killptr]); ignore(getright(ol, buf)); ignore(getright(nl, genbuf)); linecopy(buf, strlen(buf), genbuf); ol->l_dline = putline(buf); makedirty(ol); ol->l_next = nl->l_next; } } this_cmd = KILLCMD; } fixorder(line1, char1, line2, char2) register LINE **line1, **line2; register int *char1, *char2; { LINE *tline; int tchar; if (inorder(*line1, *char1, *line2, *char2)) return; tline = *line1; tchar = *char1; *line1 = *line2; *char1 = *char2; *line2 = tline; *char2 = tchar; } DelReg() { register MARK *mp = CurMark(); reg_kill(mp->m_line, mp->m_char, curline, curchar, 0); } DelWtSpace() { register char c; while (!eolp() && ((c = linebuf[curchar]) == ' ' || c == '\t')) DelNChar(); while (curchar > 0 && ((c = linebuf[curchar - 1]) == ' ' || c == '\t')) DelPChar(); }