1 /* $NetBSD: history.c,v 1.63 2019/10/08 19:17:57 christos 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.63 2019/10/08 19:17:57 christos 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;
414 size_t len, elen, slen;
416 HistEventPrivate *evp = (void *)&h->cursor->ev;
418 if (h->cursor == &h->list)
419 return history_def_enter(p, ev, str);
420 elen = Strlen(evp->str);
422 len = elen + slen + 1;
423 s = h_malloc(len * sizeof(*s));
425 he_seterrev(ev, _HE_MALLOC_FAILED);
428 memcpy(s, evp->str, elen * sizeof(*s));
429 memcpy(s + elen, str, slen * sizeof(*s));
439 history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
440 int num, void **data)
442 if (history_set_nth(h, ev, num) != 0)
444 /* magic value to skip delete (just set to n-th history) */
445 if (data == (void **)-1)
447 ev->str = Strdup(h->cursor->ev.str);
448 ev->num = h->cursor->ev.num;
450 *data = h->cursor->data;
451 history_def_delete(h, ev, h->cursor);
456 /* history_def_del():
457 * Delete element hp of the h list
461 history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
464 history_t *h = (history_t *) p;
465 if (history_def_set(h, ev, num) != 0)
467 ev->str = Strdup(h->cursor->ev.str);
468 ev->num = h->cursor->ev.num;
469 history_def_delete(h, ev, h->cursor);
474 /* history_def_delete():
475 * Delete element hp of the h list
479 history_def_delete(history_t *h,
480 TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
482 HistEventPrivate *evp = (void *)&hp->ev;
485 if (h->cursor == hp) {
486 h->cursor = hp->prev;
487 if (h->cursor == &h->list)
488 h->cursor = hp->next;
490 hp->prev->next = hp->next;
491 hp->next->prev = hp->prev;
498 /* history_def_insert():
499 * Insert element with string str in the h list
502 history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
506 c = h_malloc(sizeof(*c));
509 if ((c->ev.str = h_strdup(str)) == NULL) {
514 c->ev.num = ++h->eventid;
515 c->next = h->list.next;
517 h->list.next->prev = c;
525 he_seterrev(ev, _HE_MALLOC_FAILED);
530 /* history_def_enter():
531 * Default function to enter an item in the history
534 history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
536 history_t *h = (history_t *) p;
538 if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
539 Strcmp(h->list.next->ev.str, str) == 0)
542 if (history_def_insert(h, ev, str) == -1)
543 return -1; /* error, keep error message */
546 * Always keep at least one entry.
547 * This way we don't have to check for the empty list.
549 while (h->cur > h->max && h->cur > 0)
550 history_def_delete(h, ev, h->list.prev);
556 /* history_def_init():
557 * Default history initialization function
561 history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
563 history_t *h = (history_t *) h_malloc(sizeof(*h));
572 h->list.next = h->list.prev = &h->list;
573 h->list.ev.str = NULL;
575 h->cursor = &h->list;
582 /* history_def_clear():
583 * Default history cleanup function
586 history_def_clear(void *p, TYPE(HistEvent) *ev)
588 history_t *h = (history_t *) p;
590 while (h->list.prev != &h->list)
591 history_def_delete(h, ev, h->list.prev);
592 h->cursor = &h->list;
600 /************************************************************************/
603 * Initialization function.
606 FUN(history,init)(void)
609 TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
613 if (history_def_init(&h->h_ref, &ev, 0) == -1) {
618 h->h_next = history_def_next;
619 h->h_first = history_def_first;
620 h->h_last = history_def_last;
621 h->h_prev = history_def_prev;
622 h->h_curr = history_def_curr;
623 h->h_set = history_def_set;
624 h->h_clear = history_def_clear;
625 h->h_enter = history_def_enter;
626 h->h_add = history_def_add;
627 h->h_del = history_def_del;
637 FUN(history,end)(TYPE(History) *h)
641 if (h->h_next == history_def_next)
642 history_def_clear(h->h_ref, &ev);
649 /* history_setsize():
650 * Set history number of events
653 history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
656 if (h->h_next != history_def_next) {
657 he_seterrev(ev, _HE_NOT_ALLOWED);
661 he_seterrev(ev, _HE_BAD_PARAM);
664 history_def_setsize(h->h_ref, num);
669 /* history_getsize():
670 * Get number of events currently in history
673 history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
675 if (h->h_next != history_def_next) {
676 he_seterrev(ev, _HE_NOT_ALLOWED);
679 ev->num = history_def_getsize(h->h_ref);
681 he_seterrev(ev, _HE_SIZE_NEGATIVE);
688 /* history_setunique():
689 * Set if adjacent equal events should not be entered in history.
692 history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
695 if (h->h_next != history_def_next) {
696 he_seterrev(ev, _HE_NOT_ALLOWED);
699 history_def_setunique(h->h_ref, uni);
704 /* history_getunique():
705 * Get if adjacent equal events should not be entered in history.
708 history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
710 if (h->h_next != history_def_next) {
711 he_seterrev(ev, _HE_NOT_ALLOWED);
714 ev->num = history_def_getunique(h->h_ref);
719 /* history_set_fun():
720 * Set history functions
723 history_set_fun(TYPE(History) *h, TYPE(History) *nh)
727 if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
728 nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
729 nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
730 nh->h_del == NULL || nh->h_ref == NULL) {
731 if (h->h_next != history_def_next) {
732 if (history_def_init(&h->h_ref, &ev, 0) == -1)
734 h->h_first = history_def_first;
735 h->h_next = history_def_next;
736 h->h_last = history_def_last;
737 h->h_prev = history_def_prev;
738 h->h_curr = history_def_curr;
739 h->h_set = history_def_set;
740 h->h_clear = history_def_clear;
741 h->h_enter = history_def_enter;
742 h->h_add = history_def_add;
743 h->h_del = history_def_del;
747 if (h->h_next == history_def_next)
748 history_def_clear(h->h_ref, &ev);
751 h->h_first = nh->h_first;
752 h->h_next = nh->h_next;
753 h->h_last = nh->h_last;
754 h->h_prev = nh->h_prev;
755 h->h_curr = nh->h_curr;
756 h->h_set = nh->h_set;
757 h->h_clear = nh->h_clear;
758 h->h_enter = nh->h_enter;
759 h->h_add = nh->h_add;
760 h->h_del = nh->h_del;
767 * TYPE(History) load function
770 history_load(TYPE(History) *h, const char *fname)
782 static ct_buffer_t conv;
785 if ((fp = fopen(fname, "r")) == NULL)
790 if ((sz = getline(&line, &llen, fp)) == -1)
793 if (strncmp(line, hist_cookie, (size_t)sz) != 0)
796 ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
799 for (i = 0; (sz = getline(&line, &llen, fp)) != -1; i++) {
800 if (sz > 0 && line[sz - 1] == '\n')
802 if (max_size < (size_t)sz) {
804 max_size = ((size_t)sz + 1024) & (size_t)~1023;
805 nptr = h_realloc(ptr, max_size * sizeof(*ptr));
812 (void) strunvis(ptr, line);
813 decode_result = ct_decode_string(ptr, &conv);
814 if (decode_result == NULL)
816 if (HENTER(h, &ev, decode_result) == -1) {
830 /* history_save_fp():
831 * TYPE(History) save function
834 history_save_fp(TYPE(History) *h, size_t nelem, FILE *fp)
838 size_t len, max_size;
842 static ct_buffer_t conv;
845 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
847 if (ftell(fp) == 0 && fputs(hist_cookie, fp) == EOF)
849 ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
852 if (nelem != (size_t)-1) {
853 for (retval = HFIRST(h, &ev); retval != -1 && nelem-- > 0;
854 retval = HNEXT(h, &ev))
860 retval = HLAST(h, &ev);
862 for (i = 0; retval != -1; retval = HPREV(h, &ev), i++) {
863 str = ct_encode_string(ev.str, &conv);
864 len = strlen(str) * 4 + 1;
865 if (len > max_size) {
867 max_size = (len + 1024) & (size_t)~1023;
868 nptr = h_realloc(ptr, max_size * sizeof(*ptr));
875 (void) strvis(ptr, str, VIS_WHITE);
876 (void) fprintf(fp, "%s\n", ptr);
886 * History save function
889 history_save(TYPE(History) *h, const char *fname)
894 if ((fp = fopen(fname, "w")) == NULL)
897 i = history_save_fp(h, (size_t)-1, fp);
904 /* history_prev_event():
905 * Find the previous event, with number given
908 history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
912 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
916 he_seterrev(ev, _HE_NOT_FOUND);
922 history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
926 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
927 if (ev->num == num) {
929 *d = ((history_t *)h->h_ref)->cursor->data;
933 he_seterrev(ev, _HE_NOT_FOUND);
938 /* history_next_event():
939 * Find the next event, with number given
942 history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
946 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
950 he_seterrev(ev, _HE_NOT_FOUND);
955 /* history_prev_string():
956 * Find the previous event beginning with string
959 history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
961 size_t len = Strlen(str);
964 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
965 if (Strncmp(str, ev->str, len) == 0)
968 he_seterrev(ev, _HE_NOT_FOUND);
973 /* history_next_string():
974 * Find the next event beginning with string
977 history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
979 size_t len = Strlen(str);
982 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
983 if (Strncmp(str, ev->str, len) == 0)
986 he_seterrev(ev, _HE_NOT_FOUND);
992 * User interface to history functions.
995 FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
1003 he_seterrev(ev, _HE_OK);
1007 retval = history_getsize(h, ev);
1011 retval = history_setsize(h, ev, va_arg(va, int));
1015 retval = history_getunique(h, ev);
1019 retval = history_setunique(h, ev, va_arg(va, int));
1023 str = va_arg(va, const Char *);
1024 retval = HADD(h, ev, str);
1028 retval = HDEL(h, ev, va_arg(va, const int));
1032 str = va_arg(va, const Char *);
1033 if ((retval = HENTER(h, ev, str)) != -1)
1038 str = va_arg(va, const Char *);
1039 if ((retval = HSET(h, ev, h->h_ent)) != -1)
1040 retval = HADD(h, ev, str);
1044 retval = HFIRST(h, ev);
1048 retval = HNEXT(h, ev);
1052 retval = HLAST(h, ev);
1056 retval = HPREV(h, ev);
1060 retval = HCURR(h, ev);
1064 retval = HSET(h, ev, va_arg(va, const int));
1073 retval = history_load(h, va_arg(va, const char *));
1075 he_seterrev(ev, _HE_HIST_READ);
1079 retval = history_save(h, va_arg(va, const char *));
1081 he_seterrev(ev, _HE_HIST_WRITE);
1085 retval = history_save_fp(h, (size_t)-1, va_arg(va, FILE *));
1087 he_seterrev(ev, _HE_HIST_WRITE);
1092 size_t sz = va_arg(va, size_t);
1093 retval = history_save_fp(h, sz, va_arg(va, FILE *));
1095 he_seterrev(ev, _HE_HIST_WRITE);
1100 retval = history_prev_event(h, ev, va_arg(va, int));
1104 retval = history_next_event(h, ev, va_arg(va, int));
1108 retval = history_prev_string(h, ev, va_arg(va, const Char *));
1112 retval = history_next_string(h, ev, va_arg(va, const Char *));
1119 hf.h_ref = va_arg(va, void *);
1121 hf.h_first = va_arg(va, history_gfun_t);
1122 hf.h_next = va_arg(va, history_gfun_t);
1123 hf.h_last = va_arg(va, history_gfun_t);
1124 hf.h_prev = va_arg(va, history_gfun_t);
1125 hf.h_curr = va_arg(va, history_gfun_t);
1126 hf.h_set = va_arg(va, history_sfun_t);
1127 hf.h_clear = va_arg(va, history_vfun_t);
1128 hf.h_enter = va_arg(va, history_efun_t);
1129 hf.h_add = va_arg(va, history_efun_t);
1130 hf.h_del = va_arg(va, history_sfun_t);
1132 if ((retval = history_set_fun(h, &hf)) == -1)
1133 he_seterrev(ev, _HE_PARAM_MISSING);
1138 FUN(history,end)(h);
1144 int num = va_arg(va, int);
1145 void **d = va_arg(va, void **);
1146 retval = history_next_evdata(h, ev, num, d);
1152 int num = va_arg(va, int);
1153 void **d = va_arg(va, void **);
1154 retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
1158 case H_REPLACE: /* only use after H_NEXT_EVDATA */
1160 const Char *line = va_arg(va, const Char *);
1161 void *d = va_arg(va, void *);
1163 if(!line || !(s = Strdup(line))) {
1167 ((history_t *)h->h_ref)->cursor->ev.str = s;
1168 ((history_t *)h->h_ref)->cursor->data = d;
1175 he_seterrev(ev, _HE_UNKNOWN);