diff options
author | Tim Vanderhoek <hoek@FreeBSD.org> | 2000-05-14 03:30:59 +0000 |
---|---|---|
committer | Tim Vanderhoek <hoek@FreeBSD.org> | 2000-05-14 03:30:59 +0000 |
commit | d25d4bbea97ba70310e8fd8007cb6e8b448b76a3 (patch) | |
tree | 7a60c58d0d42d162f092633359516f2461ed2d77 /usr.bin | |
parent | 2e2de7f23f09ed445e6d2503174e890cc64b9a7c (diff) | |
download | src-d25d4bbea97ba70310e8fd8007cb6e8b448b76a3.tar.gz src-d25d4bbea97ba70310e8fd8007cb6e8b448b76a3.zip |
Allow bookmarks to cross files.
Notes
Notes:
svn path=/head/; revision=60537
Diffstat (limited to 'usr.bin')
-rw-r--r-- | usr.bin/more/less.h | 11 | ||||
-rw-r--r-- | usr.bin/more/main.c | 31 | ||||
-rw-r--r-- | usr.bin/more/ncommand.c | 13 | ||||
-rw-r--r-- | usr.bin/more/prim.c | 73 |
4 files changed, 102 insertions, 26 deletions
diff --git a/usr.bin/more/less.h b/usr.bin/more/less.h index f30abd9b5fc3..e38306837680 100644 --- a/usr.bin/more/less.h +++ b/usr.bin/more/less.h @@ -43,8 +43,6 @@ #define EOI (0) #define READ_INTR (-2) -#define NO_HORIZ_OFF (-1) /* Wrap lines like normal */ - /* Special chars used to tell put_line() to do something special */ #define UL_CHAR '\201' /* Enter underline mode */ #define UE_CHAR '\202' /* Exit underline mode */ @@ -63,13 +61,16 @@ /* The return type of runmacro() */ enum runmacro { OK=0, TOOMACRO, BADMACRO, NOMACRO, BADCOMMAND }; +#define NOFLAGS 0 +#define FORCE_OPEN 0 /* edit() flag */ +#define NO_FORCE_OPEN 1 /* edit() flag */ + #ifdef DEFINEGLOBALS #define GLOBAL(var, val) var = val #else #define GLOBAL(var, val) extern var #endif - /* * This style of error-reporting (see also command.c) is only used by some * code. Eventually most of the code should use it, since it is becoming @@ -108,7 +109,7 @@ enum error { E_OK=0, E_AMBIG, E_BADMATH, E_BADVAR, E_BOGCOM, E_CANTPARSE, GLOBAL(const char *deferr[], deferrinit_ ); /* - * It is possible for erreur to become dis-synchronized from errstr if + * It is possible for erreur to become unsynchronized from errstr if * its users aren't careful. Access through the macros is considered * careful. */ @@ -129,7 +130,7 @@ GLOBAL(char *errstr, NULL); /* must point be null or free()'ble */ * * fmalloc(size, pointer-to-new-memory); * - * Don't compile this puppy with -Wall... + * Don't compile this puppy with -Wall or she'll squeel loud! */ #define FMALLOC(s,v) ((((v) = malloc(s)) ? 0 : \ diff --git a/usr.bin/more/main.c b/usr.bin/more/main.c index a41f8e968d4e..6be4b32b200b 100644 --- a/usr.bin/more/main.c +++ b/usr.bin/more/main.c @@ -87,8 +87,11 @@ extern int tagoption; * Filename "-" means standard input. * No filename means the "current" file, from the command line. If called * with the same filename in succession, filename will be closed and reopened. + * + * If called with FORCE_OPEN, the file will be re-opened even if it is + * already open. */ -edit(filename) +edit(filename, force_open) register char *filename; { register int f; @@ -98,6 +101,15 @@ edit(filename) static int didpipe; char message[MAXPATHLEN + 50], *p; char *rindex(), *strerror(), *save(), *bad_file(); + extern int horiz_off, wraplines; + + if (force_open == NO_FORCE_OPEN && + current_file && filename && !strcmp(filename, current_file)) + return(1); + + /* Okay since later code in this fcn() always forces redraw() */ + horiz_off = 0; + wraplines = 0; initial_pos = NULL_POSITION; if (filename == NULL || *filename == '\0') { @@ -176,7 +188,6 @@ edit(filename) next_name = av[curr_ac + 1]; file = f; ch_init(cbufs, 0); - init_mark(); if (isatty(STDOUT_FILENO)) { int no_display = !any_display; @@ -215,7 +226,7 @@ next_file(n) error("No (N-th) next file"); } else - (void)edit(av[curr_ac += n]); + (void)edit(av[curr_ac += n], FORCE_OPEN); } /* @@ -227,7 +238,7 @@ prev_file(n) if (curr_ac - n < 0) error("No (N-th) previous file"); else - (void)edit(av[curr_ac -= n]); + (void)edit(av[curr_ac -= n], FORCE_OPEN); } /* @@ -287,6 +298,8 @@ main(argc, argv) av = argv; curr_ac = 0; + init_mark(); + /* * Set up terminal, etc. */ @@ -296,12 +309,12 @@ main(argc, argv) * Just copy the input file(s) to output. */ if (ac < 1) { - (void)edit("-"); + (void)edit("-", NOFLAGS); if (file >= 0) cat_file(); } else { do { - (void)edit((char *)NULL); + (void)edit((char *)NULL, FORCE_OPEN); if (file >= 0) cat_file(); } while (++curr_ac < ac); @@ -321,11 +334,11 @@ main(argc, argv) * A -t option was given; edit the file selected by the * "tags" search, and search for the proper line in the file. */ - if (!tagfile || !edit(tagfile) || tagsearch()) + if (!tagfile || !edit(tagfile, NOFLAGS) || tagsearch()) quit(); } else if (ac < 1) - (void)edit("-"); /* Standard input */ + (void)edit("-", NOFLAGS); /* Standard input */ else { /* * Try all the files named as command arguments. @@ -333,7 +346,7 @@ main(argc, argv) * opened without error. */ do { - (void)edit((char *)NULL); + (void)edit((char *)NULL, NOFLAGS); } while (file < 0 && ++curr_ac < ac); } diff --git a/usr.bin/more/ncommand.c b/usr.bin/more/ncommand.c index 6ad220fa0549..b46d9ee4389b 100644 --- a/usr.bin/more/ncommand.c +++ b/usr.bin/more/ncommand.c @@ -40,16 +40,15 @@ static const char rcsid[] = * of the command line string passed to command() is then passed to a * function corresponding to the given command. The specific command * function evaluates the remainder of the command string with the help - * of getstr() and getnumb(), both of which also handle variable expansion - * into a single word. It may in the future be desirable to add a special - * getsstring(), get-search-string, function. Specific command functions - * should not try grokking the command string by themselves. + * of getstr() and getint(), both of which also handle variable expansion + * into a single word. Specific command functions should not try grokking + * the command string by themselves. * * A command and its arguments are terminated by either a NUL or a ';'. * This is recognized by both getstr() and getint(). Specific command * functions return a pointer to the end of the command (and its arguments) * thus allowing command() to accept commands that are chained together - * by semicolons. If a specific command fails it returns NULL preventing + * by semicolons. If a specific command fails, it returns NULL preventing * any proceeding commands (chained together with ';') from being parsed. * This can be considered as a feature. * @@ -1241,7 +1240,7 @@ caskfile(cident, args) * file to be re-opened. */ /* XXX should modify this() or edit() to handle lists of file, ie. * the type of lists that I get if I try to glob("*") */ - (void)edit(glob(buf)); + (void)edit(glob(buf), FORCE_OPEN); return args; } @@ -1500,7 +1499,7 @@ ctags(cident, args) /* Load the tagfile and position ourselves. */ if (tagfile == NULL) return NULL; - if (edit(tagfile)) + if (edit(tagfile, NO_FORCE_OPEN)) tagsearch(); return args; /* tag stuff still calls error() on its own */ } diff --git a/usr.bin/more/prim.c b/usr.bin/more/prim.c index eb76f95676b5..8a6577b6030b 100644 --- a/usr.bin/more/prim.c +++ b/usr.bin/more/prim.c @@ -47,6 +47,7 @@ static const char rcsid[] = #include <sys/types.h> +#include <assert.h> #include <ctype.h> #include <limits.h> #include <regex.h> @@ -64,6 +65,7 @@ extern int sigs; extern int top_scroll; extern int sc_width, sc_height; extern int horiz_off; +extern int wraplines; extern int caseless; extern int linenums; extern int tagoption; @@ -508,7 +510,9 @@ jump_loc(pos) #define LASTMARK (NMARKS-1) /* For quote */ static struct mark { int horiz_off; + int wraplines; off_t pos; + char *file; } marks[NMARKS]; /* @@ -519,7 +523,7 @@ init_mark() int i; for (i = 0; i < NMARKS; i++) - marks[i].pos = NULL_POSITION; + marks[i].pos = NULL_POSITION, marks[i].file = NULL; } /* @@ -543,16 +547,31 @@ badmark(c) setmark(c) int c; { + extern char *current_file; + if (badmark(c)) return; marks[c-'a'].pos = position(TOP); marks[c-'a'].horiz_off = horiz_off; + marks[c-'a'].wraplines = wraplines; + if (marks[c-'a'].file) free(marks[c-'a'].file); + asprintf(&marks[c-'a'].file, "%s", current_file); } +/* + * This function should be called whenever the file position we are viewing + * is changed by a significant amount. The function will record the current + * position and remember it for the user. + */ lastmark() { + extern char *current_file; + marks[LASTMARK].pos = position(TOP); marks[LASTMARK].horiz_off = horiz_off; + marks[LASTMARK].wraplines = wraplines; + if (marks[LASTMARK].file) free(marks[LASTMARK].file); + asprintf(&marks[LASTMARK].file, "%s", current_file); } /* @@ -562,15 +581,18 @@ gomark(c) int c; { off_t pos; - int new_horiz_off; + char *file; + int new_horiz_off, new_wraplines; + extern char *current_file; if (c == '\'') { pos = marks[LASTMARK].pos; if (pos == NULL_POSITION) pos = 0; + file = marks[LASTMARK].file; new_horiz_off = marks[LASTMARK].horiz_off; - } - else { + new_wraplines = marks[LASTMARK].wraplines; + } else { if (badmark(c)) return; pos = marks[c-'a'].pos; @@ -578,16 +600,57 @@ gomark(c) error("mark not set"); return; } + file = marks[c-'a'].file; new_horiz_off = marks[c-'a'].horiz_off; + new_wraplines = marks[c-'a'].wraplines; } + /* + * This can only fail if gomark('\'') is called before lastmark() + * is called, which is in turn impossible since both edit() and + * jump_back() call jump_loc() which calls lastmark() to start + * all files. + */ + assert (file); + + /* + * This can only fail if gomark() is called before any file has + * been opened. Calling gomark() before any file has been + * opened would be non-sensical. + */ + assert (current_file); + + /* + * XXX The edit() needs to return success or failure so that we + * can abort at this point if edit() fails. + */ + edit(file, NO_FORCE_OPEN); + /* Try to be nice about changing the horizontal scroll and wrapping */ - if (new_horiz_off > sc_width / 3 + horiz_off) { + if (new_horiz_off > horiz_off + sc_width / 3 || + new_horiz_off < horiz_off - sc_width / 3 || + wraplines != new_wraplines || strcmp(file, current_file)) { /* * We should change horiz_off: if we don't change horiz_off * the bookmarked location won't be readily visible. */ + + /* + * A prepaint() doesn't call lastmark() (jump_loc() does), + * but we need to call repaint() somewhere since we've + * changed the horizontal offset. We don't want to call + * jump_loc() followed by repaint() since that represents + * more unnecessary screen redrawing than I'm comfortable + * with. Manually calling lastmark() here means, however, + * that lastmark() is always called even if we scroll only + * a few lines --- unlike letting jump_loc() call lastmark() + * where lastmark() is only called for jumps of more than + * a screenful. A better interface is needed. + */ + lastmark(); + horiz_off = new_horiz_off; + wraplines = new_wraplines; prepaint(pos); } else { /* |