diff options
author | Ingo Schwarze <schwarze@openbsd.org> | 2015-07-28 18:38:55 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@openbsd.org> | 2015-07-28 18:38:55 +0000 |
commit | 2510486fc44a83002c7f77dfeaf94603b0cea866 (patch) | |
tree | 3e36cacc3887baa8d0d907ce8105b0b7e0314f98 /tag.c | |
parent | ce6fe8383153d10dc1f75f86c3f8fab0d32e2290 (diff) | |
download | mandoc-2510486fc44a83002c7f77dfeaf94603b0cea866.tar.gz |
Remove the hack of scrolling forward and backward with +G1G that
many (jmc@, millert@, espie@, deraadt@) considered revolting.
Instead, when using a pager, since we are using a temporary file
for tags anyway, use another temporary file for the formatted
page(s), as suggested by millert@ and similar to what the traditional
BSD man(1) did, except that we use only one single temporary output
file rather than one for each formatted manual page, such that
searching (both with / and :t) works across all the displayed files.
Diffstat (limited to 'tag.c')
-rw-r--r-- | tag.c | 75 |
1 files changed, 56 insertions, 19 deletions
@@ -44,29 +44,49 @@ static void tag_free(void *, void *); static void *tag_calloc(size_t, size_t, void *); static struct ohash tag_data; -static char *tag_fn = NULL; -static int tag_fd = -1; +static struct tag_files tag_files; /* - * Set up the ohash table to collect output line numbers - * where various marked-up terms are documented and create - * the temporary tags file, saving the name for the pager. + * Prepare for using a pager. + * Not all pagers are capable of using a tag file, + * but for simplicity, create it anyway. */ -char * +struct tag_files * tag_init(void) { struct ohash_info tag_info; + int ofd; - tag_fn = mandoc_strdup("/tmp/man.XXXXXXXXXX"); + ofd = -1; + tag_files.tfd = -1; + + /* Save the original standard output for use by the pager. */ + + if ((tag_files.ofd = dup(STDOUT_FILENO)) == -1) + goto fail; + + /* Create both temporary output files. */ + + (void)strlcpy(tag_files.ofn, "/tmp/man.XXXXXXXXXX", + sizeof(tag_files.ofn)); + (void)strlcpy(tag_files.tfn, "/tmp/man.XXXXXXXXXX", + sizeof(tag_files.tfn)); signal(SIGHUP, tag_signal); signal(SIGINT, tag_signal); signal(SIGTERM, tag_signal); - if ((tag_fd = mkstemp(tag_fn)) == -1) { - free(tag_fn); - tag_fn = NULL; - return(NULL); - } + if ((ofd = mkstemp(tag_files.ofn)) == -1) + goto fail; + if ((tag_files.tfd = mkstemp(tag_files.tfn)) == -1) + goto fail; + if (dup2(ofd, STDOUT_FILENO) == -1) + goto fail; + close(ofd); + + /* + * Set up the ohash table to collect output line numbers + * where various marked-up terms are documented. + */ tag_info.alloc = tag_alloc; tag_info.calloc = tag_calloc; @@ -74,7 +94,21 @@ tag_init(void) tag_info.key_offset = offsetof(struct tag_entry, s); tag_info.data = NULL; ohash_init(&tag_data, 4, &tag_info); - return(tag_fn); + return(&tag_files); + +fail: + tag_unlink(); + if (ofd != -1) + close(ofd); + if (tag_files.ofd != -1) + close(tag_files.ofd); + if (tag_files.tfd != -1) + close(tag_files.tfd); + *tag_files.ofn = '\0'; + *tag_files.tfn = '\0'; + tag_files.ofd = -1; + tag_files.tfd = -1; + return(NULL); } /* @@ -88,7 +122,7 @@ tag_put(const char *s, int prio, size_t line) size_t len; unsigned int slot; - if (tag_fd == -1) + if (tag_files.tfd <= 0) return; slot = ohash_qlookup(&tag_data, s); entry = ohash_find(&tag_data, slot); @@ -114,13 +148,14 @@ tag_write(void) struct tag_entry *entry; unsigned int slot; - if (tag_fd == -1) + if (tag_files.tfd <= 0) return; - stream = fdopen(tag_fd, "w"); + stream = fdopen(tag_files.tfd, "w"); entry = ohash_first(&tag_data, &slot); while (entry != NULL) { if (stream != NULL) - fprintf(stream, "%s - %zu\n", entry->s, entry->line); + fprintf(stream, "%s %s %zu\n", + entry->s, tag_files.ofn, entry->line); free(entry); entry = ohash_next(&tag_data, &slot); } @@ -133,8 +168,10 @@ void tag_unlink(void) { - if (tag_fn != NULL) - unlink(tag_fn); + if (*tag_files.ofn != '\0') + unlink(tag_files.ofn); + if (*tag_files.tfn != '\0') + unlink(tag_files.tfn); } static void |