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

1.7     ! deraadt     1: /*     $OpenBSD: basic.c,v 1.6 2001/05/23 22:20:34 art 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) {
                    169:                        if ((dlp = lallocx(0)) == NULL)
                    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: }