Annotation of src/usr.bin/less/command.c, Revision 1.6
1.1 etheisen 1: /*
1.6 ! millert 2: * Copyright (C) 1984-2002 Mark Nudelman
1.1 etheisen 3: *
1.6 ! millert 4: * You may distribute under the terms of either the GNU General Public
! 5: * License or the Less License, as specified in the README file.
1.1 etheisen 6: *
1.6 ! millert 7: * For more information about less, or for information on how to
! 8: * contact the author, see the README file.
1.1 etheisen 9: */
10:
11:
12: /*
13: * User-level command processor.
14: */
15:
16: #include "less.h"
1.6 ! millert 17: #if MSDOS_COMPILER==WIN32C
! 18: #include <windows.h>
! 19: #endif
1.1 etheisen 20: #include "position.h"
21: #include "option.h"
22: #include "cmd.h"
23:
24: extern int erase_char, kill_char;
25: extern int sigs;
26: extern int quit_at_eof;
1.6 ! millert 27: extern int quit_if_one_screen;
! 28: extern int squished;
1.1 etheisen 29: extern int hit_eof;
30: extern int sc_width;
31: extern int sc_height;
32: extern int swindow;
33: extern int jump_sline;
34: extern int quitting;
35: extern int wscroll;
36: extern int top_scroll;
37: extern int ignore_eoi;
1.6 ! millert 38: extern int secure;
! 39: extern int hshift;
! 40: extern int show_attn;
1.1 etheisen 41: extern char *every_first_cmd;
42: extern char *curr_altfilename;
43: extern char version[];
44: extern struct scrpos initial_scrpos;
45: extern IFILE curr_ifile;
1.6 ! millert 46: extern void constant *ml_search;
! 47: extern void constant *ml_examine;
1.1 etheisen 48: #if SHELL_ESCAPE || PIPEC
1.6 ! millert 49: extern void constant *ml_shell;
1.1 etheisen 50: #endif
51: #if EDITOR
52: extern char *editor;
53: extern char *editproto;
54: #endif
55: extern int screen_trashed; /* The screen has been overwritten */
1.6 ! millert 56: extern int shift_count;
1.2 etheisen 57: extern int be_helpful;
58:
1.6 ! millert 59: static char ungot[UNGOT_SIZE];
1.1 etheisen 60: static char *ungotp = NULL;
61: #if SHELL_ESCAPE
62: static char *shellcmd = NULL; /* For holding last shell command for "!!" */
63: #endif
64: static int mca; /* The multicharacter command (action) */
65: static int search_type; /* The previous type of search */
1.6 ! millert 66: static LINENUM number; /* The number typed by the user */
1.1 etheisen 67: static char optchar;
68: static int optflag;
1.6 ! millert 69: static int optgetname;
! 70: static POSITION bottompos;
! 71: static char *help_prompt;
1.1 etheisen 72: #if PIPEC
73: static char pipec;
74: #endif
75:
76: static void multi_search();
77:
78: /*
79: * Move the cursor to lower left before executing a command.
80: * This looks nicer if the command takes a long time before
81: * updating the screen.
82: */
83: static void
84: cmd_exec()
85: {
1.6 ! millert 86: clear_attn();
1.1 etheisen 87: lower_left();
88: flush();
89: }
90:
91: /*
92: * Set up the display to start a new multi-character command.
93: */
94: static void
1.6 ! millert 95: start_mca(action, prompt, mlist, cmdflags)
1.1 etheisen 96: int action;
97: char *prompt;
98: void *mlist;
1.6 ! millert 99: int cmdflags;
1.1 etheisen 100: {
101: mca = action;
1.6 ! millert 102: clear_cmd();
1.1 etheisen 103: cmd_putstr(prompt);
1.6 ! millert 104: set_mlist(mlist, cmdflags);
1.1 etheisen 105: }
106:
107: public int
108: in_mca()
109: {
110: return (mca != 0 && mca != A_PREFIX);
111: }
112:
113: /*
114: * Set up the display to start a new search command.
115: */
116: static void
117: mca_search()
118: {
119: if (search_type & SRCH_FORW)
120: mca = A_F_SEARCH;
121: else
122: mca = A_B_SEARCH;
123:
1.6 ! millert 124: clear_cmd();
1.1 etheisen 125:
1.6 ! millert 126: if (search_type & SRCH_NO_MATCH)
! 127: cmd_putstr("Non-match ");
1.1 etheisen 128: if (search_type & SRCH_FIRST_FILE)
1.6 ! millert 129: cmd_putstr("First-file ");
1.1 etheisen 130: if (search_type & SRCH_PAST_EOF)
1.6 ! millert 131: cmd_putstr("EOF-ignore ");
! 132: if (search_type & SRCH_NO_MOVE)
! 133: cmd_putstr("Keep-pos ");
! 134: if (search_type & SRCH_NO_REGEX)
! 135: cmd_putstr("Regex-off ");
1.1 etheisen 136:
137: if (search_type & SRCH_FORW)
138: cmd_putstr("/");
139: else
140: cmd_putstr("?");
1.6 ! millert 141: set_mlist(ml_search, 0);
! 142: }
! 143:
! 144: /*
! 145: * Set up the display to start a new toggle-option command.
! 146: */
! 147: static void
! 148: mca_opt_toggle()
! 149: {
! 150: int no_prompt;
! 151: int flag;
! 152: char *dash;
! 153:
! 154: no_prompt = (optflag & OPT_NO_PROMPT);
! 155: flag = (optflag & ~OPT_NO_PROMPT);
! 156: dash = (flag == OPT_NO_TOGGLE) ? "_" : "-";
! 157:
! 158: mca = A_OPT_TOGGLE;
! 159: clear_cmd();
! 160: cmd_putstr(dash);
! 161: if (optgetname)
! 162: cmd_putstr(dash);
! 163: if (no_prompt)
! 164: cmd_putstr("(P)");
! 165: switch (flag)
! 166: {
! 167: case OPT_UNSET:
! 168: cmd_putstr("+");
! 169: break;
! 170: case OPT_SET:
! 171: cmd_putstr("!");
! 172: break;
! 173: }
! 174: set_mlist(NULL, 0);
1.1 etheisen 175: }
176:
177: /*
178: * Execute a multicharacter command.
179: */
180: static void
181: exec_mca()
182: {
1.6 ! millert 183: register char *cbuf;
1.1 etheisen 184:
185: cmd_exec();
186: cbuf = get_cmdbuf();
187:
188: switch (mca)
189: {
190: case A_F_SEARCH:
191: case A_B_SEARCH:
1.6 ! millert 192: multi_search(cbuf, (int) number);
1.1 etheisen 193: break;
194: case A_FIRSTCMD:
195: /*
196: * Skip leading spaces or + signs in the string.
197: */
198: while (*cbuf == '+' || *cbuf == ' ')
199: cbuf++;
200: if (every_first_cmd != NULL)
201: free(every_first_cmd);
202: if (*cbuf == '\0')
203: every_first_cmd = NULL;
204: else
205: every_first_cmd = save(cbuf);
206: break;
207: case A_OPT_TOGGLE:
208: toggle_option(optchar, cbuf, optflag);
209: optchar = '\0';
210: break;
211: case A_F_BRACKET:
1.6 ! millert 212: match_brac(cbuf[0], cbuf[1], 1, (int) number);
1.1 etheisen 213: break;
214: case A_B_BRACKET:
1.6 ! millert 215: match_brac(cbuf[1], cbuf[0], 0, (int) number);
1.1 etheisen 216: break;
217: #if EXAMINE
218: case A_EXAMINE:
1.6 ! millert 219: if (secure)
! 220: break;
1.1 etheisen 221: edit_list(cbuf);
1.6 ! millert 222: #if TAGS
! 223: /* If tag structure is loaded then clean it up. */
! 224: cleantags();
! 225: #endif
1.1 etheisen 226: break;
227: #endif
228: #if SHELL_ESCAPE
229: case A_SHELL:
230: /*
231: * !! just uses whatever is in shellcmd.
232: * Otherwise, copy cmdbuf to shellcmd,
233: * expanding any special characters ("%" or "#").
234: */
235: if (*cbuf != '!')
236: {
237: if (shellcmd != NULL)
238: free(shellcmd);
239: shellcmd = fexpand(cbuf);
240: }
241:
1.6 ! millert 242: if (secure)
! 243: break;
1.1 etheisen 244: if (shellcmd == NULL)
1.6 ! millert 245: lsystem("", "!done");
1.1 etheisen 246: else
1.6 ! millert 247: lsystem(shellcmd, "!done");
1.1 etheisen 248: break;
249: #endif
250: #if PIPEC
251: case A_PIPE:
1.6 ! millert 252: if (secure)
! 253: break;
1.1 etheisen 254: (void) pipe_mark(pipec, cbuf);
255: error("|done", NULL_PARG);
256: break;
257: #endif
258: }
259: }
260:
261: /*
262: * Add a character to a multi-character command.
263: */
264: static int
265: mca_char(c)
266: int c;
267: {
268: char *p;
269: int flag;
270: char buf[3];
1.6 ! millert 271: PARG parg;
1.1 etheisen 272:
273: switch (mca)
274: {
275: case 0:
276: /*
277: * Not in a multicharacter command.
278: */
279: return (NO_MCA);
280:
281: case A_PREFIX:
282: /*
283: * In the prefix of a command.
284: * This not considered a multichar command
285: * (even tho it uses cmdbuf, etc.).
286: * It is handled in the commands() switch.
287: */
288: return (NO_MCA);
289:
290: case A_DIGIT:
291: /*
292: * Entering digits of a number.
293: * Terminated by a non-digit.
294: */
295: if ((c < '0' || c > '9') &&
1.6 ! millert 296: editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID)
1.1 etheisen 297: {
298: /*
299: * Not part of the number.
300: * Treat as a normal command character.
301: */
302: number = cmd_int();
303: mca = 0;
304: cmd_accept();
305: return (NO_MCA);
306: }
307: break;
308:
309: case A_OPT_TOGGLE:
310: /*
311: * Special case for the TOGGLE_OPTION command.
312: * If the option letter which was entered is a
313: * single-char option, execute the command immediately,
314: * so user doesn't have to hit RETURN.
315: * If the first char is + or -, this indicates
316: * OPT_UNSET or OPT_SET respectively, instead of OPT_TOGGLE.
1.6 ! millert 317: * "--" begins inputting a long option name.
1.1 etheisen 318: */
1.6 ! millert 319: if (optchar == '\0' && len_cmdbuf() == 0)
! 320: {
! 321: flag = (optflag & ~OPT_NO_PROMPT);
! 322: if (flag == OPT_NO_TOGGLE)
! 323: {
! 324: switch (c)
! 325: {
! 326: case '_':
! 327: /* "__" = long option name. */
! 328: optgetname = TRUE;
! 329: mca_opt_toggle();
! 330: return (MCA_MORE);
! 331: }
! 332: } else
! 333: {
! 334: switch (c)
! 335: {
! 336: case '+':
! 337: /* "-+" = UNSET. */
! 338: optflag = (flag == OPT_UNSET) ?
! 339: OPT_TOGGLE : OPT_UNSET;
! 340: mca_opt_toggle();
! 341: return (MCA_MORE);
! 342: case '!':
! 343: /* "-!" = SET */
! 344: optflag = (flag == OPT_SET) ?
! 345: OPT_TOGGLE : OPT_SET;
! 346: mca_opt_toggle();
! 347: return (MCA_MORE);
! 348: case CONTROL('P'):
! 349: optflag ^= OPT_NO_PROMPT;
! 350: mca_opt_toggle();
! 351: return (MCA_MORE);
! 352: case '-':
! 353: /* "--" = long option name. */
! 354: optgetname = TRUE;
! 355: mca_opt_toggle();
! 356: return (MCA_MORE);
! 357: }
! 358: }
! 359: }
! 360: if (optgetname)
! 361: {
1.1 etheisen 362: /*
1.6 ! millert 363: * We're getting a long option name.
! 364: * See if we've matched an option name yet.
! 365: * If so, display the complete name and stop
! 366: * accepting chars until user hits RETURN.
! 367: */
! 368: struct loption *o;
! 369: char *oname;
! 370: int lc;
! 371:
! 372: if (c == '\n' || c == '\r')
! 373: {
! 374: /*
! 375: * When the user hits RETURN, make sure
! 376: * we've matched an option name, then
! 377: * pretend he just entered the equivalent
! 378: * option letter.
! 379: */
! 380: if (optchar == '\0')
! 381: {
! 382: parg.p_string = get_cmdbuf();
! 383: error("There is no --%s option", &parg);
! 384: return (MCA_DONE);
! 385: }
! 386: optgetname = FALSE;
! 387: cmd_reset();
! 388: c = optchar;
! 389: } else
1.1 etheisen 390: {
1.6 ! millert 391: if (optchar != '\0')
! 392: {
! 393: /*
! 394: * Already have a match for the name.
! 395: * Don't accept anything but erase/kill.
! 396: */
! 397: if (c == erase_char || c == kill_char)
! 398: return (MCA_DONE);
! 399: return (MCA_MORE);
! 400: }
! 401: /*
! 402: * Add char to cmd buffer and try to match
! 403: * the option name.
! 404: */
! 405: if (cmd_char(c) == CC_QUIT)
! 406: return (MCA_DONE);
! 407: p = get_cmdbuf();
! 408: lc = islower(p[0]);
! 409: o = findopt_name(&p, &oname, NULL);
! 410: if (o != NULL)
! 411: {
! 412: /*
! 413: * Got a match.
! 414: * Remember the option letter and
! 415: * display the full option name.
! 416: */
! 417: optchar = o->oletter;
! 418: if (!lc && islower(optchar))
! 419: optchar = toupper(optchar);
! 420: cmd_reset();
! 421: mca_opt_toggle();
! 422: for (p = oname; *p != '\0'; p++)
! 423: {
! 424: c = *p;
! 425: if (!lc && islower(c))
! 426: c = toupper(c);
! 427: if (cmd_char(c) != CC_OK)
! 428: return (MCA_DONE);
! 429: }
! 430: }
! 431: return (MCA_MORE);
1.1 etheisen 432: }
1.6 ! millert 433: } else
! 434: {
! 435: if (c == erase_char || c == kill_char)
! 436: break;
! 437: if (optchar != '\0')
! 438: /* We already have the option letter. */
! 439: break;
1.1 etheisen 440: }
1.6 ! millert 441:
! 442: optchar = c;
! 443: if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE ||
! 444: single_char_option(c))
1.1 etheisen 445: {
1.6 ! millert 446: toggle_option(c, "", optflag);
! 447: return (MCA_DONE);
1.1 etheisen 448: }
449: /*
450: * Display a prompt appropriate for the option letter.
451: */
452: if ((p = opt_prompt(c)) == NULL)
453: {
454: buf[0] = '-';
455: buf[1] = c;
456: buf[2] = '\0';
457: p = buf;
458: }
1.6 ! millert 459: start_mca(A_OPT_TOGGLE, p, (void*)NULL, 0);
1.1 etheisen 460: return (MCA_MORE);
461:
462: case A_F_SEARCH:
463: case A_B_SEARCH:
464: /*
465: * Special case for search commands.
466: * Certain characters as the first char of
467: * the pattern have special meaning:
1.6 ! millert 468: * ! Toggle the NO_MATCH flag
1.1 etheisen 469: * * Toggle the PAST_EOF flag
470: * @ Toggle the FIRST_FILE flag
471: */
472: if (len_cmdbuf() > 0)
473: /*
474: * Only works for the first char of the pattern.
475: */
476: break;
477:
478: flag = 0;
479: switch (c)
480: {
1.6 ! millert 481: case CONTROL('E'): /* ignore END of file */
! 482: case '*':
! 483: flag = SRCH_PAST_EOF;
1.1 etheisen 484: break;
1.6 ! millert 485: case CONTROL('F'): /* FIRST file */
1.1 etheisen 486: case '@':
487: flag = SRCH_FIRST_FILE;
488: break;
1.6 ! millert 489: case CONTROL('K'): /* KEEP position */
! 490: flag = SRCH_NO_MOVE;
! 491: break;
! 492: case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */
! 493: flag = SRCH_NO_REGEX;
! 494: break;
! 495: case CONTROL('N'): /* NOT match */
! 496: case '!':
! 497: flag = SRCH_NO_MATCH;
1.1 etheisen 498: break;
499: }
500: if (flag != 0)
501: {
502: search_type ^= flag;
503: mca_search();
504: return (MCA_MORE);
505: }
506: break;
507: }
508:
509: /*
510: * Any other multicharacter command
511: * is terminated by a newline.
512: */
513: if (c == '\n' || c == '\r')
514: {
515: /*
516: * Execute the command.
517: */
518: exec_mca();
519: return (MCA_DONE);
520: }
1.6 ! millert 521:
1.1 etheisen 522: /*
523: * Append the char to the command buffer.
524: */
525: if (cmd_char(c) == CC_QUIT)
526: /*
527: * Abort the multi-char command.
528: */
529: return (MCA_DONE);
530:
531: if ((mca == A_F_BRACKET || mca == A_B_BRACKET) && len_cmdbuf() >= 2)
532: {
533: /*
534: * Special case for the bracket-matching commands.
535: * Execute the command after getting exactly two
536: * characters from the user.
537: */
538: exec_mca();
539: return (MCA_DONE);
540: }
541:
542: /*
543: * Need another character.
544: */
545: return (MCA_MORE);
546: }
547:
548: /*
1.6 ! millert 549: * Make sure the screen is displayed.
1.1 etheisen 550: */
551: static void
1.6 ! millert 552: make_display()
1.1 etheisen 553: {
554: /*
555: * If nothing is displayed yet, display starting from initial_scrpos.
556: */
557: if (empty_screen())
558: {
559: if (initial_scrpos.pos == NULL_POSITION)
560: /*
561: * {{ Maybe this should be:
562: * jump_loc(ch_zero(), jump_sline);
563: * but this behavior seems rather unexpected
564: * on the first screen. }}
565: */
566: jump_loc(ch_zero(), 1);
567: else
568: jump_loc(initial_scrpos.pos, initial_scrpos.ln);
569: } else if (screen_trashed)
570: {
571: int save_top_scroll;
572: save_top_scroll = top_scroll;
573: top_scroll = 1;
574: repaint();
575: top_scroll = save_top_scroll;
576: }
1.6 ! millert 577: }
! 578:
! 579: /*
! 580: * Display the appropriate prompt.
! 581: */
! 582: static void
! 583: prompt()
! 584: {
! 585: register char *p;
! 586:
! 587: if (ungotp != NULL && ungotp > ungot)
! 588: {
! 589: /*
! 590: * No prompt necessary if commands are from
! 591: * ungotten chars rather than from the user.
! 592: */
! 593: return;
! 594: }
! 595:
! 596: /*
! 597: * Make sure the screen is displayed.
! 598: */
! 599: make_display();
! 600: bottompos = position(BOTTOM_PLUS_ONE);
1.1 etheisen 601:
602: /*
603: * If the -E flag is set and we've hit EOF on the last file, quit.
604: */
1.6 ! millert 605: if ((quit_at_eof == OPT_ONPLUS || quit_if_one_screen) &&
! 606: hit_eof && !(ch_getflags() & CH_HELPFILE) &&
1.1 etheisen 607: next_ifile(curr_ifile) == NULL_IFILE)
608: quit(QUIT_OK);
1.6 ! millert 609: quit_if_one_screen = FALSE;
! 610: #if 0 /* This doesn't work well because some "te"s clear the screen. */
! 611: /*
! 612: * If the -e flag is set and we've hit EOF on the last file,
! 613: * and the file is squished (shorter than the screen), quit.
! 614: */
! 615: if (quit_at_eof && squished &&
! 616: next_ifile(curr_ifile) == NULL_IFILE)
! 617: quit(QUIT_OK);
! 618: #endif
1.1 etheisen 619:
1.6 ! millert 620: #if MSDOS_COMPILER==WIN32C
! 621: /*
! 622: * In Win32, display the file name in the window title.
! 623: */
! 624: if (!(ch_getflags() & CH_HELPFILE))
! 625: SetConsoleTitle(pr_expand("Less?f - %f.", 0));
! 626: #endif
1.1 etheisen 627: /*
628: * Select the proper prompt and display it.
629: */
1.6 ! millert 630: clear_cmd();
! 631: p = help_prompt ? help_prompt : pr_string();
! 632: if (p == NULL)
! 633: putchr(':');
! 634: else
! 635: {
1.1 etheisen 636: so_enter();
1.6 ! millert 637: putstr(p);
! 638: if (be_helpful && !help_prompt && strlen(p) + 40 < sc_width)
! 639: putstr(" [Press space to continue, 'q' to quit.]");
1.1 etheisen 640: so_exit();
641: }
1.6 ! millert 642: help_prompt = NULL;
1.1 etheisen 643: }
644:
1.6 ! millert 645: /*
! 646: * Display the less version message.
! 647: */
1.1 etheisen 648: public void
649: dispversion()
650: {
651: PARG parg;
652:
653: parg.p_string = version;
1.6 ! millert 654: error("less %s", &parg);
1.1 etheisen 655: }
656:
657: /*
658: * Get command character.
659: * The character normally comes from the keyboard,
660: * but may come from ungotten characters
661: * (characters previously given to ungetcc or ungetsc).
662: */
663: public int
664: getcc()
665: {
666: if (ungotp == NULL)
667: /*
668: * Normal case: no ungotten chars, so get one from the user.
669: */
670: return (getchr());
671:
672: if (ungotp > ungot)
673: /*
674: * Return the next ungotten char.
675: */
676: return (*--ungotp);
677:
678: /*
679: * We have just run out of ungotten chars.
680: */
681: ungotp = NULL;
682: if (len_cmdbuf() == 0 || !empty_screen())
683: return (getchr());
684: /*
685: * Command is incomplete, so try to complete it.
686: */
687: switch (mca)
688: {
689: case A_DIGIT:
690: /*
691: * We have a number but no command. Treat as #g.
692: */
693: return ('g');
694:
695: case A_F_SEARCH:
696: case A_B_SEARCH:
697: /*
698: * We have "/string" but no newline. Add the \n.
699: */
700: return ('\n');
701:
702: default:
703: /*
704: * Some other incomplete command. Let user complete it.
705: */
706: return (getchr());
707: }
708: }
709:
710: /*
711: * "Unget" a command character.
712: * The next getcc() will return this character.
713: */
714: public void
715: ungetcc(c)
716: int c;
717: {
718: if (ungotp == NULL)
719: ungotp = ungot;
720: if (ungotp >= ungot + sizeof(ungot))
721: {
722: error("ungetcc overflow", NULL_PARG);
723: quit(QUIT_ERROR);
724: }
725: *ungotp++ = c;
726: }
727:
728: /*
729: * Unget a whole string of command characters.
730: * The next sequence of getcc()'s will return this string.
731: */
732: public void
733: ungetsc(s)
734: char *s;
735: {
1.6 ! millert 736: register char *p;
1.1 etheisen 737:
738: for (p = s + strlen(s) - 1; p >= s; p--)
739: ungetcc(*p);
740: }
741:
742: /*
743: * Search for a pattern, possibly in multiple files.
744: * If SRCH_FIRST_FILE is set, begin searching at the first file.
745: * If SRCH_PAST_EOF is set, continue the search thru multiple files.
746: */
747: static void
748: multi_search(pattern, n)
749: char *pattern;
750: int n;
751: {
1.6 ! millert 752: register int nomore;
1.1 etheisen 753: IFILE save_ifile;
754: int changed_file;
755:
756: changed_file = 0;
1.6 ! millert 757: save_ifile = save_curr_ifile();
1.1 etheisen 758:
759: if (search_type & SRCH_FIRST_FILE)
760: {
761: /*
762: * Start at the first (or last) file
763: * in the command line list.
764: */
765: if (search_type & SRCH_FORW)
766: nomore = edit_first();
767: else
768: nomore = edit_last();
769: if (nomore)
1.6 ! millert 770: {
! 771: unsave_ifile(save_ifile);
1.1 etheisen 772: return;
1.6 ! millert 773: }
1.1 etheisen 774: changed_file = 1;
775: search_type &= ~SRCH_FIRST_FILE;
776: }
777:
778: for (;;)
779: {
1.6 ! millert 780: n = search(search_type, pattern, n);
! 781: /*
! 782: * The SRCH_NO_MOVE flag doesn't "stick": it gets cleared
! 783: * after being used once. This allows "n" to work after
! 784: * using a /@@ search.
! 785: */
! 786: search_type &= ~SRCH_NO_MOVE;
! 787: if (n == 0)
! 788: {
1.1 etheisen 789: /*
790: * Found it.
791: */
1.6 ! millert 792: unsave_ifile(save_ifile);
1.1 etheisen 793: return;
1.6 ! millert 794: }
1.1 etheisen 795:
796: if (n < 0)
797: /*
798: * Some kind of error in the search.
799: * Error message has been printed by search().
800: */
801: break;
802:
803: if ((search_type & SRCH_PAST_EOF) == 0)
804: /*
805: * We didn't find a match, but we're
806: * supposed to search only one file.
807: */
808: break;
809: /*
810: * Move on to the next file.
811: */
812: if (search_type & SRCH_FORW)
813: nomore = edit_next(1);
814: else
815: nomore = edit_prev(1);
816: if (nomore)
817: break;
818: changed_file = 1;
819: }
820:
821: /*
822: * Didn't find it.
823: * Print an error message if we haven't already.
824: */
825: if (n > 0)
826: error("Pattern not found", NULL_PARG);
827:
828: if (changed_file)
829: {
830: /*
831: * Restore the file we were originally viewing.
832: */
1.6 ! millert 833: reedit_ifile(save_ifile);
1.1 etheisen 834: }
835: }
836:
837: /*
838: * Main command processor.
839: * Accept and execute commands until a quit command.
840: */
841: public void
842: commands()
843: {
1.6 ! millert 844: register int c;
! 845: register int action;
! 846: register char *cbuf;
! 847: int newaction;
1.1 etheisen 848: int save_search_type;
1.6 ! millert 849: char *extra;
1.1 etheisen 850: char tbuf[2];
851: PARG parg;
1.6 ! millert 852: IFILE old_ifile;
! 853: IFILE new_ifile;
! 854: char *tagfile;
1.1 etheisen 855:
856: search_type = SRCH_FORW;
857: wscroll = (sc_height + 1) / 2;
1.6 ! millert 858: newaction = A_NOACTION;
1.1 etheisen 859:
860: for (;;)
861: {
862: mca = 0;
863: cmd_accept();
864: number = 0;
865: optchar = '\0';
866:
867: /*
868: * See if any signals need processing.
869: */
870: if (sigs)
871: {
872: psignals();
873: if (quitting)
874: quit(QUIT_SAVED_STATUS);
875: }
1.6 ! millert 876:
! 877: /*
! 878: * See if window size changed, for systems that don't
! 879: * generate SIGWINCH.
! 880: */
! 881: check_winch();
! 882:
1.1 etheisen 883: /*
884: * Display prompt and accept a character.
885: */
886: cmd_reset();
887: prompt();
888: if (sigs)
889: continue;
1.6 ! millert 890: if (newaction == A_NOACTION)
! 891: c = getcc();
1.1 etheisen 892:
893: again:
894: if (sigs)
895: continue;
896:
1.6 ! millert 897: if (newaction != A_NOACTION)
! 898: {
! 899: action = newaction;
! 900: newaction = A_NOACTION;
! 901: } else
! 902: {
! 903: /*
! 904: * If we are in a multicharacter command, call mca_char.
! 905: * Otherwise we call fcmd_decode to determine the
! 906: * action to be performed.
! 907: */
! 908: if (mca)
! 909: switch (mca_char(c))
! 910: {
! 911: case MCA_MORE:
! 912: /*
! 913: * Need another character.
! 914: */
! 915: c = getcc();
! 916: goto again;
! 917: case MCA_DONE:
! 918: /*
! 919: * Command has been handled by mca_char.
! 920: * Start clean with a prompt.
! 921: */
! 922: continue;
! 923: case NO_MCA:
! 924: /*
! 925: * Not a multi-char command
! 926: * (at least, not anymore).
! 927: */
! 928: break;
! 929: }
! 930:
! 931: /*
! 932: * Decode the command character and decide what to do.
! 933: */
! 934: if (mca)
1.1 etheisen 935: {
936: /*
1.6 ! millert 937: * We're in a multichar command.
! 938: * Add the character to the command buffer
! 939: * and display it on the screen.
! 940: * If the user backspaces past the start
! 941: * of the line, abort the command.
1.1 etheisen 942: */
1.6 ! millert 943: if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0)
! 944: continue;
! 945: cbuf = get_cmdbuf();
! 946: } else
! 947: {
1.1 etheisen 948: /*
1.6 ! millert 949: * Don't use cmd_char if we're starting fresh
! 950: * at the beginning of a command, because we
! 951: * don't want to echo the command until we know
! 952: * it is a multichar command. We also don't
! 953: * want erase_char/kill_char to be treated
! 954: * as line editing characters.
1.1 etheisen 955: */
1.6 ! millert 956: tbuf[0] = c;
! 957: tbuf[1] = '\0';
! 958: cbuf = tbuf;
1.1 etheisen 959: }
1.6 ! millert 960: extra = NULL;
! 961: action = fcmd_decode(cbuf, &extra);
1.1 etheisen 962: /*
1.6 ! millert 963: * If an "extra" string was returned,
! 964: * process it as a string of command characters.
! 965: */
! 966: if (extra != NULL)
! 967: ungetsc(extra);
1.1 etheisen 968: }
969: /*
970: * Clear the cmdbuf string.
971: * (But not if we're in the prefix of a command,
972: * because the partial command string is kept there.)
973: */
974: if (action != A_PREFIX)
975: cmd_reset();
976:
977: switch (action)
978: {
979: case A_DIGIT:
980: /*
981: * First digit of a number.
982: */
1.6 ! millert 983: start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE);
1.1 etheisen 984: goto again;
985:
986: case A_F_WINDOW:
987: /*
988: * Forward one window (and set the window size).
989: */
990: if (number > 0)
1.6 ! millert 991: swindow = (int) number;
1.1 etheisen 992: /* FALLTHRU */
993: case A_F_SCREEN:
994: /*
995: * Forward one screen.
996: */
997: if (number <= 0)
998: number = get_swindow();
999: cmd_exec();
1.6 ! millert 1000: if (show_attn)
! 1001: set_attnpos(bottompos);
! 1002: forward((int) number, 0, 1);
1.1 etheisen 1003: break;
1004:
1005: case A_B_WINDOW:
1006: /*
1007: * Backward one window (and set the window size).
1008: */
1009: if (number > 0)
1.6 ! millert 1010: swindow = (int) number;
1.1 etheisen 1011: /* FALLTHRU */
1012: case A_B_SCREEN:
1013: /*
1014: * Backward one screen.
1015: */
1016: if (number <= 0)
1017: number = get_swindow();
1018: cmd_exec();
1.6 ! millert 1019: backward((int) number, 0, 1);
1.1 etheisen 1020: break;
1021:
1022: case A_F_LINE:
1023: /*
1024: * Forward N (default 1) line.
1025: */
1026: if (number <= 0)
1027: number = 1;
1028: cmd_exec();
1.6 ! millert 1029: if (show_attn == OPT_ONPLUS && number > 1)
! 1030: set_attnpos(bottompos);
! 1031: forward((int) number, 0, 0);
1.1 etheisen 1032: break;
1033:
1034: case A_B_LINE:
1035: /*
1036: * Backward N (default 1) line.
1037: */
1038: if (number <= 0)
1039: number = 1;
1040: cmd_exec();
1.6 ! millert 1041: backward((int) number, 0, 0);
1.1 etheisen 1042: break;
1043:
1044: case A_FF_LINE:
1045: /*
1046: * Force forward N (default 1) line.
1047: */
1048: if (number <= 0)
1049: number = 1;
1050: cmd_exec();
1.6 ! millert 1051: if (show_attn == OPT_ONPLUS && number > 1)
! 1052: set_attnpos(bottompos);
! 1053: forward((int) number, 1, 0);
1.1 etheisen 1054: break;
1055:
1056: case A_BF_LINE:
1057: /*
1058: * Force backward N (default 1) line.
1059: */
1060: if (number <= 0)
1061: number = 1;
1062: cmd_exec();
1.6 ! millert 1063: backward((int) number, 1, 0);
1.1 etheisen 1064: break;
1065:
1.6 ! millert 1066: case A_FF_SCREEN:
! 1067: /*
! 1068: * Force forward one screen.
! 1069: */
! 1070: if (number <= 0)
! 1071: number = get_swindow();
! 1072: cmd_exec();
! 1073: if (show_attn == OPT_ONPLUS)
! 1074: set_attnpos(bottompos);
! 1075: forward((int) number, 1, 0);
! 1076: break;
! 1077:
1.1 etheisen 1078: case A_F_FOREVER:
1079: /*
1080: * Forward forever, ignoring EOF.
1081: */
1.6 ! millert 1082: if (ch_getflags() & CH_HELPFILE)
! 1083: break;
1.1 etheisen 1084: cmd_exec();
1085: jump_forw();
1086: ignore_eoi = 1;
1087: hit_eof = 0;
1.6 ! millert 1088: while (!sigs)
1.1 etheisen 1089: forward(1, 0, 0);
1090: ignore_eoi = 0;
1.6 ! millert 1091: /*
! 1092: * This gets us back in "F mode" after processing
! 1093: * a non-abort signal (e.g. window-change).
! 1094: */
! 1095: if (sigs && !ABORT_SIGS())
! 1096: newaction = A_F_FOREVER;
1.1 etheisen 1097: break;
1098:
1099: case A_F_SCROLL:
1100: /*
1101: * Forward N lines
1102: * (default same as last 'd' or 'u' command).
1103: */
1104: if (number > 0)
1.6 ! millert 1105: wscroll = (int) number;
1.1 etheisen 1106: cmd_exec();
1.6 ! millert 1107: if (show_attn == OPT_ONPLUS)
! 1108: set_attnpos(bottompos);
1.1 etheisen 1109: forward(wscroll, 0, 0);
1110: break;
1111:
1112: case A_B_SCROLL:
1113: /*
1114: * Forward N lines
1115: * (default same as last 'd' or 'u' command).
1116: */
1117: if (number > 0)
1.6 ! millert 1118: wscroll = (int) number;
1.1 etheisen 1119: cmd_exec();
1120: backward(wscroll, 0, 0);
1121: break;
1122:
1123: case A_FREPAINT:
1124: /*
1125: * Flush buffers, then repaint screen.
1126: * Don't flush the buffers on a pipe!
1127: */
1128: if (ch_getflags() & CH_CANSEEK)
1129: {
1130: ch_flush();
1131: clr_linenum();
1.6 ! millert 1132: #if HILITE_SEARCH
! 1133: clr_hilite();
! 1134: #endif
1.1 etheisen 1135: }
1136: /* FALLTHRU */
1137: case A_REPAINT:
1138: /*
1139: * Repaint screen.
1140: */
1141: cmd_exec();
1142: repaint();
1143: break;
1144:
1145: case A_GOLINE:
1146: /*
1147: * Go to line N, default beginning of file.
1148: */
1149: if (number <= 0)
1150: number = 1;
1151: cmd_exec();
1152: jump_back(number);
1153: break;
1154:
1155: case A_PERCENT:
1156: /*
1157: * Go to a specified percentage into the file.
1158: */
1159: if (number < 0)
1160: number = 0;
1161: if (number > 100)
1162: number = 100;
1163: cmd_exec();
1.6 ! millert 1164: jump_percent((int) number);
1.1 etheisen 1165: break;
1166:
1167: case A_GOEND:
1168: /*
1169: * Go to line N, default end of file.
1170: */
1171: cmd_exec();
1172: if (number <= 0)
1173: jump_forw();
1174: else
1175: jump_back(number);
1176: break;
1177:
1178: case A_GOPOS:
1179: /*
1180: * Go to a specified byte position in the file.
1181: */
1182: cmd_exec();
1183: if (number < 0)
1184: number = 0;
1.6 ! millert 1185: jump_line_loc((POSITION) number, jump_sline);
1.1 etheisen 1186: break;
1187:
1188: case A_STAT:
1189: /*
1190: * Print file name, etc.
1191: */
1.6 ! millert 1192: if (ch_getflags() & CH_HELPFILE)
! 1193: break;
1.1 etheisen 1194: cmd_exec();
1195: parg.p_string = eq_message();
1196: error("%s", &parg);
1197: break;
1.6 ! millert 1198:
1.1 etheisen 1199: case A_VERSION:
1200: /*
1201: * Print version number, without the "@(#)".
1202: */
1203: cmd_exec();
1204: dispversion();
1205: break;
1206:
1207: case A_QUIT:
1208: /*
1209: * Exit.
1210: */
1.6 ! millert 1211: if (curr_ifile != NULL_IFILE &&
! 1212: ch_getflags() & CH_HELPFILE)
! 1213: {
! 1214: /*
! 1215: * Quit while viewing the help file
! 1216: * just means return to viewing the
! 1217: * previous file.
! 1218: */
! 1219: if (edit_prev(1) == 0)
! 1220: break;
! 1221: }
! 1222: if (extra != NULL)
! 1223: quit(*extra);
1.1 etheisen 1224: quit(QUIT_OK);
1.6 ! millert 1225: break;
1.1 etheisen 1226:
1227: /*
1228: * Define abbreviation for a commonly used sequence below.
1229: */
1230: #define DO_SEARCH() if (number <= 0) number = 1; \
1231: mca_search(); \
1232: cmd_exec(); \
1.6 ! millert 1233: multi_search((char *)NULL, (int) number);
1.1 etheisen 1234:
1235:
1236: case A_F_SEARCH:
1237: /*
1238: * Search forward for a pattern.
1239: * Get the first char of the pattern.
1240: */
1241: search_type = SRCH_FORW;
1242: if (number <= 0)
1243: number = 1;
1244: mca_search();
1245: c = getcc();
1246: goto again;
1247:
1248: case A_B_SEARCH:
1249: /*
1250: * Search backward for a pattern.
1251: * Get the first char of the pattern.
1252: */
1253: search_type = SRCH_BACK;
1254: if (number <= 0)
1255: number = 1;
1256: mca_search();
1257: c = getcc();
1258: goto again;
1259:
1260: case A_AGAIN_SEARCH:
1261: /*
1262: * Repeat previous search.
1263: */
1264: DO_SEARCH();
1265: break;
1266:
1267: case A_T_AGAIN_SEARCH:
1268: /*
1269: * Repeat previous search, multiple files.
1270: */
1271: search_type |= SRCH_PAST_EOF;
1272: DO_SEARCH();
1273: break;
1274:
1275: case A_REVERSE_SEARCH:
1276: /*
1277: * Repeat previous search, in reverse direction.
1278: */
1279: save_search_type = search_type;
1280: search_type = SRCH_REVERSE(search_type);
1281: DO_SEARCH();
1282: search_type = save_search_type;
1283: break;
1284:
1285: case A_T_REVERSE_SEARCH:
1286: /*
1287: * Repeat previous search,
1288: * multiple files in reverse direction.
1289: */
1290: save_search_type = search_type;
1291: search_type = SRCH_REVERSE(search_type);
1292: search_type |= SRCH_PAST_EOF;
1293: DO_SEARCH();
1294: search_type = save_search_type;
1295: break;
1296:
1297: case A_UNDO_SEARCH:
1298: undo_search();
1299: break;
1300:
1301: case A_HELP:
1302: /*
1303: * Help.
1304: */
1.6 ! millert 1305: if (ch_getflags() & CH_HELPFILE)
1.1 etheisen 1306: break;
1307: cmd_exec();
1.6 ! millert 1308: (void) edit(FAKE_HELPFILE);
1.1 etheisen 1309: break;
1310:
1311: case A_EXAMINE:
1312: #if EXAMINE
1313: /*
1314: * Edit a new file. Get the filename.
1315: */
1.6 ! millert 1316: if (secure)
! 1317: {
! 1318: error("Command not available", NULL_PARG);
! 1319: break;
! 1320: }
! 1321: start_mca(A_EXAMINE, "Examine: ", ml_examine, 0);
1.1 etheisen 1322: c = getcc();
1323: goto again;
1324: #else
1325: error("Command not available", NULL_PARG);
1326: break;
1327: #endif
1328:
1329: case A_VISUAL:
1330: /*
1331: * Invoke an editor on the input file.
1332: */
1333: #if EDITOR
1.6 ! millert 1334: if (secure)
! 1335: {
! 1336: error("Command not available", NULL_PARG);
! 1337: break;
! 1338: }
! 1339: if (ch_getflags() & CH_HELPFILE)
! 1340: break;
1.1 etheisen 1341: if (strcmp(get_filename(curr_ifile), "-") == 0)
1342: {
1343: error("Cannot edit standard input", NULL_PARG);
1344: break;
1345: }
1346: if (curr_altfilename != NULL)
1347: {
1348: error("Cannot edit file processed with LESSOPEN",
1349: NULL_PARG);
1350: break;
1351: }
1.6 ! millert 1352: start_mca(A_SHELL, "!", ml_shell, 0);
1.1 etheisen 1353: /*
1354: * Expand the editor prototype string
1355: * and pass it to the system to execute.
1.6 ! millert 1356: * (Make sure the screen is displayed so the
! 1357: * expansion of "+%lm" works.)
1.1 etheisen 1358: */
1.6 ! millert 1359: make_display();
1.1 etheisen 1360: cmd_exec();
1.6 ! millert 1361: lsystem(pr_expand(editproto, 0), (char*)NULL);
1.1 etheisen 1362: break;
1363: #else
1364: error("Command not available", NULL_PARG);
1365: break;
1366: #endif
1367:
1368: case A_NEXT_FILE:
1369: /*
1370: * Examine next file.
1371: */
1.6 ! millert 1372: #if TAGS
! 1373: if (ntags())
! 1374: {
! 1375: error("No next file", NULL_PARG);
! 1376: break;
! 1377: }
! 1378: #endif
1.1 etheisen 1379: if (number <= 0)
1380: number = 1;
1.6 ! millert 1381: if (edit_next((int) number))
1.1 etheisen 1382: {
1.6 ! millert 1383: if (quit_at_eof && hit_eof &&
! 1384: !(ch_getflags() & CH_HELPFILE))
1.1 etheisen 1385: quit(QUIT_OK);
1386: parg.p_string = (number > 1) ? "(N-th) " : "";
1387: error("No %snext file", &parg);
1388: }
1389: break;
1390:
1391: case A_PREV_FILE:
1392: /*
1393: * Examine previous file.
1394: */
1.6 ! millert 1395: #if TAGS
! 1396: if (ntags())
! 1397: {
! 1398: error("No previous file", NULL_PARG);
! 1399: break;
! 1400: }
! 1401: #endif
1.1 etheisen 1402: if (number <= 0)
1403: number = 1;
1.6 ! millert 1404: if (edit_prev((int) number))
1.1 etheisen 1405: {
1406: parg.p_string = (number > 1) ? "(N-th) " : "";
1407: error("No %sprevious file", &parg);
1408: }
1409: break;
1410:
1.6 ! millert 1411: case A_NEXT_TAG:
! 1412: #if TAGS
! 1413: if (number <= 0)
! 1414: number = 1;
! 1415: tagfile = nexttag((int) number);
! 1416: if (tagfile == NULL)
! 1417: {
! 1418: error("No next tag", NULL_PARG);
! 1419: break;
! 1420: }
! 1421: if (edit(tagfile) == 0)
! 1422: {
! 1423: POSITION pos = tagsearch();
! 1424: if (pos != NULL_POSITION)
! 1425: jump_loc(pos, jump_sline);
! 1426: }
! 1427: #else
! 1428: error("Command not available", NULL_PARG);
! 1429: #endif
! 1430: break;
! 1431:
! 1432: case A_PREV_TAG:
! 1433: #if TAGS
! 1434: if (number <= 0)
! 1435: number = 1;
! 1436: tagfile = prevtag((int) number);
! 1437: if (tagfile == NULL)
! 1438: {
! 1439: error("No previous tag", NULL_PARG);
! 1440: break;
! 1441: }
! 1442: if (edit(tagfile) == 0)
! 1443: {
! 1444: POSITION pos = tagsearch();
! 1445: if (pos != NULL_POSITION)
! 1446: jump_loc(pos, jump_sline);
! 1447: }
! 1448: #else
! 1449: error("Command not available", NULL_PARG);
! 1450: #endif
! 1451: break;
! 1452:
1.1 etheisen 1453: case A_INDEX_FILE:
1454: /*
1455: * Examine a particular file.
1456: */
1457: if (number <= 0)
1458: number = 1;
1.6 ! millert 1459: if (edit_index((int) number))
1.1 etheisen 1460: error("No such file", NULL_PARG);
1461: break;
1462:
1.6 ! millert 1463: case A_REMOVE_FILE:
! 1464: if (ch_getflags() & CH_HELPFILE)
! 1465: break;
! 1466: old_ifile = curr_ifile;
! 1467: new_ifile = getoff_ifile(curr_ifile);
! 1468: if (new_ifile == NULL_IFILE)
! 1469: {
! 1470: bell();
! 1471: break;
! 1472: }
! 1473: if (edit_ifile(new_ifile) != 0)
! 1474: {
! 1475: reedit_ifile(old_ifile);
! 1476: break;
! 1477: }
! 1478: del_ifile(old_ifile);
! 1479: break;
! 1480:
1.1 etheisen 1481: case A_OPT_TOGGLE:
1482: optflag = OPT_TOGGLE;
1.6 ! millert 1483: optgetname = FALSE;
! 1484: mca_opt_toggle();
1.1 etheisen 1485: c = getcc();
1486: goto again;
1487:
1488: case A_DISP_OPTION:
1489: /*
1490: * Report a flag setting.
1491: */
1.6 ! millert 1492: optflag = OPT_NO_TOGGLE;
! 1493: optgetname = FALSE;
! 1494: mca_opt_toggle();
1.1 etheisen 1495: c = getcc();
1.6 ! millert 1496: goto again;
1.1 etheisen 1497:
1498: case A_FIRSTCMD:
1499: /*
1500: * Set an initial command for new files.
1501: */
1.6 ! millert 1502: start_mca(A_FIRSTCMD, "+", (void*)NULL, 0);
1.1 etheisen 1503: c = getcc();
1504: goto again;
1505:
1506: case A_SHELL:
1507: /*
1508: * Shell escape.
1509: */
1510: #if SHELL_ESCAPE
1.6 ! millert 1511: if (secure)
! 1512: {
! 1513: error("Command not available", NULL_PARG);
! 1514: break;
! 1515: }
! 1516: start_mca(A_SHELL, "!", ml_shell, 0);
1.1 etheisen 1517: c = getcc();
1518: goto again;
1519: #else
1520: error("Command not available", NULL_PARG);
1521: break;
1522: #endif
1523:
1524: case A_SETMARK:
1525: /*
1526: * Set a mark.
1527: */
1.6 ! millert 1528: if (ch_getflags() & CH_HELPFILE)
! 1529: break;
! 1530: start_mca(A_SETMARK, "mark: ", (void*)NULL, 0);
1.1 etheisen 1531: c = getcc();
1532: if (c == erase_char || c == kill_char ||
1533: c == '\n' || c == '\r')
1534: break;
1535: setmark(c);
1536: break;
1537:
1538: case A_GOMARK:
1539: /*
1540: * Go to a mark.
1541: */
1.6 ! millert 1542: start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0);
1.1 etheisen 1543: c = getcc();
1544: if (c == erase_char || c == kill_char ||
1545: c == '\n' || c == '\r')
1546: break;
1547: gomark(c);
1548: break;
1549:
1550: case A_PIPE:
1551: #if PIPEC
1.6 ! millert 1552: if (secure)
! 1553: {
! 1554: error("Command not available", NULL_PARG);
! 1555: break;
! 1556: }
! 1557: start_mca(A_PIPE, "|mark: ", (void*)NULL, 0);
1.1 etheisen 1558: c = getcc();
1559: if (c == erase_char || c == kill_char)
1560: break;
1561: if (c == '\n' || c == '\r')
1562: c = '.';
1563: if (badmark(c))
1564: break;
1565: pipec = c;
1.6 ! millert 1566: start_mca(A_PIPE, "!", ml_shell, 0);
1.1 etheisen 1567: c = getcc();
1568: goto again;
1569: #else
1570: error("Command not available", NULL_PARG);
1571: break;
1572: #endif
1573:
1574: case A_B_BRACKET:
1575: case A_F_BRACKET:
1.6 ! millert 1576: start_mca(action, "Brackets: ", (void*)NULL, 0);
1.1 etheisen 1577: c = getcc();
1578: goto again;
1579:
1.6 ! millert 1580: case A_LSHIFT:
! 1581: if (number > 0)
! 1582: shift_count = number;
! 1583: else
! 1584: number = (shift_count > 0) ?
! 1585: shift_count : sc_width / 2;
! 1586: if (number > hshift)
! 1587: number = hshift;
! 1588: hshift -= number;
! 1589: screen_trashed = 1;
! 1590: break;
! 1591:
! 1592: case A_RSHIFT:
! 1593: if (number > 0)
! 1594: shift_count = number;
! 1595: else
! 1596: number = (shift_count > 0) ?
! 1597: shift_count : sc_width / 2;
! 1598: hshift += number;
! 1599: screen_trashed = 1;
! 1600: break;
! 1601:
1.1 etheisen 1602: case A_PREFIX:
1603: /*
1604: * The command is incomplete (more chars are needed).
1605: * Display the current char, so the user knows
1606: * what's going on, and get another character.
1607: */
1608: if (mca != A_PREFIX)
1609: {
1610: cmd_reset();
1.6 ! millert 1611: start_mca(A_PREFIX, " ", (void*)NULL,
! 1612: CF_QUIT_ON_ERASE);
1.1 etheisen 1613: (void) cmd_char(c);
1614: }
1615: c = getcc();
1616: goto again;
1617:
1618: case A_NOACTION:
1619: break;
1620:
1621: default:
1.2 etheisen 1622: if (be_helpful)
1.6 ! millert 1623: help_prompt = "[Press 'h' for instructions.]";
1.2 etheisen 1624: else
1625: bell();
1.1 etheisen 1626: break;
1627: }
1628: }
1629: }