* Copyright (c) 1988 Mark Nudleman
* Copyright (c) 1988 Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)command.c 5.20 (Berkeley) %G%";
extern int erase_char
, kill_char
, werase_char
;
extern int screen_trashed
; /* The screen has been overwritten */
static char cmdbuf
[120]; /* Buffer for holding a multi-char command */
static char *cp
; /* Pointer into cmdbuf */
static int cmd_col
; /* Current column of the multi-char command */
static int longprompt
; /* if stat command instead of prompt */
static int mca
; /* The multicharacter command (action) */
static int last_mca
; /* The previous mca */
static int number
; /* The number typed by the user */
static int wsearch
; /* Search for matches (1) or non-matches (0) */
#define CMD_RESET cp = cmdbuf /* reset command buffer to empty */
#define CMD_EXEC lower_left(); flush()
/* backspace in command buffer. */
* backspace past beginning of the string: this usually means
/* erase an extra character, for the carat. */
if (CONTROL_CHAR(*--cp
)) {
/* set up the display to start a new multi-character command. */
start_mca(action
, prompt
)
cmd_col
= strlen(prompt
);
* process a single character of a multi-character command, such as
* a number, or the pattern of a search command.
/* in this order, in case werase == erase_char */
while (isspace(cp
[-1]) && !cmd_erase());
while (!isspace(cp
[-1]) && !cmd_erase());
while (isspace(cp
[-1]) && !cmd_erase());
* No room in the command buffer, or no room on the screen;
* {{ Could get fancy here; maybe shift the displayed line
* and make room for more chars, like ksh. }}
if (cp
>= &cmdbuf
[sizeof(cmdbuf
)-1] || cmd_col
>= sc_width
-3)
extern int linenums
, short_file
;
extern char *current_name
, *firstsearch
, *next_name
;
off_t len
, pos
, ch_length(), position(), forw_line();
* if nothing is displayed yet, display starting from line 1;
* if search string provided, go there instead.
if (position(TOP
) == NULL_POSITION
) {
if (forw_line((off_t
)0) == NULL_POSITION
)
if (!firstsearch
|| !search(1, firstsearch
, 1, 1))
/* if no -e flag and we've hit EOF on the last file, quit. */
if ((!quit_at_eof
|| short_file
) && hit_eof
&& curr_ac
+ 1 >= ac
)
/* select the proper prompt and display it. */
(void)sprintf(pbuf
, " file %d/%d", curr_ac
+ 1, ac
);
(void)sprintf(pbuf
, " line %d", currline(BOTTOM
));
if ((pos
= position(BOTTOM
)) != NULL_POSITION
) {
(void)sprintf(pbuf
, " byte %ld", pos
);
if (!ispipe
&& (len
= ch_length())) {
(void)sprintf(pbuf
, "/%ld pct %ld%%",
len
, ((100 * pos
) / len
));
putstr(": END (next file: ");
(pos
= position(BOTTOM
)) != NULL_POSITION
&&
(void)sprintf(pbuf
, " (%ld%%)", ((100 * pos
) / len
));
/* get command character. */
/* left over from error() routine. */
if (cp
> cmdbuf
&& position(TOP
) == NULL_POSITION
) {
* Command is incomplete, so try to complete it.
* There are only two cases:
* 1. We have "/string" but no newline. Add the \n.
* 2. We have a number but no command. Treat as #g.
* (This is all pretty hokey.)
/* Not a number; must be search string */
/* A number; append a 'g' */
/* execute a multicharacter command. */
(void)search(1, cmdbuf
, number
, wsearch
);
(void)search(0, cmdbuf
, number
, wsearch
);
for (p
= cmdbuf
; isspace(*p
); ++p
);
for (p
= cmdbuf
; isspace(*p
); ++p
);
/* add a character to a multi-character command. */
case 0: /* not in a multicharacter command. */
case A_PREFIX
: /* in the prefix of a command. */
* Entering digits of a number.
* Terminated by a non-digit.
if (!isascii(c
) || !isdigit(c
) &&
c
!= erase_char
&& c
!= kill_char
&& c
!= werase_char
) {
* Not part of the number.
* Treat as a normal command character.
* Any other multicharacter command
* is terminated by a newline.
if (c
== '\n' || c
== '\r') {
/* append the char to the command buffer. */
* Main command processor.
* Accept and execute commands until a quit command, then return.
scroll
= (sc_height
+ 1) / 2;
* See if any signals need processing.
* Display prompt and accept a character.
* If we are in a multicharacter command, call mca_char.
* Otherwise we call cmd_decode to determine the
* action to be performed.
* Need another character.
* Command has been handled by mca_char.
* Start clean with a prompt.
* Not a multi-char command
* (at least, not anymore).
/* decode the command character and decide what to do. */
switch (action
= cmd_decode(c
)) {
case A_DIGIT
: /* first digit of a number */
case A_F_SCREEN
: /* forward one screen */
if (number
<= 0 && (number
= sc_window
) <= 0)
case A_B_SCREEN
: /* backward one screen */
if (number
<= 0 && (number
= sc_window
) <= 0)
case A_F_LINE
: /* forward N (default 1) line */
forward(number
<= 0 ? 1 : number
, 0);
case A_B_LINE
: /* backward N (default 1) line */
backward(number
<= 0 ? 1 : number
, 0);
case A_F_SCROLL
: /* forward N lines */
case A_B_SCROLL
: /* backward N lines */
case A_FREPAINT
: /* flush buffers and repaint */
case A_REPAINT
: /* repaint the screen */
case A_GOLINE
: /* go to line N, default 1 */
case A_PERCENT
: /* go to percent of file */
case A_GOEND
: /* go to line N, default end */
case A_STAT
: /* print file name, etc. */
case A_F_SEARCH
: /* search for a pattern */
start_mca(action
, (action
==A_F_SEARCH
) ? "/" : "?");
* Invert the sense of the search; set wsearch
* to 0 and get a new character for the start
(action
== A_F_SEARCH
) ? "!/" : "!?");
case A_AGAIN_SEARCH
: /* repeat previous search */
(last_mca
== A_F_SEARCH
) ? "/" : "?");
(last_mca
== A_F_SEARCH
) ? "!/" : "!?");
(void)search(mca
== A_F_SEARCH
, (char *)NULL
,
case A_TAGFILE
: /* tag a new file */
start_mca(A_TAGFILE
, "Tag: ");
case A_FILE_LIST
: /* show list of file names */
case A_EXAMINE
: /* edit a new file */
start_mca(A_EXAMINE
, "Examine: ");
case A_VISUAL
: /* invoke the editor */
error("Cannot edit standard input");
case A_NEXT_FILE
: /* examine next file */
case A_PREV_FILE
: /* examine previous file */
case A_SETMARK
: /* set a mark */
start_mca(A_SETMARK
, "mark: ");
if (c
== erase_char
|| c
== kill_char
)
case A_GOMARK
: /* go to mark */
start_mca(A_GOMARK
, "goto mark: ");
if (c
== erase_char
|| c
== kill_char
)
* The command is incomplete (more chars are needed).
* Display the current char so the user knows what's
* going on and get another character.
extern char *current_file
;
char buf
[MAXPATHLEN
* 2 + 20], *getenv();
editor
= getenv("EDITOR");
/* pass the line number to vi */
if (editor
== NULL
|| *editor
== '\0') {
if (dolinenumber
&& (c
= currline(MIDDLE
)))
(void)sprintf(buf
, "%s +%d %s", editor
, c
, current_file
);
(void)sprintf(buf
, "%s %s", editor
, current_file
);
register int indx
, width
;
error("No files provided as arguments.");
for (width
= indx
= 0; indx
< ac
;) {
p
= strcmp(av
[indx
], "-") ? av
[indx
] : "stdin";
if (width
+ len
+ 1 >= sc_width
) {