📄 more.c
字号:
else putcerr('\n'); _exit(0);}void copy_file(register FILE *f) { register int c; while ((c = getc(f)) != EOF) putchar(c);}#define ringbell() putcerr('\007')/* See whether the last component of the path name "path" is equal to the** string "string"*/static int tailequ (char *path, register char *string){ register char *tail; tail = path + strlen(path); while (--tail >= path) if (*tail == '/') break; ++tail; while (*tail++ == *string++) if (*tail == '\0') return(1); return(0);}static void prompt (char *filename){ if (clreol) cleareol (); else if (promptlen > 0) kill_line (); if (!hard) { promptlen = 0; if (Senter && Sexit) { my_putstring (Senter); promptlen += (2 * soglitch); } if (clreol) cleareol (); promptlen += printf(_("--More--")); if (filename != NULL) { promptlen += printf(_("(Next file: %s)"), filename); } else if (!no_intty) { promptlen += printf("(%d%%)", (int) ((file_pos * 100) / file_size)); } if (dum_opt) { promptlen += printf(_("[Press space to continue, 'q' to quit.]")); } if (Senter && Sexit) my_putstring (Sexit); if (clreol) clreos (); fflush(stdout); } else ringbell(); inwait++;}/* * Get a logical line */int get_line(register FILE *f, int *length){ int c; char *p; int column; static int colflg;#ifdef ENABLE_WIDECHAR int i; wchar_t wc; int wc_width; mbstate_t state, state_bak; /* Current status of the stream. */ unsigned char mbc[MB_LEN_MAX]; /* Buffer for one multibyte char. */ size_t mblength; /* Byte length of multibyte char. */ size_t mbc_pos = 0; /* Postion of the MBC. */ int use_mbc_buffer_flag = 0; /* If 1, mbc has data. */ int break_flag = 0; /* If 1, exit while(). */ long file_pos_bak = Ftell (f); memset (&state, '\0', sizeof (mbstate_t));#endif p = Line; column = 0; c = Getc (f); if (colflg && c == '\n') { Currline++; c = Getc (f); } while (p < &Line[LINSIZ - 1]) {#ifdef ENABLE_WIDECHAR if (fold_opt && use_mbc_buffer_flag && MB_CUR_MAX > 1) { use_mbc_buffer_flag = 0; state_bak = state; mbc[mbc_pos++] = c;process_mbc: mblength = mbrtowc (&wc, mbc, mbc_pos, &state); switch (mblength) { case (size_t)-2: /* Incomplete multibyte character. */ use_mbc_buffer_flag = 1; state = state_bak; break; case (size_t)-1: /* Invalid as a multibyte character. */ *p++ = mbc[0]; state = state_bak; column++; file_pos_bak++; if (column >= Mcol) { Fseek (f, file_pos_bak); } else { memmove (mbc, mbc + 1, --mbc_pos); if (mbc_pos > 0) { mbc[mbc_pos] = '\0'; goto process_mbc; } } break; default: wc_width = wcwidth (wc); if (column + wc_width > Mcol) { Fseek (f, file_pos_bak); break_flag = 1; } else { for (i = 0; i < mbc_pos; i++) *p++ = mbc[i]; if (wc_width > 0) column += wc_width; } } if (break_flag || column >= Mcol) break; c = Getc (f); continue; }#endif if (c == EOF) { if (p > Line) { *p = '\0'; *length = p - Line; return (column); } *length = p - Line; return (EOF); } if (c == '\n') { Currline++; break; } *p++ = c;#if 0 if (c == '\033') { /* ESC */ c = Getc(f); while (c > ' ' && c < '0' && p < &Line[LINSIZ - 1]) { *p++ = c; c = Getc(f); } if (c >= '0' && c < '\177' && p < &Line[LINSIZ - 1]) { *p++ = c; c = Getc(f); continue; } }#endif if (c == '\t') { if (!hardtabs || (column < promptlen && !hard)) { if (hardtabs && eraseln && !dumb) { column = 1 + (column | 7); my_putstring (eraseln); promptlen = 0; } else { for (--p; p < &Line[LINSIZ - 1];) { *p++ = ' '; if ((++column & 7) == 0) break; } if (column >= promptlen) promptlen = 0; } } else column = 1 + (column | 7); } else if (c == '\b' && column > 0) { column--; } else if (c == '\r') { int next = Getc(f); if (next == '\n') { p--; Currline++; break; } Ungetc(next,f); column = 0; } else if (c == '\f' && stop_opt) { p[-1] = '^'; *p++ = 'L'; column += 2; Pause++; } else if (c == EOF) { *length = p - Line; return (column); } else {#ifdef ENABLE_WIDECHAR if (fold_opt && MB_CUR_MAX > 1) { memset (mbc, '\0', MB_LEN_MAX); mbc_pos = 0; mbc[mbc_pos++] = c; state_bak = state; mblength = mbrtowc (&wc, mbc, mbc_pos, &state); /* The value of mblength is always less than 2 here. */ switch (mblength) { case (size_t)-2: p--; file_pos_bak = Ftell (f) - 1; state = state_bak; use_mbc_buffer_flag = 1; break; case (size_t)-1: state = state_bak; column++; break; default: wc_width = wcwidth (wc); if (wc_width > 0) column += wc_width; } } else#endif { if (isprint(c)) column++; } } if (column >= Mcol && fold_opt) break; c = Getc (f); } if (column >= Mcol && Mcol > 0) { if (!Wrap) { *p++ = '\n'; } } colflg = column == Mcol && fold_opt; if (colflg && eatnl && Wrap) { *p++ = '\n'; /* simulate normal wrap */ } *length = p - Line; *p = 0; return (column);}/*** Erase the rest of the prompt, assuming we are starting at column col.*/void erasep (register int col){ if (promptlen == 0) return; if (hard) { putchar ('\n'); } else { if (col == 0) putchar ('\r'); if (!dumb && eraseln) my_putstring (eraseln); else for (col = promptlen - col; col > 0; col--) putchar (' '); } promptlen = 0;}/*** Erase the current line entirely*/void kill_line(){ erasep(0); if (!eraseln || dumb) putchar('\r');}/* * force clear to end of line */void cleareol(){ my_putstring(eraseln);}void clreos(){ my_putstring(EodClr);}/* Print a buffer of n characters */void prbuf (register char *s, register int n){ register char c; /* next output character */ register int state; /* next output char's UL state */#define wouldul(s,n) ((n) >= 2 && (((s)[0] == '_' && (s)[1] == '\b') || ((s)[1] == '\b' && (s)[2] == '_'))) while (--n >= 0) if (!ul_opt) putchar (*s++); else { if (*s == ' ' && pstate == 0 && ulglitch && wouldul(s+1, n-1)) { s++; continue; } if ((state = wouldul(s, n)) != 0) { c = (*s == '_')? s[2] : *s ; n -= 2; s += 3; } else c = *s++; if (state != pstate) { if (c == ' ' && state == 0 && ulglitch && wouldul(s, n-1)) state = 1; else my_putstring(state ? ULenter : ULexit); } if (c != ' ' || pstate == 0 || state != 0 || ulglitch == 0) putchar(c); if (state && *chUL) { putsout(chBS); my_putstring(chUL); } pstate = state; }}/*** Clear the screen*/voiddoclear(){ if (Clear && !hard) { my_putstring(Clear); /* Put out carriage return so that system doesn't ** get confused by escape sequences when expanding tabs */ putchar ('\r'); promptlen = 0; }}/* * Go to home position */voidhome(){ my_putstring(Home);}static int lastcmd, lastarg, lastp;static int lastcolon;char shell_line[1000];/*** Read a command and do it. A command consists of an optional integer** argument followed by the command character. Return the number of lines** to display in the next screenful. If there is nothing more to display** in the current file, zero is returned.*/int command (char *filename, register FILE *f){ register int nlines; register int retval = 0; register int c; char colonch; int done; char comchar, cmdbuf[80];#define ret(val) retval=val;done++;break done = 0; if (!errors) prompt (filename); else errors = 0; for (;;) { nlines = number (&comchar); lastp = colonch = 0; if (comchar == '.') { /* Repeat last command */ lastp++; comchar = lastcmd; nlines = lastarg; if (lastcmd == ':') colonch = lastcolon; } lastcmd = comchar; lastarg = nlines; if ((cc_t) comchar == otty.c_cc[VERASE]) { kill_line (); prompt (filename); continue; } switch (comchar) { case ':': retval = colon (filename, colonch, nlines); if (retval >= 0) done++; break; case 'b': case ctrl('B'): { register int initline; if (no_intty) { ringbell(); return (-1); } if (nlines == 0) nlines++; putchar ('\r'); erasep (0); putchar('\n'); if (clreol) cleareol (); if (nlines != 1) printf(_("...back %d pages"), nlines); else putsout(_("...back 1 page")); if (clreol) cleareol (); putchar('\n'); initline = Currline - dlines * (nlines + 1); if (! noscroll) --initline; if (initline < 0) initline = 0; Fseek(f, 0L); Currline = 0; /* skiplns() will make Currline correct */ skiplns(initline, f); if (! noscroll) { ret(dlines + 1); } else { ret(dlines); } } case ' ': case 'z': if (nlines == 0) nlines = dlines; else if (comchar == 'z') dlines = nlines; ret (nlines); case 'd': case ctrl('D'): if (nlines != 0) nscroll = nlines; ret (nscroll); case 'q': case 'Q': end_it (0); case 's': case 'f': case ctrl('F'): if (nlines == 0) nlines++; if (comchar == 'f') nlines *= dlines; putchar ('\r'); erasep (0); putchar('\n'); if (clreol) cleareol (); if (nlines == 1) putsout(_("...skipping one line")); else printf(_("...skipping %d lines"), nlines); if (clreol) cleareol (); putchar('\n'); while (nlines > 0) { while ((c = Getc (f)) != '\n') if (c == EOF) { retval = 0; done++; goto endsw; } Currline++; nlines--; } ret (dlines); case '\n': if (nlines != 0) dlines = nlines; else nlines = 1; ret (nlines); case '\f': if (!no_intty) { doclear (); Fseek (f, screen_start.chrctr); Currline = screen_start.line; ret (dlines); } else { ringbell(); break; } case '\'': if (!no_intty) { kill_line (); putsout(_("\n***Back***\n\n")); Fseek (f, context.chrctr); Currline = context.line; ret (dlines); } else { ringbell(); break; } case '=': kill_line (); promptlen = printf("%d", Currline); fflush (stdout); break; case 'n': lastp++; case '/': if (nlines == 0) nlines++; kill_line (); putchar('/'); promptlen = 1; fflush (stdout); if (lastp) { putcerr('\r'); search (NULL, f, nlines); /* Use previous r.e. */ } else { ttyin (cmdbuf, sizeof(cmdbuf)-2, '/'); putcerr('\r'); search (cmdbuf, f, nlines); } ret (dlines-1); case '!': do_shell (filename); break; case '?': case 'h': if (noscroll) doclear(); putsout(_("\n""Most commands optionally preceded by integer argument k. ""Defaults in brackets.\n""Star (*) indicates argument becomes new default.\n")); puts("---------------------------------------" "----------------------------------------"); putsout(_("<space> Display next k lines of text [current screen size]\n""z Display next k lines of text [current screen size]*\n""<return> Display next k lines of text [1]*\n""d or ctrl-D Scroll k lines [current scroll size, initially 11]*\n""q or Q or <interrupt> Exit from more\n""s Skip forward k lines of text [1]\n""f Skip forward k screenfuls of text [1]\n""b or ctrl-B Skip backwards k screenfuls of text [1]\n""' Go to place where previous search started\n""= Display current line number\n""/<regular expression> Search for kth occurrence of regular expression [1]\n""n Search for kth occurrence of last r.e [1]\n""!<cmd> or :!<cmd> Execute <cmd> in a subshell\n""v Start up /usr/bin/vi at current line\n""ctrl-L Redraw screen\n"":n Go to kth next file [1]\n"":p Go to kth previous file [1]\n"":f Display current file name and line number\n"". Repeat previous command\n")); puts("---------------------------------------" "----------------------------------------"); prompt(filename); break; case 'v': /* This case should go right before default */ if (!no_intty) { /* * Earlier: call vi +n file. This also works for emacs. * POSIX: call vi -c n file (when editor is vi or ex). */ char *editor, *p; int n = (Currline - dlines <= 0 ? 1 : Currline - (dlines + 1) / 2); int split = 0; editor = getenv("VISUAL"); if (editor == NULL || *editor == '\0') editor = getenv("EDITOR"); if (editor == NULL || *editor == '\0') editor = VI; p = strrchr(editor, '/'); if (p) p++; else p = editor; if (!strcmp(p, "vi") || !strcmp(p, "ex")) { sprintf(cmdbuf, "-c %d", n); split = 1; } else { sprintf(cmdbuf, "+%d", n); } kill_line(); printf("%s %s %s", editor, cmdbuf, fnames[fnum]); if (split) { cmdbuf[2] = 0; execute(filename, editor, editor, cmdbuf, cmdbuf+3, fnames[fnum], (char *)0); } else execute(filename, editor, editor, cmdbuf, fnames[fnum], (char *)0); break; } /* fall through */ default: if (dum_opt) { kill_line (); if (Senter && Sexit) { my_putstring (Senter); promptlen = printf(_("[Press 'h' for instructions.]")) + 2 * soglitch; my_putstring (Sexit); } else promptlen = printf(_("[Press 'h' for instructions.]")); fflush (stdout); } else ringbell(); break; } if (done) break; } putchar ('\r');endsw: inwait = 0; notell++; return (retval);}static char ch;/* * Execute a colon-prefixed command. * Returns <0 if not a command that should cause * more of the file to be printed. */int colon (char *filename, int cmd, int nlines) { if (cmd == 0) ch = readch (); else ch = cmd; lastcolon = ch; switch (ch) { case 'f': kill_line (); if (!no_intty) promptlen = printf(_("\"%s\" line %d"), fnames[fnum], Currline); else promptlen = printf(_("[Not a file] line %d"), Currline); fflush (stdout); return (-1); case 'n': if (nlines == 0) { if (fnum >= nfiles - 1) end_it (0); nlines++; } putchar ('\r'); erasep (0); skipf (nlines); return (0); case 'p': if (no_intty) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -