Commit | Line | Data |
---|---|---|
bfe13c81 KB |
1 | /* |
2 | * Copyright (c) 1988 Mark Nudleman | |
3 | * Copyright (c) 1988 Regents of the University of California. | |
4 | * All rights reserved. | |
5 | * | |
bfe13c81 KB |
6 | * Redistribution and use in source and binary forms are permitted |
7 | * provided that the above copyright notice and this paragraph are | |
8 | * duplicated in all such forms and that any documentation, | |
9 | * advertising materials, and other materials related to such | |
10 | * distribution and use acknowledge that the software was developed | |
a942b40b KB |
11 | * by Mark Nudleman and the University of California, Berkeley. The |
12 | * name of Mark Nudleman or the | |
bfe13c81 KB |
13 | * University may not be used to endorse or promote products derived |
14 | * from this software without specific prior written permission. | |
15 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
16 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
17 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
18 | */ | |
19 | ||
20 | #ifndef lint | |
6d713a99 | 21 | static char sccsid[] = "@(#)command.c 5.11 (Berkeley) %G%"; |
bfe13c81 KB |
22 | #endif /* not lint */ |
23 | ||
24 | /* | |
25 | * User-level command processor. | |
26 | */ | |
27 | ||
bc258617 KB |
28 | #include <sys/param.h> |
29 | #include <stdio.h> | |
30 | #include <ctype.h> | |
31 | #include <less.h> | |
bfe13c81 KB |
32 | |
33 | #define NO_MCA 0 | |
34 | #define MCA_DONE 1 | |
35 | #define MCA_MORE 2 | |
36 | ||
bc258617 | 37 | extern int erase_char, kill_char, werase_char; |
bfe13c81 KB |
38 | extern int ispipe; |
39 | extern int sigs; | |
40 | extern int quit_at_eof; | |
41 | extern int hit_eof; | |
42 | extern int sc_width; | |
43 | extern int sc_height; | |
44 | extern int sc_window; | |
45 | extern int curr_ac; | |
46 | extern int ac; | |
47 | extern int quitting; | |
48 | extern int scroll; | |
bfe13c81 KB |
49 | extern int screen_trashed; /* The screen has been overwritten */ |
50 | ||
51 | static char cmdbuf[120]; /* Buffer for holding a multi-char command */ | |
bfe13c81 KB |
52 | static char *cp; /* Pointer into cmdbuf */ |
53 | static int cmd_col; /* Current column of the multi-char command */ | |
bc258617 | 54 | static int longprompt; /* if stat command instead of prompt */ |
bfe13c81 KB |
55 | static int mca; /* The multicharacter command (action) */ |
56 | static int last_mca; /* The previous mca */ | |
57 | static int number; /* The number typed by the user */ | |
58 | static int wsearch; /* Search for matches (1) or non-matches (0) */ | |
59 | ||
60 | /* | |
61 | * Reset command buffer (to empty). | |
62 | */ | |
63 | cmd_reset() | |
64 | { | |
65 | cp = cmdbuf; | |
66 | } | |
67 | ||
68 | /* | |
69 | * Backspace in command buffer. | |
70 | */ | |
bc258617 | 71 | static |
bfe13c81 KB |
72 | cmd_erase() |
73 | { | |
74 | if (cp == cmdbuf) | |
75 | /* | |
76 | * Backspace past beginning of the string: | |
77 | * this usually means abort the command. | |
78 | */ | |
bc258617 | 79 | return(1); |
bfe13c81 | 80 | |
bc258617 | 81 | if (CONTROL_CHAR(*--cp)) { |
bfe13c81 KB |
82 | /* |
83 | * Erase an extra character, for the carat. | |
84 | */ | |
85 | backspace(); | |
bc258617 | 86 | --cmd_col; |
bfe13c81 KB |
87 | } |
88 | backspace(); | |
bc258617 KB |
89 | --cmd_col; |
90 | return(0); | |
bfe13c81 KB |
91 | } |
92 | ||
93 | /* | |
94 | * Set up the display to start a new multi-character command. | |
95 | */ | |
96 | start_mca(action, prompt) | |
97 | int action; | |
98 | char *prompt; | |
99 | { | |
100 | lower_left(); | |
101 | clear_eol(); | |
102 | putstr(prompt); | |
103 | cmd_col = strlen(prompt); | |
104 | mca = action; | |
105 | } | |
106 | ||
107 | /* | |
108 | * Process a single character of a multi-character command, such as | |
109 | * a number, or the pattern of a search command. | |
110 | */ | |
bc258617 | 111 | static |
bfe13c81 KB |
112 | cmd_char(c) |
113 | int c; | |
114 | { | |
115 | if (c == erase_char) | |
bc258617 KB |
116 | return(cmd_erase()); |
117 | /* in this order, in case werase == erase_char */ | |
118 | if (c == werase_char) { | |
119 | if (cp > cmdbuf) { | |
120 | while (isspace(cp[-1]) && !cmd_erase()); | |
121 | while (!isspace(cp[-1]) && !cmd_erase()); | |
122 | while (isspace(cp[-1]) && !cmd_erase()); | |
123 | } | |
124 | return(cp == cmdbuf); | |
125 | } | |
126 | if (c == kill_char) { | |
127 | while (!cmd_erase()); | |
128 | return(1); | |
129 | } | |
130 | /* | |
131 | * No room in the command buffer, or no room on the screen; | |
132 | * {{ Could get fancy here; maybe shift the displayed line | |
133 | * and make room for more chars, like ksh. }} | |
134 | */ | |
135 | if (cp >= &cmdbuf[sizeof(cmdbuf)-1] || cmd_col >= sc_width-3) | |
bfe13c81 | 136 | bell(); |
bc258617 | 137 | else { |
bfe13c81 | 138 | *cp++ = c; |
bc258617 | 139 | if (CONTROL_CHAR(c)) { |
bfe13c81 KB |
140 | putchr('^'); |
141 | cmd_col++; | |
bc258617 | 142 | c = CARAT_CHAR(c); |
bfe13c81 KB |
143 | } |
144 | putchr(c); | |
145 | cmd_col++; | |
146 | } | |
bc258617 | 147 | return(0); |
bfe13c81 KB |
148 | } |
149 | ||
150 | /* | |
151 | * Return the number currently in the command buffer. | |
152 | */ | |
153 | static int | |
154 | cmd_int() | |
155 | { | |
156 | *cp = '\0'; | |
157 | cp = cmdbuf; | |
158 | return (atoi(cmdbuf)); | |
159 | } | |
160 | ||
161 | /* | |
162 | * Move the cursor to lower left before executing a command. | |
163 | * This looks nicer if the command takes a long time before | |
164 | * updating the screen. | |
165 | */ | |
bc258617 | 166 | static |
bfe13c81 KB |
167 | cmd_exec() |
168 | { | |
169 | lower_left(); | |
170 | flush(); | |
171 | } | |
172 | ||
bfe13c81 KB |
173 | prompt() |
174 | { | |
bc258617 KB |
175 | extern int terseprompt, linenums; |
176 | extern char *current_name, *firstsearch; | |
177 | off_t len, pos, ch_length(), position(), forw_line(); | |
178 | char pbuf[40]; | |
bfe13c81 KB |
179 | |
180 | /* | |
bc258617 KB |
181 | * if nothing is displayed yet, display starting from line 1; |
182 | * if search string provided, go there instead. | |
bfe13c81 | 183 | */ |
bc258617 KB |
184 | if (position(TOP) == NULL_POSITION) { |
185 | if (forw_line((off_t)0) == NULL_POSITION) | |
186 | return(0); | |
187 | if (!firstsearch || !search(1, firstsearch, 1, 1)) | |
188 | jump_back(1); | |
189 | } | |
bfe13c81 KB |
190 | else if (screen_trashed) |
191 | repaint(); | |
192 | ||
bc258617 KB |
193 | /* if no -e flag and we've hit EOF on the last file, quit. */ |
194 | if (!quit_at_eof && hit_eof && curr_ac + 1 >= ac) | |
bfe13c81 KB |
195 | quit(); |
196 | ||
bc258617 | 197 | /* select the proper prompt and display it. */ |
bfe13c81 KB |
198 | lower_left(); |
199 | clear_eol(); | |
bc258617 KB |
200 | if (longprompt) { |
201 | so_enter(); | |
202 | putstr(current_name); | |
203 | putstr(":"); | |
204 | if (!ispipe) { | |
205 | (void)sprintf(pbuf, " file %d/%d", curr_ac + 1, ac); | |
206 | putstr(pbuf); | |
207 | } | |
208 | if (linenums) { | |
6d713a99 | 209 | (void)sprintf(pbuf, " line %d", currline(BOTTOM)); |
bc258617 KB |
210 | putstr(pbuf); |
211 | } | |
6d713a99 | 212 | if ((pos = position(BOTTOM)) != NULL_POSITION) { |
bc258617 KB |
213 | (void)sprintf(pbuf, " byte %ld", pos); |
214 | putstr(pbuf); | |
215 | if (!ispipe && (len = ch_length())) { | |
6d713a99 KB |
216 | (void)sprintf(pbuf, "/%ld pct %ld%%", |
217 | len, ((100 * pos) / len)); | |
bc258617 KB |
218 | putstr(pbuf); |
219 | } | |
220 | } | |
221 | so_exit(); | |
222 | longprompt = 0; | |
223 | } | |
224 | else if (terseprompt) | |
bfe13c81 | 225 | putchr(':'); |
bc258617 | 226 | else { |
bfe13c81 | 227 | so_enter(); |
bc258617 KB |
228 | putstr(current_name); |
229 | if (hit_eof) | |
230 | putstr(": END"); | |
231 | else if (linenums) { | |
232 | (void)sprintf(pbuf, ": %d", currline(TOP)); | |
233 | putstr(pbuf); | |
234 | } | |
bfe13c81 KB |
235 | so_exit(); |
236 | } | |
bc258617 | 237 | return(1); |
bfe13c81 KB |
238 | } |
239 | ||
240 | /* | |
241 | * Get command character. | |
bfe13c81 | 242 | */ |
bc258617 | 243 | static |
bfe13c81 KB |
244 | getcc() |
245 | { | |
bc258617 | 246 | if (cp > cmdbuf && position(TOP) == NULL_POSITION) { |
bfe13c81 | 247 | /* |
bc258617 KB |
248 | * Command is incomplete, so try to complete it. |
249 | * There are only two cases: | |
250 | * 1. We have "/string" but no newline. Add the \n. | |
251 | * 2. We have a number but no command. Treat as #g. | |
252 | * (This is all pretty hokey.) | |
bfe13c81 | 253 | */ |
bc258617 KB |
254 | if (mca != A_DIGIT) |
255 | /* Not a number; must be search string */ | |
256 | return('\n'); | |
257 | else | |
258 | /* A number; append a 'g' */ | |
259 | return('g'); | |
bfe13c81 | 260 | } |
bc258617 | 261 | return(getchr()); |
bfe13c81 KB |
262 | } |
263 | ||
264 | /* | |
265 | * Execute a multicharacter command. | |
266 | */ | |
bc258617 | 267 | static |
bfe13c81 KB |
268 | exec_mca() |
269 | { | |
bc258617 KB |
270 | extern int file; |
271 | extern char *tagfile; | |
bfe13c81 | 272 | register char *p; |
bc258617 | 273 | char *glob(); |
bfe13c81 KB |
274 | |
275 | *cp = '\0'; | |
276 | cmd_exec(); | |
bc258617 | 277 | switch (mca) { |
bfe13c81 | 278 | case A_F_SEARCH: |
bc258617 | 279 | (void)search(1, cmdbuf, number, wsearch); |
bfe13c81 KB |
280 | break; |
281 | case A_B_SEARCH: | |
bc258617 | 282 | (void)search(0, cmdbuf, number, wsearch); |
bfe13c81 KB |
283 | break; |
284 | case A_EXAMINE: | |
bc258617 KB |
285 | for (p = cmdbuf; isspace(*p); ++p); |
286 | (void)edit(glob(p)); | |
287 | break; | |
288 | case A_TAGFILE: | |
289 | for (p = cmdbuf; isspace(*p); ++p); | |
290 | findtag(p); | |
291 | if (tagfile == NULL) | |
292 | break; | |
293 | if (edit(tagfile)) | |
294 | (void)tagsearch(); | |
bfe13c81 | 295 | break; |
bfe13c81 KB |
296 | } |
297 | } | |
298 | ||
299 | /* | |
300 | * Add a character to a multi-character command. | |
301 | */ | |
bc258617 | 302 | static |
bfe13c81 KB |
303 | mca_char(c) |
304 | int c; | |
305 | { | |
bc258617 KB |
306 | switch (mca) { |
307 | case 0: /* not in a multicharacter command. */ | |
308 | case A_PREFIX: /* in the prefix of a command. */ | |
309 | return(NO_MCA); | |
bfe13c81 KB |
310 | case A_DIGIT: |
311 | /* | |
312 | * Entering digits of a number. | |
313 | * Terminated by a non-digit. | |
314 | */ | |
bc258617 KB |
315 | if (!isascii(c) || !isdigit(c) && |
316 | c != erase_char && c != kill_char && c != werase_char) { | |
bfe13c81 KB |
317 | /* |
318 | * Not part of the number. | |
319 | * Treat as a normal command character. | |
320 | */ | |
321 | number = cmd_int(); | |
322 | mca = 0; | |
bc258617 | 323 | return(NO_MCA); |
bfe13c81 KB |
324 | } |
325 | break; | |
326 | } | |
327 | ||
328 | /* | |
329 | * Any other multicharacter command | |
330 | * is terminated by a newline. | |
331 | */ | |
bc258617 | 332 | if (c == '\n' || c == '\r') { |
bfe13c81 KB |
333 | /* |
334 | * Execute the command. | |
335 | */ | |
336 | exec_mca(); | |
bc258617 | 337 | return(MCA_DONE); |
bfe13c81 KB |
338 | } |
339 | /* | |
340 | * Append the char to the command buffer. | |
341 | */ | |
342 | if (cmd_char(c)) | |
343 | /* | |
344 | * Abort the multi-char command. | |
345 | */ | |
bc258617 | 346 | return(MCA_DONE); |
bfe13c81 KB |
347 | /* |
348 | * Need another character. | |
349 | */ | |
bc258617 | 350 | return(MCA_MORE); |
bfe13c81 KB |
351 | } |
352 | ||
353 | /* | |
354 | * Main command processor. | |
355 | * Accept and execute commands until a quit command, then return. | |
356 | */ | |
bfe13c81 KB |
357 | commands() |
358 | { | |
359 | register int c; | |
360 | register int action; | |
361 | ||
362 | last_mca = 0; | |
363 | scroll = (sc_height + 1) / 2; | |
364 | ||
bc258617 | 365 | for (;;) { |
bfe13c81 KB |
366 | mca = 0; |
367 | number = 0; | |
368 | ||
369 | /* | |
370 | * See if any signals need processing. | |
371 | */ | |
bc258617 | 372 | if (sigs) { |
bfe13c81 KB |
373 | psignals(); |
374 | if (quitting) | |
375 | quit(); | |
376 | } | |
bfe13c81 KB |
377 | /* |
378 | * Display prompt and accept a character. | |
379 | */ | |
380 | cmd_reset(); | |
bc258617 KB |
381 | if (!prompt()) { |
382 | next_file(1); | |
383 | continue; | |
384 | } | |
bfe13c81 KB |
385 | noprefix(); |
386 | c = getcc(); | |
387 | ||
f5167107 | 388 | again: if (sigs) |
bfe13c81 KB |
389 | continue; |
390 | ||
391 | /* | |
392 | * If we are in a multicharacter command, call mca_char. | |
393 | * Otherwise we call cmd_decode to determine the | |
394 | * action to be performed. | |
395 | */ | |
396 | if (mca) | |
bc258617 | 397 | switch (mca_char(c)) { |
bfe13c81 KB |
398 | case MCA_MORE: |
399 | /* | |
400 | * Need another character. | |
401 | */ | |
402 | c = getcc(); | |
403 | goto again; | |
404 | case MCA_DONE: | |
405 | /* | |
406 | * Command has been handled by mca_char. | |
407 | * Start clean with a prompt. | |
408 | */ | |
409 | continue; | |
410 | case NO_MCA: | |
411 | /* | |
412 | * Not a multi-char command | |
413 | * (at least, not anymore). | |
414 | */ | |
415 | break; | |
416 | } | |
417 | ||
418 | /* | |
419 | * Decode the command character and decide what to do. | |
420 | */ | |
421 | switch (action = cmd_decode(c)) | |
422 | { | |
423 | case A_DIGIT: | |
424 | /* | |
425 | * First digit of a number. | |
426 | */ | |
427 | start_mca(A_DIGIT, ":"); | |
428 | goto again; | |
429 | ||
430 | case A_F_SCREEN: | |
431 | /* | |
432 | * Forward one screen. | |
433 | */ | |
434 | if (number <= 0) | |
435 | number = sc_window; | |
436 | if (number <= 0) | |
437 | number = sc_height - 1; | |
438 | cmd_exec(); | |
439 | forward(number, 1); | |
440 | break; | |
441 | ||
442 | case A_B_SCREEN: | |
443 | /* | |
444 | * Backward one screen. | |
445 | */ | |
446 | if (number <= 0) | |
447 | number = sc_window; | |
448 | if (number <= 0) | |
449 | number = sc_height - 1; | |
450 | cmd_exec(); | |
451 | backward(number, 1); | |
452 | break; | |
453 | ||
454 | case A_F_LINE: | |
455 | /* | |
456 | * Forward N (default 1) line. | |
457 | */ | |
458 | if (number <= 0) | |
459 | number = 1; | |
460 | cmd_exec(); | |
461 | forward(number, 0); | |
462 | break; | |
463 | ||
464 | case A_B_LINE: | |
465 | /* | |
466 | * Backward N (default 1) line. | |
467 | */ | |
468 | if (number <= 0) | |
469 | number = 1; | |
470 | cmd_exec(); | |
471 | backward(number, 0); | |
472 | break; | |
473 | ||
474 | case A_F_SCROLL: | |
475 | /* | |
476 | * Forward N lines | |
477 | * (default same as last 'd' or 'u' command). | |
478 | */ | |
479 | if (number > 0) | |
480 | scroll = number; | |
481 | cmd_exec(); | |
482 | forward(scroll, 0); | |
483 | break; | |
484 | ||
485 | case A_B_SCROLL: | |
486 | /* | |
487 | * Forward N lines | |
488 | * (default same as last 'd' or 'u' command). | |
489 | */ | |
490 | if (number > 0) | |
491 | scroll = number; | |
492 | cmd_exec(); | |
493 | backward(scroll, 0); | |
494 | break; | |
495 | ||
496 | case A_FREPAINT: | |
497 | /* | |
498 | * Flush buffers, then repaint screen. | |
499 | * Don't flush the buffers on a pipe! | |
500 | */ | |
501 | if (!ispipe) | |
502 | { | |
503 | ch_init(0, 0); | |
504 | clr_linenum(); | |
505 | } | |
506 | /* FALLTHRU */ | |
507 | case A_REPAINT: | |
508 | /* | |
509 | * Repaint screen. | |
510 | */ | |
511 | cmd_exec(); | |
512 | repaint(); | |
513 | break; | |
514 | ||
515 | case A_GOLINE: | |
516 | /* | |
517 | * Go to line N, default beginning of file. | |
518 | */ | |
519 | if (number <= 0) | |
520 | number = 1; | |
521 | cmd_exec(); | |
522 | jump_back(number); | |
523 | break; | |
524 | ||
525 | case A_PERCENT: | |
526 | /* | |
527 | * Go to a specified percentage into the file. | |
528 | */ | |
529 | if (number < 0) | |
530 | number = 0; | |
531 | if (number > 100) | |
532 | number = 100; | |
533 | cmd_exec(); | |
534 | jump_percent(number); | |
535 | break; | |
536 | ||
537 | case A_GOEND: | |
538 | /* | |
539 | * Go to line N, default end of file. | |
540 | */ | |
541 | cmd_exec(); | |
542 | if (number <= 0) | |
543 | jump_forw(); | |
544 | else | |
545 | jump_back(number); | |
546 | break; | |
547 | ||
bc258617 KB |
548 | case A_STAT: /* print file name, etc. */ |
549 | longprompt = 1; | |
550 | continue; | |
551 | ||
552 | case A_QUIT: /* exit */ | |
bfe13c81 KB |
553 | quit(); |
554 | ||
555 | case A_F_SEARCH: | |
556 | case A_B_SEARCH: | |
557 | /* | |
558 | * Search for a pattern. | |
559 | * Accept chars of the pattern until \n. | |
560 | */ | |
561 | if (number <= 0) | |
562 | number = 1; | |
563 | start_mca(action, (action==A_F_SEARCH) ? "/" : "?"); | |
564 | last_mca = mca; | |
565 | wsearch = 1; | |
566 | c = getcc(); | |
bc258617 | 567 | if (c == '!') { |
bfe13c81 KB |
568 | /* |
569 | * Invert the sense of the search. | |
570 | * Set wsearch to 0 and get a new | |
571 | * character for the start of the pattern. | |
572 | */ | |
573 | start_mca(action, | |
574 | (action==A_F_SEARCH) ? "!/" : "!?"); | |
575 | wsearch = 0; | |
576 | c = getcc(); | |
577 | } | |
578 | goto again; | |
579 | ||
580 | case A_AGAIN_SEARCH: | |
581 | /* | |
582 | * Repeat previous search. | |
583 | */ | |
584 | if (number <= 0) | |
585 | number = 1; | |
586 | if (wsearch) | |
587 | start_mca(last_mca, | |
588 | (last_mca==A_F_SEARCH) ? "/" : "?"); | |
589 | else | |
590 | start_mca(last_mca, | |
591 | (last_mca==A_F_SEARCH) ? "!/" : "!?"); | |
592 | cmd_exec(); | |
bc258617 KB |
593 | (void)search(mca == A_F_SEARCH, (char *)NULL, |
594 | number, wsearch); | |
bfe13c81 KB |
595 | break; |
596 | ||
597 | case A_HELP: | |
598 | /* | |
599 | * Help. | |
600 | */ | |
601 | lower_left(); | |
602 | clear_eol(); | |
603 | putstr("help"); | |
604 | cmd_exec(); | |
605 | help(); | |
606 | break; | |
607 | ||
bc258617 KB |
608 | case A_TAGFILE: /* tag a new file; get the file name */ |
609 | cmd_reset(); | |
610 | start_mca(A_TAGFILE, "Tag: "); | |
611 | c = getcc(); | |
612 | goto again; | |
613 | ||
614 | case A_EXAMINE: /* edit a new file; get the file name */ | |
bfe13c81 KB |
615 | cmd_reset(); |
616 | start_mca(A_EXAMINE, "Examine: "); | |
617 | c = getcc(); | |
618 | goto again; | |
bc258617 | 619 | |
bfe13c81 KB |
620 | case A_VISUAL: |
621 | /* | |
622 | * Invoke an editor on the input file. | |
623 | */ | |
bfe13c81 KB |
624 | if (ispipe) |
625 | { | |
626 | error("Cannot edit standard input"); | |
627 | break; | |
628 | } | |
bfe13c81 | 629 | cmd_exec(); |
1a2c8d49 | 630 | editfile(); |
bfe13c81 KB |
631 | ch_init(0, 0); |
632 | clr_linenum(); | |
633 | break; | |
bfe13c81 KB |
634 | |
635 | case A_NEXT_FILE: | |
636 | /* | |
637 | * Examine next file. | |
638 | */ | |
639 | if (number <= 0) | |
640 | number = 1; | |
641 | next_file(number); | |
642 | break; | |
643 | ||
644 | case A_PREV_FILE: | |
645 | /* | |
646 | * Examine previous file. | |
647 | */ | |
648 | if (number <= 0) | |
649 | number = 1; | |
650 | prev_file(number); | |
651 | break; | |
652 | ||
bfe13c81 KB |
653 | case A_SETMARK: |
654 | /* | |
655 | * Set a mark. | |
656 | */ | |
657 | lower_left(); | |
658 | clear_eol(); | |
659 | start_mca(A_SETMARK, "mark: "); | |
660 | c = getcc(); | |
661 | if (c == erase_char || c == kill_char) | |
662 | break; | |
663 | setmark(c); | |
664 | break; | |
665 | ||
666 | case A_GOMARK: | |
667 | /* | |
668 | * Go to a mark. | |
669 | */ | |
670 | lower_left(); | |
671 | clear_eol(); | |
672 | start_mca(A_GOMARK, "goto mark: "); | |
673 | c = getcc(); | |
674 | if (c == erase_char || c == kill_char) | |
675 | break; | |
676 | gomark(c); | |
677 | break; | |
678 | ||
679 | case A_PREFIX: | |
680 | /* | |
681 | * The command is incomplete (more chars are needed). | |
682 | * Display the current char so the user knows | |
683 | * what's going on and get another character. | |
684 | */ | |
685 | if (mca != A_PREFIX) | |
686 | start_mca(A_PREFIX, "& "); | |
bc258617 | 687 | if (CONTROL_CHAR(c)) |
bfe13c81 KB |
688 | { |
689 | putchr('^'); | |
bc258617 | 690 | c = CARAT_CHAR(c); |
bfe13c81 KB |
691 | } |
692 | putchr(c); | |
693 | c = getcc(); | |
694 | goto again; | |
695 | ||
696 | default: | |
697 | bell(); | |
698 | break; | |
699 | } | |
700 | } | |
701 | } | |
1a2c8d49 KB |
702 | |
703 | static | |
704 | editfile() | |
705 | { | |
bc258617 | 706 | extern char *current_file; |
1a2c8d49 KB |
707 | static int dolinenumber; |
708 | static char *editor; | |
709 | int c; | |
bc258617 | 710 | char buf[MAXPATHLEN * 2 + 20], *getenv(); |
1a2c8d49 KB |
711 | |
712 | if (editor == NULL) { | |
713 | editor = getenv("EDITOR"); | |
714 | /* pass the line number to vi */ | |
715 | if (editor == NULL || *editor == '\0') { | |
bc258617 KB |
716 | #define EDIT_PGM "/usr/ucb/vi" |
717 | editor = EDIT_PGM; | |
1a2c8d49 KB |
718 | dolinenumber = 1; |
719 | } | |
720 | else | |
721 | dolinenumber = 0; | |
722 | } | |
723 | if (dolinenumber && (c = currline(MIDDLE))) | |
724 | (void)sprintf(buf, "%s +%d %s", editor, c, current_file); | |
725 | else | |
726 | (void)sprintf(buf, "%s %s", editor, current_file); | |
727 | lsystem(buf); | |
728 | } |