Annotation of src/usr.bin/mg/basic.c, Revision 1.8
1.8 ! vincent 1: /* $OpenBSD: basic.c,v 1.7 2002/02/08 21:21:11 deraadt Exp $ */
1.4 niklas 2:
1.1 deraadt 3: /*
4: * Basic cursor motion commands.
5: *
6: * The routines in this file are the basic
7: * command functions for moving the cursor around on
8: * the screen, setting mark, and swapping dot with
9: * mark. Only moves between lines, which might make the
10: * current buffer framing bad, are hard.
11: */
1.3 millert 12: #include "def.h"
1.1 deraadt 13:
1.6 art 14: void setgoal __P((void));
1.1 deraadt 15:
16: /*
17: * Go to beginning of line.
18: */
1.3 millert 19: /* ARGSUSED */
20: int
1.1 deraadt 21: gotobol(f, n)
1.3 millert 22: int f, n;
1.1 deraadt 23: {
1.3 millert 24: curwp->w_doto = 0;
1.1 deraadt 25: return (TRUE);
26: }
27:
28: /*
29: * Move cursor backwards. Do the
30: * right thing if the count is less than
31: * 0. Error if you try to move back from
32: * the beginning of the buffer.
33: */
1.3 millert 34: /* ARGSUSED */
35: int
1.1 deraadt 36: backchar(f, n)
1.3 millert 37: int n;
1.1 deraadt 38: {
1.3 millert 39: LINE *lp;
1.1 deraadt 40:
1.3 millert 41: if (n < 0)
42: return forwchar(f, -n);
1.1 deraadt 43: while (n--) {
44: if (curwp->w_doto == 0) {
1.3 millert 45: if ((lp = lback(curwp->w_dotp)) == curbp->b_linep) {
1.1 deraadt 46: if (!(f & FFRAND))
47: ewprintf("Beginning of buffer");
48: return (FALSE);
49: }
1.3 millert 50: curwp->w_dotp = lp;
51: curwp->w_doto = llength(lp);
1.1 deraadt 52: curwp->w_flag |= WFMOVE;
53: } else
54: curwp->w_doto--;
55: }
56: return TRUE;
57: }
58:
59: /*
60: * Go to end of line.
61: */
1.3 millert 62: /* ARGSUSED */
63: int
1.1 deraadt 64: gotoeol(f, n)
1.3 millert 65: int f, n;
1.1 deraadt 66: {
1.3 millert 67: curwp->w_doto = llength(curwp->w_dotp);
1.1 deraadt 68: return (TRUE);
69: }
70:
71: /*
72: * Move cursor forwards. Do the
73: * right thing if the count is less than
74: * 0. Error if you try to move forward
75: * from the end of the buffer.
76: */
1.3 millert 77: /* ARGSUSED */
78: int
1.1 deraadt 79: forwchar(f, n)
1.3 millert 80: int f, n;
1.1 deraadt 81: {
1.3 millert 82:
83: if (n < 0)
84: return backchar(f, -n);
1.1 deraadt 85: while (n--) {
86: if (curwp->w_doto == llength(curwp->w_dotp)) {
1.3 millert 87: curwp->w_dotp = lforw(curwp->w_dotp);
1.1 deraadt 88: if (curwp->w_dotp == curbp->b_linep) {
89: curwp->w_dotp = lback(curwp->w_dotp);
90: if (!(f & FFRAND))
91: ewprintf("End of buffer");
92: return FALSE;
93: }
1.3 millert 94: curwp->w_doto = 0;
1.1 deraadt 95: curwp->w_flag |= WFMOVE;
96: } else
97: curwp->w_doto++;
98: }
99: return TRUE;
100: }
101:
102: /*
103: * Go to the beginning of the
104: * buffer. Setting WFHARD is conservative,
105: * but almost always the case.
106: */
1.3 millert 107: int
1.1 deraadt 108: gotobob(f, n)
1.3 millert 109: int f, n;
1.1 deraadt 110: {
1.3 millert 111:
1.6 art 112: (void) setmark(f, n);
1.3 millert 113: curwp->w_dotp = lforw(curbp->b_linep);
114: curwp->w_doto = 0;
1.1 deraadt 115: curwp->w_flag |= WFHARD;
116: return TRUE;
117: }
118:
119: /*
120: * Go to the end of the buffer.
121: * Setting WFHARD is conservative, but
122: * almost always the case.
123: */
1.3 millert 124: int
1.1 deraadt 125: gotoeob(f, n)
1.3 millert 126: int f, n;
1.1 deraadt 127: {
1.3 millert 128:
1.6 art 129: (void) setmark(f, n);
1.3 millert 130: curwp->w_dotp = lback(curbp->b_linep);
131: curwp->w_doto = llength(curwp->w_dotp);
1.1 deraadt 132: curwp->w_flag |= WFHARD;
133: return TRUE;
134: }
135:
136: /*
137: * Move forward by full lines.
138: * If the number of lines to move is less
139: * than zero, call the backward line function to
140: * actually do it. The last command controls how
141: * the goal column is set.
142: */
1.3 millert 143: /* ARGSUSED */
144: int
1.1 deraadt 145: forwline(f, n)
1.3 millert 146: int f, n;
1.1 deraadt 147: {
1.3 millert 148: LINE *dlp;
1.1 deraadt 149:
150: if (n < 0)
1.3 millert 151: return backline(f | FFRAND, -n);
152: if ((lastflag & CFCPCN) == 0) /* Fix goal. */
1.1 deraadt 153: setgoal();
154: thisflag |= CFCPCN;
1.3 millert 155: if (n == 0)
156: return TRUE;
1.1 deraadt 157: dlp = curwp->w_dotp;
1.3 millert 158: while (dlp != curbp->b_linep && n--)
1.1 deraadt 159: dlp = lforw(dlp);
160: curwp->w_flag |= WFMOVE;
1.3 millert 161: if (dlp == curbp->b_linep) { /* ^N at end of buffer creates lines
162: * (like gnu) */
163: if (!(curbp->b_flag & BFCHG)) { /* first change */
1.1 deraadt 164: curbp->b_flag |= BFCHG;
165: curwp->w_flag |= WFMODE;
166: }
167: curwp->w_doto = 0;
1.3 millert 168: while (n-- >= 0) {
1.8 ! vincent 169: if ((dlp = lalloc(0)) == NULL)
1.3 millert 170: return FALSE;
1.1 deraadt 171: dlp->l_fp = curbp->b_linep;
172: dlp->l_bp = lback(dlp->l_fp);
173: dlp->l_bp->l_fp = dlp->l_fp->l_bp = dlp;
174: }
175: curwp->w_dotp = lback(curbp->b_linep);
176: } else {
1.3 millert 177: curwp->w_dotp = dlp;
178: curwp->w_doto = getgoal(dlp);
1.1 deraadt 179: }
180: return TRUE;
181: }
182:
183: /*
184: * This function is like "forwline", but
185: * goes backwards. The scheme is exactly the same.
186: * Check for arguments that are less than zero and
187: * call your alternate. Figure out the new line and
188: * call "movedot" to perform the motion.
189: */
1.3 millert 190: /* ARGSUSED */
191: int
1.1 deraadt 192: backline(f, n)
1.3 millert 193: int f, n;
1.1 deraadt 194: {
1.3 millert 195: LINE *dlp;
1.1 deraadt 196:
1.3 millert 197: if (n < 0)
198: return forwline(f | FFRAND, -n);
199: if ((lastflag & CFCPCN) == 0) /* Fix goal. */
1.1 deraadt 200: setgoal();
201: thisflag |= CFCPCN;
202: dlp = curwp->w_dotp;
1.3 millert 203: while (n-- && lback(dlp) != curbp->b_linep)
1.1 deraadt 204: dlp = lback(dlp);
1.3 millert 205: curwp->w_dotp = dlp;
206: curwp->w_doto = getgoal(dlp);
1.1 deraadt 207: curwp->w_flag |= WFMOVE;
208: return TRUE;
209: }
210:
211: /*
1.3 millert 212: * Set the current goal column, which is saved in the external variable
213: * "curgoal", to the current cursor column. The column is never off
214: * the edge of the screen; it's more like display then show position.
1.1 deraadt 215: */
1.6 art 216: void
1.3 millert 217: setgoal()
218: {
1.1 deraadt 219:
1.3 millert 220: curgoal = getcolpos() - 1; /* Get the position. */
221: /* we can now display past end of display, don't chop! */
1.1 deraadt 222: }
223:
224: /*
225: * This routine looks at a line (pointed
226: * to by the LINE pointer "dlp") and the current
227: * vertical motion goal column (set by the "setgoal"
228: * routine above) and returns the best offset to use
229: * when a vertical motion is made into the line.
230: */
1.3 millert 231: int
232: getgoal(dlp)
233: LINE *dlp;
234: {
235: int c;
236: int col;
237: int newcol;
238: int dbo;
1.1 deraadt 239:
240: col = 0;
241: dbo = 0;
242: while (dbo != llength(dlp)) {
243: c = lgetc(dlp, dbo);
244: newcol = col;
245: if (c == '\t'
246: #ifdef NOTAB
1.3 millert 247: && !(curbp->b_flag & BFNOTAB)
1.1 deraadt 248: #endif
249: )
1.3 millert 250: newcol |= 0x07;
1.1 deraadt 251: else if (ISCTRL(c) != FALSE)
252: ++newcol;
253: ++newcol;
254: if (newcol > curgoal)
255: break;
256: col = newcol;
257: ++dbo;
258: }
259: return (dbo);
260: }
261:
262: /*
263: * Scroll forward by a specified number
264: * of lines, or by a full page if no argument.
265: * The "2" is the window overlap (this is the default
266: * value from ITS EMACS). Because the top line in
267: * the window is zapped, we have to do a hard
268: * update and get it back.
269: */
1.3 millert 270: /* ARGSUSED */
271: int
1.1 deraadt 272: forwpage(f, n)
1.3 millert 273: int f, n;
1.1 deraadt 274: {
1.3 millert 275: LINE *lp;
1.1 deraadt 276:
277: if (!(f & FFARG)) {
1.3 millert 278: n = curwp->w_ntrows - 2; /* Default scroll. */
279: if (n <= 0) /* Forget the overlap */
280: n = 1; /* if tiny window. */
1.1 deraadt 281: } else if (n < 0)
1.3 millert 282: return backpage(f | FFRAND, -n);
1.1 deraadt 283: #ifdef CVMVAS
1.3 millert 284: else /* Convert from pages */
285: n *= curwp->w_ntrows; /* to lines. */
1.1 deraadt 286: #endif
287: lp = curwp->w_linep;
1.3 millert 288: while (n-- && lforw(lp) != curbp->b_linep)
1.1 deraadt 289: lp = lforw(lp);
290: curwp->w_linep = lp;
291: curwp->w_flag |= WFHARD;
292: /* if in current window, don't move dot */
1.3 millert 293: for (n = curwp->w_ntrows; n-- && lp != curbp->b_linep; lp = lforw(lp))
294: if (lp == curwp->w_dotp)
295: return TRUE;
296: curwp->w_dotp = curwp->w_linep;
297: curwp->w_doto = 0;
1.1 deraadt 298: return TRUE;
299: }
300:
301: /*
302: * This command is like "forwpage",
303: * but it goes backwards. The "2", like above,
304: * is the overlap between the two windows. The
305: * value is from the ITS EMACS manual. The
306: * hard update is done because the top line in
307: * the window is zapped.
308: */
1.3 millert 309: /* ARGSUSED */
310: int
1.1 deraadt 311: backpage(f, n)
1.3 millert 312: int f, n;
1.1 deraadt 313: {
1.3 millert 314: LINE *lp;
1.1 deraadt 315:
316: if (!(f & FFARG)) {
1.3 millert 317: n = curwp->w_ntrows - 2; /* Default scroll. */
318: if (n <= 0) /* Don't blow up if the */
319: n = 1; /* window is tiny. */
1.1 deraadt 320: } else if (n < 0)
1.3 millert 321: return forwpage(f | FFRAND, -n);
1.1 deraadt 322: #ifdef CVMVAS
1.3 millert 323: else /* Convert from pages */
324: n *= curwp->w_ntrows; /* to lines. */
1.1 deraadt 325: #endif
326: lp = curwp->w_linep;
1.3 millert 327: while (n-- && lback(lp) != curbp->b_linep)
1.1 deraadt 328: lp = lback(lp);
329: curwp->w_linep = lp;
330: curwp->w_flag |= WFHARD;
331: /* if in current window, don't move dot */
1.3 millert 332: for (n = curwp->w_ntrows; n-- && lp != curbp->b_linep; lp = lforw(lp))
333: if (lp == curwp->w_dotp)
334: return TRUE;
1.1 deraadt 335: curwp->w_dotp = curwp->w_linep;
336: curwp->w_doto = 0;
337: return TRUE;
338: }
339:
1.3 millert 340: /*
341: * These functions are provided for compatibility with Gosling's Emacs. They
342: * are used to scroll the display up (or down) one line at a time.
1.1 deraadt 343: */
1.7 deraadt 344: int
1.1 deraadt 345: forw1page(f, n)
1.3 millert 346: int f, n;
1.1 deraadt 347: {
1.3 millert 348:
349: if (!(f & FFARG)) {
350: n = 1;
1.1 deraadt 351: f = FFUNIV;
352: }
1.3 millert 353: forwpage(f | FFRAND, n);
1.7 deraadt 354: return TRUE;
1.1 deraadt 355: }
356:
1.7 deraadt 357: int
1.1 deraadt 358: back1page(f, n)
1.3 millert 359: int f, n;
1.1 deraadt 360: {
1.3 millert 361:
1.1 deraadt 362: if (!(f & FFARG)) {
1.3 millert 363: n = 1;
1.1 deraadt 364: f = FFUNIV;
365: }
1.3 millert 366: backpage(f | FFRAND, n);
1.7 deraadt 367: return TRUE;
1.1 deraadt 368: }
369:
370: /*
371: * Page the other window. Check to make sure it exists, then
372: * nextwind, forwpage and restore window pointers.
373: */
1.3 millert 374: int
1.1 deraadt 375: pagenext(f, n)
1.3 millert 376: int f, n;
1.1 deraadt 377: {
1.3 millert 378: MGWIN *wp;
1.1 deraadt 379:
380: if (wheadp->w_wndp == NULL) {
381: ewprintf("No other window");
382: return FALSE;
383: }
384: wp = curwp;
1.6 art 385: (void) nextwind(f, n);
386: (void) forwpage(f, n);
1.1 deraadt 387: curwp = wp;
388: curbp = wp->w_bufp;
389: return TRUE;
390: }
391:
392: /*
393: * Internal set mark routine, used by other functions (daveb).
394: */
1.6 art 395: void
1.1 deraadt 396: isetmark()
397: {
1.3 millert 398:
1.1 deraadt 399: curwp->w_markp = curwp->w_dotp;
400: curwp->w_marko = curwp->w_doto;
401: }
402:
403: /*
404: * Set the mark in the current window
405: * to the value of dot. A message is written to
406: * the echo line. (ewprintf knows about macros)
407: */
1.3 millert 408: /* ARGSUSED */
409: int
1.1 deraadt 410: setmark(f, n)
1.3 millert 411: int f, n;
1.1 deraadt 412: {
1.3 millert 413:
1.1 deraadt 414: isetmark();
415: ewprintf("Mark set");
416: return TRUE;
417: }
418:
419: /*
420: * Swap the values of "dot" and "mark" in
421: * the current window. This is pretty easy, because
422: * all of the hard work gets done by the standard routine
423: * that moves the mark about. The only possible
424: * error is "no mark".
425: */
1.3 millert 426: /* ARGSUSED */
427: int
1.1 deraadt 428: swapmark(f, n)
1.3 millert 429: int f, n;
1.1 deraadt 430: {
1.3 millert 431: LINE *odotp;
432: int odoto;
1.1 deraadt 433:
434: if (curwp->w_markp == NULL) {
435: ewprintf("No mark in this window");
436: return FALSE;
437: }
438: odotp = curwp->w_dotp;
439: odoto = curwp->w_doto;
1.3 millert 440: curwp->w_dotp = curwp->w_markp;
441: curwp->w_doto = curwp->w_marko;
1.1 deraadt 442: curwp->w_markp = odotp;
443: curwp->w_marko = odoto;
444: curwp->w_flag |= WFMOVE;
445: return TRUE;
446: }
447:
448: /*
449: * Go to a specific line, mostly for
450: * looking up errors in C programs, which give the
451: * error a line number. If an argument is present, then
452: * it is the line number, else prompt for a line number
453: * to use.
454: */
1.3 millert 455: /* ARGSUSED */
456: int
1.1 deraadt 457: gotoline(f, n)
1.3 millert 458: int f, n;
1.1 deraadt 459: {
1.3 millert 460: LINE *clp;
461: int s;
462: char buf[32];
1.1 deraadt 463:
464: if (!(f & FFARG)) {
1.3 millert 465: if ((s = ereply("Goto line: ", buf, sizeof(buf))) != TRUE)
1.1 deraadt 466: return s;
467: n = atoi(buf);
468: }
1.5 millert 469: if (n >= 0) {
470: clp = lforw(curbp->b_linep); /* "clp" is first line */
1.1 deraadt 471: while (--n > 0) {
1.3 millert 472: if (lforw(clp) == curbp->b_linep)
473: break;
1.1 deraadt 474: clp = lforw(clp);
475: }
476: } else {
1.5 millert 477: clp = lback(curbp->b_linep); /* "clp" is last line */
1.1 deraadt 478: while (n < 0) {
1.3 millert 479: if (lback(clp) == curbp->b_linep)
480: break;
1.1 deraadt 481: clp = lback(clp);
482: n++;
483: }
484: }
485: curwp->w_dotp = clp;
486: curwp->w_doto = 0;
487: curwp->w_flag |= WFMOVE;
488: return TRUE;
489: }