1 /* $NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $ */
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #if !defined(lint) && !defined(SCCSID)
38 static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
40 __RCSID("$NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $");
42 #endif /* not lint && not SCCSID */
45 * hist.c: TYPE(History) access functions
53 static const char hist_cookie[] = "_HiStOrY_V2_\n";
61 #define FUN(prefix, rest) prefix ## _ ## rest
62 #define FUNW(type) type
63 #define TYPE(type) type
66 #define Strlen(s) strlen(s)
67 #define Strdup(s) strdup(s)
68 #define Strcmp(d, s) strcmp(d, s)
69 #define Strncmp(d, s, n) strncmp(d, s, n)
70 #define Strncpy(d, s, n) strncpy(d, s, n)
71 #define Strncat(d, s, n) strncat(d, s, n)
72 #define ct_decode_string(s, b) (s)
73 #define ct_encode_string(s, b) (s)
79 #define FUN(prefix, rest) prefix ## _w ## rest
80 #define FUNW(type) type ## _w
81 #define TYPE(type) type ## W
84 #define Strlen(s) wcslen(s)
85 #define Strdup(s) wcsdup(s)
86 #define Strcmp(d, s) wcscmp(d, s)
87 #define Strncmp(d, s, n) wcsncmp(d, s, n)
88 #define Strncpy(d, s, n) wcsncpy(d, s, n)
89 #define Strncat(d, s, n) wcsncat(d, s, n)
94 typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
95 typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
96 typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
97 typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
99 struct TYPE(history) {
100 void *h_ref; /* Argument for history fcns */
101 int h_ent; /* Last entry point for history */
102 history_gfun_t h_first; /* Get the first element */
103 history_gfun_t h_next; /* Get the next element */
104 history_gfun_t h_last; /* Get the last element */
105 history_gfun_t h_prev; /* Get the previous element */
106 history_gfun_t h_curr; /* Get the current element */
107 history_sfun_t h_set; /* Set the current element */
108 history_sfun_t h_del; /* Set the given element */
109 history_vfun_t h_clear; /* Clear the history list */
110 history_efun_t h_enter; /* Add an element */
111 history_efun_t h_add; /* Append to an element */
114 #define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
115 #define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
116 #define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
117 #define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
118 #define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
119 #define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
120 #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
121 #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
122 #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
123 #define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
125 #define h_strdup(a) Strdup(a)
126 #define h_malloc(a) malloc(a)
127 #define h_realloc(a, b) realloc((a), (b))
128 #define h_free(a) free(a)
136 static int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
137 static int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
138 static int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
139 static int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
140 static int history_set_fun(TYPE(History) *, TYPE(History) *);
141 static int history_load(TYPE(History) *, const char *);
142 static int history_save(TYPE(History) *, const char *);
143 static int history_save_fp(TYPE(History) *, size_t, FILE *);
144 static int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
145 static int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
146 static int history_next_string(TYPE(History) *, TYPE(HistEvent) *,
148 static int history_prev_string(TYPE(History) *, TYPE(HistEvent) *,
152 /***********************************************************************/
155 * Builtin- history implementation
157 typedef struct hentry_t {
158 TYPE(HistEvent) ev; /* What we return */
159 void *data; /* data */
160 struct hentry_t *next; /* Next entry */
161 struct hentry_t *prev; /* Previous entry */
164 typedef struct history_t {
165 hentry_t list; /* Fake list header element */
166 hentry_t *cursor; /* Current element in the list */
167 int max; /* Maximum number of events */
168 int cur; /* Current number of events */
169 int eventid; /* For generation of unique event id */
170 int flags; /* TYPE(History) flags */
171 #define H_UNIQUE 1 /* Store only unique elements */
174 static int history_def_next(void *, TYPE(HistEvent) *);
175 static int history_def_first(void *, TYPE(HistEvent) *);
176 static int history_def_prev(void *, TYPE(HistEvent) *);
177 static int history_def_last(void *, TYPE(HistEvent) *);
178 static int history_def_curr(void *, TYPE(HistEvent) *);
179 static int history_def_set(void *, TYPE(HistEvent) *, const int);
180 static void history_def_clear(void *, TYPE(HistEvent) *);
181 static int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
182 static int history_def_add(void *, TYPE(HistEvent) *, const Char *);
183 static int history_def_del(void *, TYPE(HistEvent) *, const int);
185 static int history_def_init(void **, TYPE(HistEvent) *, int);
186 static int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
187 static void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
189 static int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
190 static int history_set_nth(void *, TYPE(HistEvent) *, int);
192 #define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
193 #define history_def_getsize(p) (((history_t *)p)->cur)
194 #define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
195 #define history_def_setunique(p, uni) \
197 (((history_t *)p)->flags) |= H_UNIQUE; \
199 (((history_t *)p)->flags) &= ~H_UNIQUE
201 #define he_strerror(code) he_errlist[code]
202 #define he_seterrev(evp, code) {\
204 evp->str = he_strerror(code);\
208 static const Char *const he_errlist[] = {
210 STR("unknown error"),
211 STR("malloc() failed"),
212 STR("first event not found"),
213 STR("last event not found"),
215 STR("no next event"),
216 STR("no previous event"),
217 STR("current event is invalid"),
218 STR("event not found"),
219 STR("can't read history from file"),
220 STR("can't write history"),
221 STR("required parameter(s) not supplied"),
222 STR("history size negative"),
223 STR("function not allowed with other history-functions-set the default"),
224 STR("bad parameters")
228 #define _HE_UNKNOWN 1
229 #define _HE_MALLOC_FAILED 2
230 #define _HE_FIRST_NOTFOUND 3
231 #define _HE_LAST_NOTFOUND 4
232 #define _HE_EMPTY_LIST 5
233 #define _HE_END_REACHED 6
234 #define _HE_START_REACHED 7
235 #define _HE_CURR_INVALID 8
236 #define _HE_NOT_FOUND 9
237 #define _HE_HIST_READ 10
238 #define _HE_HIST_WRITE 11
239 #define _HE_PARAM_MISSING 12
240 #define _HE_SIZE_NEGATIVE 13
241 #define _HE_NOT_ALLOWED 14
242 #define _HE_BAD_PARAM 15
244 /* history_def_first():
245 * Default function to return the first event in the history.
248 history_def_first(void *p, TYPE(HistEvent) *ev)
250 history_t *h = (history_t *) p;
252 h->cursor = h->list.next;
253 if (h->cursor != &h->list)
256 he_seterrev(ev, _HE_FIRST_NOTFOUND);
264 /* history_def_last():
265 * Default function to return the last event in the history.
268 history_def_last(void *p, TYPE(HistEvent) *ev)
270 history_t *h = (history_t *) p;
272 h->cursor = h->list.prev;
273 if (h->cursor != &h->list)
276 he_seterrev(ev, _HE_LAST_NOTFOUND);
284 /* history_def_next():
285 * Default function to return the next event in the history.
288 history_def_next(void *p, TYPE(HistEvent) *ev)
290 history_t *h = (history_t *) p;
292 if (h->cursor == &h->list) {
293 he_seterrev(ev, _HE_EMPTY_LIST);
297 if (h->cursor->next == &h->list) {
298 he_seterrev(ev, _HE_END_REACHED);
302 h->cursor = h->cursor->next;
309 /* history_def_prev():
310 * Default function to return the previous event in the history.
313 history_def_prev(void *p, TYPE(HistEvent) *ev)
315 history_t *h = (history_t *) p;
317 if (h->cursor == &h->list) {
319 (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
323 if (h->cursor->prev == &h->list) {
324 he_seterrev(ev, _HE_START_REACHED);
328 h->cursor = h->cursor->prev;
335 /* history_def_curr():
336 * Default function to return the current event in the history.
339 history_def_curr(void *p, TYPE(HistEvent) *ev)
341 history_t *h = (history_t *) p;
343 if (h->cursor != &h->list)
347 (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
355 /* history_def_set():
356 * Default function to set the current event in the history to the
360 history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
362 history_t *h = (history_t *) p;
365 he_seterrev(ev, _HE_EMPTY_LIST);
368 if (h->cursor == &h->list || h->cursor->ev.num != n) {
369 for (h->cursor = h->list.next; h->cursor != &h->list;
370 h->cursor = h->cursor->next)
371 if (h->cursor->ev.num == n)
374 if (h->cursor == &h->list) {
375 he_seterrev(ev, _HE_NOT_FOUND);
382 /* history_set_nth():
383 * Default function to set the current event in the history to the
387 history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
389 history_t *h = (history_t *) p;
392 he_seterrev(ev, _HE_EMPTY_LIST);
395 for (h->cursor = h->list.prev; h->cursor != &h->list;
396 h->cursor = h->cursor->prev)
399 if (h->cursor == &h->list) {
400 he_seterrev(ev, _HE_NOT_FOUND);
407 /* history_def_add():
408 * Append string to element
411 history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
413 history_t *h = (history_t *) p;
416 HistEventPrivate *evp = (void *)&h->cursor->ev;
418 if (h->cursor == &h->list)
419 return history_def_enter(p, ev, str);
420 len = Strlen(evp->str) + Strlen(str) + 1;
421 s = h_malloc(len * sizeof(*s));
423 he_seterrev(ev, _HE_MALLOC_FAILED);
426 (void) Strncpy(s, h->cursor->ev.str, len);
428 (void) Strncat(s, str, len - Strlen(s) - 1);
437 history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
438 int num, void **data)
440 if (history_set_nth(h, ev, num) != 0)
442 /* magic value to skip delete (just set to n-th history) */
443 if (data == (void **)-1)
445 ev->str = Strdup(h->cursor->ev.str);
446 ev->num = h->cursor->ev.num;
448 *data = h->cursor->data;
449 history_def_delete(h, ev, h->cursor);
454 /* history_def_del():
455 * Delete element hp of the h list
459 history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
462 history_t *h = (history_t *) p;
463 if (history_def_set(h, ev, num) != 0)
465 ev->str = Strdup(h->cursor->ev.str);
466 ev->num = h->cursor->ev.num;
467 history_def_delete(h, ev, h->cursor);
472 /* history_def_delete():
473 * Delete element hp of the h list
477 history_def_delete(history_t *h,
478 TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
480 HistEventPrivate *evp = (void *)&hp->ev;
483 if (h->cursor == hp) {
484 h->cursor = hp->prev;
485 if (h->cursor == &h->list)
486 h->cursor = hp->next;
488 hp->prev->next = hp->next;
489 hp->next->prev = hp->prev;
496 /* history_def_insert():
497 * Insert element with string str in the h list
500 history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
504 c = h_malloc(sizeof(*c));
507 if ((c->ev.str = h_strdup(str)) == NULL) {
512 c->ev.num = ++h->eventid;
513 c->next = h->list.next;
515 h->list.next->prev = c;
523 he_seterrev(ev, _HE_MALLOC_FAILED);
528 /* history_def_enter():
529 * Default function to enter an item in the history
532 history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
534 history_t *h = (history_t *) p;
536 if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
537 Strcmp(h->list.next->ev.str, str) == 0)
540 if (history_def_insert(h, ev, str) == -1)
541 return -1; /* error, keep error message */
544 * Always keep at least one entry.
545 * This way we don't have to check for the empty list.
547 while (h->cur > h->max && h->cur > 0)
548 history_def_delete(h, ev, h->list.prev);
554 /* history_def_init():
555 * Default history initialization function
559 history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
561 history_t *h = (history_t *) h_malloc(sizeof(*h));
570 h->list.next = h->list.prev = &h->list;
571 h->list.ev.str = NULL;
573 h->cursor = &h->list;
580 /* history_def_clear():
581 * Default history cleanup function
584 history_def_clear(void *p, TYPE(HistEvent) *ev)
586 history_t *h = (history_t *) p;
588 while (h->list.prev != &h->list)
589 history_def_delete(h, ev, h->list.prev);
590 h->cursor = &h->list;
598 /************************************************************************/
601 * Initialization function.
604 FUN(history,init)(void)
607 TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
611 if (history_def_init(&h->h_ref, &ev, 0) == -1) {
616 h->h_next = history_def_next;
617 h->h_first = history_def_first;
618 h->h_last = history_def_last;
619 h->h_prev = history_def_prev;
620 h->h_curr = history_def_curr;
621 h->h_set = history_def_set;
622 h->h_clear = history_def_clear;
623 h->h_enter = history_def_enter;
624 h->h_add = history_def_add;
625 h->h_del = history_def_del;
635 FUN(history,end)(TYPE(History) *h)
639 if (h->h_next == history_def_next)
640 history_def_clear(h->h_ref, &ev);
647 /* history_setsize():
648 * Set history number of events
651 history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
654 if (h->h_next != history_def_next) {
655 he_seterrev(ev, _HE_NOT_ALLOWED);
659 he_seterrev(ev, _HE_BAD_PARAM);
662 history_def_setsize(h->h_ref, num);
667 /* history_getsize():
668 * Get number of events currently in history
671 history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
673 if (h->h_next != history_def_next) {
674 he_seterrev(ev, _HE_NOT_ALLOWED);
677 ev->num = history_def_getsize(h->h_ref);
679 he_seterrev(ev, _HE_SIZE_NEGATIVE);
686 /* history_setunique():
687 * Set if adjacent equal events should not be entered in history.
690 history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
693 if (h->h_next != history_def_next) {
694 he_seterrev(ev, _HE_NOT_ALLOWED);
697 history_def_setunique(h->h_ref, uni);
702 /* history_getunique():
703 * Get if adjacent equal events should not be entered in history.
706 history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
708 if (h->h_next != history_def_next) {
709 he_seterrev(ev, _HE_NOT_ALLOWED);
712 ev->num = history_def_getunique(h->h_ref);
717 /* history_set_fun():
718 * Set history functions
721 history_set_fun(TYPE(History) *h, TYPE(History) *nh)
725 if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
726 nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
727 nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
728 nh->h_del == NULL || nh->h_ref == NULL) {
729 if (h->h_next != history_def_next) {
730 if (history_def_init(&h->h_ref, &ev, 0) == -1)
732 h->h_first = history_def_first;
733 h->h_next = history_def_next;
734 h->h_last = history_def_last;
735 h->h_prev = history_def_prev;
736 h->h_curr = history_def_curr;
737 h->h_set = history_def_set;
738 h->h_clear = history_def_clear;
739 h->h_enter = history_def_enter;
740 h->h_add = history_def_add;
741 h->h_del = history_def_del;
745 if (h->h_next == history_def_next)
746 history_def_clear(h->h_ref, &ev);
749 h->h_first = nh->h_first;
750 h->h_next = nh->h_next;
751 h->h_last = nh->h_last;
752 h->h_prev = nh->h_prev;
753 h->h_curr = nh->h_curr;
754 h->h_set = nh->h_set;
755 h->h_clear = nh->h_clear;
756 h->h_enter = nh->h_enter;
757 h->h_add = nh->h_add;
758 h->h_del = nh->h_del;
765 * TYPE(History) load function
768 history_load(TYPE(History) *h, const char *fname)
780 static ct_buffer_t conv;
783 if ((fp = fopen(fname, "r")) == NULL)
788 if ((sz = getline(&line, &llen, fp)) == -1)
791 if (strncmp(line, hist_cookie, (size_t)sz) != 0)
794 ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
797 for (i = 0; (sz = getline(&line, &llen, fp)) != -1; i++) {
798 if (sz > 0 && line[sz - 1] == '\n')
800 if (max_size < (size_t)sz) {
802 max_size = ((size_t)sz + 1024) & (size_t)~1023;
803 nptr = h_realloc(ptr, max_size * sizeof(*ptr));
810 (void) strunvis(ptr, line);
811 decode_result = ct_decode_string(ptr, &conv);
812 if (decode_result == NULL)
814 if (HENTER(h, &ev, decode_result) == -1) {
828 /* history_save_fp():
829 * TYPE(History) save function
832 history_save_fp(TYPE(History) *h, size_t nelem, FILE *fp)
836 size_t len, max_size;
840 static ct_buffer_t conv;
843 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
845 if (ftell(fp) == 0 && fputs(hist_cookie, fp) == EOF)
847 ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
850 if (nelem != (size_t)-1) {
851 for (retval = HFIRST(h, &ev); retval != -1 && nelem-- > 0;
852 retval = HNEXT(h, &ev))
858 retval = HLAST(h, &ev);
860 for (i = 0; retval != -1; retval = HPREV(h, &ev), i++) {
861 str = ct_encode_string(ev.str, &conv);
862 len = strlen(str) * 4 + 1;
863 if (len > max_size) {
865 max_size = (len + 1024) & (size_t)~1023;
866 nptr = h_realloc(ptr, max_size * sizeof(*ptr));
873 (void) strvis(ptr, str, VIS_WHITE);
874 (void) fprintf(fp, "%s\n", ptr);
884 * History save function
887 history_save(TYPE(History) *h, const char *fname)
892 if ((fp = fopen(fname, "w")) == NULL)
895 i = history_save_fp(h, (size_t)-1, fp);
902 /* history_prev_event():
903 * Find the previous event, with number given
906 history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
910 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
914 he_seterrev(ev, _HE_NOT_FOUND);
920 history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
924 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
925 if (ev->num == num) {
927 *d = ((history_t *)h->h_ref)->cursor->data;
931 he_seterrev(ev, _HE_NOT_FOUND);
936 /* history_next_event():
937 * Find the next event, with number given
940 history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
944 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
948 he_seterrev(ev, _HE_NOT_FOUND);
953 /* history_prev_string():
954 * Find the previous event beginning with string
957 history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
959 size_t len = Strlen(str);
962 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
963 if (Strncmp(str, ev->str, len) == 0)
966 he_seterrev(ev, _HE_NOT_FOUND);
971 /* history_next_string():
972 * Find the next event beginning with string
975 history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
977 size_t len = Strlen(str);
980 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
981 if (Strncmp(str, ev->str, len) == 0)
984 he_seterrev(ev, _HE_NOT_FOUND);
990 * User interface to history functions.
993 FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
1001 he_seterrev(ev, _HE_OK);
1005 retval = history_getsize(h, ev);
1009 retval = history_setsize(h, ev, va_arg(va, int));
1013 retval = history_getunique(h, ev);
1017 retval = history_setunique(h, ev, va_arg(va, int));
1021 str = va_arg(va, const Char *);
1022 retval = HADD(h, ev, str);
1026 retval = HDEL(h, ev, va_arg(va, const int));
1030 str = va_arg(va, const Char *);
1031 if ((retval = HENTER(h, ev, str)) != -1)
1036 str = va_arg(va, const Char *);
1037 if ((retval = HSET(h, ev, h->h_ent)) != -1)
1038 retval = HADD(h, ev, str);
1042 retval = HFIRST(h, ev);
1046 retval = HNEXT(h, ev);
1050 retval = HLAST(h, ev);
1054 retval = HPREV(h, ev);
1058 retval = HCURR(h, ev);
1062 retval = HSET(h, ev, va_arg(va, const int));
1071 retval = history_load(h, va_arg(va, const char *));
1073 he_seterrev(ev, _HE_HIST_READ);
1077 retval = history_save(h, va_arg(va, const char *));
1079 he_seterrev(ev, _HE_HIST_WRITE);
1083 retval = history_save_fp(h, (size_t)-1, va_arg(va, FILE *));
1085 he_seterrev(ev, _HE_HIST_WRITE);
1090 size_t sz = va_arg(va, size_t);
1091 retval = history_save_fp(h, sz, va_arg(va, FILE *));
1093 he_seterrev(ev, _HE_HIST_WRITE);
1098 retval = history_prev_event(h, ev, va_arg(va, int));
1102 retval = history_next_event(h, ev, va_arg(va, int));
1106 retval = history_prev_string(h, ev, va_arg(va, const Char *));
1110 retval = history_next_string(h, ev, va_arg(va, const Char *));
1117 hf.h_ref = va_arg(va, void *);
1119 hf.h_first = va_arg(va, history_gfun_t);
1120 hf.h_next = va_arg(va, history_gfun_t);
1121 hf.h_last = va_arg(va, history_gfun_t);
1122 hf.h_prev = va_arg(va, history_gfun_t);
1123 hf.h_curr = va_arg(va, history_gfun_t);
1124 hf.h_set = va_arg(va, history_sfun_t);
1125 hf.h_clear = va_arg(va, history_vfun_t);
1126 hf.h_enter = va_arg(va, history_efun_t);
1127 hf.h_add = va_arg(va, history_efun_t);
1128 hf.h_del = va_arg(va, history_sfun_t);
1130 if ((retval = history_set_fun(h, &hf)) == -1)
1131 he_seterrev(ev, _HE_PARAM_MISSING);
1136 FUN(history,end)(h);
1142 int num = va_arg(va, int);
1143 void **d = va_arg(va, void **);
1144 retval = history_next_evdata(h, ev, num, d);
1150 int num = va_arg(va, int);
1151 void **d = va_arg(va, void **);
1152 retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
1156 case H_REPLACE: /* only use after H_NEXT_EVDATA */
1158 const Char *line = va_arg(va, const Char *);
1159 void *d = va_arg(va, void *);
1161 if(!line || !(s = Strdup(line))) {
1165 ((history_t *)h->h_ref)->cursor->ev.str = s;
1166 ((history_t *)h->h_ref)->cursor->data = d;
1173 he_seterrev(ev, _HE_UNKNOWN);