xref: /minix3/lib/libedit/history.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /*	$NetBSD: history.c,v 1.47 2014/05/11 01:05:17 christos Exp $	*/
23e1db26aSLionel Sambuc 
33e1db26aSLionel Sambuc /*-
43e1db26aSLionel Sambuc  * Copyright (c) 1992, 1993
53e1db26aSLionel Sambuc  *	The Regents of the University of California.  All rights reserved.
63e1db26aSLionel Sambuc  *
73e1db26aSLionel Sambuc  * This code is derived from software contributed to Berkeley by
83e1db26aSLionel Sambuc  * Christos Zoulas of Cornell University.
93e1db26aSLionel Sambuc  *
103e1db26aSLionel Sambuc  * Redistribution and use in source and binary forms, with or without
113e1db26aSLionel Sambuc  * modification, are permitted provided that the following conditions
123e1db26aSLionel Sambuc  * are met:
133e1db26aSLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
143e1db26aSLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
153e1db26aSLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
163e1db26aSLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
173e1db26aSLionel Sambuc  *    documentation and/or other materials provided with the distribution.
183e1db26aSLionel Sambuc  * 3. Neither the name of the University nor the names of its contributors
193e1db26aSLionel Sambuc  *    may be used to endorse or promote products derived from this software
203e1db26aSLionel Sambuc  *    without specific prior written permission.
213e1db26aSLionel Sambuc  *
223e1db26aSLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
233e1db26aSLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
243e1db26aSLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
253e1db26aSLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
263e1db26aSLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
273e1db26aSLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
283e1db26aSLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
293e1db26aSLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
303e1db26aSLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
313e1db26aSLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
323e1db26aSLionel Sambuc  * SUCH DAMAGE.
333e1db26aSLionel Sambuc  */
343e1db26aSLionel Sambuc 
353e1db26aSLionel Sambuc #include "config.h"
363e1db26aSLionel Sambuc #if !defined(lint) && !defined(SCCSID)
373e1db26aSLionel Sambuc #if 0
383e1db26aSLionel Sambuc static char sccsid[] = "@(#)history.c	8.1 (Berkeley) 6/4/93";
393e1db26aSLionel Sambuc #else
40*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: history.c,v 1.47 2014/05/11 01:05:17 christos Exp $");
413e1db26aSLionel Sambuc #endif
423e1db26aSLionel Sambuc #endif /* not lint && not SCCSID */
433e1db26aSLionel Sambuc 
443e1db26aSLionel Sambuc /*
453e1db26aSLionel Sambuc  * hist.c: TYPE(History) access functions
463e1db26aSLionel Sambuc  */
473e1db26aSLionel Sambuc #include <string.h>
483e1db26aSLionel Sambuc #include <stdlib.h>
493e1db26aSLionel Sambuc #include <stdarg.h>
503e1db26aSLionel Sambuc #include <vis.h>
513e1db26aSLionel Sambuc #include <sys/stat.h>
523e1db26aSLionel Sambuc 
533e1db26aSLionel Sambuc static const char hist_cookie[] = "_HiStOrY_V2_\n";
543e1db26aSLionel Sambuc 
553e1db26aSLionel Sambuc #include "histedit.h"
563e1db26aSLionel Sambuc #include "chartype.h"
573e1db26aSLionel Sambuc 
583e1db26aSLionel Sambuc typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
593e1db26aSLionel Sambuc typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
603e1db26aSLionel Sambuc typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
613e1db26aSLionel Sambuc typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
623e1db26aSLionel Sambuc 
TYPE(history)633e1db26aSLionel Sambuc struct TYPE(history) {
643e1db26aSLionel Sambuc 	void *h_ref;		/* Argument for history fcns	 */
653e1db26aSLionel Sambuc 	int h_ent;		/* Last entry point for history	 */
663e1db26aSLionel Sambuc 	history_gfun_t h_first;	/* Get the first element	 */
673e1db26aSLionel Sambuc 	history_gfun_t h_next;	/* Get the next element		 */
683e1db26aSLionel Sambuc 	history_gfun_t h_last;	/* Get the last element		 */
693e1db26aSLionel Sambuc 	history_gfun_t h_prev;	/* Get the previous element	 */
703e1db26aSLionel Sambuc 	history_gfun_t h_curr;	/* Get the current element	 */
713e1db26aSLionel Sambuc 	history_sfun_t h_set;	/* Set the current element	 */
723e1db26aSLionel Sambuc 	history_sfun_t h_del;	/* Set the given element	 */
733e1db26aSLionel Sambuc 	history_vfun_t h_clear;	/* Clear the history list	 */
743e1db26aSLionel Sambuc 	history_efun_t h_enter;	/* Add an element		 */
753e1db26aSLionel Sambuc 	history_efun_t h_add;	/* Append to an element		 */
763e1db26aSLionel Sambuc };
773e1db26aSLionel Sambuc 
783e1db26aSLionel Sambuc #define	HNEXT(h, ev)		(*(h)->h_next)((h)->h_ref, ev)
793e1db26aSLionel Sambuc #define	HFIRST(h, ev)		(*(h)->h_first)((h)->h_ref, ev)
803e1db26aSLionel Sambuc #define	HPREV(h, ev)		(*(h)->h_prev)((h)->h_ref, ev)
813e1db26aSLionel Sambuc #define	HLAST(h, ev)		(*(h)->h_last)((h)->h_ref, ev)
823e1db26aSLionel Sambuc #define	HCURR(h, ev)		(*(h)->h_curr)((h)->h_ref, ev)
833e1db26aSLionel Sambuc #define	HSET(h, ev, n)		(*(h)->h_set)((h)->h_ref, ev, n)
843e1db26aSLionel Sambuc #define	HCLEAR(h, ev)		(*(h)->h_clear)((h)->h_ref, ev)
853e1db26aSLionel Sambuc #define	HENTER(h, ev, str)	(*(h)->h_enter)((h)->h_ref, ev, str)
863e1db26aSLionel Sambuc #define	HADD(h, ev, str)	(*(h)->h_add)((h)->h_ref, ev, str)
873e1db26aSLionel Sambuc #define	HDEL(h, ev, n)		(*(h)->h_del)((h)->h_ref, ev, n)
883e1db26aSLionel Sambuc 
893e1db26aSLionel Sambuc #define	h_strdup(a)	Strdup(a)
903e1db26aSLionel Sambuc #define	h_malloc(a)	malloc(a)
913e1db26aSLionel Sambuc #define	h_realloc(a, b)	realloc((a), (b))
923e1db26aSLionel Sambuc #define	h_free(a)	free(a)
933e1db26aSLionel Sambuc 
943e1db26aSLionel Sambuc typedef struct {
953e1db26aSLionel Sambuc     int		num;
963e1db26aSLionel Sambuc     Char	*str;
973e1db26aSLionel Sambuc } HistEventPrivate;
983e1db26aSLionel Sambuc 
993e1db26aSLionel Sambuc 
1003e1db26aSLionel Sambuc 
1013e1db26aSLionel Sambuc private int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
1023e1db26aSLionel Sambuc private int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
1033e1db26aSLionel Sambuc private int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
1043e1db26aSLionel Sambuc private int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
1053e1db26aSLionel Sambuc private int history_set_fun(TYPE(History) *, TYPE(History) *);
1063e1db26aSLionel Sambuc private int history_load(TYPE(History) *, const char *);
1073e1db26aSLionel Sambuc private int history_save(TYPE(History) *, const char *);
108*0a6a1f1dSLionel Sambuc private int history_save_fp(TYPE(History) *, FILE *);
1093e1db26aSLionel Sambuc private int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
1103e1db26aSLionel Sambuc private int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
1113e1db26aSLionel Sambuc private int history_next_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
1123e1db26aSLionel Sambuc private int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
1133e1db26aSLionel Sambuc 
1143e1db26aSLionel Sambuc 
1153e1db26aSLionel Sambuc /***********************************************************************/
1163e1db26aSLionel Sambuc 
1173e1db26aSLionel Sambuc /*
1183e1db26aSLionel Sambuc  * Builtin- history implementation
1193e1db26aSLionel Sambuc  */
1203e1db26aSLionel Sambuc typedef struct hentry_t {
1213e1db26aSLionel Sambuc 	TYPE(HistEvent) ev;		/* What we return		 */
1223e1db26aSLionel Sambuc 	void *data;		/* data				 */
1233e1db26aSLionel Sambuc 	struct hentry_t *next;	/* Next entry			 */
1243e1db26aSLionel Sambuc 	struct hentry_t *prev;	/* Previous entry		 */
1253e1db26aSLionel Sambuc } hentry_t;
1263e1db26aSLionel Sambuc 
1273e1db26aSLionel Sambuc typedef struct history_t {
1283e1db26aSLionel Sambuc 	hentry_t list;		/* Fake list header element	*/
1293e1db26aSLionel Sambuc 	hentry_t *cursor;	/* Current element in the list	*/
1303e1db26aSLionel Sambuc 	int max;		/* Maximum number of events	*/
1313e1db26aSLionel Sambuc 	int cur;		/* Current number of events	*/
1323e1db26aSLionel Sambuc 	int eventid;		/* For generation of unique event id	 */
1333e1db26aSLionel Sambuc 	int flags;		/* TYPE(History) flags		*/
1343e1db26aSLionel Sambuc #define H_UNIQUE	1	/* Store only unique elements	*/
1353e1db26aSLionel Sambuc } history_t;
1363e1db26aSLionel Sambuc 
1373e1db26aSLionel Sambuc private int history_def_next(void *, TYPE(HistEvent) *);
1383e1db26aSLionel Sambuc private int history_def_first(void *, TYPE(HistEvent) *);
1393e1db26aSLionel Sambuc private int history_def_prev(void *, TYPE(HistEvent) *);
1403e1db26aSLionel Sambuc private int history_def_last(void *, TYPE(HistEvent) *);
1413e1db26aSLionel Sambuc private int history_def_curr(void *, TYPE(HistEvent) *);
1423e1db26aSLionel Sambuc private int history_def_set(void *, TYPE(HistEvent) *, const int);
1433e1db26aSLionel Sambuc private void history_def_clear(void *, TYPE(HistEvent) *);
1443e1db26aSLionel Sambuc private int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
1453e1db26aSLionel Sambuc private int history_def_add(void *, TYPE(HistEvent) *, const Char *);
1463e1db26aSLionel Sambuc private int history_def_del(void *, TYPE(HistEvent) *, const int);
1473e1db26aSLionel Sambuc 
1483e1db26aSLionel Sambuc private int history_def_init(void **, TYPE(HistEvent) *, int);
1493e1db26aSLionel Sambuc private int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
1503e1db26aSLionel Sambuc private void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
1513e1db26aSLionel Sambuc 
1523e1db26aSLionel Sambuc private int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
1533e1db26aSLionel Sambuc private int history_set_nth(void *, TYPE(HistEvent) *, int);
1543e1db26aSLionel Sambuc 
1553e1db26aSLionel Sambuc #define	history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
1563e1db26aSLionel Sambuc #define	history_def_getsize(p)  (((history_t *)p)->cur)
1573e1db26aSLionel Sambuc #define	history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
1583e1db26aSLionel Sambuc #define	history_def_setunique(p, uni) \
1593e1db26aSLionel Sambuc     if (uni) \
1603e1db26aSLionel Sambuc 	(((history_t *)p)->flags) |= H_UNIQUE; \
1613e1db26aSLionel Sambuc     else \
1623e1db26aSLionel Sambuc 	(((history_t *)p)->flags) &= ~H_UNIQUE
1633e1db26aSLionel Sambuc 
1643e1db26aSLionel Sambuc #define	he_strerror(code)	he_errlist[code]
1653e1db26aSLionel Sambuc #define	he_seterrev(evp, code)	{\
1663e1db26aSLionel Sambuc 				    evp->num = code;\
1673e1db26aSLionel Sambuc 				    evp->str = he_strerror(code);\
1683e1db26aSLionel Sambuc 				}
1693e1db26aSLionel Sambuc 
1703e1db26aSLionel Sambuc /* error messages */
1713e1db26aSLionel Sambuc static const Char *const he_errlist[] = {
1723e1db26aSLionel Sambuc 	STR("OK"),
1733e1db26aSLionel Sambuc 	STR("unknown error"),
1743e1db26aSLionel Sambuc 	STR("malloc() failed"),
1753e1db26aSLionel Sambuc 	STR("first event not found"),
1763e1db26aSLionel Sambuc 	STR("last event not found"),
1773e1db26aSLionel Sambuc 	STR("empty list"),
1783e1db26aSLionel Sambuc 	STR("no next event"),
1793e1db26aSLionel Sambuc 	STR("no previous event"),
1803e1db26aSLionel Sambuc 	STR("current event is invalid"),
1813e1db26aSLionel Sambuc 	STR("event not found"),
1823e1db26aSLionel Sambuc 	STR("can't read history from file"),
1833e1db26aSLionel Sambuc 	STR("can't write history"),
1843e1db26aSLionel Sambuc 	STR("required parameter(s) not supplied"),
1853e1db26aSLionel Sambuc 	STR("history size negative"),
1863e1db26aSLionel Sambuc 	STR("function not allowed with other history-functions-set the default"),
1873e1db26aSLionel Sambuc 	STR("bad parameters")
1883e1db26aSLionel Sambuc };
1893e1db26aSLionel Sambuc /* error codes */
1903e1db26aSLionel Sambuc #define	_HE_OK                   0
1913e1db26aSLionel Sambuc #define	_HE_UNKNOWN		 1
1923e1db26aSLionel Sambuc #define	_HE_MALLOC_FAILED        2
1933e1db26aSLionel Sambuc #define	_HE_FIRST_NOTFOUND       3
1943e1db26aSLionel Sambuc #define	_HE_LAST_NOTFOUND        4
1953e1db26aSLionel Sambuc #define	_HE_EMPTY_LIST           5
1963e1db26aSLionel Sambuc #define	_HE_END_REACHED          6
1973e1db26aSLionel Sambuc #define	_HE_START_REACHED	 7
1983e1db26aSLionel Sambuc #define	_HE_CURR_INVALID	 8
1993e1db26aSLionel Sambuc #define	_HE_NOT_FOUND		 9
2003e1db26aSLionel Sambuc #define	_HE_HIST_READ		10
2013e1db26aSLionel Sambuc #define	_HE_HIST_WRITE		11
2023e1db26aSLionel Sambuc #define	_HE_PARAM_MISSING	12
2033e1db26aSLionel Sambuc #define	_HE_SIZE_NEGATIVE	13
2043e1db26aSLionel Sambuc #define	_HE_NOT_ALLOWED		14
2053e1db26aSLionel Sambuc #define	_HE_BAD_PARAM		15
2063e1db26aSLionel Sambuc 
2073e1db26aSLionel Sambuc /* history_def_first():
2083e1db26aSLionel Sambuc  *	Default function to return the first event in the history.
2093e1db26aSLionel Sambuc  */
2103e1db26aSLionel Sambuc private int
history_def_first(void * p,TYPE (HistEvent)* ev)2113e1db26aSLionel Sambuc history_def_first(void *p, TYPE(HistEvent) *ev)
2123e1db26aSLionel Sambuc {
2133e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
2143e1db26aSLionel Sambuc 
2153e1db26aSLionel Sambuc 	h->cursor = h->list.next;
2163e1db26aSLionel Sambuc 	if (h->cursor != &h->list)
2173e1db26aSLionel Sambuc 		*ev = h->cursor->ev;
2183e1db26aSLionel Sambuc 	else {
2193e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_FIRST_NOTFOUND);
2203e1db26aSLionel Sambuc 		return -1;
2213e1db26aSLionel Sambuc 	}
2223e1db26aSLionel Sambuc 
2233e1db26aSLionel Sambuc 	return 0;
2243e1db26aSLionel Sambuc }
2253e1db26aSLionel Sambuc 
2263e1db26aSLionel Sambuc 
2273e1db26aSLionel Sambuc /* history_def_last():
2283e1db26aSLionel Sambuc  *	Default function to return the last event in the history.
2293e1db26aSLionel Sambuc  */
2303e1db26aSLionel Sambuc private int
history_def_last(void * p,TYPE (HistEvent)* ev)2313e1db26aSLionel Sambuc history_def_last(void *p, TYPE(HistEvent) *ev)
2323e1db26aSLionel Sambuc {
2333e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
2343e1db26aSLionel Sambuc 
2353e1db26aSLionel Sambuc 	h->cursor = h->list.prev;
2363e1db26aSLionel Sambuc 	if (h->cursor != &h->list)
2373e1db26aSLionel Sambuc 		*ev = h->cursor->ev;
2383e1db26aSLionel Sambuc 	else {
2393e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_LAST_NOTFOUND);
2403e1db26aSLionel Sambuc 		return -1;
2413e1db26aSLionel Sambuc 	}
2423e1db26aSLionel Sambuc 
2433e1db26aSLionel Sambuc 	return 0;
2443e1db26aSLionel Sambuc }
2453e1db26aSLionel Sambuc 
2463e1db26aSLionel Sambuc 
2473e1db26aSLionel Sambuc /* history_def_next():
2483e1db26aSLionel Sambuc  *	Default function to return the next event in the history.
2493e1db26aSLionel Sambuc  */
2503e1db26aSLionel Sambuc private int
history_def_next(void * p,TYPE (HistEvent)* ev)2513e1db26aSLionel Sambuc history_def_next(void *p, TYPE(HistEvent) *ev)
2523e1db26aSLionel Sambuc {
2533e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
2543e1db26aSLionel Sambuc 
2553e1db26aSLionel Sambuc 	if (h->cursor == &h->list) {
2563e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_EMPTY_LIST);
2573e1db26aSLionel Sambuc 		return -1;
2583e1db26aSLionel Sambuc 	}
2593e1db26aSLionel Sambuc 
2603e1db26aSLionel Sambuc 	if (h->cursor->next == &h->list) {
2613e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_END_REACHED);
2623e1db26aSLionel Sambuc 		return -1;
2633e1db26aSLionel Sambuc 	}
2643e1db26aSLionel Sambuc 
2653e1db26aSLionel Sambuc         h->cursor = h->cursor->next;
2663e1db26aSLionel Sambuc         *ev = h->cursor->ev;
2673e1db26aSLionel Sambuc 
2683e1db26aSLionel Sambuc 	return 0;
2693e1db26aSLionel Sambuc }
2703e1db26aSLionel Sambuc 
2713e1db26aSLionel Sambuc 
2723e1db26aSLionel Sambuc /* history_def_prev():
2733e1db26aSLionel Sambuc  *	Default function to return the previous event in the history.
2743e1db26aSLionel Sambuc  */
2753e1db26aSLionel Sambuc private int
history_def_prev(void * p,TYPE (HistEvent)* ev)2763e1db26aSLionel Sambuc history_def_prev(void *p, TYPE(HistEvent) *ev)
2773e1db26aSLionel Sambuc {
2783e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
2793e1db26aSLionel Sambuc 
2803e1db26aSLionel Sambuc 	if (h->cursor == &h->list) {
2813e1db26aSLionel Sambuc 		he_seterrev(ev,
2823e1db26aSLionel Sambuc 		    (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
2833e1db26aSLionel Sambuc 		return -1;
2843e1db26aSLionel Sambuc 	}
2853e1db26aSLionel Sambuc 
2863e1db26aSLionel Sambuc 	if (h->cursor->prev == &h->list) {
2873e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_START_REACHED);
2883e1db26aSLionel Sambuc 		return -1;
2893e1db26aSLionel Sambuc 	}
2903e1db26aSLionel Sambuc 
2913e1db26aSLionel Sambuc         h->cursor = h->cursor->prev;
2923e1db26aSLionel Sambuc         *ev = h->cursor->ev;
2933e1db26aSLionel Sambuc 
2943e1db26aSLionel Sambuc 	return 0;
2953e1db26aSLionel Sambuc }
2963e1db26aSLionel Sambuc 
2973e1db26aSLionel Sambuc 
2983e1db26aSLionel Sambuc /* history_def_curr():
2993e1db26aSLionel Sambuc  *	Default function to return the current event in the history.
3003e1db26aSLionel Sambuc  */
3013e1db26aSLionel Sambuc private int
history_def_curr(void * p,TYPE (HistEvent)* ev)3023e1db26aSLionel Sambuc history_def_curr(void *p, TYPE(HistEvent) *ev)
3033e1db26aSLionel Sambuc {
3043e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
3053e1db26aSLionel Sambuc 
3063e1db26aSLionel Sambuc 	if (h->cursor != &h->list)
3073e1db26aSLionel Sambuc 		*ev = h->cursor->ev;
3083e1db26aSLionel Sambuc 	else {
3093e1db26aSLionel Sambuc 		he_seterrev(ev,
3103e1db26aSLionel Sambuc 		    (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
3113e1db26aSLionel Sambuc 		return -1;
3123e1db26aSLionel Sambuc 	}
3133e1db26aSLionel Sambuc 
3143e1db26aSLionel Sambuc 	return 0;
3153e1db26aSLionel Sambuc }
3163e1db26aSLionel Sambuc 
3173e1db26aSLionel Sambuc 
3183e1db26aSLionel Sambuc /* history_def_set():
3193e1db26aSLionel Sambuc  *	Default function to set the current event in the history to the
3203e1db26aSLionel Sambuc  *	given one.
3213e1db26aSLionel Sambuc  */
3223e1db26aSLionel Sambuc private int
history_def_set(void * p,TYPE (HistEvent)* ev,const int n)3233e1db26aSLionel Sambuc history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
3243e1db26aSLionel Sambuc {
3253e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
3263e1db26aSLionel Sambuc 
3273e1db26aSLionel Sambuc 	if (h->cur == 0) {
3283e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_EMPTY_LIST);
3293e1db26aSLionel Sambuc 		return -1;
3303e1db26aSLionel Sambuc 	}
3313e1db26aSLionel Sambuc 	if (h->cursor == &h->list || h->cursor->ev.num != n) {
3323e1db26aSLionel Sambuc 		for (h->cursor = h->list.next; h->cursor != &h->list;
3333e1db26aSLionel Sambuc 		    h->cursor = h->cursor->next)
3343e1db26aSLionel Sambuc 			if (h->cursor->ev.num == n)
3353e1db26aSLionel Sambuc 				break;
3363e1db26aSLionel Sambuc 	}
3373e1db26aSLionel Sambuc 	if (h->cursor == &h->list) {
3383e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_NOT_FOUND);
3393e1db26aSLionel Sambuc 		return -1;
3403e1db26aSLionel Sambuc 	}
3413e1db26aSLionel Sambuc 	return 0;
3423e1db26aSLionel Sambuc }
3433e1db26aSLionel Sambuc 
3443e1db26aSLionel Sambuc 
3453e1db26aSLionel Sambuc /* history_set_nth():
3463e1db26aSLionel Sambuc  *	Default function to set the current event in the history to the
3473e1db26aSLionel Sambuc  *	n-th one.
3483e1db26aSLionel Sambuc  */
3493e1db26aSLionel Sambuc private int
history_set_nth(void * p,TYPE (HistEvent)* ev,int n)3503e1db26aSLionel Sambuc history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
3513e1db26aSLionel Sambuc {
3523e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
3533e1db26aSLionel Sambuc 
3543e1db26aSLionel Sambuc 	if (h->cur == 0) {
3553e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_EMPTY_LIST);
3563e1db26aSLionel Sambuc 		return -1;
3573e1db26aSLionel Sambuc 	}
3583e1db26aSLionel Sambuc 	for (h->cursor = h->list.prev; h->cursor != &h->list;
3593e1db26aSLionel Sambuc 	    h->cursor = h->cursor->prev)
3603e1db26aSLionel Sambuc 		if (n-- <= 0)
3613e1db26aSLionel Sambuc 			break;
3623e1db26aSLionel Sambuc 	if (h->cursor == &h->list) {
3633e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_NOT_FOUND);
3643e1db26aSLionel Sambuc 		return -1;
3653e1db26aSLionel Sambuc 	}
3663e1db26aSLionel Sambuc 	return 0;
3673e1db26aSLionel Sambuc }
3683e1db26aSLionel Sambuc 
3693e1db26aSLionel Sambuc 
3703e1db26aSLionel Sambuc /* history_def_add():
3713e1db26aSLionel Sambuc  *	Append string to element
3723e1db26aSLionel Sambuc  */
3733e1db26aSLionel Sambuc private int
history_def_add(void * p,TYPE (HistEvent)* ev,const Char * str)3743e1db26aSLionel Sambuc history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
3753e1db26aSLionel Sambuc {
3763e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
3773e1db26aSLionel Sambuc 	size_t len;
3783e1db26aSLionel Sambuc 	Char *s;
3793e1db26aSLionel Sambuc 	HistEventPrivate *evp = (void *)&h->cursor->ev;
3803e1db26aSLionel Sambuc 
3813e1db26aSLionel Sambuc 	if (h->cursor == &h->list)
3823e1db26aSLionel Sambuc 		return history_def_enter(p, ev, str);
3833e1db26aSLionel Sambuc 	len = Strlen(evp->str) + Strlen(str) + 1;
3843e1db26aSLionel Sambuc 	s = h_malloc(len * sizeof(*s));
3853e1db26aSLionel Sambuc 	if (s == NULL) {
3863e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_MALLOC_FAILED);
3873e1db26aSLionel Sambuc 		return -1;
3883e1db26aSLionel Sambuc 	}
3893e1db26aSLionel Sambuc 	(void) Strncpy(s, h->cursor->ev.str, len);
3903e1db26aSLionel Sambuc         s[len - 1] = '\0';
3913e1db26aSLionel Sambuc 	(void) Strncat(s, str, len - Strlen(s) - 1);
3923e1db26aSLionel Sambuc 	h_free(evp->str);
3933e1db26aSLionel Sambuc 	evp->str = s;
3943e1db26aSLionel Sambuc 	*ev = h->cursor->ev;
3953e1db26aSLionel Sambuc 	return 0;
3963e1db26aSLionel Sambuc }
3973e1db26aSLionel Sambuc 
3983e1db26aSLionel Sambuc 
3993e1db26aSLionel Sambuc private int
history_deldata_nth(history_t * h,TYPE (HistEvent)* ev,int num,void ** data)4003e1db26aSLionel Sambuc history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
4013e1db26aSLionel Sambuc     int num, void **data)
4023e1db26aSLionel Sambuc {
4033e1db26aSLionel Sambuc 	if (history_set_nth(h, ev, num) != 0)
4043e1db26aSLionel Sambuc 		return -1;
4053e1db26aSLionel Sambuc 	/* magic value to skip delete (just set to n-th history) */
4063e1db26aSLionel Sambuc 	if (data == (void **)-1)
4073e1db26aSLionel Sambuc 		return 0;
4083e1db26aSLionel Sambuc 	ev->str = Strdup(h->cursor->ev.str);
4093e1db26aSLionel Sambuc 	ev->num = h->cursor->ev.num;
4103e1db26aSLionel Sambuc 	if (data)
4113e1db26aSLionel Sambuc 		*data = h->cursor->data;
4123e1db26aSLionel Sambuc 	history_def_delete(h, ev, h->cursor);
4133e1db26aSLionel Sambuc 	return 0;
4143e1db26aSLionel Sambuc }
4153e1db26aSLionel Sambuc 
4163e1db26aSLionel Sambuc 
4173e1db26aSLionel Sambuc /* history_def_del():
4183e1db26aSLionel Sambuc  *	Delete element hp of the h list
4193e1db26aSLionel Sambuc  */
4203e1db26aSLionel Sambuc /* ARGSUSED */
4213e1db26aSLionel Sambuc private int
history_def_del(void * p,TYPE (HistEvent)* ev,const int num)4223e1db26aSLionel Sambuc history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
4233e1db26aSLionel Sambuc     const int num)
4243e1db26aSLionel Sambuc {
4253e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
4263e1db26aSLionel Sambuc 	if (history_def_set(h, ev, num) != 0)
4273e1db26aSLionel Sambuc 		return -1;
4283e1db26aSLionel Sambuc 	ev->str = Strdup(h->cursor->ev.str);
4293e1db26aSLionel Sambuc 	ev->num = h->cursor->ev.num;
4303e1db26aSLionel Sambuc 	history_def_delete(h, ev, h->cursor);
4313e1db26aSLionel Sambuc 	return 0;
4323e1db26aSLionel Sambuc }
4333e1db26aSLionel Sambuc 
4343e1db26aSLionel Sambuc 
4353e1db26aSLionel Sambuc /* history_def_delete():
4363e1db26aSLionel Sambuc  *	Delete element hp of the h list
4373e1db26aSLionel Sambuc  */
4383e1db26aSLionel Sambuc /* ARGSUSED */
4393e1db26aSLionel Sambuc private void
history_def_delete(history_t * h,TYPE (HistEvent)* ev,hentry_t * hp)4403e1db26aSLionel Sambuc history_def_delete(history_t *h,
4413e1db26aSLionel Sambuc 		   TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
4423e1db26aSLionel Sambuc {
4433e1db26aSLionel Sambuc 	HistEventPrivate *evp = (void *)&hp->ev;
4443e1db26aSLionel Sambuc 	if (hp == &h->list)
4453e1db26aSLionel Sambuc 		abort();
4463e1db26aSLionel Sambuc 	if (h->cursor == hp) {
4473e1db26aSLionel Sambuc 		h->cursor = hp->prev;
4483e1db26aSLionel Sambuc 		if (h->cursor == &h->list)
4493e1db26aSLionel Sambuc 			h->cursor = hp->next;
4503e1db26aSLionel Sambuc 	}
4513e1db26aSLionel Sambuc 	hp->prev->next = hp->next;
4523e1db26aSLionel Sambuc 	hp->next->prev = hp->prev;
4533e1db26aSLionel Sambuc 	h_free(evp->str);
4543e1db26aSLionel Sambuc 	h_free(hp);
4553e1db26aSLionel Sambuc 	h->cur--;
4563e1db26aSLionel Sambuc }
4573e1db26aSLionel Sambuc 
4583e1db26aSLionel Sambuc 
4593e1db26aSLionel Sambuc /* history_def_insert():
4603e1db26aSLionel Sambuc  *	Insert element with string str in the h list
4613e1db26aSLionel Sambuc  */
4623e1db26aSLionel Sambuc private int
history_def_insert(history_t * h,TYPE (HistEvent)* ev,const Char * str)4633e1db26aSLionel Sambuc history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
4643e1db26aSLionel Sambuc {
4653e1db26aSLionel Sambuc 	hentry_t *c;
4663e1db26aSLionel Sambuc 
4673e1db26aSLionel Sambuc 	c = h_malloc(sizeof(*c));
4683e1db26aSLionel Sambuc 	if (c == NULL)
4693e1db26aSLionel Sambuc 		goto oomem;
4703e1db26aSLionel Sambuc 	if ((c->ev.str = h_strdup(str)) == NULL) {
4713e1db26aSLionel Sambuc 		h_free(c);
4723e1db26aSLionel Sambuc 		goto oomem;
4733e1db26aSLionel Sambuc 	}
4743e1db26aSLionel Sambuc 	c->data = NULL;
4753e1db26aSLionel Sambuc 	c->ev.num = ++h->eventid;
4763e1db26aSLionel Sambuc 	c->next = h->list.next;
4773e1db26aSLionel Sambuc 	c->prev = &h->list;
4783e1db26aSLionel Sambuc 	h->list.next->prev = c;
4793e1db26aSLionel Sambuc 	h->list.next = c;
4803e1db26aSLionel Sambuc 	h->cur++;
4813e1db26aSLionel Sambuc 	h->cursor = c;
4823e1db26aSLionel Sambuc 
4833e1db26aSLionel Sambuc 	*ev = c->ev;
4843e1db26aSLionel Sambuc 	return 0;
4853e1db26aSLionel Sambuc oomem:
4863e1db26aSLionel Sambuc 	he_seterrev(ev, _HE_MALLOC_FAILED);
4873e1db26aSLionel Sambuc 	return -1;
4883e1db26aSLionel Sambuc }
4893e1db26aSLionel Sambuc 
4903e1db26aSLionel Sambuc 
4913e1db26aSLionel Sambuc /* history_def_enter():
4923e1db26aSLionel Sambuc  *	Default function to enter an item in the history
4933e1db26aSLionel Sambuc  */
4943e1db26aSLionel Sambuc private int
history_def_enter(void * p,TYPE (HistEvent)* ev,const Char * str)4953e1db26aSLionel Sambuc history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
4963e1db26aSLionel Sambuc {
4973e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
4983e1db26aSLionel Sambuc 
4993e1db26aSLionel Sambuc 	if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
5003e1db26aSLionel Sambuc 	    Strcmp(h->list.next->ev.str, str) == 0)
5013e1db26aSLionel Sambuc 	    return 0;
5023e1db26aSLionel Sambuc 
5033e1db26aSLionel Sambuc 	if (history_def_insert(h, ev, str) == -1)
5043e1db26aSLionel Sambuc 		return -1;	/* error, keep error message */
5053e1db26aSLionel Sambuc 
5063e1db26aSLionel Sambuc 	/*
5073e1db26aSLionel Sambuc          * Always keep at least one entry.
5083e1db26aSLionel Sambuc          * This way we don't have to check for the empty list.
5093e1db26aSLionel Sambuc          */
5103e1db26aSLionel Sambuc 	while (h->cur > h->max && h->cur > 0)
5113e1db26aSLionel Sambuc 		history_def_delete(h, ev, h->list.prev);
5123e1db26aSLionel Sambuc 
5133e1db26aSLionel Sambuc 	return 1;
5143e1db26aSLionel Sambuc }
5153e1db26aSLionel Sambuc 
5163e1db26aSLionel Sambuc 
5173e1db26aSLionel Sambuc /* history_def_init():
5183e1db26aSLionel Sambuc  *	Default history initialization function
5193e1db26aSLionel Sambuc  */
5203e1db26aSLionel Sambuc /* ARGSUSED */
5213e1db26aSLionel Sambuc private int
history_def_init(void ** p,TYPE (HistEvent)* ev,int n)5223e1db26aSLionel Sambuc history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
5233e1db26aSLionel Sambuc {
5243e1db26aSLionel Sambuc 	history_t *h = (history_t *) h_malloc(sizeof(*h));
5253e1db26aSLionel Sambuc 	if (h == NULL)
5263e1db26aSLionel Sambuc 		return -1;
5273e1db26aSLionel Sambuc 
5283e1db26aSLionel Sambuc 	if (n <= 0)
5293e1db26aSLionel Sambuc 		n = 0;
5303e1db26aSLionel Sambuc 	h->eventid = 0;
5313e1db26aSLionel Sambuc 	h->cur = 0;
5323e1db26aSLionel Sambuc 	h->max = n;
5333e1db26aSLionel Sambuc 	h->list.next = h->list.prev = &h->list;
5343e1db26aSLionel Sambuc 	h->list.ev.str = NULL;
5353e1db26aSLionel Sambuc 	h->list.ev.num = 0;
5363e1db26aSLionel Sambuc 	h->cursor = &h->list;
5373e1db26aSLionel Sambuc 	h->flags = 0;
5383e1db26aSLionel Sambuc 	*p = h;
5393e1db26aSLionel Sambuc 	return 0;
5403e1db26aSLionel Sambuc }
5413e1db26aSLionel Sambuc 
5423e1db26aSLionel Sambuc 
5433e1db26aSLionel Sambuc /* history_def_clear():
5443e1db26aSLionel Sambuc  *	Default history cleanup function
5453e1db26aSLionel Sambuc  */
5463e1db26aSLionel Sambuc private void
history_def_clear(void * p,TYPE (HistEvent)* ev)5473e1db26aSLionel Sambuc history_def_clear(void *p, TYPE(HistEvent) *ev)
5483e1db26aSLionel Sambuc {
5493e1db26aSLionel Sambuc 	history_t *h = (history_t *) p;
5503e1db26aSLionel Sambuc 
5513e1db26aSLionel Sambuc 	while (h->list.prev != &h->list)
5523e1db26aSLionel Sambuc 		history_def_delete(h, ev, h->list.prev);
5533e1db26aSLionel Sambuc 	h->cursor = &h->list;
5543e1db26aSLionel Sambuc 	h->eventid = 0;
5553e1db26aSLionel Sambuc 	h->cur = 0;
5563e1db26aSLionel Sambuc }
5573e1db26aSLionel Sambuc 
5583e1db26aSLionel Sambuc 
5593e1db26aSLionel Sambuc 
5603e1db26aSLionel Sambuc 
5613e1db26aSLionel Sambuc /************************************************************************/
5623e1db26aSLionel Sambuc 
5633e1db26aSLionel Sambuc /* history_init():
5643e1db26aSLionel Sambuc  *	Initialization function.
5653e1db26aSLionel Sambuc  */
TYPE(History)5663e1db26aSLionel Sambuc public TYPE(History) *
5673e1db26aSLionel Sambuc FUN(history,init)(void)
5683e1db26aSLionel Sambuc {
5693e1db26aSLionel Sambuc 	TYPE(HistEvent) ev;
5703e1db26aSLionel Sambuc 	TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
5713e1db26aSLionel Sambuc 	if (h == NULL)
5723e1db26aSLionel Sambuc 		return NULL;
5733e1db26aSLionel Sambuc 
5743e1db26aSLionel Sambuc 	if (history_def_init(&h->h_ref, &ev, 0) == -1) {
5753e1db26aSLionel Sambuc 		h_free(h);
5763e1db26aSLionel Sambuc 		return NULL;
5773e1db26aSLionel Sambuc 	}
5783e1db26aSLionel Sambuc 	h->h_ent = -1;
5793e1db26aSLionel Sambuc 	h->h_next = history_def_next;
5803e1db26aSLionel Sambuc 	h->h_first = history_def_first;
5813e1db26aSLionel Sambuc 	h->h_last = history_def_last;
5823e1db26aSLionel Sambuc 	h->h_prev = history_def_prev;
5833e1db26aSLionel Sambuc 	h->h_curr = history_def_curr;
5843e1db26aSLionel Sambuc 	h->h_set = history_def_set;
5853e1db26aSLionel Sambuc 	h->h_clear = history_def_clear;
5863e1db26aSLionel Sambuc 	h->h_enter = history_def_enter;
5873e1db26aSLionel Sambuc 	h->h_add = history_def_add;
5883e1db26aSLionel Sambuc 	h->h_del = history_def_del;
5893e1db26aSLionel Sambuc 
5903e1db26aSLionel Sambuc 	return h;
5913e1db26aSLionel Sambuc }
5923e1db26aSLionel Sambuc 
5933e1db26aSLionel Sambuc 
5943e1db26aSLionel Sambuc /* history_end():
5953e1db26aSLionel Sambuc  *	clean up history;
5963e1db26aSLionel Sambuc  */
5973e1db26aSLionel Sambuc public void
FUN(history,end)5983e1db26aSLionel Sambuc FUN(history,end)(TYPE(History) *h)
5993e1db26aSLionel Sambuc {
6003e1db26aSLionel Sambuc 	TYPE(HistEvent) ev;
6013e1db26aSLionel Sambuc 
6023e1db26aSLionel Sambuc 	if (h->h_next == history_def_next)
6033e1db26aSLionel Sambuc 		history_def_clear(h->h_ref, &ev);
6043e1db26aSLionel Sambuc 	h_free(h->h_ref);
6053e1db26aSLionel Sambuc 	h_free(h);
6063e1db26aSLionel Sambuc }
6073e1db26aSLionel Sambuc 
6083e1db26aSLionel Sambuc 
6093e1db26aSLionel Sambuc 
6103e1db26aSLionel Sambuc /* history_setsize():
6113e1db26aSLionel Sambuc  *	Set history number of events
6123e1db26aSLionel Sambuc  */
6133e1db26aSLionel Sambuc private int
history_setsize(TYPE (History)* h,TYPE (HistEvent)* ev,int num)6143e1db26aSLionel Sambuc history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
6153e1db26aSLionel Sambuc {
6163e1db26aSLionel Sambuc 
6173e1db26aSLionel Sambuc 	if (h->h_next != history_def_next) {
6183e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_NOT_ALLOWED);
6193e1db26aSLionel Sambuc 		return -1;
6203e1db26aSLionel Sambuc 	}
6213e1db26aSLionel Sambuc 	if (num < 0) {
6223e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_BAD_PARAM);
6233e1db26aSLionel Sambuc 		return -1;
6243e1db26aSLionel Sambuc 	}
6253e1db26aSLionel Sambuc 	history_def_setsize(h->h_ref, num);
6263e1db26aSLionel Sambuc 	return 0;
6273e1db26aSLionel Sambuc }
6283e1db26aSLionel Sambuc 
6293e1db26aSLionel Sambuc 
6303e1db26aSLionel Sambuc /* history_getsize():
6313e1db26aSLionel Sambuc  *      Get number of events currently in history
6323e1db26aSLionel Sambuc  */
6333e1db26aSLionel Sambuc private int
history_getsize(TYPE (History)* h,TYPE (HistEvent)* ev)6343e1db26aSLionel Sambuc history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
6353e1db26aSLionel Sambuc {
6363e1db26aSLionel Sambuc 	if (h->h_next != history_def_next) {
6373e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_NOT_ALLOWED);
6383e1db26aSLionel Sambuc 		return -1;
6393e1db26aSLionel Sambuc 	}
6403e1db26aSLionel Sambuc 	ev->num = history_def_getsize(h->h_ref);
6413e1db26aSLionel Sambuc 	if (ev->num < -1) {
6423e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_SIZE_NEGATIVE);
6433e1db26aSLionel Sambuc 		return -1;
6443e1db26aSLionel Sambuc 	}
6453e1db26aSLionel Sambuc 	return 0;
6463e1db26aSLionel Sambuc }
6473e1db26aSLionel Sambuc 
6483e1db26aSLionel Sambuc 
6493e1db26aSLionel Sambuc /* history_setunique():
6503e1db26aSLionel Sambuc  *	Set if adjacent equal events should not be entered in history.
6513e1db26aSLionel Sambuc  */
6523e1db26aSLionel Sambuc private int
history_setunique(TYPE (History)* h,TYPE (HistEvent)* ev,int uni)6533e1db26aSLionel Sambuc history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
6543e1db26aSLionel Sambuc {
6553e1db26aSLionel Sambuc 
6563e1db26aSLionel Sambuc 	if (h->h_next != history_def_next) {
6573e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_NOT_ALLOWED);
6583e1db26aSLionel Sambuc 		return -1;
6593e1db26aSLionel Sambuc 	}
6603e1db26aSLionel Sambuc 	history_def_setunique(h->h_ref, uni);
6613e1db26aSLionel Sambuc 	return 0;
6623e1db26aSLionel Sambuc }
6633e1db26aSLionel Sambuc 
6643e1db26aSLionel Sambuc 
6653e1db26aSLionel Sambuc /* history_getunique():
6663e1db26aSLionel Sambuc  *	Get if adjacent equal events should not be entered in history.
6673e1db26aSLionel Sambuc  */
6683e1db26aSLionel Sambuc private int
history_getunique(TYPE (History)* h,TYPE (HistEvent)* ev)6693e1db26aSLionel Sambuc history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
6703e1db26aSLionel Sambuc {
6713e1db26aSLionel Sambuc 	if (h->h_next != history_def_next) {
6723e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_NOT_ALLOWED);
6733e1db26aSLionel Sambuc 		return -1;
6743e1db26aSLionel Sambuc 	}
6753e1db26aSLionel Sambuc 	ev->num = history_def_getunique(h->h_ref);
6763e1db26aSLionel Sambuc 	return 0;
6773e1db26aSLionel Sambuc }
6783e1db26aSLionel Sambuc 
6793e1db26aSLionel Sambuc 
6803e1db26aSLionel Sambuc /* history_set_fun():
6813e1db26aSLionel Sambuc  *	Set history functions
6823e1db26aSLionel Sambuc  */
6833e1db26aSLionel Sambuc private int
history_set_fun(TYPE (History)* h,TYPE (History)* nh)6843e1db26aSLionel Sambuc history_set_fun(TYPE(History) *h, TYPE(History) *nh)
6853e1db26aSLionel Sambuc {
6863e1db26aSLionel Sambuc 	TYPE(HistEvent) ev;
6873e1db26aSLionel Sambuc 
6883e1db26aSLionel Sambuc 	if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
6893e1db26aSLionel Sambuc 	    nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
6903e1db26aSLionel Sambuc 	    nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
6913e1db26aSLionel Sambuc 	    nh->h_del == NULL || nh->h_ref == NULL) {
6923e1db26aSLionel Sambuc 		if (h->h_next != history_def_next) {
6933e1db26aSLionel Sambuc 			if (history_def_init(&h->h_ref, &ev, 0) == -1)
6943e1db26aSLionel Sambuc 				return -1;
6953e1db26aSLionel Sambuc 			h->h_first = history_def_first;
6963e1db26aSLionel Sambuc 			h->h_next = history_def_next;
6973e1db26aSLionel Sambuc 			h->h_last = history_def_last;
6983e1db26aSLionel Sambuc 			h->h_prev = history_def_prev;
6993e1db26aSLionel Sambuc 			h->h_curr = history_def_curr;
7003e1db26aSLionel Sambuc 			h->h_set = history_def_set;
7013e1db26aSLionel Sambuc 			h->h_clear = history_def_clear;
7023e1db26aSLionel Sambuc 			h->h_enter = history_def_enter;
7033e1db26aSLionel Sambuc 			h->h_add = history_def_add;
7043e1db26aSLionel Sambuc 			h->h_del = history_def_del;
7053e1db26aSLionel Sambuc 		}
7063e1db26aSLionel Sambuc 		return -1;
7073e1db26aSLionel Sambuc 	}
7083e1db26aSLionel Sambuc 	if (h->h_next == history_def_next)
7093e1db26aSLionel Sambuc 		history_def_clear(h->h_ref, &ev);
7103e1db26aSLionel Sambuc 
7113e1db26aSLionel Sambuc 	h->h_ent = -1;
7123e1db26aSLionel Sambuc 	h->h_first = nh->h_first;
7133e1db26aSLionel Sambuc 	h->h_next = nh->h_next;
7143e1db26aSLionel Sambuc 	h->h_last = nh->h_last;
7153e1db26aSLionel Sambuc 	h->h_prev = nh->h_prev;
7163e1db26aSLionel Sambuc 	h->h_curr = nh->h_curr;
7173e1db26aSLionel Sambuc 	h->h_set = nh->h_set;
7183e1db26aSLionel Sambuc 	h->h_clear = nh->h_clear;
7193e1db26aSLionel Sambuc 	h->h_enter = nh->h_enter;
7203e1db26aSLionel Sambuc 	h->h_add = nh->h_add;
7213e1db26aSLionel Sambuc 	h->h_del = nh->h_del;
7223e1db26aSLionel Sambuc 
7233e1db26aSLionel Sambuc 	return 0;
7243e1db26aSLionel Sambuc }
7253e1db26aSLionel Sambuc 
7263e1db26aSLionel Sambuc 
7273e1db26aSLionel Sambuc /* history_load():
7283e1db26aSLionel Sambuc  *	TYPE(History) load function
7293e1db26aSLionel Sambuc  */
7303e1db26aSLionel Sambuc private int
history_load(TYPE (History)* h,const char * fname)7313e1db26aSLionel Sambuc history_load(TYPE(History) *h, const char *fname)
7323e1db26aSLionel Sambuc {
7333e1db26aSLionel Sambuc 	FILE *fp;
7343e1db26aSLionel Sambuc 	char *line;
7353e1db26aSLionel Sambuc 	size_t sz, max_size;
7363e1db26aSLionel Sambuc 	char *ptr;
7373e1db26aSLionel Sambuc 	int i = -1;
7383e1db26aSLionel Sambuc 	TYPE(HistEvent) ev;
7393e1db26aSLionel Sambuc #ifdef WIDECHAR
7403e1db26aSLionel Sambuc 	static ct_buffer_t conv;
7413e1db26aSLionel Sambuc #endif
7423e1db26aSLionel Sambuc 
7433e1db26aSLionel Sambuc 	if ((fp = fopen(fname, "r")) == NULL)
7443e1db26aSLionel Sambuc 		return i;
7453e1db26aSLionel Sambuc 
7463e1db26aSLionel Sambuc 	if ((line = fgetln(fp, &sz)) == NULL)
7473e1db26aSLionel Sambuc 		goto done;
7483e1db26aSLionel Sambuc 
7493e1db26aSLionel Sambuc 	if (strncmp(line, hist_cookie, sz) != 0)
7503e1db26aSLionel Sambuc 		goto done;
7513e1db26aSLionel Sambuc 
7523e1db26aSLionel Sambuc 	ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
7533e1db26aSLionel Sambuc 	if (ptr == NULL)
7543e1db26aSLionel Sambuc 		goto done;
7553e1db26aSLionel Sambuc 	for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
7563e1db26aSLionel Sambuc 		char c = line[sz];
7573e1db26aSLionel Sambuc 
7583e1db26aSLionel Sambuc 		if (sz != 0 && line[sz - 1] == '\n')
7593e1db26aSLionel Sambuc 			line[--sz] = '\0';
7603e1db26aSLionel Sambuc 		else
7613e1db26aSLionel Sambuc 			line[sz] = '\0';
7623e1db26aSLionel Sambuc 
7633e1db26aSLionel Sambuc 		if (max_size < sz) {
7643e1db26aSLionel Sambuc 			char *nptr;
7653e1db26aSLionel Sambuc 			max_size = (sz + 1024) & (size_t)~1023;
7663e1db26aSLionel Sambuc 			nptr = h_realloc(ptr, max_size * sizeof(*ptr));
7673e1db26aSLionel Sambuc 			if (nptr == NULL) {
7683e1db26aSLionel Sambuc 				i = -1;
7693e1db26aSLionel Sambuc 				goto oomem;
7703e1db26aSLionel Sambuc 			}
7713e1db26aSLionel Sambuc 			ptr = nptr;
7723e1db26aSLionel Sambuc 		}
7733e1db26aSLionel Sambuc 		(void) strunvis(ptr, line);
7743e1db26aSLionel Sambuc 		line[sz] = c;
7753e1db26aSLionel Sambuc 		if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) {
7763e1db26aSLionel Sambuc 			i = -1;
7773e1db26aSLionel Sambuc 			goto oomem;
7783e1db26aSLionel Sambuc 		}
7793e1db26aSLionel Sambuc 	}
7803e1db26aSLionel Sambuc oomem:
7813e1db26aSLionel Sambuc 	h_free(ptr);
7823e1db26aSLionel Sambuc done:
7833e1db26aSLionel Sambuc 	(void) fclose(fp);
7843e1db26aSLionel Sambuc 	return i;
7853e1db26aSLionel Sambuc }
7863e1db26aSLionel Sambuc 
7873e1db26aSLionel Sambuc 
788*0a6a1f1dSLionel Sambuc /* history_save_fp():
7893e1db26aSLionel Sambuc  *	TYPE(History) save function
7903e1db26aSLionel Sambuc  */
7913e1db26aSLionel Sambuc private int
history_save_fp(TYPE (History)* h,FILE * fp)792*0a6a1f1dSLionel Sambuc history_save_fp(TYPE(History) *h, FILE *fp)
7933e1db26aSLionel Sambuc {
7943e1db26aSLionel Sambuc 	TYPE(HistEvent) ev;
7953e1db26aSLionel Sambuc 	int i = -1, retval;
7963e1db26aSLionel Sambuc 	size_t len, max_size;
7973e1db26aSLionel Sambuc 	char *ptr;
7983e1db26aSLionel Sambuc 	const char *str;
7993e1db26aSLionel Sambuc #ifdef WIDECHAR
8003e1db26aSLionel Sambuc 	static ct_buffer_t conv;
8013e1db26aSLionel Sambuc #endif
8023e1db26aSLionel Sambuc 
8033e1db26aSLionel Sambuc 	if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
8043e1db26aSLionel Sambuc 		goto done;
8053e1db26aSLionel Sambuc 	if (fputs(hist_cookie, fp) == EOF)
8063e1db26aSLionel Sambuc 		goto done;
8073e1db26aSLionel Sambuc 	ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
8083e1db26aSLionel Sambuc 	if (ptr == NULL)
8093e1db26aSLionel Sambuc 		goto done;
8103e1db26aSLionel Sambuc 	for (i = 0, retval = HLAST(h, &ev);
8113e1db26aSLionel Sambuc 	    retval != -1;
8123e1db26aSLionel Sambuc 	    retval = HPREV(h, &ev), i++) {
8133e1db26aSLionel Sambuc 		str = ct_encode_string(ev.str, &conv);
8143e1db26aSLionel Sambuc 		len = strlen(str) * 4;
8153e1db26aSLionel Sambuc 		if (len >= max_size) {
8163e1db26aSLionel Sambuc 			char *nptr;
8173e1db26aSLionel Sambuc 			max_size = (len + 1024) & (size_t)~1023;
8183e1db26aSLionel Sambuc 			nptr = h_realloc(ptr, max_size * sizeof(*ptr));
8193e1db26aSLionel Sambuc 			if (nptr == NULL) {
8203e1db26aSLionel Sambuc 				i = -1;
8213e1db26aSLionel Sambuc 				goto oomem;
8223e1db26aSLionel Sambuc 			}
8233e1db26aSLionel Sambuc 			ptr = nptr;
8243e1db26aSLionel Sambuc 		}
8253e1db26aSLionel Sambuc 		(void) strvis(ptr, str, VIS_WHITE);
8263e1db26aSLionel Sambuc 		(void) fprintf(fp, "%s\n", ptr);
8273e1db26aSLionel Sambuc 	}
8283e1db26aSLionel Sambuc oomem:
8293e1db26aSLionel Sambuc 	h_free(ptr);
8303e1db26aSLionel Sambuc done:
831*0a6a1f1dSLionel Sambuc 	return i;
832*0a6a1f1dSLionel Sambuc }
833*0a6a1f1dSLionel Sambuc 
834*0a6a1f1dSLionel Sambuc 
835*0a6a1f1dSLionel Sambuc /* history_save():
836*0a6a1f1dSLionel Sambuc  *    History save function
837*0a6a1f1dSLionel Sambuc  */
838*0a6a1f1dSLionel Sambuc private int
history_save(TYPE (History)* h,const char * fname)839*0a6a1f1dSLionel Sambuc history_save(TYPE(History) *h, const char *fname)
840*0a6a1f1dSLionel Sambuc {
841*0a6a1f1dSLionel Sambuc     FILE *fp;
842*0a6a1f1dSLionel Sambuc     int i;
843*0a6a1f1dSLionel Sambuc 
844*0a6a1f1dSLionel Sambuc     if ((fp = fopen(fname, "w")) == NULL)
845*0a6a1f1dSLionel Sambuc 	return -1;
846*0a6a1f1dSLionel Sambuc 
847*0a6a1f1dSLionel Sambuc     i = history_save_fp(h, fp);
848*0a6a1f1dSLionel Sambuc 
8493e1db26aSLionel Sambuc     (void) fclose(fp);
8503e1db26aSLionel Sambuc     return i;
8513e1db26aSLionel Sambuc }
8523e1db26aSLionel Sambuc 
8533e1db26aSLionel Sambuc 
8543e1db26aSLionel Sambuc /* history_prev_event():
8553e1db26aSLionel Sambuc  *	Find the previous event, with number given
8563e1db26aSLionel Sambuc  */
8573e1db26aSLionel Sambuc private int
history_prev_event(TYPE (History)* h,TYPE (HistEvent)* ev,int num)8583e1db26aSLionel Sambuc history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
8593e1db26aSLionel Sambuc {
8603e1db26aSLionel Sambuc 	int retval;
8613e1db26aSLionel Sambuc 
8623e1db26aSLionel Sambuc 	for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
8633e1db26aSLionel Sambuc 		if (ev->num == num)
8643e1db26aSLionel Sambuc 			return 0;
8653e1db26aSLionel Sambuc 
8663e1db26aSLionel Sambuc 	he_seterrev(ev, _HE_NOT_FOUND);
8673e1db26aSLionel Sambuc 	return -1;
8683e1db26aSLionel Sambuc }
8693e1db26aSLionel Sambuc 
8703e1db26aSLionel Sambuc 
8713e1db26aSLionel Sambuc private int
history_next_evdata(TYPE (History)* h,TYPE (HistEvent)* ev,int num,void ** d)8723e1db26aSLionel Sambuc history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
8733e1db26aSLionel Sambuc {
8743e1db26aSLionel Sambuc 	int retval;
8753e1db26aSLionel Sambuc 
8763e1db26aSLionel Sambuc 	for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
8773e1db26aSLionel Sambuc 		if (ev->num == num) {
8783e1db26aSLionel Sambuc 			if (d)
8793e1db26aSLionel Sambuc 				*d = ((history_t *)h->h_ref)->cursor->data;
8803e1db26aSLionel Sambuc 			return 0;
8813e1db26aSLionel Sambuc 		}
8823e1db26aSLionel Sambuc 
8833e1db26aSLionel Sambuc 	he_seterrev(ev, _HE_NOT_FOUND);
8843e1db26aSLionel Sambuc 	return -1;
8853e1db26aSLionel Sambuc }
8863e1db26aSLionel Sambuc 
8873e1db26aSLionel Sambuc 
8883e1db26aSLionel Sambuc /* history_next_event():
8893e1db26aSLionel Sambuc  *	Find the next event, with number given
8903e1db26aSLionel Sambuc  */
8913e1db26aSLionel Sambuc private int
history_next_event(TYPE (History)* h,TYPE (HistEvent)* ev,int num)8923e1db26aSLionel Sambuc history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
8933e1db26aSLionel Sambuc {
8943e1db26aSLionel Sambuc 	int retval;
8953e1db26aSLionel Sambuc 
8963e1db26aSLionel Sambuc 	for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
8973e1db26aSLionel Sambuc 		if (ev->num == num)
8983e1db26aSLionel Sambuc 			return 0;
8993e1db26aSLionel Sambuc 
9003e1db26aSLionel Sambuc 	he_seterrev(ev, _HE_NOT_FOUND);
9013e1db26aSLionel Sambuc 	return -1;
9023e1db26aSLionel Sambuc }
9033e1db26aSLionel Sambuc 
9043e1db26aSLionel Sambuc 
9053e1db26aSLionel Sambuc /* history_prev_string():
9063e1db26aSLionel Sambuc  *	Find the previous event beginning with string
9073e1db26aSLionel Sambuc  */
9083e1db26aSLionel Sambuc private int
history_prev_string(TYPE (History)* h,TYPE (HistEvent)* ev,const Char * str)9093e1db26aSLionel Sambuc history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
9103e1db26aSLionel Sambuc {
9113e1db26aSLionel Sambuc 	size_t len = Strlen(str);
9123e1db26aSLionel Sambuc 	int retval;
9133e1db26aSLionel Sambuc 
9143e1db26aSLionel Sambuc 	for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
9153e1db26aSLionel Sambuc 		if (Strncmp(str, ev->str, len) == 0)
9163e1db26aSLionel Sambuc 			return 0;
9173e1db26aSLionel Sambuc 
9183e1db26aSLionel Sambuc 	he_seterrev(ev, _HE_NOT_FOUND);
9193e1db26aSLionel Sambuc 	return -1;
9203e1db26aSLionel Sambuc }
9213e1db26aSLionel Sambuc 
9223e1db26aSLionel Sambuc 
9233e1db26aSLionel Sambuc /* history_next_string():
9243e1db26aSLionel Sambuc  *	Find the next event beginning with string
9253e1db26aSLionel Sambuc  */
9263e1db26aSLionel Sambuc private int
history_next_string(TYPE (History)* h,TYPE (HistEvent)* ev,const Char * str)9273e1db26aSLionel Sambuc history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
9283e1db26aSLionel Sambuc {
9293e1db26aSLionel Sambuc 	size_t len = Strlen(str);
9303e1db26aSLionel Sambuc 	int retval;
9313e1db26aSLionel Sambuc 
9323e1db26aSLionel Sambuc 	for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
9333e1db26aSLionel Sambuc 		if (Strncmp(str, ev->str, len) == 0)
9343e1db26aSLionel Sambuc 			return 0;
9353e1db26aSLionel Sambuc 
9363e1db26aSLionel Sambuc 	he_seterrev(ev, _HE_NOT_FOUND);
9373e1db26aSLionel Sambuc 	return -1;
9383e1db26aSLionel Sambuc }
9393e1db26aSLionel Sambuc 
9403e1db26aSLionel Sambuc 
9413e1db26aSLionel Sambuc /* history():
9423e1db26aSLionel Sambuc  *	User interface to history functions.
9433e1db26aSLionel Sambuc  */
9443e1db26aSLionel Sambuc int
FUNW(history)9453e1db26aSLionel Sambuc FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
9463e1db26aSLionel Sambuc {
9473e1db26aSLionel Sambuc 	va_list va;
9483e1db26aSLionel Sambuc 	const Char *str;
9493e1db26aSLionel Sambuc 	int retval;
9503e1db26aSLionel Sambuc 
9513e1db26aSLionel Sambuc 	va_start(va, fun);
9523e1db26aSLionel Sambuc 
9533e1db26aSLionel Sambuc 	he_seterrev(ev, _HE_OK);
9543e1db26aSLionel Sambuc 
9553e1db26aSLionel Sambuc 	switch (fun) {
9563e1db26aSLionel Sambuc 	case H_GETSIZE:
9573e1db26aSLionel Sambuc 		retval = history_getsize(h, ev);
9583e1db26aSLionel Sambuc 		break;
9593e1db26aSLionel Sambuc 
9603e1db26aSLionel Sambuc 	case H_SETSIZE:
9613e1db26aSLionel Sambuc 		retval = history_setsize(h, ev, va_arg(va, int));
9623e1db26aSLionel Sambuc 		break;
9633e1db26aSLionel Sambuc 
9643e1db26aSLionel Sambuc 	case H_GETUNIQUE:
9653e1db26aSLionel Sambuc 		retval = history_getunique(h, ev);
9663e1db26aSLionel Sambuc 		break;
9673e1db26aSLionel Sambuc 
9683e1db26aSLionel Sambuc 	case H_SETUNIQUE:
9693e1db26aSLionel Sambuc 		retval = history_setunique(h, ev, va_arg(va, int));
9703e1db26aSLionel Sambuc 		break;
9713e1db26aSLionel Sambuc 
9723e1db26aSLionel Sambuc 	case H_ADD:
9733e1db26aSLionel Sambuc 		str = va_arg(va, const Char *);
9743e1db26aSLionel Sambuc 		retval = HADD(h, ev, str);
9753e1db26aSLionel Sambuc 		break;
9763e1db26aSLionel Sambuc 
9773e1db26aSLionel Sambuc 	case H_DEL:
9783e1db26aSLionel Sambuc 		retval = HDEL(h, ev, va_arg(va, const int));
9793e1db26aSLionel Sambuc 		break;
9803e1db26aSLionel Sambuc 
9813e1db26aSLionel Sambuc 	case H_ENTER:
9823e1db26aSLionel Sambuc 		str = va_arg(va, const Char *);
9833e1db26aSLionel Sambuc 		if ((retval = HENTER(h, ev, str)) != -1)
9843e1db26aSLionel Sambuc 			h->h_ent = ev->num;
9853e1db26aSLionel Sambuc 		break;
9863e1db26aSLionel Sambuc 
9873e1db26aSLionel Sambuc 	case H_APPEND:
9883e1db26aSLionel Sambuc 		str = va_arg(va, const Char *);
9893e1db26aSLionel Sambuc 		if ((retval = HSET(h, ev, h->h_ent)) != -1)
9903e1db26aSLionel Sambuc 			retval = HADD(h, ev, str);
9913e1db26aSLionel Sambuc 		break;
9923e1db26aSLionel Sambuc 
9933e1db26aSLionel Sambuc 	case H_FIRST:
9943e1db26aSLionel Sambuc 		retval = HFIRST(h, ev);
9953e1db26aSLionel Sambuc 		break;
9963e1db26aSLionel Sambuc 
9973e1db26aSLionel Sambuc 	case H_NEXT:
9983e1db26aSLionel Sambuc 		retval = HNEXT(h, ev);
9993e1db26aSLionel Sambuc 		break;
10003e1db26aSLionel Sambuc 
10013e1db26aSLionel Sambuc 	case H_LAST:
10023e1db26aSLionel Sambuc 		retval = HLAST(h, ev);
10033e1db26aSLionel Sambuc 		break;
10043e1db26aSLionel Sambuc 
10053e1db26aSLionel Sambuc 	case H_PREV:
10063e1db26aSLionel Sambuc 		retval = HPREV(h, ev);
10073e1db26aSLionel Sambuc 		break;
10083e1db26aSLionel Sambuc 
10093e1db26aSLionel Sambuc 	case H_CURR:
10103e1db26aSLionel Sambuc 		retval = HCURR(h, ev);
10113e1db26aSLionel Sambuc 		break;
10123e1db26aSLionel Sambuc 
10133e1db26aSLionel Sambuc 	case H_SET:
10143e1db26aSLionel Sambuc 		retval = HSET(h, ev, va_arg(va, const int));
10153e1db26aSLionel Sambuc 		break;
10163e1db26aSLionel Sambuc 
10173e1db26aSLionel Sambuc 	case H_CLEAR:
10183e1db26aSLionel Sambuc 		HCLEAR(h, ev);
10193e1db26aSLionel Sambuc 		retval = 0;
10203e1db26aSLionel Sambuc 		break;
10213e1db26aSLionel Sambuc 
10223e1db26aSLionel Sambuc 	case H_LOAD:
10233e1db26aSLionel Sambuc 		retval = history_load(h, va_arg(va, const char *));
10243e1db26aSLionel Sambuc 		if (retval == -1)
10253e1db26aSLionel Sambuc 			he_seterrev(ev, _HE_HIST_READ);
10263e1db26aSLionel Sambuc 		break;
10273e1db26aSLionel Sambuc 
10283e1db26aSLionel Sambuc 	case H_SAVE:
10293e1db26aSLionel Sambuc 		retval = history_save(h, va_arg(va, const char *));
10303e1db26aSLionel Sambuc 		if (retval == -1)
10313e1db26aSLionel Sambuc 			he_seterrev(ev, _HE_HIST_WRITE);
10323e1db26aSLionel Sambuc 		break;
10333e1db26aSLionel Sambuc 
1034*0a6a1f1dSLionel Sambuc 	case H_SAVE_FP:
1035*0a6a1f1dSLionel Sambuc 		retval = history_save_fp(h, va_arg(va, FILE *));
1036*0a6a1f1dSLionel Sambuc 		if (retval == -1)
1037*0a6a1f1dSLionel Sambuc 		    he_seterrev(ev, _HE_HIST_WRITE);
1038*0a6a1f1dSLionel Sambuc 		break;
1039*0a6a1f1dSLionel Sambuc 
10403e1db26aSLionel Sambuc 	case H_PREV_EVENT:
10413e1db26aSLionel Sambuc 		retval = history_prev_event(h, ev, va_arg(va, int));
10423e1db26aSLionel Sambuc 		break;
10433e1db26aSLionel Sambuc 
10443e1db26aSLionel Sambuc 	case H_NEXT_EVENT:
10453e1db26aSLionel Sambuc 		retval = history_next_event(h, ev, va_arg(va, int));
10463e1db26aSLionel Sambuc 		break;
10473e1db26aSLionel Sambuc 
10483e1db26aSLionel Sambuc 	case H_PREV_STR:
10493e1db26aSLionel Sambuc 		retval = history_prev_string(h, ev, va_arg(va, const Char *));
10503e1db26aSLionel Sambuc 		break;
10513e1db26aSLionel Sambuc 
10523e1db26aSLionel Sambuc 	case H_NEXT_STR:
10533e1db26aSLionel Sambuc 		retval = history_next_string(h, ev, va_arg(va, const Char *));
10543e1db26aSLionel Sambuc 		break;
10553e1db26aSLionel Sambuc 
10563e1db26aSLionel Sambuc 	case H_FUNC:
10573e1db26aSLionel Sambuc 	{
10583e1db26aSLionel Sambuc 		TYPE(History) hf;
10593e1db26aSLionel Sambuc 
10603e1db26aSLionel Sambuc 		hf.h_ref = va_arg(va, void *);
10613e1db26aSLionel Sambuc 		h->h_ent = -1;
10623e1db26aSLionel Sambuc 		hf.h_first = va_arg(va, history_gfun_t);
10633e1db26aSLionel Sambuc 		hf.h_next = va_arg(va, history_gfun_t);
10643e1db26aSLionel Sambuc 		hf.h_last = va_arg(va, history_gfun_t);
10653e1db26aSLionel Sambuc 		hf.h_prev = va_arg(va, history_gfun_t);
10663e1db26aSLionel Sambuc 		hf.h_curr = va_arg(va, history_gfun_t);
10673e1db26aSLionel Sambuc 		hf.h_set = va_arg(va, history_sfun_t);
10683e1db26aSLionel Sambuc 		hf.h_clear = va_arg(va, history_vfun_t);
10693e1db26aSLionel Sambuc 		hf.h_enter = va_arg(va, history_efun_t);
10703e1db26aSLionel Sambuc 		hf.h_add = va_arg(va, history_efun_t);
10713e1db26aSLionel Sambuc 		hf.h_del = va_arg(va, history_sfun_t);
10723e1db26aSLionel Sambuc 
10733e1db26aSLionel Sambuc 		if ((retval = history_set_fun(h, &hf)) == -1)
10743e1db26aSLionel Sambuc 			he_seterrev(ev, _HE_PARAM_MISSING);
10753e1db26aSLionel Sambuc 		break;
10763e1db26aSLionel Sambuc 	}
10773e1db26aSLionel Sambuc 
10783e1db26aSLionel Sambuc 	case H_END:
10793e1db26aSLionel Sambuc 		FUN(history,end)(h);
10803e1db26aSLionel Sambuc 		retval = 0;
10813e1db26aSLionel Sambuc 		break;
10823e1db26aSLionel Sambuc 
10833e1db26aSLionel Sambuc 	case H_NEXT_EVDATA:
10843e1db26aSLionel Sambuc 	{
10853e1db26aSLionel Sambuc 		int num = va_arg(va, int);
10863e1db26aSLionel Sambuc 		void **d = va_arg(va, void **);
10873e1db26aSLionel Sambuc 		retval = history_next_evdata(h, ev, num, d);
10883e1db26aSLionel Sambuc 		break;
10893e1db26aSLionel Sambuc 	}
10903e1db26aSLionel Sambuc 
10913e1db26aSLionel Sambuc 	case H_DELDATA:
10923e1db26aSLionel Sambuc 	{
10933e1db26aSLionel Sambuc 		int num = va_arg(va, int);
10943e1db26aSLionel Sambuc 		void **d = va_arg(va, void **);
10953e1db26aSLionel Sambuc 		retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
10963e1db26aSLionel Sambuc 		break;
10973e1db26aSLionel Sambuc 	}
10983e1db26aSLionel Sambuc 
10993e1db26aSLionel Sambuc 	case H_REPLACE: /* only use after H_NEXT_EVDATA */
11003e1db26aSLionel Sambuc 	{
11013e1db26aSLionel Sambuc 		const Char *line = va_arg(va, const Char *);
11023e1db26aSLionel Sambuc 		void *d = va_arg(va, void *);
11033e1db26aSLionel Sambuc 		const Char *s;
11043e1db26aSLionel Sambuc 		if(!line || !(s = Strdup(line))) {
11053e1db26aSLionel Sambuc 			retval = -1;
11063e1db26aSLionel Sambuc 			break;
11073e1db26aSLionel Sambuc 		}
11083e1db26aSLionel Sambuc 		((history_t *)h->h_ref)->cursor->ev.str = s;
11093e1db26aSLionel Sambuc 		((history_t *)h->h_ref)->cursor->data = d;
11103e1db26aSLionel Sambuc 		retval = 0;
11113e1db26aSLionel Sambuc 		break;
11123e1db26aSLionel Sambuc 	}
11133e1db26aSLionel Sambuc 
11143e1db26aSLionel Sambuc 	default:
11153e1db26aSLionel Sambuc 		retval = -1;
11163e1db26aSLionel Sambuc 		he_seterrev(ev, _HE_UNKNOWN);
11173e1db26aSLionel Sambuc 		break;
11183e1db26aSLionel Sambuc 	}
11193e1db26aSLionel Sambuc 	va_end(va);
11203e1db26aSLionel Sambuc 	return retval;
11213e1db26aSLionel Sambuc }
1122