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

1.49    ! lum         1: /*     $OpenBSD: basic.c,v 1.48 2019/06/03 16:26:30 lum 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:  */
                     14:
1.44      bcallah    15: #include <sys/queue.h>
1.14      vincent    16: #include <ctype.h>
1.43      guenther   17: #include <limits.h>
1.44      bcallah    18: #include <signal.h>
                     19: #include <stdio.h>
                     20: #include <stdlib.h>
                     21:
                     22: #include "def.h"
1.1       deraadt    23:
1.48      lum        24: #define percint(n1, n2)                ((n1 * (int) n2) * 0.1)
                     25:
1.1       deraadt    26: /*
                     27:  * Go to beginning of line.
                     28:  */
1.3       millert    29: /* ARGSUSED */
                     30: int
1.12      vincent    31: gotobol(int f, int n)
1.1       deraadt    32: {
1.47      lum        33:        if (n == 0)
                     34:                return (TRUE);
                     35:
1.3       millert    36:        curwp->w_doto = 0;
1.1       deraadt    37:        return (TRUE);
                     38: }
                     39:
                     40: /*
                     41:  * Move cursor backwards. Do the
                     42:  * right thing if the count is less than
                     43:  * 0. Error if you try to move back from
                     44:  * the beginning of the buffer.
                     45:  */
1.3       millert    46: /* ARGSUSED */
                     47: int
1.12      vincent    48: backchar(int f, int n)
1.1       deraadt    49: {
1.21      deraadt    50:        struct line   *lp;
1.1       deraadt    51:
1.3       millert    52:        if (n < 0)
1.18      db         53:                return (forwchar(f, -n));
1.1       deraadt    54:        while (n--) {
                     55:                if (curwp->w_doto == 0) {
1.25      kjell      56:                        if ((lp = lback(curwp->w_dotp)) == curbp->b_headp) {
1.40      lum        57:                                if (!(f & FFRAND)) {
                     58:                                        dobeep();
1.1       deraadt    59:                                        ewprintf("Beginning of buffer");
1.40      lum        60:                                }
1.1       deraadt    61:                                return (FALSE);
                     62:                        }
1.3       millert    63:                        curwp->w_dotp = lp;
                     64:                        curwp->w_doto = llength(lp);
1.30      kjell      65:                        curwp->w_rflag |= WFMOVE;
1.23      kjell      66:                        curwp->w_dotline--;
1.1       deraadt    67:                } else
                     68:                        curwp->w_doto--;
                     69:        }
1.18      db         70:        return (TRUE);
1.1       deraadt    71: }
                     72:
                     73: /*
                     74:  * Go to end of line.
                     75:  */
1.3       millert    76: /* ARGSUSED */
                     77: int
1.12      vincent    78: gotoeol(int f, int n)
1.1       deraadt    79: {
1.47      lum        80:        if (n == 0)
                     81:                return (TRUE);
                     82:
1.3       millert    83:        curwp->w_doto = llength(curwp->w_dotp);
1.1       deraadt    84:        return (TRUE);
                     85: }
                     86:
                     87: /*
                     88:  * Move cursor forwards. Do the
                     89:  * right thing if the count is less than
                     90:  * 0. Error if you try to move forward
                     91:  * from the end of the buffer.
                     92:  */
1.3       millert    93: /* ARGSUSED */
                     94: int
1.12      vincent    95: forwchar(int f, int n)
1.1       deraadt    96: {
1.3       millert    97:        if (n < 0)
1.18      db         98:                return (backchar(f, -n));
1.1       deraadt    99:        while (n--) {
                    100:                if (curwp->w_doto == llength(curwp->w_dotp)) {
1.3       millert   101:                        curwp->w_dotp = lforw(curwp->w_dotp);
1.25      kjell     102:                        if (curwp->w_dotp == curbp->b_headp) {
1.1       deraadt   103:                                curwp->w_dotp = lback(curwp->w_dotp);
1.40      lum       104:                                if (!(f & FFRAND)) {
                    105:                                        dobeep();
1.1       deraadt   106:                                        ewprintf("End of buffer");
1.40      lum       107:                                }
1.18      db        108:                                return (FALSE);
1.1       deraadt   109:                        }
1.3       millert   110:                        curwp->w_doto = 0;
1.23      kjell     111:                        curwp->w_dotline++;
1.30      kjell     112:                        curwp->w_rflag |= WFMOVE;
1.1       deraadt   113:                } else
                    114:                        curwp->w_doto++;
                    115:        }
1.18      db        116:        return (TRUE);
1.1       deraadt   117: }
                    118:
                    119: /*
1.48      lum       120:  * Go to the beginning of the buffer. Setting WFFULL is conservative,
                    121:  * but almost always the case. A universal argument of higher than 9
                    122:  * puts the cursor back to the end of buffer.
1.1       deraadt   123:  */
1.3       millert   124: int
1.12      vincent   125: gotobob(int f, int n)
1.1       deraadt   126: {
1.49    ! lum       127:        if (!curwp->w_markp)
        !           128:                (void) setmark(f, n);
1.26      kjell     129:        curwp->w_dotp = bfirstlp(curbp);
1.3       millert   130:        curwp->w_doto = 0;
1.30      kjell     131:        curwp->w_rflag |= WFFULL;
1.23      kjell     132:        curwp->w_dotline = 1;
1.48      lum       133:        if (f & FFOTHARG && n > 0) {
                    134:                if (n > 9)
                    135:                        gotoeob(0, 0);
                    136:                else
                    137:                        forwline(f, percint(curwp->w_bufp->b_lines, n) - 1);
                    138:        }
1.18      db        139:        return (TRUE);
1.1       deraadt   140: }
                    141:
                    142: /*
1.37      lum       143:  * Go to the end of the buffer. Leave dot 3 lines from the bottom of the
                    144:  * window if buffer length is longer than window length; same as emacs.
1.48      lum       145:  * Setting WFFULL is conservative, but almost always the case. A universal
                    146:  * argument of higher than 9 puts the cursor back to the start of buffer.
1.1       deraadt   147:  */
1.3       millert   148: int
1.12      vincent   149: gotoeob(int f, int n)
1.1       deraadt   150: {
1.48      lum       151:        int              ln;
1.37      lum       152:        struct line     *lp;
1.46      jasper    153:
1.49    ! lum       154:        if (!curwp->w_markp)
        !           155:                (void) setmark(f, n);
1.26      kjell     156:        curwp->w_dotp = blastlp(curbp);
1.3       millert   157:        curwp->w_doto = llength(curwp->w_dotp);
1.23      kjell     158:        curwp->w_dotline = curwp->w_bufp->b_lines;
1.37      lum       159:
                    160:        lp = curwp->w_dotp;
1.48      lum       161:        ln = curwp->w_ntrows - 3;
1.37      lum       162:
1.48      lum       163:        if (ln < curwp->w_bufp->b_lines && ln >= 3) {
                    164:                while (ln--)
1.37      lum       165:                        curwp->w_dotp = lback(curwp->w_dotp);
                    166:
                    167:                curwp->w_linep = curwp->w_dotp;
                    168:                curwp->w_dotp = lp;
                    169:        }
1.48      lum       170:        if (f & FFOTHARG && n > 0) {
                    171:                if (n > 9)
                    172:                        gotobob(0, 0);
                    173:                else
                    174:                        backline(f, percint(curwp->w_bufp->b_lines, n));
                    175:        }
                    176:
1.30      kjell     177:        curwp->w_rflag |= WFFULL;
1.18      db        178:        return (TRUE);
1.1       deraadt   179: }
                    180:
                    181: /*
                    182:  * Move forward by full lines.
                    183:  * If the number of lines to move is less
                    184:  * than zero, call the backward line function to
                    185:  * actually do it. The last command controls how
                    186:  * the goal column is set.
                    187:  */
1.3       millert   188: /* ARGSUSED */
                    189: int
1.12      vincent   190: forwline(int f, int n)
1.1       deraadt   191: {
1.21      deraadt   192:        struct line  *dlp;
1.1       deraadt   193:
                    194:        if (n < 0)
1.18      db        195:                return (backline(f | FFRAND, -n));
1.41      florian   196:        if ((dlp = curwp->w_dotp) == curbp->b_headp) {
                    197:                if (!(f & FFRAND)) {
                    198:                        dobeep();
                    199:                        ewprintf("End of buffer");
                    200:                }
1.23      kjell     201:                return(TRUE);
1.41      florian   202:        }
1.14      vincent   203:        if ((lastflag & CFCPCN) == 0)   /* Fix goal. */
1.1       deraadt   204:                setgoal();
                    205:        thisflag |= CFCPCN;
1.3       millert   206:        if (n == 0)
1.18      db        207:                return (TRUE);
1.23      kjell     208:        while (n--) {
1.1       deraadt   209:                dlp = lforw(dlp);
1.25      kjell     210:                if (dlp == curbp->b_headp) {
1.23      kjell     211:                        curwp->w_dotp = lback(dlp);
                    212:                        curwp->w_doto = llength(curwp->w_dotp);
1.30      kjell     213:                        curwp->w_rflag |= WFMOVE;
1.41      florian   214:                        if (!(f & FFRAND)) {
                    215:                                dobeep();
                    216:                                ewprintf("End of buffer");
                    217:                        }
1.23      kjell     218:                        return (TRUE);
1.1       deraadt   219:                }
1.23      kjell     220:                curwp->w_dotline++;
1.1       deraadt   221:        }
1.30      kjell     222:        curwp->w_rflag |= WFMOVE;
1.23      kjell     223:        curwp->w_dotp = dlp;
                    224:        curwp->w_doto = getgoal(dlp);
                    225:
1.18      db        226:        return (TRUE);
1.1       deraadt   227: }
                    228:
                    229: /*
                    230:  * This function is like "forwline", but
                    231:  * goes backwards. The scheme is exactly the same.
                    232:  * Check for arguments that are less than zero and
                    233:  * call your alternate. Figure out the new line and
                    234:  * call "movedot" to perform the motion.
                    235:  */
1.3       millert   236: /* ARGSUSED */
                    237: int
1.12      vincent   238: backline(int f, int n)
1.1       deraadt   239: {
1.21      deraadt   240:        struct line   *dlp;
1.1       deraadt   241:
1.3       millert   242:        if (n < 0)
1.18      db        243:                return (forwline(f | FFRAND, -n));
1.14      vincent   244:        if ((lastflag & CFCPCN) == 0)   /* Fix goal. */
1.1       deraadt   245:                setgoal();
                    246:        thisflag |= CFCPCN;
                    247:        dlp = curwp->w_dotp;
1.41      florian   248:        if (lback(dlp) == curbp->b_headp)  {
                    249:                if (!(f & FFRAND)) {
                    250:                        dobeep();
                    251:                        ewprintf("Beginning of buffer");
                    252:                }
                    253:                return(TRUE);
                    254:        }
1.25      kjell     255:        while (n-- && lback(dlp) != curbp->b_headp) {
1.1       deraadt   256:                dlp = lback(dlp);
1.23      kjell     257:                curwp->w_dotline--;
1.41      florian   258:        }
                    259:        if (n > 0 && !(f & FFRAND)) {
                    260:                dobeep();
                    261:                ewprintf("Beginning of buffer");
1.23      kjell     262:        }
1.3       millert   263:        curwp->w_dotp = dlp;
                    264:        curwp->w_doto = getgoal(dlp);
1.30      kjell     265:        curwp->w_rflag |= WFMOVE;
1.18      db        266:        return (TRUE);
1.1       deraadt   267: }
                    268:
                    269: /*
1.3       millert   270:  * Set the current goal column, which is saved in the external variable
                    271:  * "curgoal", to the current cursor column. The column is never off
                    272:  * the edge of the screen; it's more like display then show position.
1.1       deraadt   273:  */
1.6       art       274: void
1.12      vincent   275: setgoal(void)
1.3       millert   276: {
1.39      florian   277:        curgoal = getcolpos(curwp);     /* Get the position. */
1.3       millert   278:        /* we can now display past end of display, don't chop! */
1.1       deraadt   279: }
                    280:
                    281: /*
                    282:  * This routine looks at a line (pointed
                    283:  * to by the LINE pointer "dlp") and the current
                    284:  * vertical motion goal column (set by the "setgoal"
                    285:  * routine above) and returns the best offset to use
                    286:  * when a vertical motion is made into the line.
                    287:  */
1.3       millert   288: int
1.21      deraadt   289: getgoal(struct line *dlp)
1.3       millert   290: {
1.14      vincent   291:        int c, i, col = 0;
1.24      kjell     292:        char tmp[5];
                    293:
1.14      vincent   294:
                    295:        for (i = 0; i < llength(dlp); i++) {
                    296:                c = lgetc(dlp, i);
1.1       deraadt   297:                if (c == '\t'
                    298: #ifdef NOTAB
1.3       millert   299:                    && !(curbp->b_flag & BFNOTAB)
1.1       deraadt   300: #endif
1.14      vincent   301:                        ) {
                    302:                        col |= 0x07;
                    303:                        col++;
                    304:                } else if (ISCTRL(c) != FALSE) {
                    305:                        col += 2;
                    306:                } else if (isprint(c))
                    307:                        col++;
                    308:                else {
1.24      kjell     309:                        col += snprintf(tmp, sizeof(tmp), "\\%o", c);
1.14      vincent   310:                }
                    311:                if (col > curgoal)
1.1       deraadt   312:                        break;
                    313:        }
1.14      vincent   314:        return (i);
1.1       deraadt   315: }
                    316:
                    317: /*
                    318:  * Scroll forward by a specified number
                    319:  * of lines, or by a full page if no argument.
                    320:  * The "2" is the window overlap (this is the default
                    321:  * value from ITS EMACS). Because the top line in
                    322:  * the window is zapped, we have to do a hard
                    323:  * update and get it back.
                    324:  */
1.3       millert   325: /* ARGSUSED */
                    326: int
1.12      vincent   327: forwpage(int f, int n)
1.1       deraadt   328: {
1.21      deraadt   329:        struct line  *lp;
1.1       deraadt   330:
                    331:        if (!(f & FFARG)) {
1.3       millert   332:                n = curwp->w_ntrows - 2;        /* Default scroll.       */
                    333:                if (n <= 0)                     /* Forget the overlap    */
                    334:                        n = 1;                  /* if tiny window.       */
1.1       deraadt   335:        } else if (n < 0)
1.18      db        336:                return (backpage(f | FFRAND, -n));
1.31      lum       337:
1.1       deraadt   338:        lp = curwp->w_linep;
1.31      lum       339:        while (n--)
1.34      lum       340:                if ((lp = lforw(lp)) == curbp->b_headp) {
1.40      lum       341:                        dobeep();
1.34      lum       342:                        ewprintf("End of buffer");
1.31      lum       343:                        return(TRUE);
1.34      lum       344:                }
1.31      lum       345:
1.1       deraadt   346:        curwp->w_linep = lp;
1.30      kjell     347:        curwp->w_rflag |= WFFULL;
1.31      lum       348:
1.1       deraadt   349:        /* if in current window, don't move dot */
1.32      lum       350:        for (n = curwp->w_ntrows; n-- && lp != curbp->b_headp; lp = lforw(lp))
1.3       millert   351:                if (lp == curwp->w_dotp)
1.18      db        352:                        return (TRUE);
1.31      lum       353:
1.27      kjell     354:        /* Advance the dot the slow way, for line nos */
                    355:        while (curwp->w_dotp != curwp->w_linep) {
                    356:                curwp->w_dotp = lforw(curwp->w_dotp);
                    357:                curwp->w_dotline++;
                    358:        }
1.3       millert   359:        curwp->w_doto = 0;
1.18      db        360:        return (TRUE);
1.1       deraadt   361: }
                    362:
                    363: /*
                    364:  * This command is like "forwpage",
                    365:  * but it goes backwards. The "2", like above,
                    366:  * is the overlap between the two windows. The
                    367:  * value is from the ITS EMACS manual. The
                    368:  * hard update is done because the top line in
                    369:  * the window is zapped.
                    370:  */
1.3       millert   371: /* ARGSUSED */
                    372: int
1.12      vincent   373: backpage(int f, int n)
1.1       deraadt   374: {
1.33      lum       375:        struct line  *lp, *lp2;
1.1       deraadt   376:
                    377:        if (!(f & FFARG)) {
1.3       millert   378:                n = curwp->w_ntrows - 2;        /* Default scroll.       */
                    379:                if (n <= 0)                     /* Don't blow up if the  */
1.35      lum       380:                        return (backline(f, 1));/* window is tiny.       */
1.1       deraadt   381:        } else if (n < 0)
1.18      db        382:                return (forwpage(f | FFRAND, -n));
1.33      lum       383:
                    384:        lp = lp2 = curwp->w_linep;
                    385:
1.25      kjell     386:        while (n-- && lback(lp) != curbp->b_headp) {
1.1       deraadt   387:                lp = lback(lp);
1.34      lum       388:        }
                    389:        if (lp == curwp->w_linep) {
1.40      lum       390:                dobeep();
1.34      lum       391:                ewprintf("Beginning of buffer");
1.23      kjell     392:        }
1.1       deraadt   393:        curwp->w_linep = lp;
1.30      kjell     394:        curwp->w_rflag |= WFFULL;
1.33      lum       395:
1.1       deraadt   396:        /* if in current window, don't move dot */
1.25      kjell     397:        for (n = curwp->w_ntrows; n-- && lp != curbp->b_headp; lp = lforw(lp))
1.3       millert   398:                if (lp == curwp->w_dotp)
1.18      db        399:                        return (TRUE);
1.33      lum       400:
                    401:         lp2 = lforw(lp2);
                    402:
1.27      kjell     403:        /* Move the dot the slow way, for line nos */
1.33      lum       404:        while (curwp->w_dotp != lp2) {
1.36      lum       405:                 if (curwp->w_dotline <= curwp->w_ntrows)
1.45      florian   406:                        goto out;
1.27      kjell     407:                curwp->w_dotp = lback(curwp->w_dotp);
                    408:                curwp->w_dotline--;
                    409:        }
1.45      florian   410: out:
1.1       deraadt   411:        curwp->w_doto = 0;
1.18      db        412:        return (TRUE);
1.1       deraadt   413: }
                    414:
1.3       millert   415: /*
                    416:  * These functions are provided for compatibility with Gosling's Emacs. They
                    417:  * are used to scroll the display up (or down) one line at a time.
1.1       deraadt   418:  */
1.7       deraadt   419: int
1.12      vincent   420: forw1page(int f, int n)
1.1       deraadt   421: {
1.3       millert   422:        if (!(f & FFARG)) {
                    423:                n = 1;
1.1       deraadt   424:                f = FFUNIV;
                    425:        }
1.3       millert   426:        forwpage(f | FFRAND, n);
1.18      db        427:        return (TRUE);
1.1       deraadt   428: }
                    429:
1.7       deraadt   430: int
1.12      vincent   431: back1page(int f, int n)
1.1       deraadt   432: {
                    433:        if (!(f & FFARG)) {
1.3       millert   434:                n = 1;
1.1       deraadt   435:                f = FFUNIV;
                    436:        }
1.3       millert   437:        backpage(f | FFRAND, n);
1.18      db        438:        return (TRUE);
1.1       deraadt   439: }
                    440:
                    441: /*
                    442:  * Page the other window. Check to make sure it exists, then
                    443:  * nextwind, forwpage and restore window pointers.
                    444:  */
1.3       millert   445: int
1.12      vincent   446: pagenext(int f, int n)
1.1       deraadt   447: {
1.21      deraadt   448:        struct mgwin *wp;
1.1       deraadt   449:
                    450:        if (wheadp->w_wndp == NULL) {
1.42      lum       451:                dobeep();
1.1       deraadt   452:                ewprintf("No other window");
1.18      db        453:                return (FALSE);
1.1       deraadt   454:        }
                    455:        wp = curwp;
1.6       art       456:        (void) nextwind(f, n);
                    457:        (void) forwpage(f, n);
1.1       deraadt   458:        curwp = wp;
                    459:        curbp = wp->w_bufp;
1.18      db        460:        return (TRUE);
1.1       deraadt   461: }
                    462:
                    463: /*
                    464:  * Internal set mark routine, used by other functions (daveb).
                    465:  */
1.6       art       466: void
1.12      vincent   467: isetmark(void)
1.1       deraadt   468: {
                    469:        curwp->w_markp = curwp->w_dotp;
                    470:        curwp->w_marko = curwp->w_doto;
1.23      kjell     471:        curwp->w_markline = curwp->w_dotline;
1.1       deraadt   472: }
                    473:
                    474: /*
                    475:  * Set the mark in the current window
                    476:  * to the value of dot. A message is written to
                    477:  * the echo line.  (ewprintf knows about macros)
                    478:  */
1.3       millert   479: /* ARGSUSED */
                    480: int
1.12      vincent   481: setmark(int f, int n)
1.1       deraadt   482: {
                    483:        isetmark();
                    484:        ewprintf("Mark set");
1.29      kjell     485:        return (TRUE);
                    486: }
                    487:
                    488: /* Clear the mark, if set. */
                    489: /* ARGSUSED */
                    490: int
                    491: clearmark(int f, int n)
                    492: {
                    493:        if (!curwp->w_markp)
                    494:                return (FALSE);
                    495:
                    496:        curwp->w_markp = NULL;
                    497:        curwp->w_marko = 0;
                    498:        curwp->w_markline = 0;
                    499:
1.18      db        500:        return (TRUE);
1.1       deraadt   501: }
                    502:
                    503: /*
                    504:  * Swap the values of "dot" and "mark" in
                    505:  * the current window. This is pretty easy, because
                    506:  * all of the hard work gets done by the standard routine
                    507:  * that moves the mark about. The only possible
                    508:  * error is "no mark".
                    509:  */
1.3       millert   510: /* ARGSUSED */
                    511: int
1.12      vincent   512: swapmark(int f, int n)
1.1       deraadt   513: {
1.21      deraadt   514:        struct line  *odotp;
1.23      kjell     515:        int odoto, odotline;
1.1       deraadt   516:
                    517:        if (curwp->w_markp == NULL) {
1.42      lum       518:                dobeep();
1.1       deraadt   519:                ewprintf("No mark in this window");
1.18      db        520:                return (FALSE);
1.1       deraadt   521:        }
                    522:        odotp = curwp->w_dotp;
                    523:        odoto = curwp->w_doto;
1.23      kjell     524:        odotline = curwp->w_dotline;
1.3       millert   525:        curwp->w_dotp = curwp->w_markp;
                    526:        curwp->w_doto = curwp->w_marko;
1.23      kjell     527:        curwp->w_dotline = curwp->w_markline;
1.1       deraadt   528:        curwp->w_markp = odotp;
                    529:        curwp->w_marko = odoto;
1.23      kjell     530:        curwp->w_markline = odotline;
1.30      kjell     531:        curwp->w_rflag |= WFMOVE;
1.18      db        532:        return (TRUE);
1.1       deraadt   533: }
                    534:
                    535: /*
                    536:  * Go to a specific line, mostly for
                    537:  * looking up errors in C programs, which give the
                    538:  * error a line number. If an argument is present, then
                    539:  * it is the line number, else prompt for a line number
                    540:  * to use.
                    541:  */
1.3       millert   542: /* ARGSUSED */
                    543: int
1.12      vincent   544: gotoline(int f, int n)
1.1       deraadt   545: {
1.23      kjell     546:        char   buf[32], *bufp;
                    547:        const char *err;
1.1       deraadt   548:
                    549:        if (!(f & FFARG)) {
1.20      kjell     550:                if ((bufp = eread("Goto line: ", buf, sizeof(buf),
                    551:                    EFNUL | EFNEW | EFCR)) == NULL)
1.24      kjell     552:                        return (ABORT);
                    553:                if (bufp[0] == '\0')
1.18      db        554:                        return (ABORT);
1.23      kjell     555:                n = (int)strtonum(buf, INT_MIN, INT_MAX, &err);
                    556:                if (err) {
1.42      lum       557:                        dobeep();
1.23      kjell     558:                        ewprintf("Line number %s", err);
1.18      db        559:                        return (FALSE);
1.9       vincent   560:                }
1.1       deraadt   561:        }
1.38      jasper    562:        return(setlineno(n));
                    563: }
                    564:
                    565: /*
                    566:  * Set the line number and switch to it.
                    567:  */
                    568: int
                    569: setlineno(int n)
                    570: {
                    571:        struct line  *clp;
                    572:
1.5       millert   573:        if (n >= 0) {
1.23      kjell     574:                if (n == 0)
                    575:                        n++;
                    576:                curwp->w_dotline = n;
1.25      kjell     577:                clp = lforw(curbp->b_headp);    /* "clp" is first line */
1.1       deraadt   578:                while (--n > 0) {
1.25      kjell     579:                        if (lforw(clp) == curbp->b_headp) {
1.23      kjell     580:                                curwp->w_dotline = curwp->w_bufp->b_lines;
1.3       millert   581:                                break;
1.23      kjell     582:                        }
1.1       deraadt   583:                        clp = lforw(clp);
                    584:                }
                    585:        } else {
1.23      kjell     586:                curwp->w_dotline = curwp->w_bufp->b_lines + n;
1.25      kjell     587:                clp = lback(curbp->b_headp);    /* "clp" is last line */
1.1       deraadt   588:                while (n < 0) {
1.25      kjell     589:                        if (lback(clp) == curbp->b_headp) {
1.23      kjell     590:                                curwp->w_dotline = 1;
1.3       millert   591:                                break;
1.23      kjell     592:                        }
1.1       deraadt   593:                        clp = lback(clp);
                    594:                        n++;
                    595:                }
                    596:        }
                    597:        curwp->w_dotp = clp;
                    598:        curwp->w_doto = 0;
1.30      kjell     599:        curwp->w_rflag |= WFMOVE;
1.18      db        600:        return (TRUE);
1.1       deraadt   601: }