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