]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
more: refactor and clarify code
authorSami Kerola <kerolasa@iki.fi>
Wed, 18 Mar 2020 20:13:16 +0000 (20:13 +0000)
committerSami Kerola <kerolasa@iki.fi>
Sat, 28 Mar 2020 07:55:59 +0000 (07:55 +0000)
Use the backspace provided dy terminfo, and if that is not possible use
fallback.

Simplify entering and exiting standard mode.  Now when these std_enter and
std_exit variables are initialized correctly they do not need to be checked
quite as complex way as earlier.

Do not call prepare_line_buffer() unnecessarily.  The line buffer needs only
to be prepared only at times of more(1) initialization and when terminal
size changes.

Add a function to print various separators, that is better than static
strings.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
text-utils/more.c

index cdc0cc2568b42ea2606f71c72be7022e5a18e772..dbcc2db0190ff49905452f8e38a4db14fc761b6b 100644 (file)
@@ -83,8 +83,7 @@
 # define NON_INTERACTIVE_MORE 1
 #endif
 
-#define BS             "\b"
-#define BSB            "\b \b"
+#define BACKSPACE      "\b"
 #define CARAT          "^"
 #define RINGBELL       '\007'
 
 #define REGERR_BUF     NUM_COLUMNS
 
 #define TERM_AUTO_RIGHT_MARGIN    "am"
+#define TERM_BACKSPACE            "cub1"
 #define TERM_CEOL                 "xhp"
 #define TERM_CLEAR                "clear"
 #define TERM_CLEAR_TO_LINE_END    "el"
 #define TERM_LINE_DOWN            "cud1"
 #define TERM_LINES                "lines"
 #define TERM_OVER_STRIKE          "os"
-#define TERM_PAD_CHAR             "pad"
 #define TERM_STANDARD_MODE        "smso"
 #define TERM_STD_MODE_GLITCH      "xmc"
 #define TERM_UNDERLINE_CHAR       "uc"
@@ -151,6 +150,7 @@ struct more_control {
        char *underline_ch;             /* underline character */
        char *backspace_ch;             /* backspace character */
        char *go_home;                  /* go to home */
+       char *move_line_down;           /* move line down */
        char *clear_rest;               /* clear rest of screen */
        int num_columns;                /* number of columns */
        char *previous_search;          /* previous search() buf[] item */
@@ -304,6 +304,13 @@ static int more_ungetc(struct more_control *ctl, int c)
        return ungetc(c, ctl->current_file);
 }
 
+static void print_separator(const int c, int n)
+{
+       while (n--)
+               putchar(c);
+       putchar('\n');
+}
+
 /* magic --
  *     check for file magic numbers.  This code would best be shared
  *     with the file(1) program or, perhaps, more should not try to be
@@ -412,8 +419,6 @@ static int get_line(struct more_control *ctl, int *length)
        memset(&state, '\0', sizeof(mbstate_t));
 #endif
 
-       prepare_line_buffer(ctl);
-
        p = ctl->line_buf;
        column = 0;
        c = more_getc(ctl);
@@ -671,7 +676,7 @@ static void print_buf(struct more_control *ctl, char *s, int n)
 #endif
                }
                if (state && *ctl->underline_ch) {
-                       fputs(ctl->backspace_ch, stdout);
+                       fputs(ctl->move_line_down, stdout);
                        putp(ctl->underline_ch);
                }
                ctl->underline_state = state;
@@ -694,7 +699,7 @@ static void output_prompt(struct more_control *ctl, char *filename)
                kill_line(ctl);
        if (!ctl->hard_tty) {
                ctl->prompt_len = 0;
-               if (ctl->enter_std && ctl->exit_std) {
+               if (ctl->enter_std) {
                        putp(ctl->enter_std);
                        ctl->prompt_len += (2 * ctl->stdout_glitch);
                }
@@ -712,7 +717,7 @@ static void output_prompt(struct more_control *ctl, char *filename)
                        ctl->prompt_len +=
                            printf(_("[Press space to continue, 'q' to quit.]"));
                }
-               if (ctl->enter_std && ctl->exit_std)
+               if (ctl->exit_std)
                        putp(ctl->exit_std);
                if (ctl->clear_line_ends)
                        putp(ctl->clear_rest);
@@ -839,12 +844,11 @@ static void more_error(struct more_control *ctl, char *mess)
        else
                kill_line(ctl);
        ctl->prompt_len += strlen(mess);
-       if (ctl->enter_std && ctl->exit_std) {
+       if (ctl->enter_std)
                putp(ctl->enter_std);
-               fputs(mess, stdout);
+       fputs(mess, stdout);
+       if (ctl->exit_std)
                putp(ctl->exit_std);
-       } else
-               fputs(mess, stdout);
        fflush(stdout);
        ctl->report_errors++;
 }
@@ -852,9 +856,8 @@ static void more_error(struct more_control *ctl, char *mess)
 static void erase_one_column(struct more_control *ctl)
 {
        if (ctl->erase_previous_ok)
-               fputs(BSB, stderr);
-       else
-               fputs(BS, stderr);
+               fprintf(stderr, "%s ", ctl->backspace_ch);
+       fputs(ctl->backspace_ch, stderr);
 }
 
 static void ttyin(struct more_control *ctl, char buf[], int nmax, char pchar)
@@ -888,16 +891,14 @@ static void ttyin(struct more_control *ctl, char buf[], int nmax, char pchar)
                                                    mbrtowc(&wc, buf + pos,
                                                            sp - buf, &state);
 
-                                               state = (mblength == (size_t)-2
-                                                        || mblength ==
-                                                        (size_t)-1) ? state_bak
-                                                   : state;
-                                               mblength =
-                                                   (mblength == (size_t)-2
-                                                    || mblength == (size_t)-1
-                                                    || mblength ==
-                                                    0) ? 1 : mblength;
-
+                                               switch (mblength) {
+                                               case (size_t)-2:
+                                               case (size_t)-1:
+                                                       state = state_bak;
+                                                       /* fallthrough */
+                                               case 0:
+                                                       mblength = 1;
+                                               }
                                                if (buf + pos + mblength >= sp)
                                                        break;
 
@@ -950,7 +951,7 @@ static void ttyin(struct more_control *ctl, char buf[], int nmax, char pchar)
                                        erase_prompt(ctl, 1);
                                else if (ctl->erase_input_ok)
                                        while (ctl->prompt_len-- > 1)
-                                               fputs(BSB, stderr);
+                                               fprintf(stderr, "%s %s", ctl->backspace_ch, ctl->backspace_ch);
                                ctl->prompt_len = 1;
                        }
                        sp = buf;
@@ -1079,6 +1080,7 @@ static void sigwinch_handler(struct more_control *ctl)
                if (win.ws_col != 0)
                        ctl->num_columns = win.ws_col;
        }
+       prepare_line_buffer(ctl);
 }
 
 static void execute(struct more_control *ctl, char *filename, char *cmd, ...)
@@ -1141,7 +1143,7 @@ static void execute(struct more_control *ctl, char *filename, char *cmd, ...)
        } else
                fputs(_("can't fork\n"), stderr);
        set_tty(ctl);
-       puts("------------------------");
+       print_separator('-', 24);
        output_prompt(ctl, filename);
 }
 
@@ -1257,8 +1259,6 @@ static void read_line(struct more_control *ctl)
        int c;
        char *p;
 
-       prepare_line_buffer(ctl);
-
        p = ctl->line_buf;
        while ((c = more_getc(ctl)) != '\n' && c != EOF
               && (size_t)(p - ctl->line_buf) < ctl->line_sz - 1)
@@ -1340,38 +1340,35 @@ static void search(struct more_control *ctl, char buf[], int n)
                line1 = ctl->file_position;
                read_line(ctl);
                lncount++;
-               if (regexec(&re, ctl->line_buf, 0, NULL, 0) == 0) {
-                       if (--n == 0) {
-                               if (lncount > 3 || (lncount > 1 && ctl->no_tty_in)) {
-                                       putchar('\n');
-                                       if (ctl->clear_line_ends)
+               if (regexec(&re, ctl->line_buf, 0, NULL, 0) == 0 && --n == 0) {
+                       if ((1 < lncount && ctl->no_tty_in) || 3 < lncount) {
+                               putchar('\n');
+                               if (ctl->clear_line_ends)
+                                       putp(ctl->erase_line);
+                               fputs(_("...skipping\n"), stdout);
+                       }
+                       if (!ctl->no_tty_in) {
+                               ctl->current_line -= (lncount < 3 ? lncount : 3);
+                               more_fseek(ctl, line3);
+                               if (ctl->no_scroll) {
+                                       if (ctl->clear_line_ends) {
+                                               putp(ctl->go_home);
                                                putp(ctl->erase_line);
-                                       fputs(_("...skipping\n"), stdout);
+                                       } else
+                                               more_clear_screen(ctl);
                                }
-                               if (!ctl->no_tty_in) {
-                                       ctl->current_line -=
-                                           (lncount >= 3 ? 3 : lncount);
-                                       more_fseek(ctl, line3);
-                                       if (ctl->no_scroll) {
-                                               if (ctl->clear_line_ends) {
-                                                       putp(ctl->go_home);
-                                                       putp(ctl->erase_line);
-                                               } else
-                                                       more_clear_screen(ctl);
-                                       }
-                               } else {
-                                       kill_line(ctl);
-                                       if (ctl->no_scroll) {
-                                               if (ctl->clear_line_ends) {
-                                                       putp(ctl->go_home);
-                                                       putp(ctl->erase_line);
-                                               } else
-                                                       more_clear_screen(ctl);
-                                       }
-                                       puts(ctl->line_buf);
+                       } else {
+                               kill_line(ctl);
+                               if (ctl->no_scroll) {
+                                       if (ctl->clear_line_ends) {
+                                               putp(ctl->go_home);
+                                               putp(ctl->erase_line);
+                                       } else
+                                               more_clear_screen(ctl);
                                }
-                               break;
+                               puts(ctl->line_buf);
                        }
+                       break;
                } else
                        more_poll(ctl, 1);
        }
@@ -1412,7 +1409,7 @@ static void runtime_usage(void)
        fputs(_("Most commands optionally preceded by integer argument k.  "
                "Defaults in brackets.\n"
                "Star (*) indicates argument becomes new default.\n"), stdout);
-       puts("-------------------------------------------------------------------------------");
+       print_separator('-', 79);
        fprintf(stdout,
                _
                ("<space>                 Display next k lines of text [current screen size]\n"
@@ -1435,16 +1432,19 @@ static void runtime_usage(void)
                 ":f                      Display current file name and line number\n"
                 ".                       Repeat previous command\n"),
                find_editor());
-       puts("-------------------------------------------------------------------------------");
+       print_separator('-', 79);
 }
 
 static void execute_editor(struct more_control *ctl, char *cmdbuf, char *filename)
 {
        char *editor, *p;
-       int n = (ctl->current_line - ctl->lines_per_screen <= 0 ? 1 :
-                ctl->current_line - (ctl->lines_per_screen + 1) / 2);
        int split = 0;
+       int n;
 
+       if ((ctl->current_line - ctl->lines_per_screen) < 1)
+               n = 1;
+       else
+               n = ctl->current_line - (ctl->lines_per_screen + 1) / 2;
        editor = find_editor();
        p = strrchr(editor, '/');
        if (p)
@@ -1698,17 +1698,13 @@ static int more_key_command(struct more_control *ctl, char *filename)
                default:
                        if (ctl->suppress_bell) {
                                kill_line(ctl);
-                               if (ctl->enter_std && ctl->exit_std) {
+                               if (ctl->enter_std)
                                        putp(ctl->enter_std);
-                                       ctl->prompt_len =
-                                           printf(_
-                                                  ("[Press 'h' for instructions.]"))
+                               ctl->prompt_len =
+                                   printf(_("[Press 'h' for instructions.]"))
                                            + 2 * ctl->stdout_glitch;
+                               if (ctl->exit_std)
                                        putp(ctl->exit_std);
-                               } else
-                                       ctl->prompt_len =
-                                           printf(_
-                                                  ("[Press 'h' for instructions.]"));
                                fflush(stdout);
                        } else
                                fputc(RINGBELL, stderr);
@@ -1831,16 +1827,15 @@ static void display_file(struct more_control *ctl, char *initbuf, int left)
                                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);
+                       print_separator(':', 14);
                        puts(ctl->file_names[ctl->argv_position]);
                        if (ctl->clear_line_ends)
                                putp(ctl->erase_line);
-                       fputs("::::::::::::::\n", stdout);
+                       print_separator(':', 14);
                        if (left > ctl->lines_per_page - 4)
                                left = ctl->lines_per_page - 4;
                }
@@ -1912,10 +1907,11 @@ static void initterm(struct more_control *ctl)
        ctl->bad_stdout = tigetflag(TERM_CEOL);
        ctl->erase_line = tigetstr(TERM_CLEAR_TO_LINE_END);
        ctl->clear = tigetstr(TERM_CLEAR);
-       ctl->enter_std = tigetstr(TERM_STANDARD_MODE);
-       ctl->exit_std = tigetstr(TERM_EXIT_STANDARD_MODE);
-       if (0 < tigetnum(TERM_STD_MODE_GLITCH))
-               ctl->stdout_glitch = 1;
+       if ((ctl->enter_std = tigetstr(TERM_STANDARD_MODE)) != NULL) {
+               ctl->exit_std = tigetstr(TERM_EXIT_STANDARD_MODE);
+               if (0 < tigetnum(TERM_STD_MODE_GLITCH))
+                       ctl->stdout_glitch = 1;
+       }
 
        /*
         * Set up for underlining.  Some terminals don't need it, others have
@@ -1952,9 +1948,11 @@ static void initterm(struct more_control *ctl)
        if (cursor_addr)
                ctl->go_home = xstrdup(cursor_addr);
 
+       if ((ctl->move_line_down = tigetstr(TERM_LINE_DOWN)) == NULL)
+               ctl->move_line_down = BACKSPACE;
        ctl->clear_rest = tigetstr(TERM_CLEAR_TO_SCREEN_END);
-       if ((ctl->backspace_ch = tigetstr(TERM_LINE_DOWN)) == NULL)
-               ctl->backspace_ch = BS;
+       if ((ctl->backspace_ch = tigetstr(TERM_BACKSPACE)) == NULL)
+               ctl->backspace_ch = BACKSPACE;
 
        if ((ctl->shell = getenv("SHELL")) == NULL)
                ctl->shell = _PATH_BSHELL;