diff options
Diffstat (limited to 'contrib/less/command.c')
-rw-r--r-- | contrib/less/command.c | 343 |
1 files changed, 222 insertions, 121 deletions
diff --git a/contrib/less/command.c b/contrib/less/command.c index 72d7c9d43280..6439556f3e80 100644 --- a/contrib/less/command.c +++ b/contrib/less/command.c @@ -27,6 +27,7 @@ extern int quit_if_one_screen; extern int squished; extern int sc_width; extern int sc_height; +extern char *kent; extern int swindow; extern int jump_sline; extern int quitting; @@ -38,9 +39,11 @@ extern int hshift; extern int bs_mode; extern int show_attn; extern int less_is_more; +extern int status_col; extern POSITION highest_hilite; +extern POSITION start_attnpos; +extern POSITION end_attnpos; extern char *every_first_cmd; -extern char *curr_altfilename; extern char version[]; extern struct scrpos initial_scrpos; extern IFILE curr_ifile; @@ -57,7 +60,6 @@ extern int screen_trashed; /* The screen has been overwritten */ extern int shift_count; extern int oldbot; extern int forw_prompt; -extern int same_pos_bell; #if SHELL_ESCAPE static char *shellcmd = NULL; /* For holding last shell command for "!!" */ @@ -77,10 +79,10 @@ static int save_bs_mode; static char pipec; #endif +/* Stack of ungotten chars (via ungetcc) */ struct ungot { struct ungot *ug_next; - char ug_char; - char ug_end_command; + LWCHAR ug_char; }; static struct ungot* ungot = NULL; @@ -94,9 +96,7 @@ static void multi_search(); static void cmd_exec() { -#if HILITE_SEARCH - clear_attn(); -#endif + clear_attn(); clear_bot(); flush(); } @@ -303,11 +303,21 @@ is_erase_char(c) } /* + * Is a character a carriage return or newline? + */ + static int +is_newline_char(c) + int c; +{ + return (c == '\n' || c == '\r'); +} + +/* * Handle the first char of an option (after the initial dash). */ static int mca_opt_first_char(c) - int c; + int c; { int flag = (optflag & ~OPT_NO_PROMPT); if (flag == OPT_NO_TOGGLE) @@ -427,7 +437,7 @@ mca_opt_char(c) if (optgetname) { /* We're getting a long option name. */ - if (c != '\n' && c != '\r') + if (!is_newline_char(c)) return (mca_opt_nonfirst_char(c)); if (curropt == NULL) { @@ -595,7 +605,7 @@ mca_char(c) /* * The multichar command is terminated by a newline. */ - if (c == '\n' || c == '\r') + if (is_newline_char(c)) { /* * Execute the command. @@ -693,7 +703,7 @@ prompt() { constant char *p; - if (ungot != NULL && !ungot->ug_end_command) + if (ungot != NULL && ungot->ug_char != CHAR_END_COMMAND) { /* * No prompt necessary if commands are from @@ -775,74 +785,122 @@ dispversion() } /* + * Return a character to complete a partial command, if possible. + */ + static LWCHAR +getcc_end_command() +{ + switch (mca) + { + case A_DIGIT: + /* We have a number but no command. Treat as #g. */ + return ('g'); + case A_F_SEARCH: + case A_B_SEARCH: + /* We have "/string" but no newline. Add the \n. */ + return ('\n'); + default: + /* Some other incomplete command. Let user complete it. */ + return (getchr()); + } +} + +/* * Get command character. * The character normally comes from the keyboard, * but may come from ungotten characters * (characters previously given to ungetcc or ungetsc). */ - public int -getcc() + static LWCHAR +getccu() { + LWCHAR c; if (ungot == NULL) { - /* - * Normal case: no ungotten chars, so get one from the user. - */ - return (getchr()); - } - - /* - * Return the next ungotten char. - */ + /* Normal case: no ungotten chars. + * Get char from the user. */ + c = getchr(); + } else { + /* Ungotten chars available: + * Take the top of stack (most recent). */ struct ungot *ug = ungot; - char c = ug->ug_char; - int end_command = ug->ug_end_command; + c = ug->ug_char; ungot = ug->ug_next; free(ug); - if (end_command) - { - /* - * Command is incomplete, so try to complete it. - */ - switch (mca) - { - case A_DIGIT: - /* - * We have a number but no command. Treat as #g. - */ - return ('g'); - case A_F_SEARCH: - case A_B_SEARCH: - /* - * We have "/string" but no newline. Add the \n. - */ - return ('\n'); + if (c == CHAR_END_COMMAND) + c = getcc_end_command(); + } + return (c); +} - default: - /* - * Some other incomplete command. Let user complete it. - */ - return (getchr()); - } +/* + * Get a command character, but if we receive the orig sequence, + * convert it to the repl sequence. + */ + static LWCHAR +getcc_repl(orig, repl, gr_getc, gr_ungetc) + char const* orig; + char const* repl; + LWCHAR (*gr_getc)(VOID_PARAM); + void (*gr_ungetc)(LWCHAR); +{ + LWCHAR c; + LWCHAR keys[16]; + int ki = 0; + + c = (*gr_getc)(); + if (orig == NULL || orig[0] == '\0') + return c; + for (;;) + { + keys[ki] = c; + if (c != orig[ki] || ki >= sizeof(keys)-1) + { + /* This is not orig we have been receiving. + * If we have stashed chars in keys[], + * unget them and return the first one. */ + while (ki > 0) + (*gr_ungetc)(keys[ki--]); + return keys[0]; + } + if (orig[++ki] == '\0') + { + /* We've received the full orig sequence. + * Return the repl sequence. */ + ki = strlen(repl)-1; + while (ki > 0) + (*gr_ungetc)(repl[ki--]); + return repl[0]; } - return (c); + /* We've received a partial orig sequence (ki chars of it). + * Get next char and see if it continues to match orig. */ + c = (*gr_getc)(); } } /* + * Get command character. + */ + public int +getcc() +{ + /* Replace kent (keypad Enter) with a newline. */ + return getcc_repl(kent, "\n", getccu, ungetcc); +} + +/* * "Unget" a command character. * The next getcc() will return this character. */ public void ungetcc(c) - int c; + LWCHAR c; { struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); - ug->ug_char = (char) c; - ug->ug_end_command = (c == CHAR_END_COMMAND); + ug->ug_char = c; ug->ug_next = ungot; ungot = ug; } @@ -862,6 +920,17 @@ ungetsc(s) } /* + * Peek the next command character, without consuming it. + */ + public LWCHAR +peekcc() +{ + LWCHAR c = getcc(); + ungetcc(c); + return c; +} + +/* * Search for a pattern, possibly in multiple files. * If SRCH_FIRST_FILE is set, begin searching at the first file. * If SRCH_PAST_EOF is set, continue the search thru multiple files. @@ -1477,6 +1546,9 @@ commands() break; case A_UNDO_SEARCH: + /* + * Clear search string highlighting. + */ undo_search(); break; @@ -1495,60 +1567,54 @@ commands() break; case A_EXAMINE: -#if EXAMINE /* * Edit a new file. Get the filename. */ - if (secure) +#if EXAMINE + if (!secure) { - error("Command not available", NULL_PARG); - break; + start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); + c = getcc(); + goto again; } - start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); - c = getcc(); - goto again; -#else +#endif error("Command not available", NULL_PARG); break; -#endif case A_VISUAL: /* * Invoke an editor on the input file. */ #if EDITOR - if (secure) + if (!secure) { - error("Command not available", NULL_PARG); - break; - } - if (ch_getflags() & CH_HELPFILE) - break; - if (strcmp(get_filename(curr_ifile), "-") == 0) - { - error("Cannot edit standard input", NULL_PARG); + if (ch_getflags() & CH_HELPFILE) + break; + if (strcmp(get_filename(curr_ifile), "-") == 0) + { + error("Cannot edit standard input", NULL_PARG); + break; + } + if (get_altfilename(curr_ifile) != NULL) + { + error("WARNING: This file was viewed via LESSOPEN", + NULL_PARG); + } + start_mca(A_SHELL, "!", ml_shell, 0); + /* + * Expand the editor prototype string + * and pass it to the system to execute. + * (Make sure the screen is displayed so the + * expansion of "+%lm" works.) + */ + make_display(); + cmd_exec(); + lsystem(pr_expand(editproto, 0), (char*)NULL); break; } - if (curr_altfilename != NULL) - { - error("WARNING: This file was viewed via LESSOPEN", - NULL_PARG); - } - start_mca(A_SHELL, "!", ml_shell, 0); - /* - * Expand the editor prototype string - * and pass it to the system to execute. - * (Make sure the screen is displayed so the - * expansion of "+%lm" works.) - */ - make_display(); - cmd_exec(); - lsystem(pr_expand(editproto, 0), (char*)NULL); - break; -#else +#endif error("Command not available", NULL_PARG); break; -#endif case A_NEXT_FILE: /* @@ -1594,6 +1660,9 @@ commands() break; case A_NEXT_TAG: + /* + * Jump to the next tag in the current tag list. + */ #if TAGS if (number <= 0) number = 1; @@ -1603,6 +1672,7 @@ commands() error("No next tag", NULL_PARG); break; } + cmd_exec(); if (edit(tagfile) == 0) { POSITION pos = tagsearch(); @@ -1615,6 +1685,9 @@ commands() break; case A_PREV_TAG: + /* + * Jump to the previous tag in the current tag list. + */ #if TAGS if (number <= 0) number = 1; @@ -1624,6 +1697,7 @@ commands() error("No previous tag", NULL_PARG); break; } + cmd_exec(); if (edit(tagfile) == 0) { POSITION pos = tagsearch(); @@ -1646,6 +1720,9 @@ commands() break; case A_REMOVE_FILE: + /* + * Remove a file from the input file list. + */ if (ch_getflags() & CH_HELPFILE) break; old_ifile = curr_ifile; @@ -1664,6 +1741,9 @@ commands() break; case A_OPT_TOGGLE: + /* + * Change the setting of an option. + */ optflag = OPT_TOGGLE; optgetname = FALSE; mca_opt_toggle(); @@ -1672,7 +1752,7 @@ commands() case A_DISP_OPTION: /* - * Report a flag setting. + * Report the setting of an option. */ optflag = OPT_NO_TOGGLE; optgetname = FALSE; @@ -1693,69 +1773,78 @@ commands() * Shell escape. */ #if SHELL_ESCAPE - if (secure) + if (!secure) { - error("Command not available", NULL_PARG); - break; + start_mca(A_SHELL, "!", ml_shell, 0); + c = getcc(); + goto again; } - start_mca(A_SHELL, "!", ml_shell, 0); - c = getcc(); - goto again; -#else +#endif error("Command not available", NULL_PARG); break; -#endif case A_SETMARK: + case A_SETMARKBOT: /* * Set a mark. */ if (ch_getflags() & CH_HELPFILE) break; - start_mca(A_SETMARK, "mark: ", (void*)NULL, 0); + start_mca(A_SETMARK, "set mark: ", (void*)NULL, 0); + c = getcc(); + if (is_erase_char(c) || is_newline_char(c)) + break; + setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP); + repaint(); + break; + + case A_CLRMARK: + /* + * Clear a mark. + */ + start_mca(A_CLRMARK, "clear mark: ", (void*)NULL, 0); c = getcc(); - if (c == erase_char || c == erase2_char || - c == kill_char || c == '\n' || c == '\r') + if (is_erase_char(c) || is_newline_char(c)) break; - setmark(c); + clrmark(c); + repaint(); break; case A_GOMARK: /* - * Go to a mark. + * Jump to a marked position. */ start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0); c = getcc(); - if (c == erase_char || c == erase2_char || - c == kill_char || c == '\n' || c == '\r') + if (is_erase_char(c) || is_newline_char(c)) break; cmd_exec(); gomark(c); break; case A_PIPE: + /* + * Write part of the input to a pipe to a shell command. + */ #if PIPEC - if (secure) + if (!secure) { - error("Command not available", NULL_PARG); - break; + start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); + c = getcc(); + if (is_erase_char(c)) + break; + if (is_newline_char(c)) + c = '.'; + if (badmark(c)) + break; + pipec = c; + start_mca(A_PIPE, "!", ml_shell, 0); + c = getcc(); + goto again; } - start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); - c = getcc(); - if (c == erase_char || c == erase2_char || c == kill_char) - break; - if (c == '\n' || c == '\r') - c = '.'; - if (badmark(c)) - break; - pipec = c; - start_mca(A_PIPE, "!", ml_shell, 0); - c = getcc(); - goto again; -#else +#endif error("Command not available", NULL_PARG); break; -#endif case A_B_BRACKET: case A_F_BRACKET: @@ -1764,6 +1853,9 @@ commands() goto again; case A_LSHIFT: + /* + * Shift view left. + */ if (number > 0) shift_count = number; else @@ -1776,6 +1868,9 @@ commands() break; case A_RSHIFT: + /* + * Shift view right. + */ if (number > 0) shift_count = number; else @@ -1786,11 +1881,17 @@ commands() break; case A_LLSHIFT: + /* + * Shift view left to margin. + */ hshift = 0; screen_trashed = 1; break; case A_RRSHIFT: + /* + * Shift view right to view rightmost char on screen. + */ hshift = rrshift(); screen_trashed = 1; break; |