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

Annotation of src/usr.bin/mg/random.c, Revision 1.3

1.1       deraadt     1: /*
                      2:  *             Assorted commands.
1.3     ! millert     3:  * This file contains the command processors for a large assortment of
        !             4:  * unrelated commands.  The only thing they have in common is that they
        !             5:  * are all command processors.
        !             6:  */
        !             7:
        !             8: #include "def.h"
1.1       deraadt     9:
                     10: /*
1.3     ! millert    11:  * Display a bunch of useful information about the current location of dot.
        !            12:  * The character under the cursor (in octal), the current line, row, and
        !            13:  * column, and approximate position of the cursor in the file (as a
        !            14:  * percentage) is displayed.  The column position assumes an infinite
        !            15:  * position display; it does not truncate just because the screen does.
1.1       deraadt    16:  * This is normally bound to "C-X =".
                     17:  */
1.2       millert    18: /* ARGSUSED */
1.3     ! millert    19: int
1.1       deraadt    20: showcpos(f, n)
1.3     ! millert    21:        int f, n;
1.1       deraadt    22: {
1.3     ! millert    23:        LINE    *clp;
        !            24:        long     nchar;
        !            25:        long     cchar;
        !            26:        int      nline, row;
        !            27:        int      cline, cbyte;          /* Current line/char/byte */
        !            28:        int      ratio;
        !            29:
        !            30:        /* collect the data */
        !            31:        clp = lforw(curbp->b_linep);
        !            32:        cchar = 0;
        !            33:        cline = 0;
        !            34:        cbyte = 0;
1.1       deraadt    35:        nchar = 0;
                     36:        nline = 0;
1.3     ! millert    37:        for (;;) {
        !            38:                /* count this line */
        !            39:                ++nline;
1.1       deraadt    40:                if (clp == curwp->w_dotp) {
1.3     ! millert    41:                        /* mark line */
        !            42:                        cline = nline;
1.1       deraadt    43:                        cchar = nchar + curwp->w_doto;
                     44:                        if (curwp->w_doto == llength(clp))
                     45:                                cbyte = '\n';
                     46:                        else
                     47:                                cbyte = lgetc(clp, curwp->w_doto);
                     48:                }
1.3     ! millert    49:                /* now count the chars */
        !            50:                nchar += llength(clp);
1.1       deraadt    51:                clp = lforw(clp);
1.2       millert    52:                if (clp == curbp->b_linep)
                     53:                        break;
1.3     ! millert    54:                /* count the newline */
        !            55:                nchar++;
1.1       deraadt    56:        }
1.3     ! millert    57:        /* determine row */
        !            58:        row = curwp->w_toprow + 1;
1.1       deraadt    59:        clp = curwp->w_linep;
1.2       millert    60:        while (clp != curbp->b_linep && clp != curwp->w_dotp) {
1.1       deraadt    61:                ++row;
                     62:                clp = lforw(clp);
                     63:        }
1.2       millert    64:        /* NOSTRICT */
                     65:        ratio = nchar ? (100L * cchar) / nchar : 100;
1.1       deraadt    66:        ewprintf("Char: %c (0%o)  point=%ld(%d%%)  line=%d  row=%d  col=%d",
1.3     ! millert    67:            cbyte, cbyte, cchar, ratio, cline, row, getcolpos());
1.1       deraadt    68:        return TRUE;
                     69: }
                     70:
1.3     ! millert    71: int
1.2       millert    72: getcolpos()
                     73: {
1.3     ! millert    74:        int     col, i, c;
        !            75:
        !            76:        /* determine column */
        !            77:        col = 1;
1.1       deraadt    78:
1.2       millert    79:        for (i = 0; i < curwp->w_doto; ++i) {
1.1       deraadt    80:                c = lgetc(curwp->w_dotp, i);
                     81:                if (c == '\t'
1.3     ! millert    82: #ifdef NOTAB
1.2       millert    83:                    && !(curbp->b_flag & BFNOTAB)
1.3     ! millert    84: #endif /* NOTAB */
1.1       deraadt    85:                        ) {
1.2       millert    86:                        col |= 0x07;
                     87:                        ++col;
1.1       deraadt    88:                } else if (ISCTRL(c) != FALSE)
                     89:                        ++col;
                     90:                ++col;
                     91:        }
                     92:        return col;
                     93: }
1.3     ! millert    94:
1.1       deraadt    95: /*
1.3     ! millert    96:  * Twiddle the two characters on either side of dot.  If dot is at the end
        !            97:  * of the line twiddle the two characters before it.  Return with an error
        !            98:  * if dot is at the beginning of line; it seems to be a bit pointless to
        !            99:  * make this work.  This fixes up a very common typo with a single stroke.
        !           100:  * Normally bound to "C-T".  This always works within a line, so "WFEDIT"
        !           101:  * is good enough.
1.1       deraadt   102:  */
1.2       millert   103: /* ARGSUSED */
1.3     ! millert   104: int
1.1       deraadt   105: twiddle(f, n)
1.3     ! millert   106:        int f, n;
1.1       deraadt   107: {
1.3     ! millert   108:        LINE    *dotp;
        !           109:        int      doto, cr;
1.1       deraadt   110:
                    111:        dotp = curwp->w_dotp;
                    112:        doto = curwp->w_doto;
1.2       millert   113:        if (doto == llength(dotp)) {
                    114:                if (--doto <= 0)
                    115:                        return FALSE;
1.1       deraadt   116:        } else {
1.2       millert   117:                if (doto == 0)
                    118:                        return FALSE;
1.1       deraadt   119:                ++curwp->w_doto;
                    120:        }
                    121:        cr = lgetc(dotp, doto--);
1.2       millert   122:        lputc(dotp, doto + 1, lgetc(dotp, doto));
1.1       deraadt   123:        lputc(dotp, doto, cr);
                    124:        lchange(WFEDIT);
                    125:        return TRUE;
                    126: }
                    127:
                    128: /*
1.3     ! millert   129:  * Open up some blank space.  The basic plan is to insert a bunch of
        !           130:  * newlines, and then back up over them.  Everything is done by the
        !           131:  * subcommand procerssors.  They even handle the looping.  Normally this
        !           132:  * is bound to "C-O".
1.1       deraadt   133:  */
1.2       millert   134: /* ARGSUSED */
1.3     ! millert   135: int
1.1       deraadt   136: openline(f, n)
1.3     ! millert   137:        int f, n;
1.1       deraadt   138: {
1.3     ! millert   139:        int     i;
        !           140:        int     s;
1.1       deraadt   141:
                    142:        if (n < 0)
                    143:                return FALSE;
                    144:        if (n == 0)
                    145:                return TRUE;
1.3     ! millert   146:
        !           147:        /* insert newlines */
        !           148:        i = n;
1.1       deraadt   149:        do {
                    150:                s = lnewline();
1.2       millert   151:        } while (s == TRUE && --i);
1.3     ! millert   152:
        !           153:        /* then go back up overtop of them all */
        !           154:        if (s == TRUE)
        !           155:                s = backchar(f | FFRAND, n);
1.1       deraadt   156:        return s;
                    157: }
                    158:
                    159: /*
1.3     ! millert   160:  * Insert a newline.  [following "feature" not present in current version of
        !           161:  * Gnu, and now disabled here too] If you are at the end of the line and the
        !           162:  * next line is a blank line, just move into the blank line.  This makes
        !           163:  * "C-O" and "C-X C-O" work nicely, and reduces the ammount of screen update
        !           164:  * that has to be done.  This would not be as critical if screen update were a
        !           165:  * lot more efficient.
1.1       deraadt   166:  */
1.2       millert   167: /* ARGSUSED */
1.3     ! millert   168: int
1.1       deraadt   169: newline(f, n)
1.3     ! millert   170:        int f, n;
1.1       deraadt   171: {
1.3     ! millert   172:        LINE    *lp;
        !           173:        int      s;
1.1       deraadt   174:
1.2       millert   175:        if (n < 0)
                    176:                return FALSE;
1.3     ! millert   177:
1.1       deraadt   178:        while (n--) {
                    179:                lp = curwp->w_dotp;
                    180: #ifdef undef
                    181:                if (llength(lp) == curwp->w_doto
1.2       millert   182:                    && lforw(lp) != curbp->b_linep
                    183:                    && llength(lforw(lp)) == 0) {
                    184:                        if ((s = forwchar(FFRAND, 1)) != TRUE)
1.1       deraadt   185:                                return s;
                    186:                } else
1.3     ! millert   187: #endif /* undef */
1.2       millert   188:                if ((s = lnewline()) != TRUE)
                    189:                        return s;
1.1       deraadt   190:        }
                    191:        return TRUE;
                    192: }
                    193:
                    194: /*
1.3     ! millert   195:  * Delete blank lines around dot. What this command does depends if dot is
        !           196:  * sitting on a blank line. If dot is sitting on a blank line, this command
        !           197:  * deletes all the blank lines above and below the current line. If it is
        !           198:  * sitting on a non blank line then it deletes all of the blank lines after
        !           199:  * the line. Normally this command is bound to "C-X C-O". Any argument is
        !           200:  * ignored.
1.1       deraadt   201:  */
1.2       millert   202: /* ARGSUSED */
1.3     ! millert   203: int
1.1       deraadt   204: deblank(f, n)
1.3     ! millert   205:        int f, n;
1.1       deraadt   206: {
1.3     ! millert   207:        LINE    *lp1, *lp2;
        !           208:        RSIZE    nld;
1.1       deraadt   209:
                    210:        lp1 = curwp->w_dotp;
1.2       millert   211:        while (llength(lp1) == 0 && (lp2 = lback(lp1)) != curbp->b_linep)
1.1       deraadt   212:                lp1 = lp2;
                    213:        lp2 = lp1;
1.3     ! millert   214:        nld = (RSIZE)0;
1.2       millert   215:        while ((lp2 = lforw(lp2)) != curbp->b_linep && llength(lp2) == 0)
1.1       deraadt   216:                ++nld;
                    217:        if (nld == 0)
                    218:                return (TRUE);
                    219:        curwp->w_dotp = lforw(lp1);
                    220:        curwp->w_doto = 0;
1.3     ! millert   221:        return ldelete((RSIZE)nld, KNONE);
1.1       deraadt   222: }
                    223:
                    224: /*
                    225:  * Delete any whitespace around dot, then insert a space.
                    226:  */
1.3     ! millert   227: int
1.2       millert   228: justone(f, n)
1.3     ! millert   229:        int f, n;
1.2       millert   230: {
1.3     ! millert   231:        (VOID)delwhite(f, n);
1.1       deraadt   232:        return linsert(1, ' ');
                    233: }
1.3     ! millert   234:
1.1       deraadt   235: /*
                    236:  * Delete any whitespace around dot.
                    237:  */
1.2       millert   238: /* ARGSUSED */
1.3     ! millert   239: int
1.1       deraadt   240: delwhite(f, n)
1.3     ! millert   241:        int f, n;
1.1       deraadt   242: {
1.3     ! millert   243:        int     col, c, s;
1.1       deraadt   244:
                    245:        col = curwp->w_doto;
1.3     ! millert   246:
1.1       deraadt   247:        while (((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')
1.2       millert   248:               && col < llength(curwp->w_dotp))
1.1       deraadt   249:                ++col;
                    250:        do {
                    251:                if (curwp->w_doto == 0) {
                    252:                        s = FALSE;
                    253:                        break;
                    254:                }
1.2       millert   255:                if ((s = backchar(FFRAND, 1)) != TRUE)
                    256:                        break;
1.1       deraadt   257:        } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t');
                    258:
1.2       millert   259:        if (s == TRUE)
1.3     ! millert   260:                (VOID)forwchar(FFRAND, 1);
        !           261:        (VOID)ldelete((RSIZE)(col - curwp->w_doto), KNONE);
1.1       deraadt   262:        return TRUE;
                    263: }
1.3     ! millert   264:
1.1       deraadt   265: /*
1.3     ! millert   266:  * Insert a newline, then enough tabs and spaces to duplicate the indentation
        !           267:  * of the previous line.  Assumes tabs are every eight characters.  Quite
        !           268:  * simple.  Figure out the indentation of the current line.  Insert a newline
        !           269:  * by calling the standard routine.  Insert the indentation by inserting the
        !           270:  * right number of tabs and spaces.  Return TRUE if all ok.  Return FALSE if
        !           271:  * one of the subcomands failed. Normally bound to "C-J".
1.1       deraadt   272:  */
1.2       millert   273: /* ARGSUSED */
1.3     ! millert   274: int
1.1       deraadt   275: indent(f, n)
1.3     ! millert   276:        int f, n;
1.1       deraadt   277: {
1.3     ! millert   278:        int     nicol;
        !           279:        int     c;
        !           280:        int     i;
1.1       deraadt   281:
1.2       millert   282:        if (n < 0)
                    283:                return (FALSE);
1.3     ! millert   284:
1.1       deraadt   285:        while (n--) {
                    286:                nicol = 0;
1.2       millert   287:                for (i = 0; i < llength(curwp->w_dotp); ++i) {
1.1       deraadt   288:                        c = lgetc(curwp->w_dotp, i);
1.2       millert   289:                        if (c != ' ' && c != '\t')
1.1       deraadt   290:                                break;
                    291:                        if (c == '\t')
                    292:                                nicol |= 0x07;
                    293:                        ++nicol;
                    294:                }
                    295:                if (lnewline() == FALSE || ((
                    296: #ifdef NOTAB
1.3     ! millert   297:                    curbp->b_flag & BFNOTAB) ? linsert(nicol, ' ') == FALSE : (
        !           298: #endif /* NOTAB */
        !           299:                    ((i = nicol / 8) != 0 && linsert(i, '\t') == FALSE) ||
        !           300:                    ((i = nicol % 8) != 0 && linsert(i, ' ') == FALSE))))
1.1       deraadt   301:                        return FALSE;
                    302:        }
                    303:        return TRUE;
                    304: }
                    305:
                    306: /*
1.3     ! millert   307:  * Delete forward.  This is real easy, because the basic delete routine does
        !           308:  * all of the work.  Watches for negative arguments, and does the right thing.
        !           309:  * If any argument is present, it kills rather than deletes, to prevent loss
        !           310:  * of text if typed with a big argument.  Normally bound to "C-D".
1.1       deraadt   311:  */
1.2       millert   312: /* ARGSUSED */
1.3     ! millert   313: int
1.1       deraadt   314: forwdel(f, n)
1.3     ! millert   315:        int f, n;
1.1       deraadt   316: {
                    317:        if (n < 0)
                    318:                return backdel(f | FFRAND, -n);
1.3     ! millert   319:
        !           320:        /* really a kill */
        !           321:        if (f & FFARG) {
1.2       millert   322:                if ((lastflag & CFKILL) == 0)
1.1       deraadt   323:                        kdelete();
                    324:                thisflag |= CFKILL;
                    325:        }
1.3     ! millert   326:
1.1       deraadt   327:        return ldelete((RSIZE) n, (f & FFARG) ? KFORW : KNONE);
                    328: }
                    329:
                    330: /*
1.3     ! millert   331:  * Delete backwards.  This is quite easy too, because it's all done with
        !           332:  * other functions.  Just move the cursor back, and delete forwards.  Like
        !           333:  * delete forward, this actually does a kill if presented with an argument.
1.1       deraadt   334:  */
1.2       millert   335: /* ARGSUSED */
1.3     ! millert   336: int
1.1       deraadt   337: backdel(f, n)
1.3     ! millert   338:        int f, n;
1.1       deraadt   339: {
1.3     ! millert   340:        int     s;
1.1       deraadt   341:
                    342:        if (n < 0)
                    343:                return forwdel(f | FFRAND, -n);
1.3     ! millert   344:
        !           345:        /* really a kill */
        !           346:        if (f & FFARG) {
1.2       millert   347:                if ((lastflag & CFKILL) == 0)
1.1       deraadt   348:                        kdelete();
                    349:                thisflag |= CFKILL;
                    350:        }
1.2       millert   351:        if ((s = backchar(f | FFRAND, n)) == TRUE)
1.3     ! millert   352:                s = ldelete((RSIZE)n, (f & FFARG) ? KFORW : KNONE);
        !           353:
1.1       deraadt   354:        return s;
                    355: }
                    356:
                    357: /*
1.3     ! millert   358:  * Kill line.  If called without an argument, it kills from dot to the end
        !           359:  * of the line, unless it is at the end of the line, when it kills the
        !           360:  * newline.  If called with an argument of 0, it kills from the start of the
        !           361:  * line to dot.  If called with a positive argument, it kills from dot
        !           362:  * forward over that number of newlines.  If called with a negative argument
        !           363:  * it kills any text before dot on the current line, then it kills back
        !           364:  * abs(arg) lines.
1.1       deraadt   365:  */
1.2       millert   366: /* ARGSUSED */
1.3     ! millert   367: int
1.2       millert   368: killline(f, n)
1.3     ! millert   369:        int f, n;
1.2       millert   370: {
1.3     ! millert   371:        LINE    *nextp;
        !           372:        RSIZE    chunk;
        !           373:        int      i, c;
        !           374:
        !           375:        /* clear kill buffer if last wasn't a kill */
        !           376:        if ((lastflag & CFKILL) == 0)
        !           377:                kdelete();
1.1       deraadt   378:        thisflag |= CFKILL;
                    379:        if (!(f & FFARG)) {
                    380:                for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
                    381:                        if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t')
                    382:                                break;
                    383:                if (i == llength(curwp->w_dotp))
1.2       millert   384:                        chunk = llength(curwp->w_dotp) - curwp->w_doto + 1;
1.1       deraadt   385:                else {
1.2       millert   386:                        chunk = llength(curwp->w_dotp) - curwp->w_doto;
1.1       deraadt   387:                        if (chunk == 0)
                    388:                                chunk = 1;
                    389:                }
                    390:        } else if (n > 0) {
1.2       millert   391:                chunk = llength(curwp->w_dotp) - curwp->w_doto + 1;
1.1       deraadt   392:                nextp = lforw(curwp->w_dotp);
                    393:                i = n;
                    394:                while (--i) {
                    395:                        if (nextp == curbp->b_linep)
                    396:                                break;
1.2       millert   397:                        chunk += llength(nextp) + 1;
1.1       deraadt   398:                        nextp = lforw(nextp);
                    399:                }
1.3     ! millert   400:        } else {
        !           401:                /* n <= 0 */
1.1       deraadt   402:                chunk = curwp->w_doto;
                    403:                curwp->w_doto = 0;
                    404:                i = n;
                    405:                while (i++) {
                    406:                        if (lback(curwp->w_dotp) == curbp->b_linep)
                    407:                                break;
                    408:                        curwp->w_dotp = lback(curwp->w_dotp);
                    409:                        curwp->w_flag |= WFMOVE;
1.2       millert   410:                        chunk += llength(curwp->w_dotp) + 1;
1.1       deraadt   411:                }
                    412:        }
                    413:        /*
1.3     ! millert   414:         * KFORW here is a bug.  Should be KBACK/KFORW, but we need to
1.1       deraadt   415:         * rewrite the ldelete code (later)?
                    416:         */
1.2       millert   417:        return (ldelete(chunk, KFORW));
1.1       deraadt   418: }
                    419:
                    420: /*
1.3     ! millert   421:  * Yank text back from the kill buffer.  This is really easy.  All of the work
        !           422:  * is done by the standard insert routines.  All you do is run the loop, and
        !           423:  * check for errors.  The blank lines are inserted with a call to "newline"
        !           424:  * instead of a call to "lnewline" so that the magic stuff that happens when
        !           425:  * you type a carriage return also happens when a carriage return is yanked
        !           426:  * back from the kill buffer.  An attempt has been made to fix the cosmetic
        !           427:  * bug associated with a yank when dot is on the top line of the window
        !           428:  * (nothing moves, because all of the new text landed off screen).
1.1       deraadt   429:  */
1.2       millert   430: /* ARGSUSED */
1.3     ! millert   431: int
1.1       deraadt   432: yank(f, n)
1.3     ! millert   433:        int f, n;
1.1       deraadt   434: {
1.3     ! millert   435:        LINE    *lp;
        !           436:        int      c, i, nline;
1.1       deraadt   437:
1.2       millert   438:        if (n < 0)
                    439:                return FALSE;
1.3     ! millert   440:
        !           441:        /* newline counting */
        !           442:        nline = 0;
        !           443:
1.1       deraadt   444:        while (n--) {
1.3     ! millert   445:                /* mark around last yank */
        !           446:                isetmark();
1.1       deraadt   447:                i = 0;
1.2       millert   448:                while ((c = kremove(i)) >= 0) {
1.1       deraadt   449:                        if (c == '\n') {
                    450:                                if (newline(FFRAND, 1) == FALSE)
                    451:                                        return FALSE;
                    452:                                ++nline;
                    453:                        } else {
                    454:                                if (linsert(1, c) == FALSE)
                    455:                                        return FALSE;
                    456:                        }
                    457:                        ++i;
                    458:                }
                    459:        }
1.3     ! millert   460:        /* cosmetic adjustment */
        !           461:        lp = curwp->w_linep;
        !           462:
        !           463:        /* if offscreen insert */
        !           464:        if (curwp->w_dotp == lp) {
1.2       millert   465:                while (nline-- && lback(lp) != curbp->b_linep)
1.1       deraadt   466:                        lp = lback(lp);
1.3     ! millert   467:                /* adjust framing */
        !           468:                curwp->w_linep = lp;
1.1       deraadt   469:                curwp->w_flag |= WFHARD;
                    470:        }
                    471:        return TRUE;
                    472: }
                    473:
                    474: #ifdef NOTAB
1.2       millert   475: /* ARGSUSED */
1.3     ! millert   476: int
1.1       deraadt   477: space_to_tabstop(f, n)
1.3     ! millert   478:        int f, n;
1.1       deraadt   479: {
1.2       millert   480:        if (n < 0)
                    481:                return FALSE;
                    482:        if (n == 0)
                    483:                return TRUE;
                    484:        return linsert((n << 3) - (curwp->w_doto & 7), ' ');
1.1       deraadt   485: }
1.3     ! millert   486: #endif /* NOTAB */