| 3.1 | --- a/history.c Mon Feb 26 16:54:26 2007 +0000
|
| 3.2 | +++ b/history.c Mon Feb 26 17:17:13 2007 +0000
|
| 3.3 | @@ -56,6 +56,145 @@
|
| 3.4 | h->last = 0;
|
| 3.5 | }
|
| 3.6 |
|
| 3.7 | +void mutt_read_histfile (void)
|
| 3.8 | +{
|
| 3.9 | + FILE *f;
|
| 3.10 | + int line = 0, hclass, read;
|
| 3.11 | + char *linebuf = NULL, *p;
|
| 3.12 | + size_t buflen;
|
| 3.13 | +
|
| 3.14 | + if ((f = fopen (HistFile, "r")) == NULL)
|
| 3.15 | + return;
|
| 3.16 | +
|
| 3.17 | + while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
|
| 3.18 | + {
|
| 3.19 | + read = 0;
|
| 3.20 | + if (sscanf (linebuf, "%d:%n", &hclass, &read) < 1 || read == 0 ||
|
| 3.21 | + *(p = linebuf + strlen (linebuf) - 1) != '|')
|
| 3.22 | + {
|
| 3.23 | + mutt_error (_("Bad history file format (line %d)"), line);
|
| 3.24 | + break;
|
| 3.25 | + }
|
| 3.26 | + *p = '\0';
|
| 3.27 | + p = safe_strdup (linebuf + read);
|
| 3.28 | + if (p)
|
| 3.29 | + {
|
| 3.30 | + mutt_convert_string (&p, "utf-8", Charset, 0);
|
| 3.31 | + mutt_history_add (hclass, p, 0);
|
| 3.32 | + FREE (&p);
|
| 3.33 | + }
|
| 3.34 | + }
|
| 3.35 | +
|
| 3.36 | + fclose (f);
|
| 3.37 | + FREE (&linebuf);
|
| 3.38 | +}
|
| 3.39 | +
|
| 3.40 | +static void shrink_histfile (void)
|
| 3.41 | +{
|
| 3.42 | + char tmpfname[_POSIX_PATH_MAX];
|
| 3.43 | + FILE *f, *tmp = NULL;
|
| 3.44 | + int n[HC_LAST] = { 0 };
|
| 3.45 | + int line, hclass;
|
| 3.46 | + char *linebuf = NULL;
|
| 3.47 | + size_t buflen;
|
| 3.48 | +
|
| 3.49 | + if ((f = fopen (HistFile, "r")) == NULL)
|
| 3.50 | + return;
|
| 3.51 | +
|
| 3.52 | + line = 0;
|
| 3.53 | + while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
|
| 3.54 | + {
|
| 3.55 | + if (sscanf (linebuf, "%d", &hclass) < 1)
|
| 3.56 | + {
|
| 3.57 | + mutt_error (_("Bad history file format (line %d)"), line);
|
| 3.58 | + goto cleanup;
|
| 3.59 | + }
|
| 3.60 | + n[hclass]++;
|
| 3.61 | + }
|
| 3.62 | +
|
| 3.63 | + for(hclass = HC_FIRST; hclass < HC_LAST; hclass++)
|
| 3.64 | + if (n[hclass] > SaveHist)
|
| 3.65 | + {
|
| 3.66 | + mutt_mktemp (tmpfname);
|
| 3.67 | + if ((tmp = safe_fopen (tmpfname, "w+")) == NULL)
|
| 3.68 | + mutt_perror (tmpfname);
|
| 3.69 | + break;
|
| 3.70 | + }
|
| 3.71 | +
|
| 3.72 | + if (tmp != NULL)
|
| 3.73 | + {
|
| 3.74 | + rewind (f);
|
| 3.75 | + line = 0;
|
| 3.76 | + while ((linebuf = mutt_read_line (linebuf, &buflen, f, &line)) != NULL)
|
| 3.77 | + {
|
| 3.78 | + if (sscanf (linebuf, "%d", &hclass) < 1)
|
| 3.79 | + {
|
| 3.80 | + mutt_error (_("Bad history file format (line %d)"), line);
|
| 3.81 | + goto cleanup;
|
| 3.82 | + }
|
| 3.83 | + if (n[hclass]-- <= SaveHist)
|
| 3.84 | + fprintf (tmp, "%s\n", linebuf);
|
| 3.85 | + }
|
| 3.86 | + }
|
| 3.87 | +
|
| 3.88 | +cleanup:
|
| 3.89 | + fclose (f);
|
| 3.90 | + FREE (&linebuf);
|
| 3.91 | + if (tmp != NULL)
|
| 3.92 | + {
|
| 3.93 | + if (fflush (tmp) == 0 &&
|
| 3.94 | + (f = fopen (HistFile, "w")) != NULL) /* __FOPEN_CHECKED__ */
|
| 3.95 | + {
|
| 3.96 | + rewind (tmp);
|
| 3.97 | + mutt_copy_stream (tmp, f);
|
| 3.98 | + fclose (f);
|
| 3.99 | + }
|
| 3.100 | + fclose (tmp);
|
| 3.101 | + unlink (tmpfname);
|
| 3.102 | + }
|
| 3.103 | +}
|
| 3.104 | +
|
| 3.105 | +static void save_history (history_class_t hclass, const char *s)
|
| 3.106 | +{
|
| 3.107 | + static int n = 0;
|
| 3.108 | + FILE *f;
|
| 3.109 | + char *tmp, *p;
|
| 3.110 | +
|
| 3.111 | + if (!s || !*s) /* This shouldn't happen, but it's safer. */
|
| 3.112 | + return;
|
| 3.113 | +
|
| 3.114 | + if ((f = fopen (HistFile, "a")) == NULL)
|
| 3.115 | + {
|
| 3.116 | + mutt_perror ("fopen");
|
| 3.117 | + return;
|
| 3.118 | + }
|
| 3.119 | +
|
| 3.120 | + tmp = safe_strdup (s);
|
| 3.121 | + mutt_convert_string (&tmp, Charset, "utf-8", 0);
|
| 3.122 | +
|
| 3.123 | + /* Format of a history item (1 line): "<histclass>:<string>|".
|
| 3.124 | + We add a '|' in order to avoid lines ending with '\'. */
|
| 3.125 | + fprintf (f, "%d:", (int) hclass);
|
| 3.126 | + for (p = tmp; *p; p++)
|
| 3.127 | + {
|
| 3.128 | + /* Don't copy \n as a history item must fit on one line. The string
|
| 3.129 | + shouldn't contain such a character anyway, but as this can happen
|
| 3.130 | + in practice, we must deal with that. */
|
| 3.131 | + if (*p != '\n')
|
| 3.132 | + putc ((unsigned char) *p, f);
|
| 3.133 | + }
|
| 3.134 | + fputs ("|\n", f);
|
| 3.135 | +
|
| 3.136 | + fclose (f);
|
| 3.137 | + FREE (&tmp);
|
| 3.138 | +
|
| 3.139 | + if (--n < 0)
|
| 3.140 | + {
|
| 3.141 | + n = SaveHist;
|
| 3.142 | + shrink_histfile();
|
| 3.143 | + }
|
| 3.144 | +}
|
| 3.145 | +
|
| 3.146 | void mutt_init_history(void)
|
| 3.147 | {
|
| 3.148 | history_class_t hclass;
|
| 3.149 | @@ -69,7 +208,7 @@
|
| 3.150 | OldSize = HistSize;
|
| 3.151 | }
|
| 3.152 |
|
| 3.153 | -void mutt_history_add (history_class_t hclass, const char *s)
|
| 3.154 | +void mutt_history_add (history_class_t hclass, const char *s, int save)
|
| 3.155 | {
|
| 3.156 | int prev;
|
| 3.157 | struct history *h = &History[hclass];
|
| 3.158 | @@ -88,6 +227,8 @@
|
| 3.159 | */
|
| 3.160 | if (*s != ' ' && (!h->hist[prev] || mutt_strcmp (h->hist[prev], s) != 0))
|
| 3.161 | {
|
| 3.162 | + if (save && SaveHist)
|
| 3.163 | + save_history (hclass, s);
|
| 3.164 | mutt_str_replace (&h->hist[h->last++], s);
|
| 3.165 | if (h->last > HistSize - 1)
|
| 3.166 | h->last = 0;
|
| 6.1 | --- a/init.h Mon Feb 26 16:54:26 2007 +0000
|
| 6.2 | +++ b/init.h Mon Feb 26 17:17:13 2007 +0000
|
| 6.3 | @@ -828,6 +828,11 @@
|
| 6.4 | ** the string history buffer. The buffer is cleared each time the
|
| 6.5 | ** variable is set.
|
| 6.6 | */
|
| 6.7 | + { "history_file", DT_PATH, R_NONE, UL &HistFile, UL "~/.mutthistory" },
|
| 6.8 | + /*
|
| 6.9 | + ** .pp
|
| 6.10 | + ** The file in which Mutt will save its history.
|
| 6.11 | + */
|
| 6.12 | { "honor_followup_to", DT_QUAD, R_NONE, OPT_MFUPTO, M_YES },
|
| 6.13 | /*
|
| 6.14 | ** .pp
|
| 6.15 | @@ -2438,6 +2443,12 @@
|
| 6.16 | ** \fBNote:\fP This only applies to mbox and MMDF folders, Mutt does not
|
| 6.17 | ** delete MH and Maildir directories.
|
| 6.18 | */
|
| 6.19 | + { "save_history", DT_NUM, R_NONE, UL &SaveHist, 0 },
|
| 6.20 | + /*
|
| 6.21 | + ** .pp
|
| 6.22 | + ** This variable controls the size of the history saved in the
|
| 6.23 | + ** ``$$history_file'' file.
|
| 6.24 | + */
|
| 6.25 | { "save_name", DT_BOOL, R_NONE, OPTSAVENAME, 0 },
|
| 6.26 | /*
|
| 6.27 | ** .pp
|