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
39 #if !defined(lint) && !defined(SCCSID)
41 static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
43 __RCSID("$NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $");
45 #endif /* not lint && not SCCSID */
48 * hist.c: TYPE(History) access functions
56 static const char hist_cookie[] = "_HiStOrY_V2_\n";
64 #define FUN(prefix, rest) prefix ## _ ## rest
65 #define FUNW(type) type
66 #define TYPE(type) type
69 #define Strlen(s) strlen(s)
70 #define Strdup(s) strdup(s)
71 #define Strcmp(d, s) strcmp(d, s)
72 #define Strncmp(d, s, n) strncmp(d, s, n)
73 #define Strncpy(d, s, n) strncpy(d, s, n)
74 #define Strncat(d, s, n) strncat(d, s, n)
75 #define ct_decode_string(s, b) (s)
76 #define ct_encode_string(s, b) (s)
82 #define FUN(prefix, rest) prefix ## _w ## rest
83 #define FUNW(type) type ## _w
84 #define TYPE(type) type ## W
87 #define Strlen(s) wcslen(s)
88 #define Strdup(s) wcsdup(s)
89 #define Strcmp(d, s) wcscmp(d, s)
90 #define Strncmp(d, s, n) wcsncmp(d, s, n)
91 #define Strncpy(d, s, n) wcsncpy(d, s, n)
92 #define Strncat(d, s, n) wcsncat(d, s, n)
97 typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
98 typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
99 typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
100 typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
102 struct TYPE(history) {
103 void *h_ref; /* Argument for history fcns */
104 int h_ent; /* Last entry point for history */
105 history_gfun_t h_first; /* Get the first element */
106 history_gfun_t h_next; /* Get the next element */
107 history_gfun_t h_last; /* Get the last element */
108 history_gfun_t h_prev; /* Get the previous element */
109 history_gfun_t h_curr; /* Get the current element */
110 history_sfun_t h_set; /* Set the current element */
111 history_sfun_t h_del; /* Set the given element */
112 history_vfun_t h_clear; /* Clear the history list */
113 history_efun_t h_enter; /* Add an element */
114 history_efun_t h_add; /* Append to an element */
117 #define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
118 #define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
119 #define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
120 #define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
121 #define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
122 #define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
123 #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
124 #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
125 #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
126 #define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
128 #define h_strdup(a) Strdup(a)
129 #define h_malloc(a) malloc(a)
130 #define h_realloc(a, b) realloc((a), (b))
131 #define h_free(a) free(a)
139 static int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
140 static int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
141 static int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
142 static int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
143 static int history_set_fun(TYPE(History) *, TYPE(History) *);
144 static int history_load(TYPE(History) *, const char *);
145 static int history_save(TYPE(History) *, const char *);
146 static int history_save_fp(TYPE(History) *, size_t, FILE *);
147 static int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
148 static int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
149 static int history_next_string(TYPE(History) *, TYPE(HistEvent) *,
151 static int history_prev_string(TYPE(History) *, TYPE(HistEvent) *,
155 /***********************************************************************/
158 * Builtin- history implementation
160 typedef struct hentry_t {
161 TYPE(HistEvent) ev; /* What we return */
162 void *data; /* data */
163 struct hentry_t *next; /* Next entry */
164 struct hentry_t *prev; /* Previous entry */
167 typedef struct history_t {
168 hentry_t list; /* Fake list header element */
169 hentry_t *cursor; /* Current element in the list */
170 int max; /* Maximum number of events */
171 int cur; /* Current number of events */
172 int eventid; /* For generation of unique event id */
173 int flags; /* TYPE(History) flags */
174 #define H_UNIQUE 1 /* Store only unique elements */
177 static int history_def_next(void *, TYPE(HistEvent) *);
178 static int history_def_first(void *, TYPE(HistEvent) *);
179 static int history_def_prev(void *, TYPE(HistEvent) *);
180 static int history_def_last(void *, TYPE(HistEvent) *);
181 static int history_def_curr(void *, TYPE(HistEvent) *);
182 static int history_def_set(void *, TYPE(HistEvent) *, const int);
183 static void history_def_clear(void *, TYPE(HistEvent) *);
184 static int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
185 static int history_def_add(void *, TYPE(HistEvent) *, const Char *);
186 static int history_def_del(void *, TYPE(HistEvent) *, const int);
188 static int history_def_init(void **, TYPE(HistEvent) *, int);
189 static int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
190 static void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
192 static int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
193 static int history_set_nth(void *, TYPE(HistEvent) *, int);
195 #define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
196 #define history_def_getsize(p) (((history_t *)p)->cur)
197 #define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
198 #define history_def_setunique(p, uni) \
200 (((history_t *)p)->flags) |= H_UNIQUE; \
202 (((history_t *)p)->flags) &= ~H_UNIQUE
204 #define he_strerror(code) he_errlist[code]
205 #define he_seterrev(evp, code) {\
207 evp->str = he_strerror(code);\
211 static const Char *const he_errlist[] = {
213 STR("unknown error"),
214 STR("malloc() failed"),
215 STR("first event not found"),
216 STR("last event not found"),
218 STR("no next event"),
219 STR("no previous event"),
220 STR("current event is invalid"),
221 STR("event not found"),
222 STR("can't read history from file"),
223 STR("can't write history"),
224 STR("required parameter(s) not supplied"),
225 STR("history size negative"),
226 STR("function not allowed with other history-functions-set the default"),
227 STR("bad parameters")
231 #define _HE_UNKNOWN 1
232 #define _HE_MALLOC_FAILED 2
233 #define _HE_FIRST_NOTFOUND 3
234 #define _HE_LAST_NOTFOUND 4
235 #define _HE_EMPTY_LIST 5
236 #define _HE_END_REACHED 6
237 #define _HE_START_REACHED 7
238 #define _HE_CURR_INVALID 8
239 #define _HE_NOT_FOUND 9
240 #define _HE_HIST_READ 10
241 #define _HE_HIST_WRITE 11
242 #define _HE_PARAM_MISSING 12
243 #define _HE_SIZE_NEGATIVE 13
244 #define _HE_NOT_ALLOWED 14
245 #define _HE_BAD_PARAM 15
247 /* history_def_first():
248 * Default function to return the first event in the history.
251 history_def_first(void *p, TYPE(HistEvent) *ev)
253 history_t *h = (history_t *) p;
255 h->cursor = h->list.next;
256 if (h->cursor != &h->list)
259 he_seterrev(ev, _HE_FIRST_NOTFOUND);
267 /* history_def_last():
268 * Default function to return the last event in the history.
271 history_def_last(void *p, TYPE(HistEvent) *ev)
273 history_t *h = (history_t *) p;
275 h->cursor = h->list.prev;
276 if (h->cursor != &h->list)
279 he_seterrev(ev, _HE_LAST_NOTFOUND);
287 /* history_def_next():
288 * Default function to return the next event in the history.
291 history_def_next(void *p, TYPE(HistEvent) *ev)
293 history_t *h = (history_t *) p;
295 if (h->cursor == &h->list) {
296 he_seterrev(ev, _HE_EMPTY_LIST);
300 if (h->cursor->next == &h->list) {
301 he_seterrev(ev, _HE_END_REACHED);
305 h->cursor = h->cursor->next;
312 /* history_def_prev():
313 * Default function to return the previous event in the history.
316 history_def_prev(void *p, TYPE(HistEvent) *ev)
318 history_t *h = (history_t *) p;
320 if (h->cursor == &h->list) {
322 (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
326 if (h->cursor->prev == &h->list) {
327 he_seterrev(ev, _HE_START_REACHED);
331 h->cursor = h->cursor->prev;
338 /* history_def_curr():
339 * Default function to return the current event in the history.
342 history_def_curr(void *p, TYPE(HistEvent) *ev)
344 history_t *h = (history_t *) p;
346 if (h->cursor != &h->list)
350 (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
358 /* history_def_set():
359 * Default function to set the current event in the history to the
363 history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
365 history_t *h = (history_t *) p;
368 he_seterrev(ev, _HE_EMPTY_LIST);
371 if (h->cursor == &h->list || h->cursor->ev.num != n) {
372 for (h->cursor = h->list.next; h->cursor != &h->list;
373 h->cursor = h->cursor->next)
374 if (h->cursor->ev.num == n)
377 if (h->cursor == &h->list) {
378 he_seterrev(ev, _HE_NOT_FOUND);
385 /* history_set_nth():
386 * Default function to set the current event in the history to the
390 history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
392 history_t *h = (history_t *) p;
395 he_seterrev(ev, _HE_EMPTY_LIST);
398 for (h->cursor = h->list.prev; h->cursor != &h->list;
399 h->cursor = h->cursor->prev)
402 if (h->cursor == &h->list) {
403 he_seterrev(ev, _HE_NOT_FOUND);
410 /* history_def_add():
411 * Append string to element
414 history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
416 history_t *h = (history_t *) p;
419 HistEventPrivate *evp = (void *)&h->cursor->ev;
421 if (h->cursor == &h->list)
422 return history_def_enter(p, ev, str);
423 len = Strlen(evp->str) + Strlen(str) + 1;
424 s = h_malloc(len * sizeof(*s));
426 he_seterrev(ev, _HE_MALLOC_FAILED);
429 (void) Strncpy(s, h->cursor->ev.str, len);
431 (void) Strncat(s, str, len - Strlen(s) - 1);
440 history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
441 int num, void **data)
443 if (history_set_nth(h, ev, num) != 0)
445 /* magic value to skip delete (just set to n-th history) */
446 if (data == (void **)-1)
448 ev->str = Strdup(h->cursor->ev.str);
449 ev->num = h->cursor->ev.num;
451 *data = h->cursor->data;
452 history_def_delete(h, ev, h->cursor);
457 /* history_def_del():
458 * Delete element hp of the h list
462 history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
465 history_t *h = (history_t *) p;
466 if (history_def_set(h, ev, num) != 0)
468 ev->str = Strdup(h->cursor->ev.str);
469 ev->num = h->cursor->ev.num;
470 history_def_delete(h, ev, h->cursor);
475 /* history_def_delete():
476 * Delete element hp of the h list
480 history_def_delete(history_t *h,
481 TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
483 HistEventPrivate *evp = (void *)&hp->ev;
486 if (h->cursor == hp) {
487 h->cursor = hp->prev;
488 if (h->cursor == &h->list)
489 h->cursor = hp->next;
491 hp->prev->next = hp->next;
492 hp->next->prev = hp->prev;
499 /* history_def_insert():
500 * Insert element with string str in the h list
503 history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
507 c = h_malloc(sizeof(*c));
510 if ((c->ev.str = h_strdup(str)) == NULL) {
515 c->ev.num = ++h->eventid;
516 c->next = h->list.next;
518 h->list.next->prev = c;
526 he_seterrev(ev, _HE_MALLOC_FAILED);
531 /* history_def_enter():
532 * Default function to enter an item in the history
535 history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
537 history_t *h = (history_t *) p;
539 if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
540 Strcmp(h->list.next->ev.str, str) == 0)
543 if (history_def_insert(h, ev, str) == -1)
544 return -1; /* error, keep error message */
547 * Always keep at least one entry.
548 * This way we don't have to check for the empty list.
550 while (h->cur > h->max && h->cur > 0)
551 history_def_delete(h, ev, h->list.prev);
557 /* history_def_init():
558 * Default history initialization function
562 history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
564 history_t *h = (history_t *) h_malloc(sizeof(*h));
573 h->list.next = h->list.prev = &h->list;
574 h->list.ev.str = NULL;
576 h->cursor = &h->list;
583 /* history_def_clear():
584 * Default history cleanup function
587 history_def_clear(void *p, TYPE(HistEvent) *ev)
589 history_t *h = (history_t *) p;
591 while (h->list.prev != &h->list)
592 history_def_delete(h, ev, h->list.prev);
593 h->cursor = &h->list;
601 /************************************************************************/
604 * Initialization function.
607 FUN(history,init)(void)
610 TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
614 if (history_def_init(&h->h_ref, &ev, 0) == -1) {
619 h->h_next = history_def_next;
620 h->h_first = history_def_first;
621 h->h_last = history_def_last;
622 h->h_prev = history_def_prev;
623 h->h_curr = history_def_curr;
624 h->h_set = history_def_set;
625 h->h_clear = history_def_clear;
626 h->h_enter = history_def_enter;
627 h->h_add = history_def_add;
628 h->h_del = history_def_del;
638 FUN(history,end)(TYPE(History) *h)
642 if (h->h_next == history_def_next)
643 history_def_clear(h->h_ref, &ev);
650 /* history_setsize():
651 * Set history number of events
654 history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
657 if (h->h_next != history_def_next) {
658 he_seterrev(ev, _HE_NOT_ALLOWED);
662 he_seterrev(ev, _HE_BAD_PARAM);
665 history_def_setsize(h->h_ref, num);
670 /* history_getsize():
671 * Get number of events currently in history
674 history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
676 if (h->h_next != history_def_next) {
677 he_seterrev(ev, _HE_NOT_ALLOWED);
680 ev->num = history_def_getsize(h->h_ref);
682 he_seterrev(ev, _HE_SIZE_NEGATIVE);
689 /* history_setunique():
690 * Set if adjacent equal events should not be entered in history.
693 history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
696 if (h->h_next != history_def_next) {
697 he_seterrev(ev, _HE_NOT_ALLOWED);
700 history_def_setunique(h->h_ref, uni);
705 /* history_getunique():
706 * Get if adjacent equal events should not be entered in history.
709 history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
711 if (h->h_next != history_def_next) {
712 he_seterrev(ev, _HE_NOT_ALLOWED);
715 ev->num = history_def_getunique(h->h_ref);
720 /* history_set_fun():
721 * Set history functions
724 history_set_fun(TYPE(History) *h, TYPE(History) *nh)
728 if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
729 nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
730 nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
731 nh->h_del == NULL || nh->h_ref == NULL) {
732 if (h->h_next != history_def_next) {
733 if (history_def_init(&h->h_ref, &ev, 0) == -1)
735 h->h_first = history_def_first;
736 h->h_next = history_def_next;
737 h->h_last = history_def_last;
738 h->h_prev = history_def_prev;
739 h->h_curr = history_def_curr;
740 h->h_set = history_def_set;
741 h->h_clear = history_def_clear;
742 h->h_enter = history_def_enter;
743 h->h_add = history_def_add;
744 h->h_del = history_def_del;
748 if (h->h_next == history_def_next)
749 history_def_clear(h->h_ref, &ev);
752 h->h_first = nh->h_first;
753 h->h_next = nh->h_next;
754 h->h_last = nh->h_last;
755 h->h_prev = nh->h_prev;
756 h->h_curr = nh->h_curr;
757 h->h_set = nh->h_set;
758 h->h_clear = nh->h_clear;
759 h->h_enter = nh->h_enter;
760 h->h_add = nh->h_add;
761 h->h_del = nh->h_del;
768 * TYPE(History) load function
771 history_load(TYPE(History) *h, const char *fname)
783 static ct_buffer_t conv;
786 if ((fp = fopen(fname, "r")) == NULL)
791 if ((sz = getline(&line, &llen, fp)) == -1)
794 if (strncmp(line, hist_cookie, (size_t)sz) != 0)
797 ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
800 for (i = 0; (sz = getline(&line, &llen, fp)) != -1; i++) {
801 if (sz > 0 && line[sz - 1] == '\n')
803 if (max_size < (size_t)sz) {
805 max_size = ((size_t)sz + 1024) & (size_t)~1023;
806 nptr = h_realloc(ptr, max_size * sizeof(*ptr));
813 (void) strunvis(ptr, line);
814 decode_result = ct_decode_string(ptr, &conv);
815 if (decode_result == NULL)
817 if (HENTER(h, &ev, decode_result) == -1) {
831 /* history_save_fp():
832 * TYPE(History) save function
835 history_save_fp(TYPE(History) *h, size_t nelem, FILE *fp)
839 size_t len, max_size;
843 static ct_buffer_t conv;
846 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
848 if (ftell(fp) == 0 && fputs(hist_cookie, fp) == EOF)
850 ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
853 if (nelem != (size_t)-1) {
854 for (retval = HFIRST(h, &ev); retval != -1 && nelem-- > 0;
855 retval = HNEXT(h, &ev))
861 retval = HLAST(h, &ev);
863 for (i = 0; retval != -1; retval = HPREV(h, &ev), i++) {
864 str = ct_encode_string(ev.str, &conv);
865 len = strlen(str) * 4 + 1;
866 if (len > max_size) {
868 max_size = (len + 1024) & (size_t)~1023;
869 nptr = h_realloc(ptr, max_size * sizeof(*ptr));
876 (void) strvis(ptr, str, VIS_WHITE);
877 (void) fprintf(fp, "%s\n", ptr);
887 * History save function
890 history_save(TYPE(History) *h, const char *fname)
895 if ((fp = fopen(fname, "w")) == NULL)
898 i = history_save_fp(h, (size_t)-1, fp);
905 /* history_prev_event():
906 * Find the previous event, with number given
909 history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
913 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
917 he_seterrev(ev, _HE_NOT_FOUND);
923 history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
927 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
928 if (ev->num == num) {
930 *d = ((history_t *)h->h_ref)->cursor->data;
934 he_seterrev(ev, _HE_NOT_FOUND);
939 /* history_next_event():
940 * Find the next event, with number given
943 history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
947 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
951 he_seterrev(ev, _HE_NOT_FOUND);
956 /* history_prev_string():
957 * Find the previous event beginning with string
960 history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
962 size_t len = Strlen(str);
965 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
966 if (Strncmp(str, ev->str, len) == 0)
969 he_seterrev(ev, _HE_NOT_FOUND);
974 /* history_next_string():
975 * Find the next event beginning with string
978 history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
980 size_t len = Strlen(str);
983 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
984 if (Strncmp(str, ev->str, len) == 0)
987 he_seterrev(ev, _HE_NOT_FOUND);
993 * User interface to history functions.
996 FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
1004 he_seterrev(ev, _HE_OK);
1008 retval = history_getsize(h, ev);
1012 retval = history_setsize(h, ev, va_arg(va, int));
1016 retval = history_getunique(h, ev);
1020 retval = history_setunique(h, ev, va_arg(va, int));
1024 str = va_arg(va, const Char *);
1025 retval = HADD(h, ev, str);
1029 retval = HDEL(h, ev, va_arg(va, const int));
1033 str = va_arg(va, const Char *);
1034 if ((retval = HENTER(h, ev, str)) != -1)
1039 str = va_arg(va, const Char *);
1040 if ((retval = HSET(h, ev, h->h_ent)) != -1)
1041 retval = HADD(h, ev, str);
1045 retval = HFIRST(h, ev);
1049 retval = HNEXT(h, ev);
1053 retval = HLAST(h, ev);
1057 retval = HPREV(h, ev);
1061 retval = HCURR(h, ev);
1065 retval = HSET(h, ev, va_arg(va, const int));
1074 retval = history_load(h, va_arg(va, const char *));
1076 he_seterrev(ev, _HE_HIST_READ);
1080 retval = history_save(h, va_arg(va, const char *));
1082 he_seterrev(ev, _HE_HIST_WRITE);
1086 retval = history_save_fp(h, (size_t)-1, va_arg(va, FILE *));
1088 he_seterrev(ev, _HE_HIST_WRITE);
1093 size_t sz = va_arg(va, size_t);
1094 retval = history_save_fp(h, sz, va_arg(va, FILE *));
1096 he_seterrev(ev, _HE_HIST_WRITE);
1101 retval = history_prev_event(h, ev, va_arg(va, int));
1105 retval = history_next_event(h, ev, va_arg(va, int));
1109 retval = history_prev_string(h, ev, va_arg(va, const Char *));
1113 retval = history_next_string(h, ev, va_arg(va, const Char *));
1120 hf.h_ref = va_arg(va, void *);
1122 hf.h_first = va_arg(va, history_gfun_t);
1123 hf.h_next = va_arg(va, history_gfun_t);
1124 hf.h_last = va_arg(va, history_gfun_t);
1125 hf.h_prev = va_arg(va, history_gfun_t);
1126 hf.h_curr = va_arg(va, history_gfun_t);
1127 hf.h_set = va_arg(va, history_sfun_t);
1128 hf.h_clear = va_arg(va, history_vfun_t);
1129 hf.h_enter = va_arg(va, history_efun_t);
1130 hf.h_add = va_arg(va, history_efun_t);
1131 hf.h_del = va_arg(va, history_sfun_t);
1133 if ((retval = history_set_fun(h, &hf)) == -1)
1134 he_seterrev(ev, _HE_PARAM_MISSING);
1139 FUN(history,end)(h);
1145 int num = va_arg(va, int);
1146 void **d = va_arg(va, void **);
1147 retval = history_next_evdata(h, ev, num, d);
1153 int num = va_arg(va, int);
1154 void **d = va_arg(va, void **);
1155 retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
1159 case H_REPLACE: /* only use after H_NEXT_EVDATA */
1161 const Char *line = va_arg(va, const Char *);
1162 void *d = va_arg(va, void *);
1164 if(!line || !(s = Strdup(line))) {
1168 ((history_t *)h->h_ref)->cursor->ev.str = s;
1169 ((history_t *)h->h_ref)->cursor->data = d;
1176 he_seterrev(ev, _HE_UNKNOWN);