version 1.5, 2003/04/10 15:53:30 |
version 1.6, 2003/04/13 18:26:25 |
|
|
/* $OpenBSD$ */ |
|
|
|
/* |
/* |
* Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman |
* Copyright (C) 1984-2002 Mark Nudelman |
* All rights reserved. |
|
* |
* |
* Redistribution and use in source and binary forms, with or without |
* You may distribute under the terms of either the GNU General Public |
* modification, are permitted provided that the following conditions |
* License or the Less License, as specified in the README file. |
* are met: |
|
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
* notice in the documentation and/or other materials provided with |
|
* the distribution. |
|
* |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY |
* For more information about less, or for information on how to |
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
* contact the author, see the README file. |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
|
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
*/ |
*/ |
|
|
|
|
|
|
*/ |
*/ |
|
|
#include "less.h" |
#include "less.h" |
|
#if MSDOS_COMPILER==WIN32C |
|
#include <windows.h> |
|
#endif |
#include "position.h" |
#include "position.h" |
#include "option.h" |
#include "option.h" |
#include "cmd.h" |
#include "cmd.h" |
|
|
extern int erase_char, kill_char; |
extern int erase_char, kill_char; |
extern int sigs; |
extern int sigs; |
extern int quit_at_eof; |
extern int quit_at_eof; |
|
extern int quit_if_one_screen; |
|
extern int squished; |
extern int hit_eof; |
extern int hit_eof; |
extern int sc_width; |
extern int sc_width; |
extern int sc_height; |
extern int sc_height; |
|
|
extern int jump_sline; |
extern int jump_sline; |
extern int quitting; |
extern int quitting; |
extern int wscroll; |
extern int wscroll; |
extern int nohelp; |
|
extern int top_scroll; |
extern int top_scroll; |
extern int ignore_eoi; |
extern int ignore_eoi; |
|
extern int secure; |
|
extern int hshift; |
|
extern int show_attn; |
extern char *every_first_cmd; |
extern char *every_first_cmd; |
extern char *curr_altfilename; |
extern char *curr_altfilename; |
extern char version[]; |
extern char version[]; |
extern struct scrpos initial_scrpos; |
extern struct scrpos initial_scrpos; |
extern IFILE curr_ifile; |
extern IFILE curr_ifile; |
#if CMD_HISTORY |
extern void constant *ml_search; |
extern void *ml_search; |
extern void constant *ml_examine; |
extern void *ml_examine; |
|
#if SHELL_ESCAPE || PIPEC |
#if SHELL_ESCAPE || PIPEC |
extern void *ml_shell; |
extern void constant *ml_shell; |
#endif |
#endif |
#else |
|
/* No CMD_HISTORY */ |
|
#define ml_search NULL |
|
#define ml_examine NULL |
|
#define ml_shell NULL |
|
#endif |
|
#if EDITOR |
#if EDITOR |
extern char *editor; |
extern char *editor; |
extern char *editproto; |
extern char *editproto; |
#endif |
#endif |
extern int screen_trashed; /* The screen has been overwritten */ |
extern int screen_trashed; /* The screen has been overwritten */ |
|
extern int shift_count; |
extern int be_helpful; |
extern int be_helpful; |
|
|
public int helpprompt; |
static char ungot[UNGOT_SIZE]; |
|
|
static char ungot[100]; |
|
static char *ungotp = NULL; |
static char *ungotp = NULL; |
#if SHELL_ESCAPE |
#if SHELL_ESCAPE |
static char *shellcmd = NULL; /* For holding last shell command for "!!" */ |
static char *shellcmd = NULL; /* For holding last shell command for "!!" */ |
#endif |
#endif |
static int mca; /* The multicharacter command (action) */ |
static int mca; /* The multicharacter command (action) */ |
static int search_type; /* The previous type of search */ |
static int search_type; /* The previous type of search */ |
static int number; /* The number typed by the user */ |
static LINENUM number; /* The number typed by the user */ |
static char optchar; |
static char optchar; |
static int optflag; |
static int optflag; |
|
static int optgetname; |
|
static POSITION bottompos; |
|
static char *help_prompt; |
#if PIPEC |
#if PIPEC |
static char pipec; |
static char pipec; |
#endif |
#endif |
|
|
static void |
static void |
cmd_exec() |
cmd_exec() |
{ |
{ |
|
clear_attn(); |
lower_left(); |
lower_left(); |
flush(); |
flush(); |
} |
} |
|
|
* Set up the display to start a new multi-character command. |
* Set up the display to start a new multi-character command. |
*/ |
*/ |
static void |
static void |
start_mca(action, prompt, mlist) |
start_mca(action, prompt, mlist, cmdflags) |
int action; |
int action; |
char *prompt; |
char *prompt; |
void *mlist; |
void *mlist; |
|
int cmdflags; |
{ |
{ |
mca = action; |
mca = action; |
clear_bot(); |
clear_cmd(); |
cmd_putstr(prompt); |
cmd_putstr(prompt); |
#if CMD_HISTORY |
set_mlist(mlist, cmdflags); |
set_mlist(mlist); |
|
#endif |
|
} |
} |
|
|
public int |
public int |
|
|
else |
else |
mca = A_B_SEARCH; |
mca = A_B_SEARCH; |
|
|
clear_bot(); |
clear_cmd(); |
|
|
|
if (search_type & SRCH_NO_MATCH) |
|
cmd_putstr("Non-match "); |
if (search_type & SRCH_FIRST_FILE) |
if (search_type & SRCH_FIRST_FILE) |
cmd_putstr("@"); |
cmd_putstr("First-file "); |
|
|
if (search_type & SRCH_PAST_EOF) |
if (search_type & SRCH_PAST_EOF) |
cmd_putstr("*"); |
cmd_putstr("EOF-ignore "); |
|
if (search_type & SRCH_NO_MOVE) |
|
cmd_putstr("Keep-pos "); |
|
if (search_type & SRCH_NO_REGEX) |
|
cmd_putstr("Regex-off "); |
|
|
if (search_type & SRCH_NOMATCH) |
|
cmd_putstr("!"); |
|
|
|
if (search_type & SRCH_FORW) |
if (search_type & SRCH_FORW) |
cmd_putstr("/"); |
cmd_putstr("/"); |
else |
else |
cmd_putstr("?"); |
cmd_putstr("?"); |
#if CMD_HISTORY |
set_mlist(ml_search, 0); |
set_mlist(ml_search); |
|
#endif |
|
} |
} |
|
|
/* |
/* |
|
* Set up the display to start a new toggle-option command. |
|
*/ |
|
static void |
|
mca_opt_toggle() |
|
{ |
|
int no_prompt; |
|
int flag; |
|
char *dash; |
|
|
|
no_prompt = (optflag & OPT_NO_PROMPT); |
|
flag = (optflag & ~OPT_NO_PROMPT); |
|
dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; |
|
|
|
mca = A_OPT_TOGGLE; |
|
clear_cmd(); |
|
cmd_putstr(dash); |
|
if (optgetname) |
|
cmd_putstr(dash); |
|
if (no_prompt) |
|
cmd_putstr("(P)"); |
|
switch (flag) |
|
{ |
|
case OPT_UNSET: |
|
cmd_putstr("+"); |
|
break; |
|
case OPT_SET: |
|
cmd_putstr("!"); |
|
break; |
|
} |
|
set_mlist(NULL, 0); |
|
} |
|
|
|
/* |
* Execute a multicharacter command. |
* Execute a multicharacter command. |
*/ |
*/ |
static void |
static void |
exec_mca() |
exec_mca() |
{ |
{ |
char *cbuf; |
register char *cbuf; |
|
|
cmd_exec(); |
cmd_exec(); |
cbuf = get_cmdbuf(); |
cbuf = get_cmdbuf(); |
|
|
{ |
{ |
case A_F_SEARCH: |
case A_F_SEARCH: |
case A_B_SEARCH: |
case A_B_SEARCH: |
multi_search(cbuf, number); |
multi_search(cbuf, (int) number); |
break; |
break; |
case A_FIRSTCMD: |
case A_FIRSTCMD: |
/* |
/* |
|
|
optchar = '\0'; |
optchar = '\0'; |
break; |
break; |
case A_F_BRACKET: |
case A_F_BRACKET: |
match_brac(cbuf[0], cbuf[1], 1, number); |
match_brac(cbuf[0], cbuf[1], 1, (int) number); |
break; |
break; |
case A_B_BRACKET: |
case A_B_BRACKET: |
match_brac(cbuf[1], cbuf[0], 0, number); |
match_brac(cbuf[1], cbuf[0], 0, (int) number); |
break; |
break; |
#if EXAMINE |
#if EXAMINE |
case A_EXAMINE: |
case A_EXAMINE: |
|
if (secure) |
|
break; |
edit_list(cbuf); |
edit_list(cbuf); |
|
#if TAGS |
|
/* If tag structure is loaded then clean it up. */ |
|
cleantags(); |
|
#endif |
break; |
break; |
#endif |
#endif |
#if SHELL_ESCAPE |
#if SHELL_ESCAPE |
|
|
shellcmd = fexpand(cbuf); |
shellcmd = fexpand(cbuf); |
} |
} |
|
|
|
if (secure) |
|
break; |
if (shellcmd == NULL) |
if (shellcmd == NULL) |
lsystem(""); |
lsystem("", "!done"); |
else |
else |
lsystem(shellcmd); |
lsystem(shellcmd, "!done"); |
error("!done", NULL_PARG); |
|
break; |
break; |
#endif |
#endif |
#if PIPEC |
#if PIPEC |
case A_PIPE: |
case A_PIPE: |
|
if (secure) |
|
break; |
(void) pipe_mark(pipec, cbuf); |
(void) pipe_mark(pipec, cbuf); |
error("|done", NULL_PARG); |
error("|done", NULL_PARG); |
break; |
break; |
|
|
char *p; |
char *p; |
int flag; |
int flag; |
char buf[3]; |
char buf[3]; |
|
PARG parg; |
|
|
switch (mca) |
switch (mca) |
{ |
{ |
|
|
* Terminated by a non-digit. |
* Terminated by a non-digit. |
*/ |
*/ |
if ((c < '0' || c > '9') && |
if ((c < '0' || c > '9') && |
editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE) == A_INVALID) |
editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID) |
{ |
{ |
/* |
/* |
* Not part of the number. |
* Not part of the number. |
|
|
* so user doesn't have to hit RETURN. |
* so user doesn't have to hit RETURN. |
* If the first char is + or -, this indicates |
* If the first char is + or -, this indicates |
* OPT_UNSET or OPT_SET respectively, instead of OPT_TOGGLE. |
* OPT_UNSET or OPT_SET respectively, instead of OPT_TOGGLE. |
|
* "--" begins inputting a long option name. |
*/ |
*/ |
if (c == erase_char || c == kill_char) |
if (optchar == '\0' && len_cmdbuf() == 0) |
break; |
{ |
if (optchar != '\0' && optchar != '+' && optchar != '-') |
flag = (optflag & ~OPT_NO_PROMPT); |
|
if (flag == OPT_NO_TOGGLE) |
|
{ |
|
switch (c) |
|
{ |
|
case '_': |
|
/* "__" = long option name. */ |
|
optgetname = TRUE; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
} |
|
} else |
|
{ |
|
switch (c) |
|
{ |
|
case '+': |
|
/* "-+" = UNSET. */ |
|
optflag = (flag == OPT_UNSET) ? |
|
OPT_TOGGLE : OPT_UNSET; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
case '!': |
|
/* "-!" = SET */ |
|
optflag = (flag == OPT_SET) ? |
|
OPT_TOGGLE : OPT_SET; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
case CONTROL('P'): |
|
optflag ^= OPT_NO_PROMPT; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
case '-': |
|
/* "--" = long option name. */ |
|
optgetname = TRUE; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
} |
|
} |
|
} |
|
if (optgetname) |
|
{ |
/* |
/* |
* We already have the option letter. |
* We're getting a long option name. |
|
* See if we've matched an option name yet. |
|
* If so, display the complete name and stop |
|
* accepting chars until user hits RETURN. |
*/ |
*/ |
break; |
struct loption *o; |
switch (c) |
char *oname; |
{ |
int lc; |
case '+': |
|
optflag = OPT_UNSET; |
if (c == '\n' || c == '\r') |
break; |
|
case '-': |
|
optflag = OPT_SET; |
|
break; |
|
default: |
|
optchar = c; |
|
if (optflag != OPT_TOGGLE || single_char_option(c)) |
|
{ |
{ |
toggle_option(c, "", optflag); |
/* |
return (MCA_DONE); |
* When the user hits RETURN, make sure |
|
* we've matched an option name, then |
|
* pretend he just entered the equivalent |
|
* option letter. |
|
*/ |
|
if (optchar == '\0') |
|
{ |
|
parg.p_string = get_cmdbuf(); |
|
error("There is no --%s option", &parg); |
|
return (MCA_DONE); |
|
} |
|
optgetname = FALSE; |
|
cmd_reset(); |
|
c = optchar; |
|
} else |
|
{ |
|
if (optchar != '\0') |
|
{ |
|
/* |
|
* Already have a match for the name. |
|
* Don't accept anything but erase/kill. |
|
*/ |
|
if (c == erase_char || c == kill_char) |
|
return (MCA_DONE); |
|
return (MCA_MORE); |
|
} |
|
/* |
|
* Add char to cmd buffer and try to match |
|
* the option name. |
|
*/ |
|
if (cmd_char(c) == CC_QUIT) |
|
return (MCA_DONE); |
|
p = get_cmdbuf(); |
|
lc = islower(p[0]); |
|
o = findopt_name(&p, &oname, NULL); |
|
if (o != NULL) |
|
{ |
|
/* |
|
* Got a match. |
|
* Remember the option letter and |
|
* display the full option name. |
|
*/ |
|
optchar = o->oletter; |
|
if (!lc && islower(optchar)) |
|
optchar = toupper(optchar); |
|
cmd_reset(); |
|
mca_opt_toggle(); |
|
for (p = oname; *p != '\0'; p++) |
|
{ |
|
c = *p; |
|
if (!lc && islower(c)) |
|
c = toupper(c); |
|
if (cmd_char(c) != CC_OK) |
|
return (MCA_DONE); |
|
} |
|
} |
|
return (MCA_MORE); |
} |
} |
break; |
} else |
|
{ |
|
if (c == erase_char || c == kill_char) |
|
break; |
|
if (optchar != '\0') |
|
/* We already have the option letter. */ |
|
break; |
} |
} |
if (optchar == '+' || optchar == '-') |
|
|
optchar = c; |
|
if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || |
|
single_char_option(c)) |
{ |
{ |
optchar = c; |
toggle_option(c, "", optflag); |
break; |
return (MCA_DONE); |
} |
} |
/* |
/* |
* Display a prompt appropriate for the option letter. |
* Display a prompt appropriate for the option letter. |
|
|
buf[2] = '\0'; |
buf[2] = '\0'; |
p = buf; |
p = buf; |
} |
} |
start_mca(A_OPT_TOGGLE, p, (void*)NULL); |
start_mca(A_OPT_TOGGLE, p, (void*)NULL, 0); |
return (MCA_MORE); |
return (MCA_MORE); |
|
|
case A_F_SEARCH: |
case A_F_SEARCH: |
|
|
* Special case for search commands. |
* Special case for search commands. |
* Certain characters as the first char of |
* Certain characters as the first char of |
* the pattern have special meaning: |
* the pattern have special meaning: |
* ! Toggle the NOMATCH flag |
* ! Toggle the NO_MATCH flag |
* * Toggle the PAST_EOF flag |
* * Toggle the PAST_EOF flag |
* @ Toggle the FIRST_FILE flag |
* @ Toggle the FIRST_FILE flag |
*/ |
*/ |
|
|
flag = 0; |
flag = 0; |
switch (c) |
switch (c) |
{ |
{ |
case '!': |
case CONTROL('E'): /* ignore END of file */ |
flag = SRCH_NOMATCH; |
case '*': |
|
flag = SRCH_PAST_EOF; |
break; |
break; |
|
case CONTROL('F'): /* FIRST file */ |
case '@': |
case '@': |
flag = SRCH_FIRST_FILE; |
flag = SRCH_FIRST_FILE; |
break; |
break; |
case '*': |
case CONTROL('K'): /* KEEP position */ |
flag = SRCH_PAST_EOF; |
flag = SRCH_NO_MOVE; |
break; |
break; |
|
case CONTROL('R'): /* Don't use REGULAR EXPRESSIONS */ |
|
flag = SRCH_NO_REGEX; |
|
break; |
|
case CONTROL('N'): /* NOT match */ |
|
case '!': |
|
flag = SRCH_NO_MATCH; |
|
break; |
} |
} |
if (flag != 0) |
if (flag != 0) |
{ |
{ |
|
|
exec_mca(); |
exec_mca(); |
return (MCA_DONE); |
return (MCA_DONE); |
} |
} |
|
|
/* |
/* |
* Append the char to the command buffer. |
* Append the char to the command buffer. |
*/ |
*/ |
|
|
} |
} |
|
|
/* |
/* |
* Display the appropriate prompt. |
* Make sure the screen is displayed. |
*/ |
*/ |
static void |
static void |
prompt() |
make_display() |
{ |
{ |
char *p; |
|
|
|
if (ungotp != NULL && ungotp > ungot) |
|
{ |
|
/* |
|
* No prompt necessary if commands are from |
|
* ungotten chars rather than from the user. |
|
*/ |
|
return; |
|
} |
|
|
|
/* |
/* |
* If nothing is displayed yet, display starting from initial_scrpos. |
* If nothing is displayed yet, display starting from initial_scrpos. |
*/ |
*/ |
|
|
repaint(); |
repaint(); |
top_scroll = save_top_scroll; |
top_scroll = save_top_scroll; |
} |
} |
|
} |
|
|
|
/* |
|
* Display the appropriate prompt. |
|
*/ |
|
static void |
|
prompt() |
|
{ |
|
register char *p; |
|
|
|
if (ungotp != NULL && ungotp > ungot) |
|
{ |
|
/* |
|
* No prompt necessary if commands are from |
|
* ungotten chars rather than from the user. |
|
*/ |
|
return; |
|
} |
|
|
/* |
/* |
|
* Make sure the screen is displayed. |
|
*/ |
|
make_display(); |
|
bottompos = position(BOTTOM_PLUS_ONE); |
|
|
|
/* |
* If the -E flag is set and we've hit EOF on the last file, quit. |
* If the -E flag is set and we've hit EOF on the last file, quit. |
*/ |
*/ |
if (quit_at_eof == OPT_ONPLUS && hit_eof && |
if ((quit_at_eof == OPT_ONPLUS || quit_if_one_screen) && |
|
hit_eof && !(ch_getflags() & CH_HELPFILE) && |
next_ifile(curr_ifile) == NULL_IFILE) |
next_ifile(curr_ifile) == NULL_IFILE) |
quit(QUIT_OK); |
quit(QUIT_OK); |
|
quit_if_one_screen = FALSE; |
|
#if 0 /* This doesn't work well because some "te"s clear the screen. */ |
|
/* |
|
* If the -e flag is set and we've hit EOF on the last file, |
|
* and the file is squished (shorter than the screen), quit. |
|
*/ |
|
if (quit_at_eof && squished && |
|
next_ifile(curr_ifile) == NULL_IFILE) |
|
quit(QUIT_OK); |
|
#endif |
|
|
|
#if MSDOS_COMPILER==WIN32C |
|
/* |
|
* In Win32, display the file name in the window title. |
|
*/ |
|
if (!(ch_getflags() & CH_HELPFILE)) |
|
SetConsoleTitle(pr_expand("Less?f - %f.", 0)); |
|
#endif |
/* |
/* |
* Select the proper prompt and display it. |
* Select the proper prompt and display it. |
*/ |
*/ |
clear_bot(); |
clear_cmd(); |
if (helpprompt) { |
p = help_prompt ? help_prompt : pr_string(); |
|
if (p == NULL) |
|
putchr(':'); |
|
else |
|
{ |
so_enter(); |
so_enter(); |
putstr("[Press 'h' for instructions.]"); |
putstr(p); |
|
if (be_helpful && !help_prompt && strlen(p) + 40 < sc_width) |
|
putstr(" [Press space to continue, 'q' to quit.]"); |
so_exit(); |
so_exit(); |
helpprompt = 0; |
|
} else { |
|
p = pr_string(); |
|
if (p == NULL) |
|
putchr(':'); |
|
else |
|
{ |
|
so_enter(); |
|
putstr(p); |
|
if (be_helpful && strlen(p) + 40 < sc_width) |
|
putstr(" [Press space to continue, 'q' to quit.]"); |
|
so_exit(); |
|
} |
|
} |
} |
|
help_prompt = NULL; |
} |
} |
|
|
|
/* |
|
* Display the less version message. |
|
*/ |
public void |
public void |
dispversion() |
dispversion() |
{ |
{ |
PARG parg; |
PARG parg; |
|
|
parg.p_string = version; |
parg.p_string = version; |
error("less version %s", &parg); |
error("less %s", &parg); |
} |
} |
|
|
/* |
/* |
|
|
ungetsc(s) |
ungetsc(s) |
char *s; |
char *s; |
{ |
{ |
char *p; |
register char *p; |
|
|
for (p = s + strlen(s) - 1; p >= s; p--) |
for (p = s + strlen(s) - 1; p >= s; p--) |
ungetcc(*p); |
ungetcc(*p); |
|
|
char *pattern; |
char *pattern; |
int n; |
int n; |
{ |
{ |
int nomore; |
register int nomore; |
IFILE save_ifile; |
IFILE save_ifile; |
int changed_file; |
int changed_file; |
|
|
changed_file = 0; |
changed_file = 0; |
save_ifile = curr_ifile; |
save_ifile = save_curr_ifile(); |
|
|
if (search_type & SRCH_FIRST_FILE) |
if (search_type & SRCH_FIRST_FILE) |
{ |
{ |
|
|
else |
else |
nomore = edit_last(); |
nomore = edit_last(); |
if (nomore) |
if (nomore) |
|
{ |
|
unsave_ifile(save_ifile); |
return; |
return; |
|
} |
changed_file = 1; |
changed_file = 1; |
search_type &= ~SRCH_FIRST_FILE; |
search_type &= ~SRCH_FIRST_FILE; |
} |
} |
|
|
for (;;) |
for (;;) |
{ |
{ |
if ((n = search(search_type, pattern, n)) == 0) |
n = search(search_type, pattern, n); |
|
/* |
|
* The SRCH_NO_MOVE flag doesn't "stick": it gets cleared |
|
* after being used once. This allows "n" to work after |
|
* using a /@@ search. |
|
*/ |
|
search_type &= ~SRCH_NO_MOVE; |
|
if (n == 0) |
|
{ |
/* |
/* |
* Found it. |
* Found it. |
*/ |
*/ |
|
unsave_ifile(save_ifile); |
return; |
return; |
|
} |
|
|
if (n < 0) |
if (n < 0) |
/* |
/* |
|
|
/* |
/* |
* Restore the file we were originally viewing. |
* Restore the file we were originally viewing. |
*/ |
*/ |
if (edit_ifile(save_ifile)) |
reedit_ifile(save_ifile); |
quit(QUIT_ERROR); |
|
} |
} |
} |
} |
|
|
|
|
public void |
public void |
commands() |
commands() |
{ |
{ |
int c; |
register int c; |
int action; |
register int action; |
char *cbuf; |
register char *cbuf; |
|
int newaction; |
int save_search_type; |
int save_search_type; |
char *s; |
char *extra; |
char tbuf[2]; |
char tbuf[2]; |
PARG parg; |
PARG parg; |
|
IFILE old_ifile; |
|
IFILE new_ifile; |
|
char *tagfile; |
|
|
search_type = SRCH_FORW; |
search_type = SRCH_FORW; |
wscroll = (sc_height + 1) / 2; |
wscroll = (sc_height + 1) / 2; |
|
newaction = A_NOACTION; |
|
|
for (;;) |
for (;;) |
{ |
{ |
|
|
if (quitting) |
if (quitting) |
quit(QUIT_SAVED_STATUS); |
quit(QUIT_SAVED_STATUS); |
} |
} |
|
|
/* |
/* |
|
* See if window size changed, for systems that don't |
|
* generate SIGWINCH. |
|
*/ |
|
check_winch(); |
|
|
|
/* |
* Display prompt and accept a character. |
* Display prompt and accept a character. |
*/ |
*/ |
cmd_reset(); |
cmd_reset(); |
prompt(); |
prompt(); |
if (sigs) |
if (sigs) |
continue; |
continue; |
c = getcc(); |
if (newaction == A_NOACTION) |
|
c = getcc(); |
|
|
again: |
again: |
if (sigs) |
if (sigs) |
continue; |
continue; |
|
|
/* |
if (newaction != A_NOACTION) |
* If we are in a multicharacter command, call mca_char. |
{ |
* Otherwise we call fcmd_decode to determine the |
action = newaction; |
* action to be performed. |
newaction = A_NOACTION; |
*/ |
} else |
if (mca) |
{ |
switch (mca_char(c)) |
/* |
|
* If we are in a multicharacter command, call mca_char. |
|
* Otherwise we call fcmd_decode to determine the |
|
* action to be performed. |
|
*/ |
|
if (mca) |
|
switch (mca_char(c)) |
|
{ |
|
case MCA_MORE: |
|
/* |
|
* Need another character. |
|
*/ |
|
c = getcc(); |
|
goto again; |
|
case MCA_DONE: |
|
/* |
|
* Command has been handled by mca_char. |
|
* Start clean with a prompt. |
|
*/ |
|
continue; |
|
case NO_MCA: |
|
/* |
|
* Not a multi-char command |
|
* (at least, not anymore). |
|
*/ |
|
break; |
|
} |
|
|
|
/* |
|
* Decode the command character and decide what to do. |
|
*/ |
|
if (mca) |
{ |
{ |
case MCA_MORE: |
|
/* |
/* |
* Need another character. |
* We're in a multichar command. |
|
* Add the character to the command buffer |
|
* and display it on the screen. |
|
* If the user backspaces past the start |
|
* of the line, abort the command. |
*/ |
*/ |
c = getcc(); |
if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) |
goto again; |
continue; |
case MCA_DONE: |
cbuf = get_cmdbuf(); |
|
} else |
|
{ |
/* |
/* |
* Command has been handled by mca_char. |
* Don't use cmd_char if we're starting fresh |
* Start clean with a prompt. |
* at the beginning of a command, because we |
|
* don't want to echo the command until we know |
|
* it is a multichar command. We also don't |
|
* want erase_char/kill_char to be treated |
|
* as line editing characters. |
*/ |
*/ |
continue; |
tbuf[0] = c; |
case NO_MCA: |
tbuf[1] = '\0'; |
/* |
cbuf = tbuf; |
* Not a multi-char command |
|
* (at least, not anymore). |
|
*/ |
|
break; |
|
} |
} |
|
extra = NULL; |
/* |
action = fcmd_decode(cbuf, &extra); |
* Decode the command character and decide what to do. |
|
*/ |
|
if (mca) |
|
{ |
|
/* |
/* |
* We're in a multichar command. |
* If an "extra" string was returned, |
* Add the character to the command buffer |
* process it as a string of command characters. |
* and display it on the screen. |
|
* If the user backspaces past the start |
|
* of the line, abort the command. |
|
*/ |
*/ |
if (cmd_char(c) == CC_QUIT || len_cmdbuf() == 0) |
if (extra != NULL) |
continue; |
ungetsc(extra); |
cbuf = get_cmdbuf(); |
|
} else |
|
{ |
|
/* |
|
* Don't use cmd_char if we're starting fresh |
|
* at the beginning of a command, because we |
|
* don't want to echo the command until we know |
|
* it is a multichar command. We also don't |
|
* want erase_char/kill_char to be treated |
|
* as line editing characters. |
|
*/ |
|
tbuf[0] = c; |
|
tbuf[1] = '\0'; |
|
cbuf = tbuf; |
|
} |
} |
s = NULL; |
|
action = fcmd_decode(cbuf, &s); |
|
/* |
/* |
* If an "extra" string was returned, |
|
* process it as a string of command characters. |
|
*/ |
|
if (s != NULL) |
|
ungetsc(s); |
|
/* |
|
* Clear the cmdbuf string. |
* Clear the cmdbuf string. |
* (But not if we're in the prefix of a command, |
* (But not if we're in the prefix of a command, |
* because the partial command string is kept there.) |
* because the partial command string is kept there.) |
|
|
/* |
/* |
* First digit of a number. |
* First digit of a number. |
*/ |
*/ |
start_mca(A_DIGIT, ":", (void*)NULL); |
start_mca(A_DIGIT, ":", (void*)NULL, CF_QUIT_ON_ERASE); |
goto again; |
goto again; |
|
|
case A_F_WINDOW: |
case A_F_WINDOW: |
|
|
* Forward one window (and set the window size). |
* Forward one window (and set the window size). |
*/ |
*/ |
if (number > 0) |
if (number > 0) |
swindow = number; |
swindow = (int) number; |
/* FALLTHRU */ |
/* FALLTHRU */ |
case A_F_SCREEN: |
case A_F_SCREEN: |
/* |
/* |
|
|
if (number <= 0) |
if (number <= 0) |
number = get_swindow(); |
number = get_swindow(); |
cmd_exec(); |
cmd_exec(); |
forward(number, 0, 1); |
if (show_attn) |
|
set_attnpos(bottompos); |
|
forward((int) number, 0, 1); |
break; |
break; |
|
|
case A_B_WINDOW: |
case A_B_WINDOW: |
|
|
* Backward one window (and set the window size). |
* Backward one window (and set the window size). |
*/ |
*/ |
if (number > 0) |
if (number > 0) |
swindow = number; |
swindow = (int) number; |
/* FALLTHRU */ |
/* FALLTHRU */ |
case A_B_SCREEN: |
case A_B_SCREEN: |
/* |
/* |
|
|
if (number <= 0) |
if (number <= 0) |
number = get_swindow(); |
number = get_swindow(); |
cmd_exec(); |
cmd_exec(); |
backward(number, 0, 1); |
backward((int) number, 0, 1); |
break; |
break; |
|
|
case A_F_LINE: |
case A_F_LINE: |
|
|
if (number <= 0) |
if (number <= 0) |
number = 1; |
number = 1; |
cmd_exec(); |
cmd_exec(); |
forward(number, 0, 0); |
if (show_attn == OPT_ONPLUS && number > 1) |
|
set_attnpos(bottompos); |
|
forward((int) number, 0, 0); |
break; |
break; |
|
|
case A_B_LINE: |
case A_B_LINE: |
|
|
if (number <= 0) |
if (number <= 0) |
number = 1; |
number = 1; |
cmd_exec(); |
cmd_exec(); |
backward(number, 0, 0); |
backward((int) number, 0, 0); |
break; |
break; |
|
|
case A_FF_LINE: |
case A_FF_LINE: |
|
|
if (number <= 0) |
if (number <= 0) |
number = 1; |
number = 1; |
cmd_exec(); |
cmd_exec(); |
forward(number, 1, 0); |
if (show_attn == OPT_ONPLUS && number > 1) |
|
set_attnpos(bottompos); |
|
forward((int) number, 1, 0); |
break; |
break; |
|
|
case A_BF_LINE: |
case A_BF_LINE: |
|
|
if (number <= 0) |
if (number <= 0) |
number = 1; |
number = 1; |
cmd_exec(); |
cmd_exec(); |
backward(number, 1, 0); |
backward((int) number, 1, 0); |
break; |
break; |
|
|
|
case A_FF_SCREEN: |
|
/* |
|
* Force forward one screen. |
|
*/ |
|
if (number <= 0) |
|
number = get_swindow(); |
|
cmd_exec(); |
|
if (show_attn == OPT_ONPLUS) |
|
set_attnpos(bottompos); |
|
forward((int) number, 1, 0); |
|
break; |
|
|
case A_F_FOREVER: |
case A_F_FOREVER: |
/* |
/* |
* Forward forever, ignoring EOF. |
* Forward forever, ignoring EOF. |
*/ |
*/ |
|
if (ch_getflags() & CH_HELPFILE) |
|
break; |
cmd_exec(); |
cmd_exec(); |
jump_forw(); |
jump_forw(); |
ignore_eoi = 1; |
ignore_eoi = 1; |
hit_eof = 0; |
hit_eof = 0; |
while (!ABORT_SIGS()) |
while (!sigs) |
forward(1, 0, 0); |
forward(1, 0, 0); |
ignore_eoi = 0; |
ignore_eoi = 0; |
|
/* |
|
* This gets us back in "F mode" after processing |
|
* a non-abort signal (e.g. window-change). |
|
*/ |
|
if (sigs && !ABORT_SIGS()) |
|
newaction = A_F_FOREVER; |
break; |
break; |
|
|
case A_F_SCROLL: |
case A_F_SCROLL: |
|
|
* (default same as last 'd' or 'u' command). |
* (default same as last 'd' or 'u' command). |
*/ |
*/ |
if (number > 0) |
if (number > 0) |
wscroll = number; |
wscroll = (int) number; |
cmd_exec(); |
cmd_exec(); |
|
if (show_attn == OPT_ONPLUS) |
|
set_attnpos(bottompos); |
forward(wscroll, 0, 0); |
forward(wscroll, 0, 0); |
break; |
break; |
|
|
|
|
* (default same as last 'd' or 'u' command). |
* (default same as last 'd' or 'u' command). |
*/ |
*/ |
if (number > 0) |
if (number > 0) |
wscroll = number; |
wscroll = (int) number; |
cmd_exec(); |
cmd_exec(); |
backward(wscroll, 0, 0); |
backward(wscroll, 0, 0); |
break; |
break; |
|
|
{ |
{ |
ch_flush(); |
ch_flush(); |
clr_linenum(); |
clr_linenum(); |
|
#if HILITE_SEARCH |
|
clr_hilite(); |
|
#endif |
} |
} |
/* FALLTHRU */ |
/* FALLTHRU */ |
case A_REPAINT: |
case A_REPAINT: |
|
|
if (number > 100) |
if (number > 100) |
number = 100; |
number = 100; |
cmd_exec(); |
cmd_exec(); |
jump_percent(number); |
jump_percent((int) number); |
break; |
break; |
|
|
case A_GOEND: |
case A_GOEND: |
|
|
cmd_exec(); |
cmd_exec(); |
if (number < 0) |
if (number < 0) |
number = 0; |
number = 0; |
jump_line_loc((POSITION)number, jump_sline); |
jump_line_loc((POSITION) number, jump_sline); |
break; |
break; |
|
|
case A_STAT: |
case A_STAT: |
/* |
/* |
* Print file name, etc. |
* Print file name, etc. |
*/ |
*/ |
|
if (ch_getflags() & CH_HELPFILE) |
|
break; |
cmd_exec(); |
cmd_exec(); |
parg.p_string = eq_message(); |
parg.p_string = eq_message(); |
error("%s", &parg); |
error("%s", &parg); |
break; |
break; |
|
|
case A_VERSION: |
case A_VERSION: |
/* |
/* |
* Print version number, without the "@(#)". |
* Print version number, without the "@(#)". |
|
|
/* |
/* |
* Exit. |
* Exit. |
*/ |
*/ |
|
if (curr_ifile != NULL_IFILE && |
|
ch_getflags() & CH_HELPFILE) |
|
{ |
|
/* |
|
* Quit while viewing the help file |
|
* just means return to viewing the |
|
* previous file. |
|
*/ |
|
if (edit_prev(1) == 0) |
|
break; |
|
} |
|
if (extra != NULL) |
|
quit(*extra); |
quit(QUIT_OK); |
quit(QUIT_OK); |
|
break; |
|
|
/* |
/* |
* Define abbreviation for a commonly used sequence below. |
* Define abbreviation for a commonly used sequence below. |
|
|
#define DO_SEARCH() if (number <= 0) number = 1; \ |
#define DO_SEARCH() if (number <= 0) number = 1; \ |
mca_search(); \ |
mca_search(); \ |
cmd_exec(); \ |
cmd_exec(); \ |
multi_search((char *)NULL, number); |
multi_search((char *)NULL, (int) number); |
|
|
|
|
case A_F_SEARCH: |
case A_F_SEARCH: |
|
|
/* |
/* |
* Help. |
* Help. |
*/ |
*/ |
if (nohelp) |
if (ch_getflags() & CH_HELPFILE) |
{ |
|
bell(); |
|
break; |
break; |
} |
|
clear_bot(); |
|
putstr(" help"); |
|
cmd_exec(); |
cmd_exec(); |
help(0); |
(void) edit(FAKE_HELPFILE); |
break; |
break; |
|
|
case A_EXAMINE: |
case A_EXAMINE: |
|
|
/* |
/* |
* Edit a new file. Get the filename. |
* Edit a new file. Get the filename. |
*/ |
*/ |
start_mca(A_EXAMINE, "Examine: ", ml_examine); |
if (secure) |
|
{ |
|
error("Command not available", NULL_PARG); |
|
break; |
|
} |
|
start_mca(A_EXAMINE, "Examine: ", ml_examine, 0); |
c = getcc(); |
c = getcc(); |
goto again; |
goto again; |
#else |
#else |
|
|
* Invoke an editor on the input file. |
* Invoke an editor on the input file. |
*/ |
*/ |
#if EDITOR |
#if EDITOR |
|
if (secure) |
|
{ |
|
error("Command not available", NULL_PARG); |
|
break; |
|
} |
|
if (ch_getflags() & CH_HELPFILE) |
|
break; |
if (strcmp(get_filename(curr_ifile), "-") == 0) |
if (strcmp(get_filename(curr_ifile), "-") == 0) |
{ |
{ |
error("Cannot edit standard input", NULL_PARG); |
error("Cannot edit standard input", NULL_PARG); |
|
|
NULL_PARG); |
NULL_PARG); |
break; |
break; |
} |
} |
|
start_mca(A_SHELL, "!", ml_shell, 0); |
/* |
/* |
* Expand the editor prototype string |
* Expand the editor prototype string |
* and pass it to the system to execute. |
* and pass it to the system to execute. |
|
* (Make sure the screen is displayed so the |
|
* expansion of "+%lm" works.) |
*/ |
*/ |
|
make_display(); |
cmd_exec(); |
cmd_exec(); |
lsystem(pr_expand(editproto, 0)); |
lsystem(pr_expand(editproto, 0), (char*)NULL); |
/* |
|
* Re-edit the file, since data may have changed. |
|
* Some editors even recreate the file, so flushing |
|
* buffers is not sufficient. |
|
*/ |
|
if (edit_ifile(curr_ifile)) |
|
quit(QUIT_ERROR); |
|
break; |
break; |
#else |
#else |
error("Command not available", NULL_PARG); |
error("Command not available", NULL_PARG); |
|
|
/* |
/* |
* Examine next file. |
* Examine next file. |
*/ |
*/ |
|
#if TAGS |
|
if (ntags()) |
|
{ |
|
error("No next file", NULL_PARG); |
|
break; |
|
} |
|
#endif |
if (number <= 0) |
if (number <= 0) |
number = 1; |
number = 1; |
if (edit_next(number)) |
if (edit_next((int) number)) |
{ |
{ |
if (quit_at_eof && hit_eof) |
if (quit_at_eof && hit_eof && |
|
!(ch_getflags() & CH_HELPFILE)) |
quit(QUIT_OK); |
quit(QUIT_OK); |
parg.p_string = (number > 1) ? "(N-th) " : ""; |
parg.p_string = (number > 1) ? "(N-th) " : ""; |
error("No %snext file", &parg); |
error("No %snext file", &parg); |
|
|
/* |
/* |
* Examine previous file. |
* Examine previous file. |
*/ |
*/ |
|
#if TAGS |
|
if (ntags()) |
|
{ |
|
error("No previous file", NULL_PARG); |
|
break; |
|
} |
|
#endif |
if (number <= 0) |
if (number <= 0) |
number = 1; |
number = 1; |
if (edit_prev(number)) |
if (edit_prev((int) number)) |
{ |
{ |
parg.p_string = (number > 1) ? "(N-th) " : ""; |
parg.p_string = (number > 1) ? "(N-th) " : ""; |
error("No %sprevious file", &parg); |
error("No %sprevious file", &parg); |
} |
} |
break; |
break; |
|
|
|
case A_NEXT_TAG: |
|
#if TAGS |
|
if (number <= 0) |
|
number = 1; |
|
tagfile = nexttag((int) number); |
|
if (tagfile == NULL) |
|
{ |
|
error("No next tag", NULL_PARG); |
|
break; |
|
} |
|
if (edit(tagfile) == 0) |
|
{ |
|
POSITION pos = tagsearch(); |
|
if (pos != NULL_POSITION) |
|
jump_loc(pos, jump_sline); |
|
} |
|
#else |
|
error("Command not available", NULL_PARG); |
|
#endif |
|
break; |
|
|
|
case A_PREV_TAG: |
|
#if TAGS |
|
if (number <= 0) |
|
number = 1; |
|
tagfile = prevtag((int) number); |
|
if (tagfile == NULL) |
|
{ |
|
error("No previous tag", NULL_PARG); |
|
break; |
|
} |
|
if (edit(tagfile) == 0) |
|
{ |
|
POSITION pos = tagsearch(); |
|
if (pos != NULL_POSITION) |
|
jump_loc(pos, jump_sline); |
|
} |
|
#else |
|
error("Command not available", NULL_PARG); |
|
#endif |
|
break; |
|
|
case A_INDEX_FILE: |
case A_INDEX_FILE: |
/* |
/* |
* Examine a particular file. |
* Examine a particular file. |
*/ |
*/ |
if (number <= 0) |
if (number <= 0) |
number = 1; |
number = 1; |
if (edit_index(number)) |
if (edit_index((int) number)) |
error("No such file", NULL_PARG); |
error("No such file", NULL_PARG); |
break; |
break; |
|
|
|
case A_REMOVE_FILE: |
|
if (ch_getflags() & CH_HELPFILE) |
|
break; |
|
old_ifile = curr_ifile; |
|
new_ifile = getoff_ifile(curr_ifile); |
|
if (new_ifile == NULL_IFILE) |
|
{ |
|
bell(); |
|
break; |
|
} |
|
if (edit_ifile(new_ifile) != 0) |
|
{ |
|
reedit_ifile(old_ifile); |
|
break; |
|
} |
|
del_ifile(old_ifile); |
|
break; |
|
|
case A_OPT_TOGGLE: |
case A_OPT_TOGGLE: |
start_mca(A_OPT_TOGGLE, "-", (void*)NULL); |
|
optflag = OPT_TOGGLE; |
optflag = OPT_TOGGLE; |
|
optgetname = FALSE; |
|
mca_opt_toggle(); |
c = getcc(); |
c = getcc(); |
goto again; |
goto again; |
|
|
|
|
/* |
/* |
* Report a flag setting. |
* Report a flag setting. |
*/ |
*/ |
start_mca(A_DISP_OPTION, "_", (void*)NULL); |
optflag = OPT_NO_TOGGLE; |
|
optgetname = FALSE; |
|
mca_opt_toggle(); |
c = getcc(); |
c = getcc(); |
if (c == erase_char || c == kill_char) |
goto again; |
break; |
|
toggle_option(c, "", OPT_NO_TOGGLE); |
|
break; |
|
|
|
case A_FIRSTCMD: |
case A_FIRSTCMD: |
/* |
/* |
* Set an initial command for new files. |
* Set an initial command for new files. |
*/ |
*/ |
start_mca(A_FIRSTCMD, "+", (void*)NULL); |
start_mca(A_FIRSTCMD, "+", (void*)NULL, 0); |
c = getcc(); |
c = getcc(); |
goto again; |
goto again; |
|
|
|
|
* Shell escape. |
* Shell escape. |
*/ |
*/ |
#if SHELL_ESCAPE |
#if SHELL_ESCAPE |
start_mca(A_SHELL, "!", ml_shell); |
if (secure) |
|
{ |
|
error("Command not available", NULL_PARG); |
|
break; |
|
} |
|
start_mca(A_SHELL, "!", ml_shell, 0); |
c = getcc(); |
c = getcc(); |
goto again; |
goto again; |
#else |
#else |
|
|
/* |
/* |
* Set a mark. |
* Set a mark. |
*/ |
*/ |
start_mca(A_SETMARK, "mark: ", (void*)NULL); |
if (ch_getflags() & CH_HELPFILE) |
|
break; |
|
start_mca(A_SETMARK, "mark: ", (void*)NULL, 0); |
c = getcc(); |
c = getcc(); |
if (c == erase_char || c == kill_char || |
if (c == erase_char || c == kill_char || |
c == '\n' || c == '\r') |
c == '\n' || c == '\r') |
|
|
/* |
/* |
* Go to a mark. |
* Go to a mark. |
*/ |
*/ |
start_mca(A_GOMARK, "goto mark: ", (void*)NULL); |
start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0); |
c = getcc(); |
c = getcc(); |
if (c == erase_char || c == kill_char || |
if (c == erase_char || c == kill_char || |
c == '\n' || c == '\r') |
c == '\n' || c == '\r') |
|
|
|
|
case A_PIPE: |
case A_PIPE: |
#if PIPEC |
#if PIPEC |
start_mca(A_PIPE, "|mark: ", (void*)NULL); |
if (secure) |
|
{ |
|
error("Command not available", NULL_PARG); |
|
break; |
|
} |
|
start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); |
c = getcc(); |
c = getcc(); |
if (c == erase_char || c == kill_char) |
if (c == erase_char || c == kill_char) |
break; |
break; |
|
|
if (badmark(c)) |
if (badmark(c)) |
break; |
break; |
pipec = c; |
pipec = c; |
start_mca(A_PIPE, "!", ml_shell); |
start_mca(A_PIPE, "!", ml_shell, 0); |
c = getcc(); |
c = getcc(); |
goto again; |
goto again; |
#else |
#else |
|
|
|
|
case A_B_BRACKET: |
case A_B_BRACKET: |
case A_F_BRACKET: |
case A_F_BRACKET: |
start_mca(action, "Brackets: ", (void*)NULL); |
start_mca(action, "Brackets: ", (void*)NULL, 0); |
c = getcc(); |
c = getcc(); |
goto again; |
goto again; |
|
|
|
case A_LSHIFT: |
|
if (number > 0) |
|
shift_count = number; |
|
else |
|
number = (shift_count > 0) ? |
|
shift_count : sc_width / 2; |
|
if (number > hshift) |
|
number = hshift; |
|
hshift -= number; |
|
screen_trashed = 1; |
|
break; |
|
|
|
case A_RSHIFT: |
|
if (number > 0) |
|
shift_count = number; |
|
else |
|
number = (shift_count > 0) ? |
|
shift_count : sc_width / 2; |
|
hshift += number; |
|
screen_trashed = 1; |
|
break; |
|
|
case A_PREFIX: |
case A_PREFIX: |
/* |
/* |
* The command is incomplete (more chars are needed). |
* The command is incomplete (more chars are needed). |
|
|
*/ |
*/ |
if (mca != A_PREFIX) |
if (mca != A_PREFIX) |
{ |
{ |
start_mca(A_PREFIX, " ", (void*)NULL); |
|
cmd_reset(); |
cmd_reset(); |
|
start_mca(A_PREFIX, " ", (void*)NULL, |
|
CF_QUIT_ON_ERASE); |
(void) cmd_char(c); |
(void) cmd_char(c); |
} |
} |
c = getcc(); |
c = getcc(); |
|
|
|
|
default: |
default: |
if (be_helpful) |
if (be_helpful) |
helpprompt = 1; |
help_prompt = "[Press 'h' for instructions.]"; |
else |
else |
bell(); |
bell(); |
break; |
break; |