diff -rdu mutt-cvs/PATCHES mutt/PATCHES --- mutt-cvs/PATCHES 2002-12-11 14:44:49.000000000 +0100 +++ mutt/PATCHES 2004-09-01 09:55:03.779649216 +0200 @@ -0,0 +1 @@ +patch-1.5.1.vl.savehist.1 diff -rdu mutt-cvs/enter.c mutt/enter.c --- mutt-cvs/enter.c 2003-11-09 13:34:14.000000000 +0100 +++ mutt/enter.c 2004-09-01 09:55:03.782648760 +0200 @@ -525,7 +525,7 @@ { mutt_pretty_mailbox (buf); if (!pass) - mutt_history_add (hclass, buf); + mutt_history_add (hclass, buf, 1); rv = 0; goto bye; } @@ -652,7 +652,7 @@ /* Convert from wide characters */ my_wcstombs (buf, buflen, state->wbuf, state->lastchar); if (!pass) - mutt_history_add (hclass, buf); + mutt_history_add (hclass, buf, 1); if (multiple) { diff -rdu mutt-cvs/globals.h mutt/globals.h --- mutt-cvs/globals.h 2004-09-01 09:23:34.426874496 +0200 +++ mutt/globals.h 2004-09-01 09:55:03.784648456 +0200 @@ -50,6 +50,7 @@ WHERE char *ForwFmt; WHERE char *Fqdn; WHERE char *HdrFmt; +WHERE char *HistFile; WHERE char *Homedir; WHERE char *Hostname; #ifdef USE_IMAP @@ -153,6 +154,7 @@ WHERE short PagerContext; WHERE short PagerIndexLines; WHERE short ReadInc; +WHERE short SaveHist; WHERE short SendmailWait; WHERE short SleepTime INITVAL (1); WHERE short Timeout; diff -rdu mutt-cvs/history.c mutt/history.c --- mutt-cvs/history.c 2002-12-11 14:44:49.000000000 +0100 +++ mutt/history.c 2004-09-01 09:58:59.074878904 +0200 @@ -52,6 +52,117 @@ h->last = 0; } +static void read_histfile(void) +{ + FILE *f; + int line = 0, hclass, read; + char *linebuf = NULL, *p; + size_t buflen; + + if ((f = fopen (HistFile, "r")) == NULL) + return; + + while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL) + { + read = 0; + if (sscanf (linebuf, "%d:%n", &hclass, &read) < 1 || read == 0 || + *(p = linebuf + strlen (linebuf) - 1) != '|') + { + mutt_error (_("Bad history file format (line %d)"), line); + break; + } + *p = '\0'; + mutt_history_add (hclass, linebuf + read, 0); + } + + safe_free (&linebuf); + fclose (f); +} + +static void shrink_histfile (void) +{ + char tmpfname[_POSIX_PATH_MAX]; + FILE *f, *tmp = NULL; + int n[HC_LAST] = { 0 }; + int line, hclass; + char *linebuf = NULL; + size_t buflen; + + if ((f = fopen (HistFile, "r")) == NULL) + return; + + line = 0; + while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL) + { + if (sscanf (linebuf, "%d", &hclass) < 1) + { + mutt_error (_("Bad history file format (line %d)"), line); + goto cleanup; + } + n[hclass]++; + } + + for(hclass = HC_FIRST; hclass < HC_LAST; hclass++) + if (n[hclass] > SaveHist) + { + mutt_mktemp (tmpfname); + if ((tmp = safe_fopen (tmpfname, "w+")) == NULL) + mutt_perror (tmpfname); + break; + } + + if (tmp != NULL) + { + rewind (f); + line = 0; + while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL) + { + if (sscanf (linebuf, "%d", &hclass) < 1) + { + mutt_error (_("Bad history file format (line %d)"), line); + goto cleanup; + } + if (n[hclass]-- <= SaveHist) + fprintf (tmp, "%s\n", linebuf); + } + } + +cleanup: + fclose (f); + safe_free (&linebuf); + if (tmp != NULL) + { + if (fflush (tmp) == 0 && (f = fopen (HistFile, "w")) != NULL) + { + rewind (tmp); + mutt_copy_stream (tmp, f); + fclose (f); + } + fclose (tmp); + unlink (tmpfname); + } +} + +static void save_history (history_class_t hclass, const char *s) +{ + static int n = 0; + FILE *f; + + if ((f = fopen (HistFile, "a")) == NULL) + { + mutt_perror ("fopen"); + return; + } + + fprintf (f, "%d:%s|\n", (int) hclass, s); /* avoid line ending with '\' */ + fclose (f); + if (--n < 0) + { + n = SaveHist; + shrink_histfile(); + } +} + void mutt_init_history(void) { history_class_t hclass; @@ -63,9 +174,10 @@ init_history(&History[hclass]); OldSize = HistSize; + read_histfile(); } -void mutt_history_add (history_class_t hclass, const char *s) +void mutt_history_add (history_class_t hclass, const char *s, int save) { int prev; struct history *h = &History[hclass]; @@ -79,6 +191,8 @@ if (prev < 0) prev = HistSize - 1; if (!h->hist[prev] || mutt_strcmp (h->hist[prev], s) != 0) { + if (save && SaveHist) + save_history (hclass, s); mutt_str_replace (&h->hist[h->last++], s); if (h->last > HistSize - 1) h->last = 0; diff -rdu mutt-cvs/history.h mutt/history.h --- mutt-cvs/history.h 2002-12-11 14:44:49.000000000 +0100 +++ mutt/history.h 2004-09-01 09:55:03.787648000 +0200 @@ -35,7 +35,7 @@ typedef enum history_class history_class_t; void mutt_init_history(void); -void mutt_history_add(history_class_t, const char *); +void mutt_history_add(history_class_t, const char *, int); char *mutt_history_next(history_class_t); char *mutt_history_prev(history_class_t); diff -rdu mutt-cvs/init.h mutt/init.h --- mutt-cvs/init.h 2004-09-01 09:23:34.604847440 +0200 +++ mutt/init.h 2004-09-01 09:55:03.795646784 +0200 @@ -750,6 +750,11 @@ ** the string history buffer. The buffer is cleared each time the ** variable is set. */ + { "history_file", DT_PATH, R_NONE, UL &HistFile, UL "~/.mutthistory" }, + /* + ** .pp + ** The file in which Mutt will save its history. + */ { "honor_followup_to", DT_QUAD, R_NONE, OPT_MFUPTO, M_YES }, /* ** .pp @@ -2224,6 +2229,12 @@ ** \fBNote:\fP This only applies to mbox and MMDF folders, Mutt does not ** delete MH and Maildir directories. */ + { "save_history", DT_NUM, R_NONE, UL &SaveHist, 0 }, + /* + ** .pp + ** This variable controls the size of the history saved in the + ** ``$$history_file'' file. + */ { "save_name", DT_BOOL, R_NONE, OPTSAVENAME, 0 }, /* ** .pp