Annotation of 43BSD/contrib/mh/miscellany/less/command.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * User-level command processor.
        !             3:  */
        !             4: 
        !             5: #include "less.h"
        !             6: #include "position.h"
        !             7: #include <setjmp.h>
        !             8: 
        !             9: extern jmp_buf main_loop;
        !            10: extern int erase_char, kill_char;
        !            11: extern int pr_type;
        !            12: extern int sigs;
        !            13: extern int ispipe;
        !            14: extern int quit_at_eof;
        !            15: extern int hit_eof;
        !            16: extern int sc_width, sc_height;
        !            17: extern char *first_cmd;
        !            18: extern char version[];
        !            19: extern char current_file[];
        !            20: extern char *editor;
        !            21: 
        !            22: static char cmdbuf[90];                /* Buffer for holding a multi-char command */
        !            23: static char *cp;               /* Pointer into cmdbuf */
        !            24: static int cmd_col;            /* Current column of the multi-char command */
        !            25: static char mcc;               /* The multi-char command letter (e.g. '/') */
        !            26: static char last_mcc;          /* The previous mcc */
        !            27: 
        !            28: /*
        !            29:  * Reset command buffer (to empty).
        !            30:  */
        !            31: cmd_reset()
        !            32: {
        !            33:        cp = cmdbuf;
        !            34: }
        !            35: 
        !            36: /*
        !            37:  * Backspace in command buffer.
        !            38:  */
        !            39:        static int
        !            40: cmd_erase()
        !            41: {
        !            42:        if (cp == cmdbuf)
        !            43:                /*
        !            44:                 * Backspace past beginning of the string:
        !            45:                 * this usually means abort the command.
        !            46:                 */
        !            47:                return (1);
        !            48: 
        !            49:        if (control_char(*--cp))
        !            50:        {
        !            51:                /*
        !            52:                 * Erase an extra character, for the carat.
        !            53:                 */
        !            54:                backspace();
        !            55:                cmd_col--;
        !            56:        }
        !            57:        backspace();
        !            58:        cmd_col--;
        !            59:        return (0);
        !            60: }
        !            61: 
        !            62: /*
        !            63:  * Set up the display to start a new multi-character command.
        !            64:  */
        !            65: start_mcc()
        !            66: {
        !            67:        lower_left();
        !            68:        clear_eol();
        !            69:        putc(mcc);
        !            70:        cmd_col = 1;
        !            71: }
        !            72: 
        !            73: /*
        !            74:  * Process a single character of a multi-character command, such as
        !            75:  * a number, or the pattern of a search command.
        !            76:  */
        !            77:        static int
        !            78: cmd_char(c)
        !            79:        int c;
        !            80: {
        !            81:        if (c == erase_char)
        !            82:        {
        !            83:                if (cmd_erase())
        !            84:                        return (1);
        !            85:        } else if (c == kill_char)
        !            86:        {
        !            87:                /* {{ Could do this faster, but who cares? }} */
        !            88:                while (cmd_erase() == 0)
        !            89:                        ;
        !            90:        } else
        !            91:        {
        !            92:                /*
        !            93:                 * Append the character to the string,
        !            94:                 * if there is room in the buffer and on the screen.
        !            95:                 */
        !            96:                if (cp < &cmdbuf[sizeof(cmdbuf)-1] && cmd_col < sc_width-3)
        !            97:                {
        !            98:                        *cp++ = c;
        !            99:                        if (control_char(c))
        !           100:                        {
        !           101:                                putc('^');
        !           102:                                cmd_col++;
        !           103:                                c = carat_char(c);
        !           104:                        }
        !           105:                        putc(c);
        !           106:                        cmd_col++;
        !           107:                } else
        !           108:                        bell();
        !           109:        }
        !           110:        return (0);
        !           111: }
        !           112: 
        !           113: /*
        !           114:  * Return the number currently in the command buffer.
        !           115:  */
        !           116:        static int
        !           117: cmd_int()
        !           118: {
        !           119:        *cp = '\0';
        !           120:        cp = cmdbuf;
        !           121:        return (atoi(cmdbuf));
        !           122: }
        !           123: 
        !           124: /*
        !           125:  * Move the cursor to lower left before executing a command.
        !           126:  * This looks nicer if the command takes a long time before
        !           127:  * updating the screen.
        !           128:  */
        !           129:        static void
        !           130: cmd_exec()
        !           131: {
        !           132:        lower_left();
        !           133:        flush();
        !           134: }
        !           135: 
        !           136: /*
        !           137:  * Display the appropriate prompt.
        !           138:  */
        !           139:        static void
        !           140: prompt()
        !           141: {
        !           142:        register char *p;
        !           143: 
        !           144:        if (first_cmd != NULL && *first_cmd != '\0')
        !           145:                /*
        !           146:                 * No prompt necessary if commands are from first_cmd
        !           147:                 * rather than from the user.
        !           148:                 */
        !           149:                return;
        !           150: 
        !           151:        /*
        !           152:         * Select the proper prompt and display it.
        !           153:         */
        !           154:        p = pr_string();
        !           155:        if (p == NULL)
        !           156:                putc(':');
        !           157:        else
        !           158:        {
        !           159:                so_enter();
        !           160:                puts(p);
        !           161:                so_exit();
        !           162:        }
        !           163: }
        !           164: 
        !           165: /*
        !           166:  * Get command character.
        !           167:  * The character normally comes from the keyboard,
        !           168:  * but may come from the "first_cmd" string.
        !           169:  */
        !           170:        static int
        !           171: getcc()
        !           172: {
        !           173:        if (first_cmd == NULL)
        !           174:                return (getc());
        !           175: 
        !           176:        if (*first_cmd == '\0')
        !           177:        {
        !           178:                /*
        !           179:                 * Reached end of first_cmd input.
        !           180:                 */
        !           181:                first_cmd = NULL;
        !           182:                if (cp > cmdbuf && position(TOP) == NULL_POSITION)
        !           183:                {
        !           184:                        /*
        !           185:                         * Command is incomplete, so try to complete it.
        !           186:                         * There are only two cases:
        !           187:                         * 1. We have "/string" but no newline.  Add the \n.
        !           188:                         * 2. We have a number but no command.  Treat as #g.
        !           189:                         * (This is all pretty hokey.)
        !           190:                         */
        !           191:                        if (mcc != ':')
        !           192:                                return ('\n'); 
        !           193:                        else
        !           194:                                return ('g');
        !           195:                }
        !           196:                return (getc());
        !           197:        }
        !           198:        return (*first_cmd++);
        !           199: }
        !           200: 
        !           201: /*
        !           202:  * Main command processor.
        !           203:  * Accept and execute commands until a quit command, then return.
        !           204:  */
        !           205:        public void
        !           206: commands()
        !           207: {
        !           208:        register int c;
        !           209:        register int n;
        !           210:        register int scroll = 10;
        !           211: 
        !           212:        mcc = last_mcc = 0;
        !           213: 
        !           214:        setjmp(main_loop);
        !           215:        for (;;)
        !           216:        {
        !           217:                /*
        !           218:                 * Display prompt and accept a character.
        !           219:                 */
        !           220:                psignals();     /* See if any signals need processing */
        !           221: 
        !           222:                if (quit_at_eof && hit_eof > 1)
        !           223:                        /*
        !           224:                         * After hitting end-of-file for the second time,
        !           225:                         * automatically advance to the next file.
        !           226:                         * If there are no more files, quit.
        !           227:                         */
        !           228:                        next_file(1);
        !           229: 
        !           230:                cmd_reset();
        !           231:                lower_left();
        !           232:                clear_eol();
        !           233:                prompt();
        !           234:                c = getcc();
        !           235: 
        !           236:        again:
        !           237:                if (sigs)
        !           238:                        continue;
        !           239: 
        !           240:                if (mcc)
        !           241:                {
        !           242:                        /*
        !           243:                         * We are in a multi-character command.  
        !           244:                         * All chars until newline go into the command buffer.
        !           245:                         * (Note that mcc == ':' is a special case that
        !           246:                         *  means a number is being entered.)
        !           247:                         */
        !           248:                        if (mcc != ':' && (c == '\n' || c == '\r'))
        !           249:                        {
        !           250:                                /*
        !           251:                                 * Execute the command.
        !           252:                                 */
        !           253:                                *cp = '\0';
        !           254:                                cmd_exec();
        !           255:                                if (mcc == 'E')
        !           256:                                {
        !           257:                                        char *p;
        !           258:                                        /*
        !           259:                                         * Ignore leading spaces 
        !           260:                                         * in the filename.
        !           261:                                         */
        !           262:                                        for (p = cmdbuf;  *p == ' ';  p++) ;
        !           263:                                        edit(p);
        !           264: #if SHELL_ESCAPE
        !           265:                                } else if (mcc == '!')
        !           266:                                {
        !           267:                                        lsystem(cmdbuf);
        !           268:                                        error("!done");
        !           269:                                        first_cmd = "r";        /* Repaint */
        !           270: #endif
        !           271:                                } else
        !           272:                                        search(mcc, cmdbuf, n);
        !           273:                                mcc = 0;
        !           274:                        } else
        !           275:                        {
        !           276:                                if (mcc == ':' && (c < '0' || c > '9') &&
        !           277:                                        c != erase_char && c != kill_char)
        !           278:                                {
        !           279:                                        /*
        !           280:                                         * This is not part of the number
        !           281:                                         * we were entering.  Process
        !           282:                                         * it as a regular character.
        !           283:                                         */
        !           284:                                        mcc = 0;
        !           285:                                        goto again;
        !           286:                                }
        !           287: 
        !           288:                                /*
        !           289:                                 * Append the char to the command buffer.
        !           290:                                 */
        !           291:                                if (cmd_char(c))
        !           292:                                {
        !           293:                                        /* Abort the multi-char command. */
        !           294:                                        mcc = 0;
        !           295:                                        continue;
        !           296:                                }
        !           297:                                c = getcc();
        !           298:                                goto again;
        !           299:                        }
        !           300:                } else switch (c)
        !           301:                {
        !           302:                case '0': case '1': case '2': case '3': case '4':
        !           303:                case '5': case '6': case '7': case '8': case '9':
        !           304:                        /*
        !           305:                         * First digit of a number.
        !           306:                         */
        !           307:                        mcc = ':';
        !           308:                        start_mcc();
        !           309:                        goto again;
        !           310: 
        !           311:                case 'f':
        !           312:                case ' ':
        !           313:                case CONTROL('F'):
        !           314:                        /*
        !           315:                         * Forward one screen.
        !           316:                         */
        !           317:                        n = cmd_int();
        !           318:                        if (n <= 0)
        !           319:                                n = sc_height - 1;
        !           320:                        forward(n, 1);
        !           321:                        break;
        !           322: 
        !           323:                case 'b':
        !           324:                case CONTROL('B'):
        !           325:                        /*
        !           326:                         * Backward one screen.
        !           327:                         */
        !           328:                        n = cmd_int();
        !           329:                        if (n <= 0)
        !           330:                                n = sc_height - 1;
        !           331:                        backward(n, 1);
        !           332:                        break;
        !           333: 
        !           334:                case 'e':
        !           335:                case 'j':
        !           336:                case '\r':
        !           337:                case '\n':
        !           338:                case CONTROL('E'):
        !           339:                        /*
        !           340:                         * Forward N (default 1) line.
        !           341:                         */
        !           342:                        n = cmd_int();
        !           343:                        if (n <= 0)
        !           344:                                n = 1;
        !           345:                        forward(n, 0);
        !           346:                        break;
        !           347: 
        !           348:                case 'y':
        !           349:                case 'k':
        !           350:                case CONTROL('K'):
        !           351:                case CONTROL('Y'):
        !           352:                        /*
        !           353:                         * Backward N (default 1) line.
        !           354:                         */
        !           355:                        n = cmd_int();
        !           356:                        if (n <= 0)
        !           357:                                n = 1;
        !           358:                        backward(n, 0);
        !           359:                        break;
        !           360: 
        !           361:                case 'd':
        !           362:                case CONTROL('D'):
        !           363:                        /*
        !           364:                         * Forward N lines 
        !           365:                         * (default same as last 'd' or 'u' command).
        !           366:                         */
        !           367:                        n = cmd_int();
        !           368:                        if (n > 0)
        !           369:                                scroll = n;
        !           370:                        forward(scroll, 0);
        !           371:                        break;
        !           372: 
        !           373:                case 'u':
        !           374:                case CONTROL('U'):
        !           375:                        /*
        !           376:                         * Forward N lines 
        !           377:                         * (default same as last 'd' or 'u' command).
        !           378:                         */
        !           379:                        n = cmd_int();
        !           380:                        if (n > 0)
        !           381:                                scroll = n;
        !           382:                        backward(scroll, 0);
        !           383:                        break;
        !           384: 
        !           385:                case 'R':
        !           386:                        /*
        !           387:                         * Flush buffers, then repaint screen.
        !           388:                         */
        !           389:                        ch_init(0);
        !           390:                        /* Fall thru */
        !           391:                case 'r':
        !           392:                case CONTROL('R'):
        !           393:                case CONTROL('L'):
        !           394:                        /*
        !           395:                         * Repaint screen.
        !           396:                         */
        !           397:                        repaint();
        !           398:                        break;
        !           399: 
        !           400:                case 'g':
        !           401:                        /*
        !           402:                         * Go to line N, default beginning of file.
        !           403:                         */
        !           404:                        n = cmd_int();
        !           405:                        if (n <= 0)
        !           406:                                n = 1;
        !           407:                        cmd_exec();
        !           408:                        jump_back(n);
        !           409:                        break;
        !           410: 
        !           411:                case 'p':
        !           412:                case '%':
        !           413:                        /*
        !           414:                         * Go to a specified percentage into the file.
        !           415:                         */
        !           416:                        n = cmd_int();
        !           417:                        if (n < 0)
        !           418:                                n = 0;
        !           419:                        if (n > 100)
        !           420:                                n = 100;
        !           421:                        cmd_exec();
        !           422:                        jump_percent(n);
        !           423:                        break;
        !           424: 
        !           425:                case 'G':
        !           426:                        /*
        !           427:                         * Go to line N, default end of file.
        !           428:                         */
        !           429:                        n = cmd_int();
        !           430:                        cmd_exec();
        !           431:                        if (n <= 0)
        !           432:                                jump_forw();
        !           433:                        else
        !           434:                                jump_back(n);
        !           435:                        break;
        !           436: 
        !           437:                case '=':
        !           438:                case CONTROL('G'):
        !           439:                        /*
        !           440:                         * Print file name, etc.
        !           441:                         */
        !           442:                        error(eq_message());
        !           443:                        break;
        !           444:                        
        !           445:                case 'V':
        !           446:                        /*
        !           447:                         * Print version number, without the "@(#)".
        !           448:                         */
        !           449:                        error(version+4);
        !           450:                        break;
        !           451: 
        !           452:                case 'q':
        !           453:                        /*
        !           454:                         * Exit.
        !           455:                         */
        !           456:                        return;
        !           457: 
        !           458:                case '/':
        !           459:                case '?':
        !           460:                        /*
        !           461:                         * Search for a pattern.
        !           462:                         * Accept chars of the pattern until \n.
        !           463:                         */
        !           464:                        n = cmd_int();
        !           465:                        if (n <= 0)
        !           466:                                n = 1;
        !           467:                        mcc = last_mcc = c;
        !           468:                        start_mcc();
        !           469:                        c = getcc();
        !           470:                        goto again;
        !           471: 
        !           472:                case 'n':
        !           473:                        /*
        !           474:                         * Repeat previous search.
        !           475:                         */
        !           476:                        n = cmd_int();
        !           477:                        if (n <= 0)
        !           478:                                n = 1;
        !           479:                        mcc = last_mcc;
        !           480:                        start_mcc();
        !           481:                        cmd_exec();
        !           482:                        search(mcc, (char *)NULL, n);
        !           483:                        mcc = 0;
        !           484:                        break;
        !           485: 
        !           486:                case 'h':
        !           487:                        /*
        !           488:                         * Help.
        !           489:                         */
        !           490:                        help();
        !           491:                        repaint();
        !           492:                        break;
        !           493: 
        !           494:                case 'E':
        !           495:                        /*
        !           496:                         * Edit a new file.  Get the filename.
        !           497:                         */
        !           498:                        cmd_reset();
        !           499:                        mcc = 'E';
        !           500:                        start_mcc();
        !           501:                        puts("dit: ");  /* This looks nicer */
        !           502:                        cmd_col += 5;
        !           503:                        c = getcc();
        !           504:                        goto again;
        !           505:                        
        !           506: #if SHELL_ESCAPE
        !           507:                case '!':
        !           508:                        /*
        !           509:                         * Shell escape.
        !           510:                         */
        !           511:                        cmd_reset();
        !           512:                        mcc = '!';
        !           513:                        start_mcc();
        !           514:                        c = getcc();
        !           515:                        goto again;
        !           516: #endif
        !           517: 
        !           518: #if EDITOR
        !           519:                case 'v':
        !           520:                        if (ispipe)
        !           521:                        {
        !           522:                                error("Cannot edit standard input");
        !           523:                                break;
        !           524:                        }
        !           525:                        sprintf(cmdbuf, "%s %s", editor, current_file);
        !           526:                        lsystem(cmdbuf);
        !           527:                        first_cmd = "R";
        !           528:                        break;
        !           529: #endif
        !           530: 
        !           531:                case 'N':
        !           532:                        /*
        !           533:                         * Examine next file.
        !           534:                         */
        !           535:                        n = cmd_int();
        !           536:                        if (n <= 0)
        !           537:                                n = 1;
        !           538:                        next_file(n);
        !           539:                        break;
        !           540: 
        !           541:                case 'P':
        !           542:                        /*
        !           543:                         * Examine previous file.
        !           544:                         */
        !           545:                        n = cmd_int();
        !           546:                        if (n <= 0)
        !           547:                                n = 1;
        !           548:                        prev_file(n);
        !           549:                        break;
        !           550: 
        !           551:                case '-':
        !           552:                        /*
        !           553:                         * Toggle a flag setting.
        !           554:                         */
        !           555:                        mcc = '-';
        !           556:                        start_mcc();
        !           557:                        c = getcc();
        !           558:                        mcc = 0;
        !           559:                        if (c == erase_char || c == kill_char)
        !           560:                                break;
        !           561:                        toggle_option(c);
        !           562:                        break;
        !           563: 
        !           564:                case 'm':
        !           565:                        /*
        !           566:                         * Set a mark.
        !           567:                         */
        !           568:                        lower_left();
        !           569:                        clear_eol();
        !           570:                        puts("mark: ");
        !           571:                        c = getcc();
        !           572:                        if (c == erase_char || c == kill_char)
        !           573:                                break;
        !           574:                        setmark(c);
        !           575:                        break;
        !           576: 
        !           577:                case '\'':
        !           578:                        /*
        !           579:                         * Go to a mark.
        !           580:                         */
        !           581:                        lower_left();
        !           582:                        clear_eol();
        !           583:                        puts("goto mark: ");
        !           584:                        c = getcc();
        !           585:                        if (c == erase_char || c == kill_char)
        !           586:                                break;
        !           587:                        gomark(c);
        !           588:                        break;
        !           589: 
        !           590:                default:
        !           591:                        bell();
        !           592:                        break;
        !           593:                }
        !           594:        }
        !           595: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.