[BACK]Return to basic.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/basic.c, Revision 1.27

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