version 1.8, 2003/04/14 15:09:57 |
version 1.9, 2011/09/16 18:12:09 |
|
|
/* |
/* |
* Copyright (C) 1984-2002 Mark Nudelman |
* Copyright (C) 1984-2011 Mark Nudelman |
* |
* |
* You may distribute under the terms of either the GNU General Public |
* You may distribute under the terms of either the GNU General Public |
* License or the Less License, as specified in the README file. |
* License or the Less License, as specified in the README file. |
|
|
#include "option.h" |
#include "option.h" |
#include "cmd.h" |
#include "cmd.h" |
|
|
extern int erase_char, kill_char; |
extern int erase_char, erase2_char, kill_char; |
extern int sigs; |
extern int sigs; |
extern int quit_at_eof; |
|
extern int quit_if_one_screen; |
extern int quit_if_one_screen; |
extern int squished; |
extern int squished; |
extern int hit_eof; |
|
extern int sc_width; |
extern int sc_width; |
extern int sc_height; |
extern int sc_height; |
extern int swindow; |
extern int swindow; |
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 secure; |
|
|
#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 shift_count; |
|
extern int oldbot; |
|
extern int forw_prompt; |
extern int be_helpful; |
extern int be_helpful; |
|
|
static char ungot[UNGOT_SIZE]; |
|
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 LINENUM number; /* The number typed by the user */ |
static LINENUM number; /* The number typed by the user */ |
static char optchar; |
static long fraction; /* The fractional part of the number */ |
|
static struct loption *curropt; |
|
static int opt_lower; |
static int optflag; |
static int optflag; |
static int optgetname; |
static int optgetname; |
static POSITION bottompos; |
static POSITION bottompos; |
|
static int save_hshift; |
static char *help_prompt; |
static char *help_prompt; |
#if PIPEC |
#if PIPEC |
static char pipec; |
static char pipec; |
#endif |
#endif |
|
|
|
struct ungot { |
|
struct ungot *ug_next; |
|
char ug_char; |
|
}; |
|
static struct ungot* ungot = NULL; |
|
static int unget_end = 0; |
|
|
static void multi_search(); |
static void multi_search(); |
|
|
/* |
/* |
* Move the cursor to lower left before executing a command. |
* Move the cursor to start of prompt line before executing a command. |
* This looks nicer if the command takes a long time before |
* This looks nicer if the command takes a long time before |
* updating the screen. |
* updating the screen. |
*/ |
*/ |
static void |
static void |
cmd_exec() |
cmd_exec() |
{ |
{ |
|
#if HILITE_SEARCH |
clear_attn(); |
clear_attn(); |
lower_left(); |
#endif |
|
clear_bot(); |
flush(); |
flush(); |
} |
} |
|
|
|
|
int cmdflags; |
int cmdflags; |
{ |
{ |
mca = action; |
mca = action; |
|
clear_bot(); |
clear_cmd(); |
clear_cmd(); |
cmd_putstr(prompt); |
cmd_putstr(prompt); |
set_mlist(mlist, cmdflags); |
set_mlist(mlist, cmdflags); |
|
|
static void |
static void |
mca_search() |
mca_search() |
{ |
{ |
|
#if HILITE_SEARCH |
|
if (search_type & SRCH_FILTER) |
|
mca = A_FILTER; |
|
else |
|
#endif |
if (search_type & SRCH_FORW) |
if (search_type & SRCH_FORW) |
mca = A_F_SEARCH; |
mca = A_F_SEARCH; |
else |
else |
mca = A_B_SEARCH; |
mca = A_B_SEARCH; |
|
|
|
clear_bot(); |
clear_cmd(); |
clear_cmd(); |
|
|
if (search_type & SRCH_NO_MATCH) |
if (search_type & SRCH_NO_MATCH) |
|
|
if (search_type & SRCH_NO_REGEX) |
if (search_type & SRCH_NO_REGEX) |
cmd_putstr("Regex-off "); |
cmd_putstr("Regex-off "); |
|
|
|
#if HILITE_SEARCH |
|
if (search_type & SRCH_FILTER) |
|
cmd_putstr("&/"); |
|
else |
|
#endif |
if (search_type & SRCH_FORW) |
if (search_type & SRCH_FORW) |
cmd_putstr("/"); |
cmd_putstr("/"); |
else |
else |
|
|
dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; |
dash = (flag == OPT_NO_TOGGLE) ? "_" : "-"; |
|
|
mca = A_OPT_TOGGLE; |
mca = A_OPT_TOGGLE; |
|
clear_bot(); |
clear_cmd(); |
clear_cmd(); |
cmd_putstr(dash); |
cmd_putstr(dash); |
#if GNU_OPTIONS |
#if GNU_OPTIONS |
|
|
case A_B_SEARCH: |
case A_B_SEARCH: |
multi_search(cbuf, (int) number); |
multi_search(cbuf, (int) number); |
break; |
break; |
|
#if HILITE_SEARCH |
|
case A_FILTER: |
|
search_type ^= SRCH_NO_MATCH; |
|
set_filter_pattern(cbuf, search_type); |
|
break; |
|
#endif |
case A_FIRSTCMD: |
case A_FIRSTCMD: |
/* |
/* |
* Skip leading spaces or + signs in the string. |
* Skip leading spaces or + signs in the string. |
|
|
every_first_cmd = save(cbuf); |
every_first_cmd = save(cbuf); |
break; |
break; |
case A_OPT_TOGGLE: |
case A_OPT_TOGGLE: |
toggle_option(optchar, cbuf, optflag); |
toggle_option(curropt, opt_lower, cbuf, optflag); |
optchar = '\0'; |
curropt = NULL; |
break; |
break; |
case A_F_BRACKET: |
case A_F_BRACKET: |
match_brac(cbuf[0], cbuf[1], 1, (int) number); |
match_brac(cbuf[0], cbuf[1], 1, (int) number); |
|
|
} |
} |
|
|
/* |
/* |
* Add a character to a multi-character command. |
* Is a character an erase or kill char? |
*/ |
*/ |
static int |
static int |
mca_char(c) |
is_erase_char(c) |
int c; |
int c; |
{ |
{ |
|
return (c == erase_char || c == erase2_char || c == kill_char); |
|
} |
|
|
|
/* |
|
* Handle the first char of an option (after the initial dash). |
|
*/ |
|
static int |
|
mca_opt_first_char(c) |
|
int c; |
|
{ |
|
int flag = (optflag & ~OPT_NO_PROMPT); |
|
#if GNU_OPTIONS |
|
if (flag == OPT_NO_TOGGLE) |
|
{ |
|
switch (c) |
|
{ |
|
case '_': |
|
/* "__" = long option name. */ |
|
optgetname = TRUE; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
} |
|
} else |
|
#endif |
|
{ |
|
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); |
|
#if GNU_OPTIONS |
|
case '-': |
|
/* "--" = long option name. */ |
|
optgetname = TRUE; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
#endif |
|
} |
|
} |
|
/* Char was not handled here. */ |
|
return (NO_MCA); |
|
} |
|
|
|
#if GNU_OPTIONS |
|
/* |
|
* Add a char to a long option name. |
|
* See if we've got a match for an option name yet. |
|
* If so, display the complete name and stop |
|
* accepting chars until user hits RETURN. |
|
*/ |
|
static int |
|
mca_opt_nonfirst_char(c) |
|
int c; |
|
{ |
char *p; |
char *p; |
int flag; |
char *oname; |
char buf[3]; |
|
|
if (curropt != NULL) |
|
{ |
|
/* |
|
* Already have a match for the name. |
|
* Don't accept anything but erase/kill. |
|
*/ |
|
if (is_erase_char(c)) |
|
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(); |
|
opt_lower = ASCII_IS_LOWER(p[0]); |
|
curropt = findopt_name(&p, &oname, NULL); |
|
if (curropt != NULL) |
|
{ |
|
/* |
|
* Got a match. |
|
* Remember the option and |
|
* display the full option name. |
|
*/ |
|
cmd_reset(); |
|
mca_opt_toggle(); |
|
for (p = oname; *p != '\0'; p++) |
|
{ |
|
c = *p; |
|
if (!opt_lower && ASCII_IS_LOWER(c)) |
|
c = ASCII_TO_UPPER(c); |
|
if (cmd_char(c) != CC_OK) |
|
return (MCA_DONE); |
|
} |
|
} |
|
return (MCA_MORE); |
|
} |
|
#endif |
|
|
|
/* |
|
* Handle a char of an option toggle command. |
|
*/ |
|
static int |
|
mca_opt_char(c) |
|
int c; |
|
{ |
PARG parg; |
PARG parg; |
|
|
|
/* |
|
* This may be a short option (single char), |
|
* or one char of a long option name, |
|
* or one char of the option parameter. |
|
*/ |
|
if (curropt == NULL && len_cmdbuf() == 0) |
|
{ |
|
int ret = mca_opt_first_char(c); |
|
if (ret != NO_MCA) |
|
return (ret); |
|
} |
|
#if GNU_OPTIONS |
|
if (optgetname) |
|
{ |
|
/* We're getting a long option name. */ |
|
if (c != '\n' && c != '\r') |
|
return (mca_opt_nonfirst_char(c)); |
|
if (curropt == NULL) |
|
{ |
|
parg.p_string = get_cmdbuf(); |
|
error("There is no --%s option", &parg); |
|
return (MCA_DONE); |
|
} |
|
optgetname = FALSE; |
|
cmd_reset(); |
|
} else |
|
#endif |
|
{ |
|
if (is_erase_char(c)) |
|
return (NO_MCA); |
|
if (curropt != NULL) |
|
/* We're getting the option parameter. */ |
|
return (NO_MCA); |
|
curropt = findopt(c); |
|
if (curropt == NULL) |
|
{ |
|
parg.p_string = propt(c); |
|
error("There is no %s option", &parg); |
|
return (MCA_DONE); |
|
} |
|
} |
|
/* |
|
* If the option which was entered does not take a |
|
* parameter, toggle the option immediately, |
|
* so user doesn't have to hit RETURN. |
|
*/ |
|
if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || |
|
!opt_has_param(curropt)) |
|
{ |
|
toggle_option(curropt, ASCII_IS_LOWER(c), "", optflag); |
|
return (MCA_DONE); |
|
} |
|
/* |
|
* Display a prompt appropriate for the option parameter. |
|
*/ |
|
start_mca(A_OPT_TOGGLE, opt_prompt(curropt), (void*)NULL, 0); |
|
return (MCA_MORE); |
|
} |
|
|
|
/* |
|
* Handle a char of a search command. |
|
*/ |
|
static int |
|
mca_search_char(c) |
|
int c; |
|
{ |
|
int flag = 0; |
|
|
|
/* |
|
* Certain characters as the first char of |
|
* the pattern have special meaning: |
|
* ! Toggle the NO_MATCH flag |
|
* * Toggle the PAST_EOF flag |
|
* @ Toggle the FIRST_FILE flag |
|
*/ |
|
if (len_cmdbuf() > 0) |
|
return (NO_MCA); |
|
|
|
switch (c) |
|
{ |
|
case CONTROL('E'): /* ignore END of file */ |
|
case '*': |
|
if (mca != A_FILTER) |
|
flag = SRCH_PAST_EOF; |
|
break; |
|
case CONTROL('F'): /* FIRST file */ |
|
case '@': |
|
if (mca != A_FILTER) |
|
flag = SRCH_FIRST_FILE; |
|
break; |
|
case CONTROL('K'): /* KEEP position */ |
|
if (mca != A_FILTER) |
|
flag = SRCH_NO_MOVE; |
|
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) |
|
{ |
|
search_type ^= flag; |
|
mca_search(); |
|
return (MCA_MORE); |
|
} |
|
return (NO_MCA); |
|
} |
|
|
|
/* |
|
* Handle a character of a multi-character command. |
|
*/ |
|
static int |
|
mca_char(c) |
|
int c; |
|
{ |
|
int ret; |
|
|
switch (mca) |
switch (mca) |
{ |
{ |
case 0: |
case 0: |
/* |
/* |
* Not in a multicharacter command. |
* We're not in a multicharacter command. |
*/ |
*/ |
return (NO_MCA); |
return (NO_MCA); |
|
|
|
|
* Entering digits of a number. |
* Entering digits of a number. |
* Terminated by a non-digit. |
* Terminated by a non-digit. |
*/ |
*/ |
if ((c < '0' || c > '9') && |
if (!((c >= '0' && c <= '9') || c == '.') && |
editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID) |
editchar(c, EC_PEEK|EC_NOHISTORY|EC_NOCOMPLETE|EC_NORIGHTLEFT) == A_INVALID) |
{ |
{ |
/* |
/* |
* Not part of the number. |
* Not part of the number. |
* Treat as a normal command character. |
* End the number and treat this char |
|
* as a normal command character. |
*/ |
*/ |
number = cmd_int(); |
number = cmd_int(&fraction); |
mca = 0; |
mca = 0; |
cmd_accept(); |
cmd_accept(); |
return (NO_MCA); |
return (NO_MCA); |
|
|
break; |
break; |
|
|
case A_OPT_TOGGLE: |
case A_OPT_TOGGLE: |
/* |
ret = mca_opt_char(c); |
* Special case for the TOGGLE_OPTION command. |
if (ret != NO_MCA) |
* If the option letter which was entered is a |
return (ret); |
* single-char option, execute the command immediately, |
break; |
* so user doesn't have to hit RETURN. |
|
* If the first char is + or -, this indicates |
|
* OPT_UNSET or OPT_SET respectively, instead of OPT_TOGGLE. |
|
* "--" begins inputting a long option name. |
|
*/ |
|
if (optchar == '\0' && len_cmdbuf() == 0) |
|
{ |
|
flag = (optflag & ~OPT_NO_PROMPT); |
|
#if GNU_OPTIONS |
|
if (flag == OPT_NO_TOGGLE) |
|
{ |
|
switch (c) |
|
{ |
|
case '_': |
|
/* "__" = long option name. */ |
|
optgetname = TRUE; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
} |
|
} else |
|
#endif |
|
{ |
|
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); |
|
#if GNU_OPTIONS |
|
case '-': |
|
/* "--" = long option name. */ |
|
optgetname = TRUE; |
|
mca_opt_toggle(); |
|
return (MCA_MORE); |
|
#endif |
|
} |
|
} |
|
} |
|
#if GNU_OPTIONS |
|
if (optgetname) |
|
{ |
|
/* |
|
* 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. |
|
*/ |
|
struct loption *o; |
|
char *oname; |
|
int lc; |
|
|
|
if (c == '\n' || c == '\r') |
|
{ |
|
/* |
|
* 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); |
|
} |
|
} else |
|
#endif |
|
{ |
|
if (c == erase_char || c == kill_char) |
|
break; |
|
if (optchar != '\0') |
|
/* We already have the option letter. */ |
|
break; |
|
} |
|
|
|
optchar = c; |
|
if ((optflag & ~OPT_NO_PROMPT) != OPT_TOGGLE || |
|
single_char_option(c)) |
|
{ |
|
toggle_option(c, "", optflag); |
|
return (MCA_DONE); |
|
} |
|
/* |
|
* Display a prompt appropriate for the option letter. |
|
*/ |
|
if ((p = opt_prompt(c)) == NULL) |
|
{ |
|
buf[0] = '-'; |
|
buf[1] = c; |
|
buf[2] = '\0'; |
|
p = buf; |
|
} |
|
start_mca(A_OPT_TOGGLE, p, (void*)NULL, 0); |
|
return (MCA_MORE); |
|
|
|
case A_F_SEARCH: |
case A_F_SEARCH: |
case A_B_SEARCH: |
case A_B_SEARCH: |
/* |
case A_FILTER: |
* Special case for search commands. |
ret = mca_search_char(c); |
* Certain characters as the first char of |
if (ret != NO_MCA) |
* the pattern have special meaning: |
return (ret); |
* ! Toggle the NO_MATCH flag |
break; |
* * Toggle the PAST_EOF flag |
|
* @ Toggle the FIRST_FILE flag |
|
*/ |
|
if (len_cmdbuf() > 0) |
|
/* |
|
* Only works for the first char of the pattern. |
|
*/ |
|
break; |
|
|
|
flag = 0; |
default: |
switch (c) |
/* Other multicharacter command. */ |
{ |
|
case CONTROL('E'): /* ignore END of file */ |
|
case '*': |
|
flag = SRCH_PAST_EOF; |
|
break; |
|
case CONTROL('F'): /* FIRST file */ |
|
case '@': |
|
flag = SRCH_FIRST_FILE; |
|
break; |
|
case CONTROL('K'): /* KEEP position */ |
|
flag = SRCH_NO_MOVE; |
|
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) |
|
{ |
|
search_type ^= flag; |
|
mca_search(); |
|
return (MCA_MORE); |
|
} |
|
break; |
break; |
} |
} |
|
|
/* |
/* |
* Any other multicharacter command |
* The multichar command is terminated by a newline. |
* is terminated by a newline. |
|
*/ |
*/ |
if (c == '\n' || c == '\r') |
if (c == '\n' || c == '\r') |
{ |
{ |
|
|
} |
} |
|
|
/* |
/* |
|
* Discard any buffered file data. |
|
*/ |
|
static void |
|
clear_buffers() |
|
{ |
|
if (!(ch_getflags() & CH_CANSEEK)) |
|
return; |
|
ch_flush(); |
|
clr_linenum(); |
|
#if HILITE_SEARCH |
|
clr_hilite(); |
|
#endif |
|
} |
|
|
|
/* |
* Make sure the screen is displayed. |
* Make sure the screen is displayed. |
*/ |
*/ |
static void |
static void |
|
|
jump_loc(initial_scrpos.pos, initial_scrpos.ln); |
jump_loc(initial_scrpos.pos, initial_scrpos.ln); |
} else if (screen_trashed) |
} else if (screen_trashed) |
{ |
{ |
int save_top_scroll; |
int save_top_scroll = top_scroll; |
save_top_scroll = top_scroll; |
int save_ignore_eoi = ignore_eoi; |
top_scroll = 1; |
top_scroll = 1; |
|
ignore_eoi = 0; |
|
if (screen_trashed == 2) |
|
{ |
|
/* Special case used by ignore_eoi: re-open the input file |
|
* and jump to the end of the file. */ |
|
reopen_curr_ifile(); |
|
jump_forw(); |
|
} |
repaint(); |
repaint(); |
top_scroll = save_top_scroll; |
top_scroll = save_top_scroll; |
|
ignore_eoi = save_ignore_eoi; |
} |
} |
} |
} |
|
|
|
|
{ |
{ |
register char *p; |
register char *p; |
|
|
if (ungotp != NULL && ungotp > ungot) |
if (ungot != NULL) |
{ |
{ |
/* |
/* |
* No prompt necessary if commands are from |
* No prompt necessary if commands are from |
|
|
bottompos = position(BOTTOM_PLUS_ONE); |
bottompos = position(BOTTOM_PLUS_ONE); |
|
|
/* |
/* |
* If the -E flag is set and we've hit EOF on the last file, quit. |
* If we've hit EOF on the last file and the -E flag is set, quit. |
*/ |
*/ |
if ((quit_at_eof == OPT_ONPLUS || quit_if_one_screen) && |
if (get_quit_at_eof() == OPT_ONPLUS && |
hit_eof && next_ifile(curr_ifile) == NULL_IFILE) |
eof_displayed() && !(ch_getflags() & CH_HELPFILE) && |
|
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, |
* If the entire file is displayed and the -F flag is set, quit. |
* and the file is squished (shorter than the screen), quit. |
|
*/ |
*/ |
if (quit_at_eof && squished && |
if (quit_if_one_screen && |
|
entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) && |
next_ifile(curr_ifile) == NULL_IFILE) |
next_ifile(curr_ifile) == NULL_IFILE) |
quit(QUIT_OK); |
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. |
*/ |
*/ |
|
/* |
|
* If the previous action was a forward movement, |
|
* don't clear the bottom line of the display; |
|
* just print the prompt since the forward movement guarantees |
|
* that we're in the right position to display the prompt. |
|
* Clearing the line could cause a problem: for example, if the last |
|
* line displayed ended at the right screen edge without a newline, |
|
* then clearing would clear the last displayed line rather than |
|
* the prompt line. |
|
*/ |
|
if (!forw_prompt) |
|
clear_bot(); |
clear_cmd(); |
clear_cmd(); |
|
forw_prompt = 0; |
p = help_prompt ? help_prompt : pr_string(); |
p = help_prompt ? help_prompt : pr_string(); |
if (p == NULL) |
if (is_filtering()) |
|
putstr("& "); |
|
if (p == NULL || *p == '\0') |
putchr(':'); |
putchr(':'); |
else |
else |
{ |
{ |
so_enter(); |
at_enter(AT_STANDOUT); |
putstr(p); |
putstr(p); |
if (be_helpful && !help_prompt && strlen(p) + 40 < sc_width) |
if (be_helpful && !help_prompt && strlen(p) + 40 < sc_width) |
putstr(" [Press space to continue, 'q' to quit.]"); |
putstr(" [Press space to continue, 'q' to quit.]"); |
so_exit(); |
at_exit(); |
} |
} |
help_prompt = NULL; |
help_prompt = NULL; |
|
clear_eol(); |
} |
} |
|
|
/* |
/* |
|
|
public int |
public int |
getcc() |
getcc() |
{ |
{ |
if (ungotp == NULL) |
if (unget_end) |
|
{ |
/* |
/* |
* Normal case: no ungotten chars, so get one from the user. |
* We have just run out of ungotten chars. |
*/ |
*/ |
return (getchr()); |
unget_end = 0; |
|
if (len_cmdbuf() == 0 || !empty_screen()) |
if (ungotp > ungot) |
return (getchr()); |
/* |
/* |
* Return the next ungotten char. |
* Command is incomplete, so try to complete it. |
*/ |
*/ |
return (*--ungotp); |
switch (mca) |
|
{ |
|
case A_DIGIT: |
|
/* |
|
* We have a number but no command. Treat as #g. |
|
*/ |
|
return ('g'); |
|
|
/* |
case A_F_SEARCH: |
* We have just run out of ungotten chars. |
case A_B_SEARCH: |
*/ |
/* |
ungotp = NULL; |
* We have "/string" but no newline. Add the \n. |
if (len_cmdbuf() == 0 || !empty_screen()) |
*/ |
return (getchr()); |
return ('\n'); |
/* |
|
* 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: |
default: |
case A_B_SEARCH: |
/* |
/* |
* Some other incomplete command. Let user complete it. |
* We have "/string" but no newline. Add the \n. |
*/ |
*/ |
return (getchr()); |
return ('\n'); |
} |
|
} |
|
|
default: |
if (ungot == NULL) |
|
{ |
/* |
/* |
* Some other incomplete command. Let user complete it. |
* Normal case: no ungotten chars, so get one from the user. |
*/ |
*/ |
return (getchr()); |
return (getchr()); |
} |
} |
|
|
|
/* |
|
* Return the next ungotten char. |
|
*/ |
|
{ |
|
struct ungot *ug = ungot; |
|
char c = ug->ug_char; |
|
ungot = ug->ug_next; |
|
free(ug); |
|
unget_end = (ungot == NULL); |
|
return (c); |
|
} |
} |
} |
|
|
/* |
/* |
|
|
ungetcc(c) |
ungetcc(c) |
int c; |
int c; |
{ |
{ |
if (ungotp == NULL) |
struct ungot *ug = (struct ungot *) ecalloc(1, sizeof(struct ungot)); |
ungotp = ungot; |
|
if (ungotp >= ungot + sizeof(ungot)) |
ug->ug_char = c; |
{ |
ug->ug_next = ungot; |
error("ungetcc overflow", NULL_PARG); |
ungot = ug; |
quit(QUIT_ERROR); |
unget_end = 0; |
} |
|
*ungotp++ = c; |
|
} |
} |
|
|
/* |
/* |
|
|
* Restore the file we were originally viewing. |
* Restore the file we were originally viewing. |
*/ |
*/ |
reedit_ifile(save_ifile); |
reedit_ifile(save_ifile); |
|
} else |
|
{ |
|
unsave_ifile(save_ifile); |
} |
} |
} |
} |
|
|
|
|
mca = 0; |
mca = 0; |
cmd_accept(); |
cmd_accept(); |
number = 0; |
number = 0; |
optchar = '\0'; |
curropt = NULL; |
|
|
/* |
/* |
* See if any signals need processing. |
* See if any signals need processing. |
|
|
/* |
/* |
* 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; |
|
while (!sigs) |
while (!sigs) |
|
{ |
|
make_display(); |
forward(1, 0, 0); |
forward(1, 0, 0); |
|
} |
ignore_eoi = 0; |
ignore_eoi = 0; |
/* |
/* |
* This gets us back in "F mode" after processing |
* This gets us back in "F mode" after processing |
|
|
* Flush buffers, then repaint screen. |
* Flush buffers, then repaint screen. |
* Don't flush the buffers on a pipe! |
* Don't flush the buffers on a pipe! |
*/ |
*/ |
if (ch_getflags() & CH_CANSEEK) |
clear_buffers(); |
{ |
|
ch_flush(); |
|
clr_linenum(); |
|
#if HILITE_SEARCH |
|
clr_hilite(); |
|
#endif |
|
} |
|
/* FALLTHRU */ |
/* FALLTHRU */ |
case A_REPAINT: |
case A_REPAINT: |
/* |
/* |
|
|
* Go to a specified percentage into the file. |
* Go to a specified percentage into the file. |
*/ |
*/ |
if (number < 0) |
if (number < 0) |
|
{ |
number = 0; |
number = 0; |
|
fraction = 0; |
|
} |
if (number > 100) |
if (number > 100) |
|
{ |
number = 100; |
number = 100; |
|
fraction = 0; |
|
} |
cmd_exec(); |
cmd_exec(); |
jump_percent((int) number); |
jump_percent((int) number, fraction); |
break; |
break; |
|
|
case A_GOEND: |
case A_GOEND: |
|
|
/* |
/* |
* 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); |
|
|
/* |
/* |
* Exit. |
* Exit. |
*/ |
*/ |
|
#if !SMALL |
|
if (curr_ifile != NULL_IFILE && |
|
ch_getflags() & CH_HELPFILE) |
|
{ |
|
/* |
|
* Quit while viewing the help file |
|
* just means return to viewing the |
|
* previous file. |
|
*/ |
|
hshift = save_hshift; |
|
if (edit_prev(1) == 0) |
|
break; |
|
} |
|
#endif /* !SMALL */ |
if (extra != NULL) |
if (extra != NULL) |
quit(*extra); |
quit(*extra); |
quit(QUIT_OK); |
quit(QUIT_OK); |
|
|
/* |
/* |
* 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, (int) number); |
multi_search((char *)NULL, (int) number); |
|
|
c = getcc(); |
c = getcc(); |
goto again; |
goto again; |
|
|
|
case A_FILTER: |
|
#if HILITE_SEARCH |
|
search_type = SRCH_FORW | SRCH_FILTER; |
|
mca_search(); |
|
c = getcc(); |
|
goto again; |
|
#else |
|
error("Command not available", NULL_PARG); |
|
break; |
|
#endif |
|
|
case A_AGAIN_SEARCH: |
case A_AGAIN_SEARCH: |
/* |
/* |
* Repeat previous search. |
* Repeat previous search. |
|
|
break; |
break; |
|
|
case A_HELP: |
case A_HELP: |
|
#if !SMALL |
/* |
/* |
* Help. |
* Help. |
*/ |
*/ |
if (nohelp) |
if (ch_getflags() & CH_HELPFILE) |
{ |
|
bell(); |
|
break; |
break; |
} |
|
clear_bot(); |
|
putstr(" help"); |
|
cmd_exec(); |
cmd_exec(); |
help(0); |
save_hshift = hshift; |
|
hshift = 0; |
|
(void) edit(HELPFILE); |
|
#endif /* !SMALL */ |
break; |
break; |
|
|
case A_EXAMINE: |
case A_EXAMINE: |
|
|
error("Command not available", NULL_PARG); |
error("Command not available", NULL_PARG); |
break; |
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); |
|
|
} |
} |
if (curr_altfilename != NULL) |
if (curr_altfilename != NULL) |
{ |
{ |
error("Cannot edit file processed with LESSOPEN", |
error("WARNING: This file was viewed via LESSOPEN", |
NULL_PARG); |
NULL_PARG); |
break; |
|
} |
} |
start_mca(A_SHELL, "!", ml_shell, 0); |
start_mca(A_SHELL, "!", ml_shell, 0); |
/* |
/* |
|
|
number = 1; |
number = 1; |
if (edit_next((int) number)) |
if (edit_next((int) number)) |
{ |
{ |
if (quit_at_eof && hit_eof) |
if (get_quit_at_eof() && eof_displayed() && |
|
!(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); |
|
|
break; |
break; |
|
|
case A_REMOVE_FILE: |
case A_REMOVE_FILE: |
|
if (ch_getflags() & CH_HELPFILE) |
|
break; |
old_ifile = curr_ifile; |
old_ifile = curr_ifile; |
new_ifile = getoff_ifile(curr_ifile); |
new_ifile = getoff_ifile(curr_ifile); |
if (new_ifile == NULL_IFILE) |
if (new_ifile == NULL_IFILE) |
|
|
/* |
/* |
* Set a mark. |
* Set a mark. |
*/ |
*/ |
|
if (ch_getflags() & CH_HELPFILE) |
|
break; |
start_mca(A_SETMARK, "mark: ", (void*)NULL, 0); |
start_mca(A_SETMARK, "mark: ", (void*)NULL, 0); |
c = getcc(); |
c = getcc(); |
if (c == erase_char || c == kill_char || |
if (c == erase_char || c == erase2_char || |
c == '\n' || c == '\r') |
c == kill_char || c == '\n' || c == '\r') |
break; |
break; |
setmark(c); |
setmark(c); |
break; |
break; |
|
|
*/ |
*/ |
start_mca(A_GOMARK, "goto mark: ", (void*)NULL, 0); |
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 == erase2_char || |
c == '\n' || c == '\r') |
c == kill_char || c == '\n' || c == '\r') |
break; |
break; |
|
cmd_exec(); |
gomark(c); |
gomark(c); |
break; |
break; |
|
|
|
|
} |
} |
start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); |
start_mca(A_PIPE, "|mark: ", (void*)NULL, 0); |
c = getcc(); |
c = getcc(); |
if (c == erase_char || c == kill_char) |
if (c == erase_char || c == erase2_char || c == kill_char) |
break; |
break; |
if (c == '\n' || c == '\r') |
if (c == '\n' || c == '\r') |
c = '.'; |
c = '.'; |