more: add display_file() to show files and stdin

Earlier main() inline code implemented input files and stdin displaying
separately.  With small restructuring this code can be shared.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2020-03-28 07:50:43 +00:00
parent 22ff9a38cb
commit 63f96f682f
No known key found for this signature in database
GPG Key ID: 0D46FEF7E61DBB46
1 changed files with 72 additions and 84 deletions

View File

@ -167,6 +167,7 @@ struct more_control {
bad_stdout:1, /* true if overwriting does not turn off standout */
catch_suspend:1, /* we should catch the SIGTSTP signal */
clear_line_ends:1, /* do not scroll, paint each screen from the top */
clear_first:1, /* is first character in file \f */
dumb_tty:1, /* is terminal type known */
eat_newline:1, /* is newline ignored after 80 cols */
enable_underlining:1, /* underline as best we can */
@ -176,13 +177,16 @@ struct more_control {
fold_long_lines:1, /* fold long lines */
hard_tabs:1, /* print spaces instead of '\t' */
hard_tty:1, /* is this hard copy terminal (a printer or such) */
jump_at_start:1, /* jump to line N defined at start up */
is_paused:1, /* is output paused */
no_quit_dialog:1, /* suppress quit dialog */
no_scroll:1, /* do not scroll, clear the screen and then display text */
no_tty_in:1, /* is input in interactive mode */
no_tty_out:1, /* is output in interactive mode */
print_banner:1, /* print file name banner */
report_errors:1, /* is an error reported */
run_previous_command:1, /* run previous key command */
search_at_start:1, /* search pattern defined at start up */
search_called:1, /* previous more command was a search */
squeeze_spaces:1, /* suppress white space */
stdout_glitch:1, /* terminal has standout mode glitch */
@ -332,7 +336,7 @@ static int check_magic(FILE *f, char *fs)
/* Check whether the file named by fs is an ASCII file which the user may
* access. If it is, return the opened file. Otherwise return NULL. */
static void checkf(struct more_control *ctl, char *fs, int *clearfirst)
static void checkf(struct more_control *ctl, char *fs)
{
struct stat st;
int c;
@ -364,7 +368,7 @@ static void checkf(struct more_control *ctl, char *fs, int *clearfirst)
}
fcntl(fileno(ctl->current_file), F_SETFD, FD_CLOEXEC);
c = more_getc(ctl);
*clearfirst = (c == '\f');
ctl->clear_first = (c == '\f');
more_ungetc(ctl, c);
if ((ctl->file_size = st.st_size) == 0)
ctl->file_size = LONG_MAX;
@ -1794,6 +1798,64 @@ static void copy_file(FILE *f)
fwrite(&buf, sizeof(char), sz, stdout);
}
static void display_file(struct more_control *ctl, char *initbuf, int left)
{
if (!ctl->current_file)
return;
ctl->context.line_num = ctl->context.row_num = 0;
ctl->current_line = 0;
if (ctl->first_file) {
ctl->first_file = 0;
if (ctl->search_at_start) {
free(ctl->previous_search);
ctl->previous_search = xstrdup(initbuf);
search(ctl, initbuf, 1);
if (ctl->no_scroll)
left--;
} else if (ctl->jump_at_start)
skip_lines(ctl, ctl->search_at_start);
} else if (ctl->argv_position < ctl->num_files && !ctl->no_tty_out)
left =
more_key_command(ctl, ctl->file_names[ctl->argv_position]);
if (left != 0) {
if ((ctl->no_scroll || ctl->clear_first)
&& (ctl->file_size != LONG_MAX)) {
if (ctl->clear_line_ends)
putp(ctl->go_home);
else
more_clear_screen(ctl);
}
if (ctl->print_banner) {
if (ctl->bad_stdout)
erase_prompt(ctl, 0);
if (ctl->clear_line_ends)
putp(ctl->erase_line);
fputs("::::::::::::::", stdout);
if (ctl->prompt_len > 14)
erase_prompt(ctl, 14);
putchar('\n');
if (ctl->clear_line_ends)
putp(ctl->erase_line);
puts(ctl->file_names[ctl->argv_position]);
if (ctl->clear_line_ends)
putp(ctl->erase_line);
fputs("::::::::::::::\n", stdout);
if (left > ctl->lines_per_page - 4)
left = ctl->lines_per_page - 4;
}
if (ctl->no_tty_out)
copy_file(ctl->current_file);
else
screen(ctl, left);
}
fflush(stdout);
fclose(ctl->current_file);
ctl->current_file = NULL;
ctl->screen_start.line_num = ctl->screen_start.row_num = 0L;
ctl->context.line_num = ctl->context.row_num = 0L;
}
static void initterm(struct more_control *ctl)
{
int ret;
@ -1903,10 +1965,6 @@ int main(int argc, char **argv)
char *s;
int chr;
int left;
int print_names = 0;
int init = 0;
int search_at_start = 0;
int skip_file = 0;
int start_at_line = 0;
char *initbuf = NULL;
struct more_control ctl = {
@ -1959,10 +2017,10 @@ int main(int argc, char **argv)
} else if (chr == '+') {
s = *ctl.file_names;
if (*++s == '/') {
search_at_start++;
ctl.search_at_start = 1;
initbuf = xstrdup(s + 1);
} else {
init++;
ctl.jump_at_start = 1;
for (start_at_line = 0; *s != '\0'; s++)
if (isdigit(*s))
start_at_line =
@ -1986,7 +2044,7 @@ int main(int argc, char **argv)
ctl.lines_per_screen = ctl.lines_per_page - 1;
left = ctl.lines_per_screen;
if (ctl.num_files > 1)
print_names++;
ctl.print_banner = 1;
if (!ctl.no_tty_in && ctl.num_files == 0) {
warnx(_("bad usage"));
errtryhelp(EXIT_FAILURE);
@ -2009,89 +2067,19 @@ int main(int argc, char **argv)
if (ctl.no_tty_out)
copy_file(stdin);
else {
if ((chr = getc(ctl.current_file)) == '\f')
more_clear_screen(&ctl);
else {
ungetc(chr, ctl.current_file);
if (ctl.no_scroll && (chr != EOF)) {
if (ctl.clear_line_ends)
putp(ctl.go_home);
else
more_clear_screen(&ctl);
}
}
ctl.current_file = stdin;
if (search_at_start) {
free(ctl.previous_search);
ctl.previous_search = xstrdup(initbuf);
search(&ctl, initbuf, 1);
if (ctl.no_scroll)
left--;
} else if (init)
skip_lines(&ctl, start_at_line);
screen(&ctl, left);
display_file(&ctl, initbuf, left);
}
ctl.no_tty_in = 0;
print_names++;
ctl.print_banner = 1;
ctl.first_file = 0;
}
while (ctl.argv_position < ctl.num_files) {
checkf(&ctl, ctl.file_names[ctl.argv_position], &skip_file);
if (ctl.current_file != NULL) {
ctl.context.line_num = ctl.context.row_num = 0;
ctl.current_line = 0;
if (ctl.first_file) {
ctl.first_file = 0;
if (search_at_start) {
free(ctl.previous_search);
ctl.previous_search = xstrdup(initbuf);
search(&ctl, initbuf, 1);
if (ctl.no_scroll)
left--;
} else if (init)
skip_lines(&ctl, start_at_line);
} else if (ctl.argv_position < ctl.num_files && !ctl.no_tty_out)
left = more_key_command(&ctl, ctl.file_names[ctl.argv_position]);
if (left != 0) {
if ((ctl.no_scroll || skip_file)
&& (ctl.file_size != LONG_MAX)) {
if (ctl.clear_line_ends)
putp(ctl.go_home);
else
more_clear_screen(&ctl);
}
if (print_names) {
if (ctl.bad_stdout)
erase_prompt(&ctl, 0);
if (ctl.clear_line_ends)
putp(ctl.erase_line);
fputs("::::::::::::::", stdout);
if (ctl.prompt_len > 14)
erase_prompt(&ctl, 14);
putchar('\n');
if (ctl.clear_line_ends)
putp(ctl.erase_line);
puts(ctl.file_names[ctl.argv_position]);
if (ctl.clear_line_ends)
putp(ctl.erase_line);
fputs("::::::::::::::\n", stdout);
if (left > ctl.lines_per_page - 4)
left = ctl.lines_per_page - 4;
}
if (ctl.no_tty_out)
copy_file(ctl.current_file);
else
screen(&ctl, left);
}
fflush(stdout);
fclose(ctl.current_file);
ctl.current_file = NULL;
ctl.screen_start.line_num = ctl.screen_start.row_num = 0L;
ctl.context.line_num = ctl.context.row_num = 0L;
}
ctl.argv_position++;
checkf(&ctl, ctl.file_names[ctl.argv_position]);
display_file(&ctl, initbuf, left);
ctl.first_file = 0;
ctl.argv_position++;
}
free(ctl.previous_search);
free(initbuf);