[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.16

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