|
|
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:
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)
141: f_char(num);
142: else
143: b_char(num);
144: if (before.p_line == curline && before.p_char == curchar)
145: complain((char *) 0);
146: if (killp)
147: reg_kill(before.p_line, before.p_char, 1);
148: else {
149: DOTsave(&after);
150: (void) fixorder(&before.p_line, &before.p_char, &after.p_line, &after.p_char);
151: patchup(before.p_line, before.p_char, after.p_line, after.p_char);
152: lremove(before.p_line, after.p_line);
153: }
154: }
155:
156: /* This kills a region between point, and line1/char1 and puts it on
157: the kill-ring. If the last command was one of the kill commands,
158: the region is appended (prepended if backwards) to the last entry. */
159:
160: int killptr = 0;
161: Line *killbuf[NUMKILLS];
162:
163: void
164: reg_kill(line2, char2, dot_moved)
165: Line *line2;
166: {
167: Line *nl,
168: *line1 = curline;
169: int char1 = curchar;
170: int backwards;
171:
172: backwards = !fixorder(&line1, &char1, &line2, &char2);
173: /* This is a kludge! But it possible for commands that don't
174: know which direction they are deleting in (e.g., delete
175: previous word could have been called with a negative argument
176: in which case, it wouldn't know that it really deleted
177: forward. */
178:
179: if (!dot_moved)
180: backwards = !backwards;
181:
182: DotTo(line1, char1);
183:
184: nl = reg_delete(line1, char1, line2, char2);
185:
186: if (last_cmd != KILLCMD) {
187: killptr = ((killptr + 1) % NUMKILLS);
188: lfreelist(killbuf[killptr]);
189: killbuf[killptr] = nl;
190: } else {
191: Line *lastln = lastline(nl);
192:
193: if (backwards)
194: (void) DoYank(nl, 0, lastln, length(lastln), killbuf[killptr], 0, (Buffer *) 0);
195: else {
196: Line *olastln = lastline(killbuf[killptr]);
197:
198: (void) DoYank(nl, 0, lastln, length(lastln), olastln, length(olastln), (Buffer *) 0);
199: }
200: }
201: this_cmd = KILLCMD;
202: }
203:
204: void
205: DelReg()
206: {
207: register Mark *mp = CurMark();
208:
209: reg_kill(mp->m_line, mp->m_char, 0);
210: }
211:
212: /* Save a region. A pretend kill. */
213:
214: void
215: CopyRegion()
216: {
217: register Line *nl;
218: register Mark *mp;
219: register int status;
220:
221: mp = CurMark();
222: if (mp->m_line == curline && mp->m_char == curchar)
223: complain((char *) 0);
224:
225: killptr = ((killptr + 1) % NUMKILLS);
226: if (killbuf[killptr])
227: lfreelist(killbuf[killptr]);
228: nl = killbuf[killptr] = nbufline();
229: SavLine(nl, NullStr);
230: nl->l_next = nl->l_prev = 0;
231:
232: status = inorder(mp->m_line, mp->m_char, curline, curchar);
233: if (status == -1)
234: return;
235:
236: if (status)
237: (void) DoYank(mp->m_line, mp->m_char, curline, curchar,
238: nl, 0, (Buffer *) 0);
239: else
240: (void) DoYank(curline, curchar, mp->m_line, mp->m_char,
241: nl, 0, (Buffer *) 0);
242: }
243:
244: void
245: DelWtSpace()
246: {
247: register char *ep = &linebuf[curchar],
248: *sp = &linebuf[curchar];
249:
250: while (*ep == ' ' || *ep == '\t')
251: ep += 1;
252: while (sp > linebuf && *(sp - 1) == ' ' || *(sp - 1) == '\t')
253: sp -= 1;
254: if (sp != ep) {
255: curchar = sp - linebuf;
256: DFixMarks(curline, curchar, curline, curchar + (ep - sp));
257: strcpy(sp, ep);
258: makedirty(curline);
259: modify();
260: }
261: }
262:
263: void
264: DelBlnkLines()
265: {
266: register Mark *dot;
267: int all;
268:
269: if (!blnkp(&linebuf[curchar]))
270: return;
271: dot = MakeMark(curline, curchar, M_FLOATER);
272: all = !blnkp(linebuf);
273: while (blnkp(linebuf) && curline->l_prev)
274: SetLine(curline->l_prev);
275: all |= (firstp(curline));
276: Eol();
277: DelWtSpace();
278: line_move(FORWARD, 1, NO);
279: while (blnkp(linebuf) && !eobp()) {
280: DelWtSpace();
281: del_char(FORWARD, 1);
282: }
283: if (!all && !eobp())
284: open_lines(1);
285: ToMark(dot);
286: DelMark(dot);
287: }
288:
289: void
290: DelNWord()
291: {
292: dword(1);
293: }
294:
295: void
296: DelPWord()
297: {
298: dword(0);
299: }
300:
301: void
302: dword(forward)
303: {
304: Bufpos savedot;
305:
306: DOTsave(&savedot);
307: if (forward)
308: ForWord();
309: else
310: BackWord();
311: reg_kill(savedot.p_line, savedot.p_char, 1);
312: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.