NeoMutt  2025-12-11-769-g906513
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
history.c File Reference

Read/write command history from/to a file. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
#include "lib.h"
#include "module_data.h"
+ Include dependency graph for history.c:

Go to the source code of this file.

Macros

#define HC_FIRST   HC_EXT_COMMAND
 

Functions

static struct Historyget_history (enum HistoryClass hclass)
 Get a particular history.
 
static void init_history (struct History *h, int old_size)
 Set up a new History ring buffer.
 
static int dup_hash_dec (struct HashTable *dup_hash, char *str)
 Decrease the refcount of a history string.
 
static int dup_hash_inc (struct HashTable *dup_hash, char *str)
 Increase the refcount of a history string.
 
static void shrink_histfile (void)
 Read, de-dupe and write the history file.
 
static void save_history (enum HistoryClass hclass, const char *str)
 Save one history string to a file.
 
static void remove_history_dups (enum HistoryClass hclass, const char *str)
 De-dupe the history.
 
int mutt_hist_search (const char *find, enum HistoryClass hclass, struct StringArray *matches)
 Find matches in a history list.
 
void mutt_hist_cleanup (void)
 Free all the history lists.
 
void mutt_hist_init (void)
 Create a set of empty History ring buffers.
 
void mutt_hist_add (enum HistoryClass hclass, const char *str, bool save)
 Add a string to a history.
 
char * mutt_hist_next (enum HistoryClass hclass)
 Get the next string in a History.
 
char * mutt_hist_prev (enum HistoryClass hclass)
 Get the previous string in a History.
 
void mutt_hist_reset_state (enum HistoryClass hclass)
 Move the 'current' position to the end of the History.
 
void mutt_hist_read_file (void)
 Read the History from a file.
 
bool mutt_hist_at_scratch (enum HistoryClass hclass)
 Is the current History position at the 'scratch' place?
 
void mutt_hist_save_scratch (enum HistoryClass hclass, const char *str)
 Save a temporary string to the History.
 
void mutt_hist_complete (struct Buffer *buf, enum HistoryClass hclass)
 Complete a string from a history list.
 
int main_hist_observer (struct NotifyCallback *nc)
 Notification that a Config Variable has change - Implements observer_t -.
 

Detailed Description

Read/write command history from/to a file.

Authors
  • Richard Russon
  • Pietro Cerutti
  • Dennis Schön

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file history.c.

Macro Definition Documentation

◆ HC_FIRST

#define HC_FIRST   HC_EXT_COMMAND

Definition at line 84 of file history.c.

Function Documentation

◆ get_history()

static struct History * get_history ( enum HistoryClass hclass)
static

Get a particular history.

Parameters
hclassType of history to find
Return values
ptrHistory ring buffer

Definition at line 91 of file history.c.

92{
94 const short c_history = cs_subset_number(NeoMutt->sub, "history");
95 if ((hclass >= HC_MAX) || (c_history == 0))
96 return NULL;
97
98 struct History *hist = &mod_data->histories[hclass];
99 return hist->hist ? hist : NULL;
100}
short cs_subset_number(const struct ConfigSubset *sub, const char *name)
Get a number config item by name.
Definition helpers.c:143
@ HC_MAX
Definition lib.h:62
@ MODULE_ID_HISTORY
ModuleHistory, History
Definition module_api.h:69
void * neomutt_get_module_data(struct NeoMutt *n, enum ModuleId id)
Get the private data for a Module.
Definition neomutt.c:665
History private Module data.
Definition module_data.h:44
struct History histories[HC_MAX]
Command histories, one for each HistoryClass.
Definition module_data.h:46
Saved list of user-entered commands/searches.
Definition module_data.h:34
char ** hist
Array of history items.
Definition module_data.h:35
Container for Accounts, Notifications.
Definition neomutt.h:41
struct ConfigSubset * sub
Inherited config items.
Definition neomutt.h:49
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ init_history()

static void init_history ( struct History * h,
int old_size )
static

Set up a new History ring buffer.

Parameters
hHistory to populate
old_sizePrevious number of history entries to save

If the History already has entries, they will be freed.

Definition at line 109 of file history.c.

110{
111 if (old_size != 0)
112 {
113 if (h->hist)
114 {
115 for (int i = 0; i <= old_size; i++)
116 FREE(&h->hist[i]);
117 FREE(&h->hist);
118 }
119 }
120
121 const short c_history = cs_subset_number(NeoMutt->sub, "history");
122 if (c_history != 0)
123 h->hist = MUTT_MEM_CALLOC(c_history + 1, char *);
124
125 h->cur = 0;
126 h->last = 0;
127}
#define FREE(x)
Free memory and set the pointer to NULL.
Definition memory.h:68
#define MUTT_MEM_CALLOC(n, type)
Definition memory.h:52
short cur
Current history item.
Definition module_data.h:36
short last
Last history item.
Definition module_data.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dup_hash_dec()

static int dup_hash_dec ( struct HashTable * dup_hash,
char * str )
static

Decrease the refcount of a history string.

Parameters
dup_hashHash Table containing unique history strings
strString to find
Return values
0String was deleted from the Hash Table
>0Refcount of string
-1Error, string not found

If the string's refcount is 1, then the string will be deleted.

Definition at line 139 of file history.c.

140{
141 struct HashElem *he = mutt_hash_find_elem(dup_hash, str);
142 if (!he)
143 return -1;
144
145 uintptr_t count = (uintptr_t) he->data;
146 if (count <= 1)
147 {
148 mutt_hash_delete(dup_hash, str, NULL);
149 return 0;
150 }
151
152 count--;
153 he->data = (void *) count;
154 return count;
155}
void mutt_hash_delete(struct HashTable *table, const char *strkey, const void *data)
Remove an element from a Hash Table.
Definition hash.c:429
struct HashElem * mutt_hash_find_elem(const struct HashTable *table, const char *strkey)
Find the HashElem in a Hash Table element using a key.
Definition hash.c:379
The item stored in a Hash Table.
Definition hash.h:44
void * data
User-supplied data.
Definition hash.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dup_hash_inc()

static int dup_hash_inc ( struct HashTable * dup_hash,
char * str )
static

Increase the refcount of a history string.

Parameters
dup_hashHash Table containing unique history strings
strString to find
Return values
numRefcount of string

If the string isn't found it will be added to the Hash Table.

Definition at line 165 of file history.c.

166{
167 uintptr_t count;
168
169 struct HashElem *he = mutt_hash_find_elem(dup_hash, str);
170 if (!he)
171 {
172 count = 1;
173 mutt_hash_insert(dup_hash, str, (void *) count);
174 return count;
175 }
176
177 count = (uintptr_t) he->data;
178 count++;
179 he->data = (void *) count;
180 return count;
181}
struct HashElem * mutt_hash_insert(struct HashTable *table, const char *strkey, void *data)
Add a new element to the Hash Table (with string keys)
Definition hash.c:337
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ shrink_histfile()

static void shrink_histfile ( void )
static

Read, de-dupe and write the history file.

Definition at line 186 of file history.c.

187{
188 FILE *fp_tmp = NULL;
189 int n[HC_MAX] = { 0 };
190 int line, hclass = 0, read = 0;
191 char *linebuf = NULL, *p = NULL;
192 size_t buflen;
193 bool regen_file = false;
194 struct HashTable *dup_hashes[HC_MAX] = { 0 };
195
196 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
197 FILE *fp = mutt_file_fopen(c_history_file, "r");
198 if (!fp)
199 return;
200
201 /* If duplicate removal is enabled, build per-class hash tables to track
202 * how many times each history entry appears in the file */
203 const bool c_history_remove_dups = cs_subset_bool(NeoMutt->sub, "history_remove_dups");
204 const short c_save_history = cs_subset_number(NeoMutt->sub, "save_history");
205 if (c_history_remove_dups)
206 {
207 for (hclass = 0; hclass < HC_MAX; hclass++)
208 dup_hashes[hclass] = mutt_hash_new(MAX(10, c_save_history * 2), MUTT_HASH_STRDUP_KEYS);
209 }
210
211 /* First pass: count entries per class, detect duplicates, and validate
212 * the file format (each line is "class:entry|") */
213 line = 0;
214 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
215 {
216 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
217 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
218 {
219 mutt_error(_("%s:%d: Bad history file format"), c_history_file, line);
220 regen_file = true;
221 continue;
222 }
223 /* silently ignore too high class (probably newer neomutt) */
224 if (hclass >= HC_MAX)
225 continue;
226 *p = '\0';
227 if (c_history_remove_dups && (dup_hash_inc(dup_hashes[hclass], linebuf + read) > 1))
228 {
229 regen_file = true;
230 continue;
231 }
232 n[hclass]++;
233 }
234
235 if (!regen_file)
236 {
237 for (hclass = HC_FIRST; hclass < HC_MAX; hclass++)
238 {
239 if (n[hclass] > c_save_history)
240 {
241 regen_file = true;
242 break;
243 }
244 }
245 }
246
247 if (regen_file)
248 {
249 /* Second pass: rewrite the file keeping only the most recent
250 * c_save_history entries per class, omitting duplicates */
251 fp_tmp = mutt_file_mkstemp();
252 if (!fp_tmp)
253 {
254 mutt_perror(_("Can't create temporary file"));
255 goto cleanup;
256 }
257 rewind(fp);
258 line = 0;
259 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
260 {
261 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
262 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
263 {
264 continue;
265 }
266 if (hclass >= HC_MAX)
267 continue;
268 *p = '\0';
269 if (c_history_remove_dups && (dup_hash_dec(dup_hashes[hclass], linebuf + read) > 0))
270 {
271 continue;
272 }
273 *p = '|';
274 if (n[hclass]-- <= c_save_history)
275 fprintf(fp_tmp, "%s\n", linebuf);
276 }
277 }
278
279cleanup:
280 mutt_file_fclose(&fp);
281 FREE(&linebuf);
282 if (fp_tmp)
283 {
284 if (fflush(fp_tmp) == 0)
285 {
286 fp = mutt_file_fopen(c_history_file, "w");
287 if (fp)
288 {
289 rewind(fp_tmp);
290 mutt_file_copy_stream(fp_tmp, fp);
291 mutt_file_fclose(&fp);
292 }
293 }
294 mutt_file_fclose(&fp_tmp);
295 }
296 if (c_history_remove_dups)
297 for (hclass = 0; hclass < HC_MAX; hclass++)
298 mutt_hash_free(&dup_hashes[hclass]);
299}
const char * cs_subset_path(const struct ConfigSubset *sub, const char *name)
Get a path config item by name.
Definition helpers.c:168
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
Definition helpers.c:47
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition file.c:224
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition file.c:678
#define mutt_file_fclose(FP)
Definition file.h:139
#define mutt_file_fopen(PATH, MODE)
Definition file.h:138
#define MUTT_RL_NO_FLAGS
No flags are set.
Definition file.h:40
#define mutt_error(...)
Definition logging2.h:94
#define mutt_perror(...)
Definition logging2.h:95
struct HashTable * mutt_hash_new(size_t num_elems, HashFlags flags)
Create a new Hash Table (with string keys)
Definition hash.c:261
void mutt_hash_free(struct HashTable **ptr)
Free a hash table.
Definition hash.c:459
#define MUTT_HASH_STRDUP_KEYS
make a copy of the keys
Definition hash.h:113
static int dup_hash_inc(struct HashTable *dup_hash, char *str)
Increase the refcount of a history string.
Definition history.c:165
#define HC_FIRST
Definition history.c:84
static int dup_hash_dec(struct HashTable *dup_hash, char *str)
Decrease the refcount of a history string.
Definition history.c:139
#define MAX(a, b)
Return the maximum of two values.
Definition memory.h:38
#define _(a)
Definition message.h:28
A Hash Table.
Definition hash.h:99
#define mutt_file_mkstemp()
Definition tmp.h:36
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ save_history()

static void save_history ( enum HistoryClass hclass,
const char * str )
static

Save one history string to a file.

Parameters
hclassHistory type
strString to save

Definition at line 306 of file history.c.

307{
308 if (!str || (*str == '\0')) // This shouldn't happen, but it's safer
309 return;
310
311 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
312 FILE *fp = mutt_file_fopen(c_history_file, "a");
313 if (!fp)
314 return;
315
316 char *tmp = mutt_str_dup(str);
318
319 // If tmp contains '\n' terminate it there.
320 char *nl = strchr(tmp, '\n');
321 if (nl)
322 *nl = '\0';
323
324 /* Format of a history item (1 line): "<histclass>:<string>|".
325 * We add a '|' in order to avoid lines ending with '\'. */
326 fprintf(fp, "%d:%s|\n", (int) hclass, tmp);
327
328 mutt_file_fclose(&fp);
329 FREE(&tmp);
330
332}
const char * cc_charset(void)
Get the cached value of $charset.
static void shrink_histfile(void)
Read, de-dupe and write the history file.
Definition history.c:186
int mutt_ch_convert_string(char **ps, const char *from, const char *to, uint8_t flags)
Convert a string between encodings.
Definition charset.c:817
#define MUTT_ICONV_NO_FLAGS
No flags are set.
Definition charset.h:66
char * mutt_str_dup(const char *str)
Copy a string, safely.
Definition string.c:257
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ remove_history_dups()

static void remove_history_dups ( enum HistoryClass hclass,
const char * str )
static

De-dupe the history.

Parameters
hclassHistory to de-dupe
strString to find

If the string is found, it is removed from the history.

When removing dups, we want the created "blanks" to be right below the resulting h->last position. See the comment section above 'struct History'.

Definition at line 344 of file history.c.

345{
346 struct History *h = get_history(hclass);
347 if (!h)
348 return; /* disabled */
349
350 /* Remove dups from 0..last-1 compacting up. */
351 int source = 0;
352 int dest = 0;
353 while (source < h->last)
354 {
355 if (mutt_str_equal(h->hist[source], str))
356 FREE(&h->hist[source++]);
357 else
358 h->hist[dest++] = h->hist[source++];
359 }
360
361 /* Move 'last' entry up. */
362 h->hist[dest] = h->hist[source];
363 int old_last = h->last;
364 h->last = dest;
365
366 /* Fill in moved entries with NULL */
367 while (source > h->last)
368 h->hist[source--] = NULL;
369
370 /* Remove dups from last+1 .. `$history` compacting down. */
371 const short c_history = cs_subset_number(NeoMutt->sub, "history");
372 source = c_history;
373 dest = c_history;
374 while (source > old_last)
375 {
376 if (mutt_str_equal(h->hist[source], str))
377 FREE(&h->hist[source--]);
378 else
379 h->hist[dest--] = h->hist[source--];
380 }
381
382 /* Fill in moved entries with NULL */
383 while (dest > old_last)
384 h->hist[dest--] = NULL;
385}
static struct History * get_history(enum HistoryClass hclass)
Get a particular history.
Definition history.c:91
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition string.c:665
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_search()

int mutt_hist_search ( const char * find,
enum HistoryClass hclass,
struct StringArray * matches )

Find matches in a history list.

Parameters
[in]findString to find
[in]hclassHistory list
[out]matchesAll the matching lines
Return values
numMatches found

Definition at line 394 of file history.c.

395{
396 if (!find || !matches)
397 return 0;
398
399 struct History *h = get_history(hclass);
400 if (!h)
401 return 0;
402
403 int cur = h->last;
404 const short c_history = cs_subset_number(NeoMutt->sub, "history");
405
406 do
407 {
408 cur--;
409 if (cur < 0)
410 cur = c_history;
411
412 if (cur == h->last)
413 break;
414
415 if (mutt_istr_find(h->hist[cur], find))
416 ARRAY_ADD(matches, h->hist[cur]);
417
418 } while (ARRAY_SIZE(matches) < c_history);
419
420 return ARRAY_SIZE(matches);
421}
#define ARRAY_ADD(head, elem)
Add an element at the end of the array.
Definition array.h:157
#define ARRAY_SIZE(head)
The number of elements stored.
Definition array.h:87
const char * mutt_istr_find(const char *haystack, const char *needle)
Find first occurrence of string (ignoring case)
Definition string.c:528
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_cleanup()

void mutt_hist_cleanup ( void )

Free all the history lists.

Definition at line 426 of file history.c.

427{
429 for (enum HistoryClass hclass = HC_FIRST; hclass < HC_MAX; hclass++)
430 {
431 struct History *h = &mod_data->histories[hclass];
432 if (!h->hist)
433 continue;
434
435 /* The array has (mod_data->old_size+1) elements */
436 for (int i = 0; i <= mod_data->old_size; i++)
437 {
438 FREE(&h->hist[i]);
439 }
440 FREE(&h->hist);
441 }
442}
HistoryClass
Type to differentiate different histories.
Definition lib.h:54
int old_size
The previous number of history entries to save.
Definition module_data.h:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_init()

void mutt_hist_init ( void )

Create a set of empty History ring buffers.

This just creates empty histories. To fill them, call mutt_hist_read_file().

Definition at line 450 of file history.c.

451{
453 const short c_history = cs_subset_number(NeoMutt->sub, "history");
454 if (c_history == mod_data->old_size)
455 return;
456
457 for (enum HistoryClass hclass = HC_FIRST; hclass < HC_MAX; hclass++)
458 init_history(&mod_data->histories[hclass], mod_data->old_size);
459
460 mod_data->old_size = c_history;
461}
static void init_history(struct History *h, int old_size)
Set up a new History ring buffer.
Definition history.c:109
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_add()

void mutt_hist_add ( enum HistoryClass hclass,
const char * str,
bool save )

Add a string to a history.

Parameters
hclassHistory to add to
strString to add
saveShould the changes be saved to file immediately?

Definition at line 469 of file history.c.

470{
471 struct History *h = get_history(hclass);
472 if (!h)
473 return; /* disabled */
474
475 if (str && *str)
476 {
477 int prev = h->last - 1;
478 const short c_history = cs_subset_number(NeoMutt->sub, "history");
479 if (prev < 0)
480 prev = c_history;
481
482 /* don't add to prompt history:
483 * - lines beginning by a space
484 * - repeated lines */
485 if ((*str != ' ') && (!h->hist[prev] || !mutt_str_equal(h->hist[prev], str)))
486 {
487 const bool c_history_remove_dups = cs_subset_bool(NeoMutt->sub, "history_remove_dups");
488 if (c_history_remove_dups)
489 remove_history_dups(hclass, str);
490 const short c_save_history = cs_subset_number(NeoMutt->sub, "save_history");
491 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
492 if (save && (c_save_history != 0) && c_history_file)
493 save_history(hclass, str);
494 mutt_str_replace(&h->hist[h->last++], str);
495 if (h->last > c_history)
496 h->last = 0;
497 }
498 }
499 h->cur = h->last; /* reset to the last entry */
500}
static void remove_history_dups(enum HistoryClass hclass, const char *str)
De-dupe the history.
Definition history.c:344
static void save_history(enum HistoryClass hclass, const char *str)
Save one history string to a file.
Definition history.c:306
char * mutt_str_replace(char **p, const char *s)
Replace one string with another.
Definition string.c:284
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_next()

char * mutt_hist_next ( enum HistoryClass hclass)

Get the next string in a History.

Parameters
hclassHistory to choose
Return values
ptrNext string

If there is no next string, and empty string will be returned.

Definition at line 509 of file history.c.

510{
511 struct History *h = get_history(hclass);
512 if (!h)
513 return ""; /* disabled */
514
515 int next = h->cur;
516 const short c_history = cs_subset_number(NeoMutt->sub, "history");
517 do
518 {
519 next++;
520 if (next > c_history)
521 next = 0;
522 if (next == h->last)
523 break;
524 } while (!h->hist[next]);
525
526 h->cur = next;
527 return NONULL(h->hist[h->cur]);
528}
#define NONULL(x)
Definition string2.h:44
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_prev()

char * mutt_hist_prev ( enum HistoryClass hclass)

Get the previous string in a History.

Parameters
hclassHistory to choose
Return values
ptrPrevious string

If there is no previous string, and empty string will be returned.

Definition at line 537 of file history.c.

538{
539 struct History *h = get_history(hclass);
540 if (!h)
541 return ""; /* disabled */
542
543 int prev = h->cur;
544 const short c_history = cs_subset_number(NeoMutt->sub, "history");
545 do
546 {
547 prev--;
548 if (prev < 0)
549 prev = c_history;
550 if (prev == h->last)
551 break;
552 } while (!h->hist[prev]);
553
554 h->cur = prev;
555 return NONULL(h->hist[h->cur]);
556}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_reset_state()

void mutt_hist_reset_state ( enum HistoryClass hclass)

Move the 'current' position to the end of the History.

Parameters
hclassHistory to reset

After calling mutt_hist_next() and mutt_hist_prev(), this function resets the current position ('cur' pointer).

Definition at line 565 of file history.c.

566{
567 struct History *h = get_history(hclass);
568 if (!h)
569 return; /* disabled */
570
571 h->cur = h->last;
572}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_read_file()

void mutt_hist_read_file ( void )

Read the History from a file.

The file $history_file is read and parsed into separate History ring buffers.

Definition at line 579 of file history.c.

580{
581 const char *const c_history_file = cs_subset_path(NeoMutt->sub, "history_file");
582 if (!c_history_file)
583 return;
584
585 FILE *fp = mutt_file_fopen(c_history_file, "r");
586 if (!fp)
587 return;
588
589 int line = 0, hclass = 0, read = 0;
590 char *linebuf = NULL, *p = NULL;
591 size_t buflen;
592
593 const char *const c_charset = cc_charset();
594 while ((linebuf = mutt_file_read_line(linebuf, &buflen, fp, &line, MUTT_RL_NO_FLAGS)))
595 {
596 read = 0;
597 if ((sscanf(linebuf, "%d:%n", &hclass, &read) < 1) || (read == 0) ||
598 (*(p = linebuf + strlen(linebuf) - 1) != '|') || (hclass < 0))
599 {
600 mutt_error(_("%s:%d: Bad history file format"), c_history_file, line);
601 continue;
602 }
603 /* silently ignore too high class (probably newer neomutt) */
604 if (hclass >= HC_MAX)
605 continue;
606 *p = '\0';
607 p = mutt_str_dup(linebuf + read);
608 if (p)
609 {
610 mutt_ch_convert_string(&p, "utf-8", c_charset, MUTT_ICONV_NO_FLAGS);
611 mutt_hist_add(hclass, p, false);
612 FREE(&p);
613 }
614 }
615
616 mutt_file_fclose(&fp);
617 FREE(&linebuf);
618}
void mutt_hist_add(enum HistoryClass hclass, const char *str, bool save)
Add a string to a history.
Definition history.c:469
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_at_scratch()

bool mutt_hist_at_scratch ( enum HistoryClass hclass)

Is the current History position at the 'scratch' place?

Parameters
hclassHistory to use
Return values
trueHistory is at 'scratch' place

The last entry in the history is used as a 'scratch' area. It can be overwritten as the user types and edits.

To get (back) to the scratch area, call mutt_hist_next(), mutt_hist_prev() or mutt_hist_reset_state().

Definition at line 631 of file history.c.

632{
633 struct History *h = get_history(hclass);
634 if (!h)
635 return false; /* disabled */
636
637 return h->cur == h->last;
638}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_save_scratch()

void mutt_hist_save_scratch ( enum HistoryClass hclass,
const char * str )

Save a temporary string to the History.

Parameters
hclassHistory to alter
strString to set

Write a 'scratch' string into the History's current position. This is useful to preserver a user's edits.

Definition at line 648 of file history.c.

649{
650 struct History *h = get_history(hclass);
651 if (!h)
652 return; /* disabled */
653
654 /* Don't check if str has a value because the scratch buffer may contain
655 * an old garbage value that should be overwritten */
656 mutt_str_replace(&h->hist[h->last], str);
657}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_hist_complete()

void mutt_hist_complete ( struct Buffer * buf,
enum HistoryClass hclass )

Complete a string from a history list.

Parameters
bufBuffer in which to save string
hclassHistory list to use

Definition at line 664 of file history.c.

665{
666 struct StringArray matches = ARRAY_HEAD_INITIALIZER;
667
668 int match_count = mutt_hist_search(buf_string(buf), hclass, &matches);
669 if (match_count != 0)
670 {
671 if (match_count == 1)
672 {
673 const char **pstr = ARRAY_GET(&matches, 0);
674 buf_strcpy(buf, *pstr);
675 }
676 else
677 {
678 dlg_history(buf, &matches);
679 }
680 }
681
682 ARRAY_FREE(&matches);
683}
#define ARRAY_FREE(head)
Release all memory.
Definition array.h:209
#define ARRAY_GET(head, idx)
Return the element at index.
Definition array.h:109
#define ARRAY_HEAD_INITIALIZER
Static initializer for arrays.
Definition array.h:58
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition buffer.c:395
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition buffer.h:96
void dlg_history(struct Buffer *buf, struct StringArray *matches)
Select an item from a history list -.
int mutt_hist_search(const char *find, enum HistoryClass hclass, struct StringArray *matches)
Find matches in a history list.
Definition history.c:394
+ Here is the call graph for this function:
+ Here is the caller graph for this function: