diff options
Diffstat (limited to 'Src')
-rw-r--r-- | Src/hist.c | 151 |
1 files changed, 135 insertions, 16 deletions
diff --git a/Src/hist.c b/Src/hist.c index e0be6e030..7f8bc7cc9 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -1791,13 +1791,26 @@ resizehistents(void) } /* Remember the last line in the history file so we can find it again. */ -static struct { +static struct histfile_stats { char *text; time_t stim, mtim; off_t fpos, fsiz; int next_write_ev; } lasthist; +static struct histsave { + struct histfile_stats lasthist; + char *histfile; + HashTable histtab; + Histent hist_ring; + int curhist; + int histlinect; + int histsiz; + int savehistsiz; +} *histsave_stack; +static int histsave_stack_size = 0; +static int histsave_stack_pos = 0; + static int histfile_linect; static int @@ -2078,31 +2091,20 @@ savehistfile(char *fn, int err, int writeflags) fclose(out); if ((writeflags & (HFILE_SKIPOLD | HFILE_FAST)) == HFILE_SKIPOLD) { - HashTable remember_histtab = histtab; - Histent remember_hist_ring = hist_ring; - int remember_histlinect = histlinect; - int remember_curhist = curhist; - int remember_histsiz = histsiz; int remember_histactive = histactive; - hist_ring = NULL; - curhist = histlinect = 0; - histsiz = savehistsiz; + /* Zeroing histactive avoids unnecessary munging of curline. */ histactive = 0; - createhisttable(); /* sets histtab */ + /* The NULL leaves HISTFILE alone, preserving fn's value. */ + pushhiststack(NULL, savehistsiz, savehistsiz); hist_ignore_all_dups |= isset(HISTSAVENODUPS); readhistfile(fn, err, 0); hist_ignore_all_dups = isset(HISTIGNOREALLDUPS); if (histlinect) savehistfile(fn, err, 0); - deletehashtable(histtab); - curhist = remember_curhist; - histlinect = remember_histlinect; - hist_ring = remember_hist_ring; - histtab = remember_histtab; - histsiz = remember_histsiz; + pophiststack(); histactive = remember_histactive; } } else if (err) @@ -2331,3 +2333,120 @@ bufferwords(LinkList list, char *buf, int *index) return list; } + +/* Move the current history list out of the way and prepare a fresh history + * list using hf for HISTFILE, hs for HISTSIZE, and shs for SAVEHIST. If + * the hf value is an empty string, HISTFILE will be unset from the new + * environment; if it is NULL, HISTFILE will not be changed, not even by the + * pop function (this functionality is used internally to rewrite the current + * history file without affecting pointers into the environment). + */ + +/**/ +int +pushhiststack(char *hf, int hs, int shs) +{ + struct histsave *h; + int curline_in_ring = (histactive & HA_ACTIVE) && hist_ring == &curline; + + if (histsave_stack_pos == histsave_stack_size) { + histsave_stack_size += 5; + histsave_stack = zrealloc(histsave_stack, + histsave_stack_size * sizeof (struct histsave)); + } + + if (curline_in_ring) + unlinkcurline(); + + h = &histsave_stack[histsave_stack_pos++]; + + h->lasthist = lasthist; + if (hf) { + if ((h->histfile = getsparam("HISTFILE")) != NULL && *h->histfile) + h->histfile = ztrdup(h->histfile); + else + h->histfile = ""; + } else + h->histfile = NULL; + h->histtab = histtab; + h->hist_ring = hist_ring; + h->curhist = curhist; + h->histlinect = histlinect; + h->histsiz = histsiz; + h->savehistsiz = savehistsiz; + + memset(&lasthist, 0, sizeof lasthist); + if (hf) { + if (*hf) + setsparam("HISTFILE", ztrdup(hf)); + else + unsetparam("HISTFILE"); + } + hist_ring = NULL; + curhist = histlinect = 0; + histsiz = hs; + savehistsiz = shs; + inithist(); /* sets histtab */ + + if (curline_in_ring) + linkcurline(); + + return histsave_stack_pos; +} + + +/**/ +int +pophiststack(void) +{ + struct histsave *h; + int curline_in_ring = (histactive & HA_ACTIVE) && hist_ring == &curline; + + if (histsave_stack_pos == 0) + return 0; + + if (curline_in_ring) + unlinkcurline(); + + deletehashtable(histtab); + zsfree(lasthist.text); + + h = &histsave_stack[--histsave_stack_pos]; + + lasthist = h->lasthist; + if (h->histfile) { + if (*h->histfile) + setsparam("HISTFILE", h->histfile); + else + unsetparam("HISTFILE"); + } + histtab = h->histtab; + hist_ring = h->hist_ring; + curhist = h->curhist; + histlinect = h->histlinect; + histsiz = h->histsiz; + savehistsiz = h->savehistsiz; + + if (curline_in_ring) + linkcurline(); + + return histsave_stack_pos + 1; +} + +/**/ +int +saveandpophiststack(int down_through) +{ + if (down_through < 0) + down_through += histsave_stack_pos + 1; + if (down_through <= 0) + down_through = 1; + if (histsave_stack_pos < down_through) + return 0; + do { + if (!nohistsave) + savehistfile(NULL, 1, HFILE_USE_OPTIONS); + pophiststack(); + } while (histsave_stack_pos >= down_through); + return 1; +} |