Annotation of 43BSDReno/contrib/mh/miscellany/less/command.c, revision 1.1.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.