diff -Naurd mutt-1.5.12-old/PATCHES mutt-1.5.12-new/PATCHES --- mutt-1.5.12-old/PATCHES 2006-07-14 18:12:47.000000000 +0000 +++ mutt-1.5.12-new/PATCHES 2006-08-03 17:01:28.000000000 +0000 @@ -0,0 +1 @@ +patch-1.5.12.vl.savehist.1 diff -Naurd mutt-1.5.12-old/enter.c mutt-1.5.12-new/enter.c --- mutt-1.5.12-old/enter.c 2006-05-18 18:44:29.000000000 +0000 +++ mutt-1.5.12-new/enter.c 2006-08-03 17:01:28.000000000 +0000 @@ -548,7 +548,7 @@ { mutt_pretty_mailbox (buf); if (!pass) - mutt_history_add (hclass, buf); + mutt_history_add (hclass, buf, 1); rv = 0; goto bye; } @@ -653,7 +653,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 -Naurd mutt-1.5.12-old/globals.h mutt-1.5.12-new/globals.h --- mutt-1.5.12-old/globals.h 2006-07-05 08:40:05.000000000 +0000 +++ mutt-1.5.12-new/globals.h 2006-08-03 17:01:28.000000000 +0000 @@ -51,6 +51,7 @@ WHERE char *ForwFmt; WHERE char *Fqdn; WHERE char *HdrFmt; +WHERE char *HistFile; WHERE char *Homedir; WHERE char *Hostname; #ifdef USE_IMAP @@ -189,6 +190,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 -Naurd mutt-1.5.12-old/history.c mutt-1.5.12-new/history.c --- mutt-1.5.12-old/history.c 2006-07-05 08:40:05.000000000 +0000 +++ mutt-1.5.12-new/history.c 2006-08-03 17:01:28.000000000 +0000 @@ -56,6 +56,144 @@ h->last = 0; } +void mutt_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'; + p = safe_strdup (linebuf + read); + if (p) + { + mutt_convert_string (&p, "utf-8", Charset, 0); + mutt_history_add (hclass, p, 0); + FREE (&p); + } + } + + fclose (f); + FREE (&linebuf); +} + +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); + 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; + char *tmp, *p; + + if (!s || !*s) /* This shouldn't happen, but it's safer. */ + return; + + if ((f = fopen (HistFile, "a")) == NULL) + { + mutt_perror ("fopen"); + return; + } + + tmp = safe_strdup (s); + mutt_convert_string (&tmp, Charset, "utf-8", 0); + + /* Format of a history item (1 line): ":|". + We add a '|' in order to avoid lines ending with '\'. */ + fprintf (f, "%d:", (int) hclass); + for (p = tmp; *p; p++) + { + /* Don't copy \n as a history item must fit on one line. The string + shouldn't contain such a character anyway, but as this can happen + in practice, we must deal with that. */ + if (*p != '\n') + putc ((unsigned char) *p, f); + } + fputs ("|\n", f); + + fclose (f); + FREE (&tmp); + + if (--n < 0) + { + n = SaveHist; + shrink_histfile(); + } +} + void mutt_init_history(void) { history_class_t hclass; @@ -69,7 +207,7 @@ OldSize = HistSize; } -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]; @@ -88,6 +226,8 @@ */ if (*s != ' ' && (!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 -Naurd mutt-1.5.12-old/history.h mutt-1.5.12-new/history.h --- mutt-1.5.12-old/history.h 2005-09-18 08:22:22.000000000 +0000 +++ mutt-1.5.12-new/history.h 2006-08-03 17:01:28.000000000 +0000 @@ -35,7 +35,8 @@ typedef enum history_class history_class_t; void mutt_init_history(void); -void mutt_history_add(history_class_t, const char *); +void mutt_read_histfile(void); +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 -Naurd mutt-1.5.12-old/init.c mutt-1.5.12-new/init.c --- mutt-1.5.12-old/init.c 2006-07-05 08:40:05.000000000 +0000 +++ mutt-1.5.12-new/init.c 2006-08-03 17:01:28.000000000 +0000 @@ -3012,6 +3012,8 @@ mutt_exit(1); } + mutt_read_histfile (); + #if 0 set_option (OPTWEED); /* turn weeding on by default */ #endif diff -Naurd mutt-1.5.12-old/init.h mutt-1.5.12-new/init.h --- mutt-1.5.12-old/init.h 2006-07-05 08:40:05.000000000 +0000 +++ mutt-1.5.12-new/init.h 2006-08-03 17:01:28.000000000 +0000 @@ -779,6 +779,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 @@ -2385,6 +2390,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