# 2.11BSD#431 - /usr/src/local/less/command.c

##### Functions

    cmd_reset         X
    commands          X
    start_mcc         X

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

#### Defined functions

cmd_char defined in line 82; used 1 times

- in line 324

cmd_erase defined in line 42; used 2 times

- in line 88-93(2)

cmd_exec defined in line 134; used 6 times

- in line 274, 441, 455, 464, 515, 527

cmd_int defined in line 121; used 13 times

- in line 349, 360, 374, 387, 399, 411, 438, 450, 463, 499, 511, 578, 588

cmd_reset defined in line 34; used 4 times

- in line 249, 536, 548, 607

commands defined in line 223; used 2 times

- in /usr/src/local/less/funcs.h line 77
- in /usr/src/local/less/main.c line 333

getcc defined in line 186; used 9 times

- in line 251, 330, 504, 540, 550, 599, 609, 619, 632

prompt defined in line 144; used 1 times

- in line 250

start_mcc defined in line 68; used 7 times

- in line 340, 502, 514, 537, 549, 598, 608

#### Defined variables

cmd_col defined in line 26; used 7 times

- in line 58-61(2), 75, 101, 107-111(2), 539

cmdbuf defined in line 24; used 13 times

- in line 36, 45, 101(2), 125-126(2), 198, 278-281(2), 295-300(2), 564-565(2)

cp defined in line 25; used 9 times

- in line 36, 45, 52, 101-103(2), 124-125(2), 198, 273

last_mcc defined in line 28; used 3 times

- in line 230, 503, 514

mcc defined in line 27; used 15 times

- in line 71-74(2), 207, 232, 257, 265, 275-278(2), 306-309(2), 317, 327, 516-517(2), 600

public defined in line 223; never used
screen_trashed defined in line 29; used 5 times

- in line 161-163(2), 301, 529, 567

Last modified: 1990-07-10 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1359 |