|
|
1.1 root 1: /*
2: * The routines in this file move the cursor around on the screen.
3: * They compute a new value for the cursor, then adjust ".".
4: * The display code always updates the cursor location, so only moves
5: * between lines, or functions that adjust the top line in the window
6: * and invalidate the framing, are hard.
7: */
8: #include <stdio.h>
9: #include "ed.h"
10:
11: /*
12: * Move the cursor to the beginning of the current line.
13: * Trivial.
14: */
15: gotobol(f, n)
16: {
17: curwp->w_doto = 0;
18: return (TRUE);
19: }
20:
21: /*
22: * Move the cursor backwards by "n" characters. If "n" is less than
23: * zero call "forwchar" to actually do the move. Otherwise compute
24: * the new cursor location. Error if you try and move out of the buffer.
25: * Set the flag if the line pointer for dot changes.
26: */
27: backchar(f, n)
28: register int n;
29: {
30: register LINE *lp;
31:
32: if (n < 0)
33: return (forwchar(f, -n));
34: while (n--) {
35: if (curwp->w_doto == 0) {
36: if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
37: return (FALSE);
38: curwp->w_dotp = lp;
39: curwp->w_doto = llength(lp);
40: curwp->w_flag |= WFMOVE;
41: } else
42: curwp->w_doto--;
43: }
44: return (TRUE);
45: }
46:
47: /*
48: * Move the cursor to the end of the current line. Trivial.
49: * No errors.
50: */
51: gotoeol(f, n)
52: {
53: curwp->w_doto = llength(curwp->w_dotp);
54: return (TRUE);
55: }
56:
57: /*
58: * Move the cursor forwards by "n" characters. If "n" is less than
59: * zero call "backchar" to actually do the move. Otherwise compute
60: * the new cursor location, and move ".". Error if you try and move
61: * off the end of the buffer. Set the flag if the line pointer
62: * for dot changes.
63: */
64: forwchar(f, n)
65: register int n;
66: {
67: if (n < 0)
68: return (backchar(f, -n));
69: while (n--) {
70: if (curwp->w_doto == llength(curwp->w_dotp)) {
71: if (curwp->w_dotp == curbp->b_linep)
72: return (FALSE);
73: curwp->w_dotp = lforw(curwp->w_dotp);
74: curwp->w_doto = 0;
75: curwp->w_flag |= WFMOVE;
76: } else
77: curwp->w_doto++;
78: }
79: return (TRUE);
80: }
81:
82: /*
83: * Goto the beginning of the buffer.
84: * Massive adjustment of dot. This is considered to be hard motion;
85: * it really isn't if the original value of dot is the same as the
86: * new value of dot.
87: * Normally bound to "M-<".
88: */
89: gotobob(f, n)
90: {
91: curwp->w_dotp = lforw(curbp->b_linep);
92: curwp->w_doto = 0;
93: curwp->w_flag |= WFHARD;
94: return (TRUE);
95: }
96:
97: /*
98: * Move to the end of the buffer.
99: * Dot is always put at the end of the file (ZJ). The standard screen code does
100: * most of the hard parts of update. Bound to "M->".
101: */
102: gotoeob(f, n)
103: {
104: curwp->w_dotp = curbp->b_linep;
105: curwp->w_doto = 0;
106: curwp->w_flag |= WFHARD;
107: return (TRUE);
108: }
109:
110: /*
111: * Move forward by full lines.
112: * If the number of lines to move is less than zero, call the backward line
113: * function to actually do it. The last command controls how the goal column
114: * is set. Bound to "C-N". No errors are possible.
115: */
116: forwline(f, n)
117: {
118: register LINE *dlp;
119:
120: if (n < 0)
121: return (backline(f, -n));
122: if ((lastflag&CFCPCN) == 0) /* Reset goal if last */
123: curgoal = curcol; /* not C-P or C-N */
124: thisflag |= CFCPCN;
125: dlp = curwp->w_dotp;
126: while (n-- && dlp!=curbp->b_linep)
127: dlp = lforw(dlp);
128: curwp->w_dotp = dlp;
129: curwp->w_doto = getgoal(dlp);
130: curwp->w_flag |= WFMOVE;
131: return (TRUE);
132: }
133:
134: /*
135: * This function is like "forwline", but goes backwards.
136: * The scheme is exactly the same. Check for arguments that are
137: * less than zero and call your alternate. Figure out the new line and
138: * call "movedot" to perform the motion. No errors are possible.
139: * Bound to "C-P".
140: */
141: backline(f, n)
142: {
143: register LINE *dlp;
144:
145: if (n < 0)
146: return (forwline(f, -n));
147: if ((lastflag&CFCPCN) == 0) /* Reset goal if the */
148: curgoal = curcol; /* last isn't C-P, C-N */
149: thisflag |= CFCPCN;
150: dlp = curwp->w_dotp;
151: while (n-- && lback(dlp)!=curbp->b_linep)
152: dlp = lback(dlp);
153: curwp->w_dotp = dlp;
154: curwp->w_doto = getgoal(dlp);
155: curwp->w_flag |= WFMOVE;
156: return (TRUE);
157: }
158:
159: /*
160: * This routine, given a pointer to a LINE, and the current cursor goal
161: * column, return the best choice for the offset. The offset is returned.
162: * Used by "C-N" and "C-P".
163: */
164: getgoal(dlp)
165: register LINE *dlp;
166: {
167: unsigned c;
168: register int col;
169: register int newcol;
170: register int dbo;
171:
172: col = 0;
173: dbo = 0;
174: while (dbo != llength(dlp)) {
175: c = lgetc(dlp, dbo);
176: newcol = col;
177: switch (dblchr(c)) {
178: case 2:
179: taber(newcol);
180: break;
181: case 1:
182: ++newcol;
183: }
184: ++newcol;
185: if (newcol > curgoal)
186: break;
187: col = newcol;
188: ++dbo;
189: }
190: return (dbo);
191: }
192:
193: /*
194: * Scroll forward by a specified number of lines, or by a full page if
195: * no argument.
196: * The "2" in the arithmetic on the window size is the overlap; this value is
197: * the default overlap value in ITS EMACS. Because this zaps the top line in
198: * the display window, we have to do a hard update.
199: * Bound to "C-V".
200: */
201: forwpage(f, n)
202: register int n;
203: {
204: register LINE *lp;
205:
206: if (f == FALSE) {
207: n = curwp->w_ntrows - 2; /* Default scroll. */
208: if (n <= 0) /* Forget the overlap */
209: n = 1; /* if tiny window. */
210: } else if (n < 0)
211: return (backpage(f, -n));
212: #if CVMVAS
213: else /* Convert from pages */
214: n *= curwp->w_ntrows; /* to lines. */
215: #endif
216: lp = curwp->w_linep;
217: while (n-- && lp!=curbp->b_linep)
218: lp = lforw(lp);
219: curwp->w_linep = lp;
220: curwp->w_dotp = lp;
221: curwp->w_doto = 0;
222: curwp->w_flag |= WFHARD;
223: return (TRUE);
224: }
225:
226: /*
227: * This command is like "forwpage", but it goes backwards.
228: * The "2", like above, is the overlap between the two windows. The
229: * value is from the ITS EMACS manual. We do a hard update for exactly
230: * the same reason.
231: * Bound to "M-V".
232: */
233: backpage(f, n)
234: register int n;
235: {
236: register LINE *lp;
237:
238: if (f == FALSE) {
239: n = curwp->w_ntrows - 2; /* Default scroll. */
240: if (n <= 0) /* Don't blow up if the */
241: n = 1; /* window is tiny. */
242: } else if (n < 0)
243: return (forwpage(f, -n));
244: #if CVMVAS
245: else /* Convert from pages */
246: n *= curwp->w_ntrows; /* to lines. */
247: #endif
248: lp = curwp->w_linep;
249: while (n-- && lback(lp)!=curbp->b_linep)
250: lp = lback(lp);
251: curwp->w_linep = lp;
252: curwp->w_dotp = lp;
253: curwp->w_doto = 0;
254: curwp->w_flag |= WFHARD;
255: return (TRUE);
256: }
257:
258: /*
259: * Set the mark in the current window to the value of "." in the window.
260: * No errors are possible.
261: * Bound to "M-.".
262: */
263: setmark(f, n)
264: {
265: curwp->w_markp = curwp->w_dotp;
266: curwp->w_marko = curwp->w_doto;
267: mlwrite("[Mark set]");
268: return (TRUE);
269: }
270:
271: /*
272: * Swap the values of "." and "mark" in the current window.
273: * This is pretty easy, because all of the hard work gets done by the
274: * standard routine that moves the mark about. The only possible error is
275: * "no mark".
276: * Bound to "C-X C-X".
277: */
278: swapmark(f, n)
279: {
280: register LINE *odotp;
281: register int odoto;
282:
283: if (curwp->w_markp == NULL) {
284: mlwrite("No mark in this window");
285: return (FALSE);
286: }
287: odotp = curwp->w_dotp;
288: odoto = curwp->w_doto;
289: curwp->w_dotp = curwp->w_markp;
290: curwp->w_doto = curwp->w_marko;
291: curwp->w_markp = odotp;
292: curwp->w_marko = odoto;
293: curwp->w_flag |= WFMOVE;
294: return (TRUE);
295: }
296:
297: /*
298: * Go to a specific line in the buffer, mostly for
299: * looking up errors in C programs, which give the
300: * error a line number. If an argument is present, then
301: * it is the line number, else prompt for a line number
302: * to use.
303: */
304: gotoline(f, n)
305: register int n;
306: {
307: register LINE *clp;
308: register int s;
309: uchar buf[32];
310:
311: if (f == FALSE) {
312: if ((s=mlreply("Goto line: ", buf, sizeof(buf))) != TRUE)
313: return (s);
314: n = atoi(buf);
315: }
316: if (n <= 0) {
317: mlwrite("Bad line");
318: return (FALSE);
319: }
320: clp = lforw(curbp->b_linep); /* "clp" is first line */
321: while (n != 1) {
322: if (clp == curbp->b_linep) {
323: mlwrite("Line too large");
324: return (FALSE);
325: }
326: clp = lforw(clp);
327: --n;
328: }
329: curwp->w_dotp = clp;
330: curwp->w_doto = 0;
331: curwp->w_flag |= WFMOVE;
332: return (TRUE);
333: }
334:
335: /*
336: * Go to a specific line from the original file, mostly for
337: * looking up errors in C programs, which give the
338: * error a line number. If an argument is present, then
339: * it is the line number, else prompt for a line number
340: * to use.
341: */
342: gotofline(f, n)
343: register int n;
344: {
345: register LINE *clp;
346: register int s;
347: uchar buf[32];
348:
349: if (f == FALSE) {
350: if ((s=mlreply("Goto line: ", buf, sizeof(buf))) != TRUE)
351: return (s);
352: n = atoi(buf);
353: }
354: if (n <= 0) {
355: mlwrite("Bad line");
356: return (FALSE);
357: }
358: clp = lforw(curbp->b_linep); /* "clp" is first line */
359: while (n != l_number(clp)) {
360: if (clp == curbp->b_linep) {
361: mlwrite("Line not in buffer");
362: return (FALSE);
363: }
364: clp = lforw(clp);
365: }
366: curwp->w_dotp = clp;
367: curwp->w_doto = 0;
368: curwp->w_flag |= WFMOVE;
369: return (TRUE);
370: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.