1*5b133f3fSguenther /* $OpenBSD: history.c,v 1.29 2023/03/08 04:43:05 guenther Exp $ */
2aed0ee81Snicm /* $NetBSD: history.c,v 1.37 2010/01/03 18:27:10 christos Exp $ */
3babb851aSmillert
4df930be7Sderaadt /*-
5df930be7Sderaadt * Copyright (c) 1992, 1993
6df930be7Sderaadt * The Regents of the University of California. All rights reserved.
7df930be7Sderaadt *
8df930be7Sderaadt * This code is derived from software contributed to Berkeley by
9df930be7Sderaadt * Christos Zoulas of Cornell University.
10df930be7Sderaadt *
11df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
12df930be7Sderaadt * modification, are permitted provided that the following conditions
13df930be7Sderaadt * are met:
14df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
15df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
16df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
17df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
18df930be7Sderaadt * documentation and/or other materials provided with the distribution.
196580fee3Smillert * 3. Neither the name of the University nor the names of its contributors
20df930be7Sderaadt * may be used to endorse or promote products derived from this software
21df930be7Sderaadt * without specific prior written permission.
22df930be7Sderaadt *
23df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33df930be7Sderaadt * SUCH DAMAGE.
34df930be7Sderaadt */
35df930be7Sderaadt
36d484b7d0Sotto #include "config.h"
37df930be7Sderaadt
38df930be7Sderaadt /*
39aed0ee81Snicm * hist.c: TYPE(History) access functions
40df930be7Sderaadt */
417ccfa089Sschwarze #include <sys/stat.h>
42df930be7Sderaadt #include <stdarg.h>
437ccfa089Sschwarze #include <stdlib.h>
447ccfa089Sschwarze #include <string.h>
45d484b7d0Sotto #ifdef HAVE_VIS_H
46d484b7d0Sotto #include <vis.h>
47d484b7d0Sotto #else
48d484b7d0Sotto #include "np/vis.h"
49d484b7d0Sotto #endif
50df930be7Sderaadt
51d484b7d0Sotto static const char hist_cookie[] = "_HiStOrY_V2_\n";
528bd3f282Sderaadt
53df930be7Sderaadt #include "histedit.h"
54df930be7Sderaadt
555c93237dSschwarze
565c93237dSschwarze #ifdef NARROWCHAR
575c93237dSschwarze
58e3191321Sschwarze #define Char char
595c93237dSschwarze #define FUN(prefix, rest) prefix ## _ ## rest
605c93237dSschwarze #define FUNW(type) type
615c93237dSschwarze #define TYPE(type) type
625c93237dSschwarze #define STR(x) x
635c93237dSschwarze
645c93237dSschwarze #define Strlen(s) strlen(s)
655c93237dSschwarze #define Strdup(s) strdup(s)
665c93237dSschwarze #define Strcmp(d, s) strcmp(d, s)
675c93237dSschwarze #define Strncmp(d, s, n) strncmp(d, s, n)
685c93237dSschwarze #define Strncpy(d, s, n) strncpy(d, s, n)
695c93237dSschwarze #define Strncat(d, s, n) strncat(d, s, n)
708dc8c690Sschwarze #define ct_decode_string(s, b) (s)
718dc8c690Sschwarze #define ct_encode_string(s, b) (s)
725c93237dSschwarze
735c93237dSschwarze #else
748dc8c690Sschwarze #include "chartype.h"
755c93237dSschwarze
76e3191321Sschwarze #define Char wchar_t
775c93237dSschwarze #define FUN(prefix, rest) prefix ## _w ## rest
785c93237dSschwarze #define FUNW(type) type ## _w
795c93237dSschwarze #define TYPE(type) type ## W
805c93237dSschwarze #define STR(x) L ## x
815c93237dSschwarze
825c93237dSschwarze #define Strlen(s) wcslen(s)
835c93237dSschwarze #define Strdup(s) wcsdup(s)
845c93237dSschwarze #define Strcmp(d, s) wcscmp(d, s)
855c93237dSschwarze #define Strncmp(d, s, n) wcsncmp(d, s, n)
865c93237dSschwarze #define Strncpy(d, s, n) wcsncpy(d, s, n)
875c93237dSschwarze #define Strncat(d, s, n) wcsncat(d, s, n)
885c93237dSschwarze
895c93237dSschwarze #endif
905c93237dSschwarze
915c93237dSschwarze
927b85e16bSschwarze typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
937b85e16bSschwarze typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
947b85e16bSschwarze typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
957b85e16bSschwarze typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
96df930be7Sderaadt
TYPE(history)97aed0ee81Snicm struct TYPE(history) {
987b85e16bSschwarze void *h_ref; /* Argument for history fcns */
99d484b7d0Sotto int h_ent; /* Last entry point for history */
100df930be7Sderaadt history_gfun_t h_first; /* Get the first element */
101df930be7Sderaadt history_gfun_t h_next; /* Get the next element */
102df930be7Sderaadt history_gfun_t h_last; /* Get the last element */
103df930be7Sderaadt history_gfun_t h_prev; /* Get the previous element */
104df930be7Sderaadt history_gfun_t h_curr; /* Get the current element */
105d484b7d0Sotto history_sfun_t h_set; /* Set the current element */
106aed0ee81Snicm history_sfun_t h_del; /* Set the given element */
1078bd3f282Sderaadt history_vfun_t h_clear; /* Clear the history list */
108df930be7Sderaadt history_efun_t h_enter; /* Add an element */
109df930be7Sderaadt history_efun_t h_add; /* Append to an element */
110df930be7Sderaadt };
111df930be7Sderaadt
112d484b7d0Sotto #define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
113d484b7d0Sotto #define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
114d484b7d0Sotto #define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
115d484b7d0Sotto #define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
116d484b7d0Sotto #define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
117d484b7d0Sotto #define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
118d484b7d0Sotto #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
119d484b7d0Sotto #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
120d484b7d0Sotto #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
121aed0ee81Snicm #define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
122df930be7Sderaadt
123aed0ee81Snicm #define h_strdup(a) Strdup(a)
124df930be7Sderaadt
125d484b7d0Sotto typedef struct {
126d484b7d0Sotto int num;
127aed0ee81Snicm Char *str;
128d484b7d0Sotto } HistEventPrivate;
129df930be7Sderaadt
130d484b7d0Sotto
131ddc81437Sschwarze static int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
132ddc81437Sschwarze static int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
133ddc81437Sschwarze static int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
134ddc81437Sschwarze static int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
135ddc81437Sschwarze static int history_set_fun(TYPE(History) *, TYPE(History) *);
136ddc81437Sschwarze static int history_load(TYPE(History) *, const char *);
137ddc81437Sschwarze static int history_save(TYPE(History) *, const char *);
138ddc81437Sschwarze static int history_save_fp(TYPE(History) *, FILE *);
139ddc81437Sschwarze static int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
140ddc81437Sschwarze static int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
141ddc81437Sschwarze static int history_next_string(TYPE(History) *, TYPE(HistEvent) *,
142ddc81437Sschwarze const Char *);
143ddc81437Sschwarze static int history_prev_string(TYPE(History) *, TYPE(HistEvent) *,
144ddc81437Sschwarze const Char *);
145df930be7Sderaadt
146df930be7Sderaadt
147df930be7Sderaadt /***********************************************************************/
148df930be7Sderaadt
149df930be7Sderaadt /*
150df930be7Sderaadt * Builtin- history implementation
151df930be7Sderaadt */
152df930be7Sderaadt typedef struct hentry_t {
153aed0ee81Snicm TYPE(HistEvent) ev; /* What we return */
154aed0ee81Snicm void *data; /* data */
155df930be7Sderaadt struct hentry_t *next; /* Next entry */
156df930be7Sderaadt struct hentry_t *prev; /* Previous entry */
157df930be7Sderaadt } hentry_t;
158df930be7Sderaadt
159df930be7Sderaadt typedef struct history_t {
160df930be7Sderaadt hentry_t list; /* Fake list header element */
161df930be7Sderaadt hentry_t *cursor; /* Current element in the list */
162df930be7Sderaadt int max; /* Maximum number of events */
163df930be7Sderaadt int cur; /* Current number of events */
164d484b7d0Sotto int eventid; /* For generation of unique event id */
165aed0ee81Snicm int flags; /* TYPE(History) flags */
166d484b7d0Sotto #define H_UNIQUE 1 /* Store only unique elements */
167df930be7Sderaadt } history_t;
168df930be7Sderaadt
169ddc81437Sschwarze static int history_def_next(void *, TYPE(HistEvent) *);
170ddc81437Sschwarze static int history_def_first(void *, TYPE(HistEvent) *);
171ddc81437Sschwarze static int history_def_prev(void *, TYPE(HistEvent) *);
172ddc81437Sschwarze static int history_def_last(void *, TYPE(HistEvent) *);
173ddc81437Sschwarze static int history_def_curr(void *, TYPE(HistEvent) *);
174ddc81437Sschwarze static int history_def_set(void *, TYPE(HistEvent) *, const int);
175ddc81437Sschwarze static void history_def_clear(void *, TYPE(HistEvent) *);
176ddc81437Sschwarze static int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
177ddc81437Sschwarze static int history_def_add(void *, TYPE(HistEvent) *, const Char *);
178ddc81437Sschwarze static int history_def_del(void *, TYPE(HistEvent) *, const int);
179aed0ee81Snicm
180ddc81437Sschwarze static int history_def_init(void **, TYPE(HistEvent) *, int);
181ddc81437Sschwarze static int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
182ddc81437Sschwarze static void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
183aed0ee81Snicm
184ddc81437Sschwarze static int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
185ddc81437Sschwarze static int history_set_nth(void *, TYPE(HistEvent) *, int);
186df930be7Sderaadt
187d484b7d0Sotto #define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
188d484b7d0Sotto #define history_def_getsize(p) (((history_t *)p)->cur)
189d484b7d0Sotto #define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
190d484b7d0Sotto #define history_def_setunique(p, uni) \
191d484b7d0Sotto if (uni) \
192d484b7d0Sotto (((history_t *)p)->flags) |= H_UNIQUE; \
193d484b7d0Sotto else \
194d484b7d0Sotto (((history_t *)p)->flags) &= ~H_UNIQUE
195df930be7Sderaadt
196d484b7d0Sotto #define he_strerror(code) he_errlist[code]
197d484b7d0Sotto #define he_seterrev(evp, code) {\
198d484b7d0Sotto evp->num = code;\
199d484b7d0Sotto evp->str = he_strerror(code);\
200d484b7d0Sotto }
201d484b7d0Sotto
202d484b7d0Sotto /* error messages */
203aed0ee81Snicm static const Char *const he_errlist[] = {
204aed0ee81Snicm STR("OK"),
205aed0ee81Snicm STR("unknown error"),
206aed0ee81Snicm STR("malloc() failed"),
207aed0ee81Snicm STR("first event not found"),
208aed0ee81Snicm STR("last event not found"),
209aed0ee81Snicm STR("empty list"),
210aed0ee81Snicm STR("no next event"),
211aed0ee81Snicm STR("no previous event"),
212aed0ee81Snicm STR("current event is invalid"),
213aed0ee81Snicm STR("event not found"),
214aed0ee81Snicm STR("can't read history from file"),
215aed0ee81Snicm STR("can't write history"),
216aed0ee81Snicm STR("required parameter(s) not supplied"),
217aed0ee81Snicm STR("history size negative"),
218aed0ee81Snicm STR("function not allowed with other history-functions-set the default"),
219aed0ee81Snicm STR("bad parameters")
220d484b7d0Sotto };
221d484b7d0Sotto /* error codes */
222d484b7d0Sotto #define _HE_OK 0
223d484b7d0Sotto #define _HE_UNKNOWN 1
224d484b7d0Sotto #define _HE_MALLOC_FAILED 2
225d484b7d0Sotto #define _HE_FIRST_NOTFOUND 3
226d484b7d0Sotto #define _HE_LAST_NOTFOUND 4
227d484b7d0Sotto #define _HE_EMPTY_LIST 5
228d484b7d0Sotto #define _HE_END_REACHED 6
229d484b7d0Sotto #define _HE_START_REACHED 7
230d484b7d0Sotto #define _HE_CURR_INVALID 8
231d484b7d0Sotto #define _HE_NOT_FOUND 9
232d484b7d0Sotto #define _HE_HIST_READ 10
233d484b7d0Sotto #define _HE_HIST_WRITE 11
234d484b7d0Sotto #define _HE_PARAM_MISSING 12
235d484b7d0Sotto #define _HE_SIZE_NEGATIVE 13
236d484b7d0Sotto #define _HE_NOT_ALLOWED 14
237d484b7d0Sotto #define _HE_BAD_PARAM 15
238df930be7Sderaadt
239df930be7Sderaadt /* history_def_first():
240df930be7Sderaadt * Default function to return the first event in the history.
241df930be7Sderaadt */
242ddc81437Sschwarze static int
history_def_first(void * p,TYPE (HistEvent)* ev)2437b85e16bSschwarze history_def_first(void *p, TYPE(HistEvent) *ev)
244df930be7Sderaadt {
245df930be7Sderaadt history_t *h = (history_t *) p;
246d484b7d0Sotto
247df930be7Sderaadt h->cursor = h->list.next;
248df930be7Sderaadt if (h->cursor != &h->list)
249d484b7d0Sotto *ev = h->cursor->ev;
250d484b7d0Sotto else {
251d484b7d0Sotto he_seterrev(ev, _HE_FIRST_NOTFOUND);
25228d54ee8Sschwarze return -1;
253df930be7Sderaadt }
254df930be7Sderaadt
25528d54ee8Sschwarze return 0;
256d484b7d0Sotto }
257d484b7d0Sotto
258d484b7d0Sotto
259df930be7Sderaadt /* history_def_last():
260df930be7Sderaadt * Default function to return the last event in the history.
261df930be7Sderaadt */
262ddc81437Sschwarze static int
history_def_last(void * p,TYPE (HistEvent)* ev)2637b85e16bSschwarze history_def_last(void *p, TYPE(HistEvent) *ev)
264df930be7Sderaadt {
265df930be7Sderaadt history_t *h = (history_t *) p;
266d484b7d0Sotto
267df930be7Sderaadt h->cursor = h->list.prev;
268df930be7Sderaadt if (h->cursor != &h->list)
269d484b7d0Sotto *ev = h->cursor->ev;
270d484b7d0Sotto else {
271d484b7d0Sotto he_seterrev(ev, _HE_LAST_NOTFOUND);
27228d54ee8Sschwarze return -1;
273df930be7Sderaadt }
274df930be7Sderaadt
27528d54ee8Sschwarze return 0;
276d484b7d0Sotto }
277d484b7d0Sotto
278d484b7d0Sotto
279df930be7Sderaadt /* history_def_next():
280df930be7Sderaadt * Default function to return the next event in the history.
281df930be7Sderaadt */
282ddc81437Sschwarze static int
history_def_next(void * p,TYPE (HistEvent)* ev)2837b85e16bSschwarze history_def_next(void *p, TYPE(HistEvent) *ev)
284df930be7Sderaadt {
285df930be7Sderaadt history_t *h = (history_t *) p;
286df930be7Sderaadt
287aed0ee81Snicm if (h->cursor == &h->list) {
288d484b7d0Sotto he_seterrev(ev, _HE_EMPTY_LIST);
28928d54ee8Sschwarze return -1;
290d484b7d0Sotto }
291df930be7Sderaadt
292aed0ee81Snicm if (h->cursor->next == &h->list) {
293d484b7d0Sotto he_seterrev(ev, _HE_END_REACHED);
29428d54ee8Sschwarze return -1;
295d484b7d0Sotto }
296d484b7d0Sotto
297aed0ee81Snicm h->cursor = h->cursor->next;
298aed0ee81Snicm *ev = h->cursor->ev;
299aed0ee81Snicm
30028d54ee8Sschwarze return 0;
301df930be7Sderaadt }
302df930be7Sderaadt
303df930be7Sderaadt
304df930be7Sderaadt /* history_def_prev():
305df930be7Sderaadt * Default function to return the previous event in the history.
306df930be7Sderaadt */
307ddc81437Sschwarze static int
history_def_prev(void * p,TYPE (HistEvent)* ev)3087b85e16bSschwarze history_def_prev(void *p, TYPE(HistEvent) *ev)
309df930be7Sderaadt {
310df930be7Sderaadt history_t *h = (history_t *) p;
311df930be7Sderaadt
312aed0ee81Snicm if (h->cursor == &h->list) {
313d484b7d0Sotto he_seterrev(ev,
314d484b7d0Sotto (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
31528d54ee8Sschwarze return -1;
316d484b7d0Sotto }
317df930be7Sderaadt
318aed0ee81Snicm if (h->cursor->prev == &h->list) {
319d484b7d0Sotto he_seterrev(ev, _HE_START_REACHED);
32028d54ee8Sschwarze return -1;
321d484b7d0Sotto }
322d484b7d0Sotto
323aed0ee81Snicm h->cursor = h->cursor->prev;
324aed0ee81Snicm *ev = h->cursor->ev;
325aed0ee81Snicm
32628d54ee8Sschwarze return 0;
327df930be7Sderaadt }
328df930be7Sderaadt
329df930be7Sderaadt
330df930be7Sderaadt /* history_def_curr():
331df930be7Sderaadt * Default function to return the current event in the history.
332df930be7Sderaadt */
333ddc81437Sschwarze static int
history_def_curr(void * p,TYPE (HistEvent)* ev)3347b85e16bSschwarze history_def_curr(void *p, TYPE(HistEvent) *ev)
335df930be7Sderaadt {
336df930be7Sderaadt history_t *h = (history_t *) p;
337df930be7Sderaadt
338df930be7Sderaadt if (h->cursor != &h->list)
339d484b7d0Sotto *ev = h->cursor->ev;
340d484b7d0Sotto else {
341d484b7d0Sotto he_seterrev(ev,
342d484b7d0Sotto (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
34328d54ee8Sschwarze return -1;
344df930be7Sderaadt }
345df930be7Sderaadt
34628d54ee8Sschwarze return 0;
347d484b7d0Sotto }
348d484b7d0Sotto
349d484b7d0Sotto
350d484b7d0Sotto /* history_def_set():
351d484b7d0Sotto * Default function to set the current event in the history to the
352d484b7d0Sotto * given one.
353d484b7d0Sotto */
354ddc81437Sschwarze static int
history_def_set(void * p,TYPE (HistEvent)* ev,const int n)3557b85e16bSschwarze history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
356d484b7d0Sotto {
357d484b7d0Sotto history_t *h = (history_t *) p;
358d484b7d0Sotto
359d484b7d0Sotto if (h->cur == 0) {
360d484b7d0Sotto he_seterrev(ev, _HE_EMPTY_LIST);
36128d54ee8Sschwarze return -1;
362d484b7d0Sotto }
363d484b7d0Sotto if (h->cursor == &h->list || h->cursor->ev.num != n) {
364d484b7d0Sotto for (h->cursor = h->list.next; h->cursor != &h->list;
365d484b7d0Sotto h->cursor = h->cursor->next)
366d484b7d0Sotto if (h->cursor->ev.num == n)
367d484b7d0Sotto break;
368d484b7d0Sotto }
369d484b7d0Sotto if (h->cursor == &h->list) {
370d484b7d0Sotto he_seterrev(ev, _HE_NOT_FOUND);
37128d54ee8Sschwarze return -1;
372d484b7d0Sotto }
37328d54ee8Sschwarze return 0;
374d484b7d0Sotto }
375d484b7d0Sotto
376d484b7d0Sotto
377aed0ee81Snicm /* history_set_nth():
378aed0ee81Snicm * Default function to set the current event in the history to the
379aed0ee81Snicm * n-th one.
380aed0ee81Snicm */
381ddc81437Sschwarze static int
history_set_nth(void * p,TYPE (HistEvent)* ev,int n)3827b85e16bSschwarze history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
383aed0ee81Snicm {
384aed0ee81Snicm history_t *h = (history_t *) p;
385aed0ee81Snicm
386aed0ee81Snicm if (h->cur == 0) {
387aed0ee81Snicm he_seterrev(ev, _HE_EMPTY_LIST);
38828d54ee8Sschwarze return -1;
389aed0ee81Snicm }
390aed0ee81Snicm for (h->cursor = h->list.prev; h->cursor != &h->list;
391aed0ee81Snicm h->cursor = h->cursor->prev)
392aed0ee81Snicm if (n-- <= 0)
393aed0ee81Snicm break;
394aed0ee81Snicm if (h->cursor == &h->list) {
395aed0ee81Snicm he_seterrev(ev, _HE_NOT_FOUND);
39628d54ee8Sschwarze return -1;
397aed0ee81Snicm }
39828d54ee8Sschwarze return 0;
399aed0ee81Snicm }
400aed0ee81Snicm
401aed0ee81Snicm
402df930be7Sderaadt /* history_def_add():
403df930be7Sderaadt * Append string to element
404df930be7Sderaadt */
405ddc81437Sschwarze static int
history_def_add(void * p,TYPE (HistEvent)* ev,const Char * str)4067b85e16bSschwarze history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
407df930be7Sderaadt {
408df930be7Sderaadt history_t *h = (history_t *) p;
409df930be7Sderaadt size_t len;
410aed0ee81Snicm Char *s;
411d484b7d0Sotto HistEventPrivate *evp = (void *)&h->cursor->ev;
412df930be7Sderaadt
413df930be7Sderaadt if (h->cursor == &h->list)
41428d54ee8Sschwarze return history_def_enter(p, ev, str);
415aed0ee81Snicm len = Strlen(evp->str) + Strlen(str) + 1;
416014b1be8Sderaadt s = reallocarray(NULL, len, sizeof(*s));
417d484b7d0Sotto if (s == NULL) {
418d484b7d0Sotto he_seterrev(ev, _HE_MALLOC_FAILED);
41928d54ee8Sschwarze return -1;
420d484b7d0Sotto }
421aed0ee81Snicm (void) Strncpy(s, h->cursor->ev.str, len);
422aed0ee81Snicm s[len - 1] = '\0';
423aed0ee81Snicm (void) Strncat(s, str, len - Strlen(s) - 1);
4247b85e16bSschwarze free(evp->str);
425d484b7d0Sotto evp->str = s;
426d484b7d0Sotto *ev = h->cursor->ev;
42728d54ee8Sschwarze return 0;
428df930be7Sderaadt }
429df930be7Sderaadt
430df930be7Sderaadt
431ddc81437Sschwarze static int
history_deldata_nth(history_t * h,TYPE (HistEvent)* ev,int num,void ** data)432aed0ee81Snicm history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
433aed0ee81Snicm int num, void **data)
434aed0ee81Snicm {
435aed0ee81Snicm if (history_set_nth(h, ev, num) != 0)
43628d54ee8Sschwarze return -1;
437aed0ee81Snicm /* magic value to skip delete (just set to n-th history) */
438aed0ee81Snicm if (data == (void **)-1)
43928d54ee8Sschwarze return 0;
440aed0ee81Snicm ev->str = Strdup(h->cursor->ev.str);
441aed0ee81Snicm ev->num = h->cursor->ev.num;
442aed0ee81Snicm if (data)
443aed0ee81Snicm *data = h->cursor->data;
444aed0ee81Snicm history_def_delete(h, ev, h->cursor);
44528d54ee8Sschwarze return 0;
446aed0ee81Snicm }
447aed0ee81Snicm
448aed0ee81Snicm
449aed0ee81Snicm /* history_def_del():
450aed0ee81Snicm * Delete element hp of the h list
451aed0ee81Snicm */
452ddc81437Sschwarze static int
history_def_del(void * p,TYPE (HistEvent)* ev,const int num)4537b85e16bSschwarze history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
454aed0ee81Snicm const int num)
455aed0ee81Snicm {
456aed0ee81Snicm history_t *h = (history_t *) p;
457aed0ee81Snicm if (history_def_set(h, ev, num) != 0)
45828d54ee8Sschwarze return -1;
459aed0ee81Snicm ev->str = Strdup(h->cursor->ev.str);
460aed0ee81Snicm ev->num = h->cursor->ev.num;
461aed0ee81Snicm history_def_delete(h, ev, h->cursor);
46228d54ee8Sschwarze return 0;
463aed0ee81Snicm }
464aed0ee81Snicm
465aed0ee81Snicm
466df930be7Sderaadt /* history_def_delete():
467df930be7Sderaadt * Delete element hp of the h list
468df930be7Sderaadt */
469ddc81437Sschwarze static void
history_def_delete(history_t * h,TYPE (HistEvent)* ev,hentry_t * hp)470d484b7d0Sotto history_def_delete(history_t *h,
471aed0ee81Snicm TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
472df930be7Sderaadt {
473d484b7d0Sotto HistEventPrivate *evp = (void *)&hp->ev;
474df930be7Sderaadt if (hp == &h->list)
475df930be7Sderaadt abort();
476aed0ee81Snicm if (h->cursor == hp) {
477aed0ee81Snicm h->cursor = hp->prev;
478aed0ee81Snicm if (h->cursor == &h->list)
479aed0ee81Snicm h->cursor = hp->next;
480aed0ee81Snicm }
481df930be7Sderaadt hp->prev->next = hp->next;
482df930be7Sderaadt hp->next->prev = hp->prev;
4837b85e16bSschwarze free(evp->str);
484014b1be8Sderaadt free(hp);
485df930be7Sderaadt h->cur--;
486df930be7Sderaadt }
487df930be7Sderaadt
488df930be7Sderaadt
489df930be7Sderaadt /* history_def_insert():
490df930be7Sderaadt * Insert element with string str in the h list
491df930be7Sderaadt */
492ddc81437Sschwarze static int
history_def_insert(history_t * h,TYPE (HistEvent)* ev,const Char * str)493aed0ee81Snicm history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
494df930be7Sderaadt {
495d484b7d0Sotto
496014b1be8Sderaadt h->cursor = (hentry_t *) malloc(sizeof(hentry_t));
497d484b7d0Sotto if (h->cursor == NULL)
498d484b7d0Sotto goto oomem;
4996e02e073Sotto if ((h->cursor->ev.str = h_strdup(str)) == NULL) {
5007b85e16bSschwarze free(h->cursor);
501d484b7d0Sotto goto oomem;
502d484b7d0Sotto }
503aed0ee81Snicm h->cursor->data = NULL;
504d484b7d0Sotto h->cursor->ev.num = ++h->eventid;
505df930be7Sderaadt h->cursor->next = h->list.next;
506df930be7Sderaadt h->cursor->prev = &h->list;
507df930be7Sderaadt h->list.next->prev = h->cursor;
508df930be7Sderaadt h->list.next = h->cursor;
509df930be7Sderaadt h->cur++;
510df930be7Sderaadt
511d484b7d0Sotto *ev = h->cursor->ev;
51228d54ee8Sschwarze return 0;
513d484b7d0Sotto oomem:
514d484b7d0Sotto he_seterrev(ev, _HE_MALLOC_FAILED);
51528d54ee8Sschwarze return -1;
516df930be7Sderaadt }
517df930be7Sderaadt
518df930be7Sderaadt
519df930be7Sderaadt /* history_def_enter():
520df930be7Sderaadt * Default function to enter an item in the history
521df930be7Sderaadt */
522ddc81437Sschwarze static int
history_def_enter(void * p,TYPE (HistEvent)* ev,const Char * str)5237b85e16bSschwarze history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
524df930be7Sderaadt {
525df930be7Sderaadt history_t *h = (history_t *) p;
526df930be7Sderaadt
527d484b7d0Sotto if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
528aed0ee81Snicm Strcmp(h->list.next->ev.str, str) == 0)
52928d54ee8Sschwarze return 0;
530df930be7Sderaadt
531d484b7d0Sotto if (history_def_insert(h, ev, str) == -1)
53228d54ee8Sschwarze return -1; /* error, keep error message */
533df930be7Sderaadt
534df930be7Sderaadt /*
535df930be7Sderaadt * Always keep at least one entry.
536df930be7Sderaadt * This way we don't have to check for the empty list.
537df930be7Sderaadt */
538d484b7d0Sotto while (h->cur > h->max && h->cur > 0)
539d484b7d0Sotto history_def_delete(h, ev, h->list.prev);
540d484b7d0Sotto
54128d54ee8Sschwarze return 1;
542df930be7Sderaadt }
543df930be7Sderaadt
544df930be7Sderaadt
545df930be7Sderaadt /* history_def_init():
546df930be7Sderaadt * Default history initialization function
547df930be7Sderaadt */
548ddc81437Sschwarze static int
history_def_init(void ** p,TYPE (HistEvent)* ev,int n)5497b85e16bSschwarze history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
550df930be7Sderaadt {
551014b1be8Sderaadt history_t *h = (history_t *) malloc(sizeof(history_t));
552d484b7d0Sotto if (h == NULL)
553d484b7d0Sotto return -1;
554d484b7d0Sotto
555df930be7Sderaadt if (n <= 0)
556df930be7Sderaadt n = 0;
557d484b7d0Sotto h->eventid = 0;
558df930be7Sderaadt h->cur = 0;
559df930be7Sderaadt h->max = n;
560df930be7Sderaadt h->list.next = h->list.prev = &h->list;
561df930be7Sderaadt h->list.ev.str = NULL;
562df930be7Sderaadt h->list.ev.num = 0;
563df930be7Sderaadt h->cursor = &h->list;
564d484b7d0Sotto h->flags = 0;
5657b85e16bSschwarze *p = h;
566d484b7d0Sotto return 0;
567df930be7Sderaadt }
568df930be7Sderaadt
569df930be7Sderaadt
5708bd3f282Sderaadt /* history_def_clear():
571df930be7Sderaadt * Default history cleanup function
572df930be7Sderaadt */
573ddc81437Sschwarze static void
history_def_clear(void * p,TYPE (HistEvent)* ev)5747b85e16bSschwarze history_def_clear(void *p, TYPE(HistEvent) *ev)
575df930be7Sderaadt {
576df930be7Sderaadt history_t *h = (history_t *) p;
577df930be7Sderaadt
578df930be7Sderaadt while (h->list.prev != &h->list)
579d484b7d0Sotto history_def_delete(h, ev, h->list.prev);
580d484b7d0Sotto h->eventid = 0;
5818bd3f282Sderaadt h->cur = 0;
582df930be7Sderaadt }
583df930be7Sderaadt
5848bd3f282Sderaadt
5858bd3f282Sderaadt
5868bd3f282Sderaadt
587df930be7Sderaadt /************************************************************************/
588df930be7Sderaadt
589df930be7Sderaadt /* history_init():
590df930be7Sderaadt * Initialization function.
591df930be7Sderaadt */
TYPE(History)592ddc81437Sschwarze TYPE(History) *
593aed0ee81Snicm FUN(history,init)(void)
594df930be7Sderaadt {
595aed0ee81Snicm TYPE(HistEvent) ev;
596014b1be8Sderaadt TYPE(History) *h = (TYPE(History) *) malloc(sizeof(TYPE(History)));
597d484b7d0Sotto if (h == NULL)
598d484b7d0Sotto return NULL;
599df930be7Sderaadt
600d484b7d0Sotto if (history_def_init(&h->h_ref, &ev, 0) == -1) {
6017b85e16bSschwarze free(h);
602d484b7d0Sotto return NULL;
603d484b7d0Sotto }
604d484b7d0Sotto h->h_ent = -1;
605df930be7Sderaadt h->h_next = history_def_next;
606df930be7Sderaadt h->h_first = history_def_first;
607df930be7Sderaadt h->h_last = history_def_last;
608df930be7Sderaadt h->h_prev = history_def_prev;
609df930be7Sderaadt h->h_curr = history_def_curr;
610d484b7d0Sotto h->h_set = history_def_set;
6118bd3f282Sderaadt h->h_clear = history_def_clear;
612df930be7Sderaadt h->h_enter = history_def_enter;
613df930be7Sderaadt h->h_add = history_def_add;
614aed0ee81Snicm h->h_del = history_def_del;
615df930be7Sderaadt
61628d54ee8Sschwarze return h;
617df930be7Sderaadt }
618df930be7Sderaadt
619df930be7Sderaadt
620df930be7Sderaadt /* history_end():
621df930be7Sderaadt * clean up history;
622df930be7Sderaadt */
623ddc81437Sschwarze void
FUN(history,end)624aed0ee81Snicm FUN(history,end)(TYPE(History) *h)
625df930be7Sderaadt {
626aed0ee81Snicm TYPE(HistEvent) ev;
627d484b7d0Sotto
628df930be7Sderaadt if (h->h_next == history_def_next)
629d484b7d0Sotto history_def_clear(h->h_ref, &ev);
630014b1be8Sderaadt free(h->h_ref);
631014b1be8Sderaadt free(h);
632df930be7Sderaadt }
633df930be7Sderaadt
634df930be7Sderaadt
635df930be7Sderaadt
636d484b7d0Sotto /* history_setsize():
637df930be7Sderaadt * Set history number of events
638df930be7Sderaadt */
639ddc81437Sschwarze static int
history_setsize(TYPE (History)* h,TYPE (HistEvent)* ev,int num)640aed0ee81Snicm history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
641df930be7Sderaadt {
642d484b7d0Sotto
643d484b7d0Sotto if (h->h_next != history_def_next) {
644d484b7d0Sotto he_seterrev(ev, _HE_NOT_ALLOWED);
64528d54ee8Sschwarze return -1;
646d484b7d0Sotto }
647d484b7d0Sotto if (num < 0) {
648d484b7d0Sotto he_seterrev(ev, _HE_BAD_PARAM);
64928d54ee8Sschwarze return -1;
650d484b7d0Sotto }
651d484b7d0Sotto history_def_setsize(h->h_ref, num);
65228d54ee8Sschwarze return 0;
653d484b7d0Sotto }
654d484b7d0Sotto
655d484b7d0Sotto
656d484b7d0Sotto /* history_getsize():
657d484b7d0Sotto * Get number of events currently in history
658d484b7d0Sotto */
659ddc81437Sschwarze static int
history_getsize(TYPE (History)* h,TYPE (HistEvent)* ev)660aed0ee81Snicm history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
661d484b7d0Sotto {
662d484b7d0Sotto if (h->h_next != history_def_next) {
663d484b7d0Sotto he_seterrev(ev, _HE_NOT_ALLOWED);
66428d54ee8Sschwarze return -1;
665d484b7d0Sotto }
666d484b7d0Sotto ev->num = history_def_getsize(h->h_ref);
667d484b7d0Sotto if (ev->num < -1) {
668d484b7d0Sotto he_seterrev(ev, _HE_SIZE_NEGATIVE);
66928d54ee8Sschwarze return -1;
670d484b7d0Sotto }
67128d54ee8Sschwarze return 0;
672d484b7d0Sotto }
673d484b7d0Sotto
674d484b7d0Sotto
675d484b7d0Sotto /* history_setunique():
676d484b7d0Sotto * Set if adjacent equal events should not be entered in history.
677d484b7d0Sotto */
678ddc81437Sschwarze static int
history_setunique(TYPE (History)* h,TYPE (HistEvent)* ev,int uni)679aed0ee81Snicm history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
680d484b7d0Sotto {
681d484b7d0Sotto
682d484b7d0Sotto if (h->h_next != history_def_next) {
683d484b7d0Sotto he_seterrev(ev, _HE_NOT_ALLOWED);
68428d54ee8Sschwarze return -1;
685d484b7d0Sotto }
686d484b7d0Sotto history_def_setunique(h->h_ref, uni);
68728d54ee8Sschwarze return 0;
688d484b7d0Sotto }
689d484b7d0Sotto
690d484b7d0Sotto
691d484b7d0Sotto /* history_getunique():
692d484b7d0Sotto * Get if adjacent equal events should not be entered in history.
693d484b7d0Sotto */
694ddc81437Sschwarze static int
history_getunique(TYPE (History)* h,TYPE (HistEvent)* ev)695aed0ee81Snicm history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
696d484b7d0Sotto {
697d484b7d0Sotto if (h->h_next != history_def_next) {
698d484b7d0Sotto he_seterrev(ev, _HE_NOT_ALLOWED);
69928d54ee8Sschwarze return -1;
700d484b7d0Sotto }
701d484b7d0Sotto ev->num = history_def_getunique(h->h_ref);
70228d54ee8Sschwarze return 0;
703df930be7Sderaadt }
704df930be7Sderaadt
705df930be7Sderaadt
706df930be7Sderaadt /* history_set_fun():
707df930be7Sderaadt * Set history functions
708df930be7Sderaadt */
709ddc81437Sschwarze static int
history_set_fun(TYPE (History)* h,TYPE (History)* nh)710aed0ee81Snicm history_set_fun(TYPE(History) *h, TYPE(History) *nh)
711df930be7Sderaadt {
712aed0ee81Snicm TYPE(HistEvent) ev;
713d484b7d0Sotto
714d484b7d0Sotto if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
715d484b7d0Sotto nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
7168bd3f282Sderaadt nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
717aed0ee81Snicm nh->h_del == NULL || nh->h_ref == NULL) {
718df930be7Sderaadt if (h->h_next != history_def_next) {
719d484b7d0Sotto history_def_init(&h->h_ref, &ev, 0);
720df930be7Sderaadt h->h_first = history_def_first;
721df930be7Sderaadt h->h_next = history_def_next;
722df930be7Sderaadt h->h_last = history_def_last;
723df930be7Sderaadt h->h_prev = history_def_prev;
724df930be7Sderaadt h->h_curr = history_def_curr;
725d484b7d0Sotto h->h_set = history_def_set;
7268bd3f282Sderaadt h->h_clear = history_def_clear;
727df930be7Sderaadt h->h_enter = history_def_enter;
728df930be7Sderaadt h->h_add = history_def_add;
729aed0ee81Snicm h->h_del = history_def_del;
730df930be7Sderaadt }
73128d54ee8Sschwarze return -1;
732df930be7Sderaadt }
733df930be7Sderaadt if (h->h_next == history_def_next)
734d484b7d0Sotto history_def_clear(h->h_ref, &ev);
735df930be7Sderaadt
736d484b7d0Sotto h->h_ent = -1;
7378bd3f282Sderaadt h->h_first = nh->h_first;
7388bd3f282Sderaadt h->h_next = nh->h_next;
7398bd3f282Sderaadt h->h_last = nh->h_last;
7408bd3f282Sderaadt h->h_prev = nh->h_prev;
7418bd3f282Sderaadt h->h_curr = nh->h_curr;
742d484b7d0Sotto h->h_set = nh->h_set;
7438bd3f282Sderaadt h->h_clear = nh->h_clear;
7448bd3f282Sderaadt h->h_enter = nh->h_enter;
7458bd3f282Sderaadt h->h_add = nh->h_add;
746aed0ee81Snicm h->h_del = nh->h_del;
7478bd3f282Sderaadt
74828d54ee8Sschwarze return 0;
749df930be7Sderaadt }
750df930be7Sderaadt
751df930be7Sderaadt
7528bd3f282Sderaadt /* history_load():
753aed0ee81Snicm * TYPE(History) load function
7548bd3f282Sderaadt */
755ddc81437Sschwarze static int
history_load(TYPE (History)* h,const char * fname)756aed0ee81Snicm history_load(TYPE(History) *h, const char *fname)
7578bd3f282Sderaadt {
7588bd3f282Sderaadt FILE *fp;
759f3a50c9eSschwarze char *line;
760f3a50c9eSschwarze size_t llen;
761f3a50c9eSschwarze ssize_t sz;
762f3a50c9eSschwarze size_t max_size;
763d484b7d0Sotto char *ptr;
7648bd3f282Sderaadt int i = -1;
765aed0ee81Snicm TYPE(HistEvent) ev;
76659aed043Sschwarze #ifndef NARROWCHAR
767aed0ee81Snicm static ct_buffer_t conv;
768aed0ee81Snicm #endif
7698bd3f282Sderaadt
7708bd3f282Sderaadt if ((fp = fopen(fname, "r")) == NULL)
77128d54ee8Sschwarze return i;
7728bd3f282Sderaadt
773f3a50c9eSschwarze line = NULL;
774f3a50c9eSschwarze llen = 0;
775f3a50c9eSschwarze if ((sz = getline(&line, &llen, fp)) == -1)
7768bd3f282Sderaadt goto done;
7778bd3f282Sderaadt
7788bd3f282Sderaadt if (strncmp(line, hist_cookie, sz) != 0)
7798bd3f282Sderaadt goto done;
7808bd3f282Sderaadt
781014b1be8Sderaadt ptr = malloc(max_size = 1024);
782d484b7d0Sotto if (ptr == NULL)
783d484b7d0Sotto goto done;
784f3a50c9eSschwarze for (i = 0; (sz = getline(&line, &llen, fp)) != -1; i++) {
785f3a50c9eSschwarze if (sz > 0 && line[sz - 1] == '\n')
786f3a50c9eSschwarze line[--sz] = '\0';
787f3a50c9eSschwarze if (max_size < sz) {
788d484b7d0Sotto char *nptr;
789aed0ee81Snicm max_size = (sz + 1024) & ~1023;
790014b1be8Sderaadt nptr = realloc(ptr, max_size);
791d484b7d0Sotto if (nptr == NULL) {
792d484b7d0Sotto i = -1;
793d484b7d0Sotto goto oomem;
794d484b7d0Sotto }
795d484b7d0Sotto ptr = nptr;
796d484b7d0Sotto }
797d484b7d0Sotto (void) strunvis(ptr, line);
798aed0ee81Snicm if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) {
799aed0ee81Snicm i = -1;
800aed0ee81Snicm goto oomem;
801d484b7d0Sotto }
802d484b7d0Sotto }
803d484b7d0Sotto oomem:
8047b85e16bSschwarze free(ptr);
8058bd3f282Sderaadt done:
806f3a50c9eSschwarze free(line);
8078bd3f282Sderaadt (void) fclose(fp);
80828d54ee8Sschwarze return i;
8098bd3f282Sderaadt }
8108bd3f282Sderaadt
8118bd3f282Sderaadt
812d47027c4Snicm /* history_save_fp():
813aed0ee81Snicm * TYPE(History) save function
8148bd3f282Sderaadt */
815ddc81437Sschwarze static int
history_save_fp(TYPE (History)* h,FILE * fp)816d47027c4Snicm history_save_fp(TYPE(History) *h, FILE *fp)
8178bd3f282Sderaadt {
818aed0ee81Snicm TYPE(HistEvent) ev;
819d484b7d0Sotto int i = -1, retval;
820d484b7d0Sotto size_t len, max_size;
821d484b7d0Sotto char *ptr;
82259aed043Sschwarze #ifndef NARROWCHAR
823aed0ee81Snicm static ct_buffer_t conv;
824aed0ee81Snicm #endif
8258bd3f282Sderaadt
826d484b7d0Sotto if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
827d484b7d0Sotto goto done;
828d484b7d0Sotto if (fputs(hist_cookie, fp) == EOF)
829d484b7d0Sotto goto done;
830014b1be8Sderaadt ptr = malloc(max_size = 1024);
831d484b7d0Sotto if (ptr == NULL)
832d484b7d0Sotto goto done;
833d484b7d0Sotto for (i = 0, retval = HLAST(h, &ev);
834d484b7d0Sotto retval != -1;
835d484b7d0Sotto retval = HPREV(h, &ev), i++) {
8369e89f419Stobias len = Strlen(ev.str) * 4 + 1;
8379e89f419Stobias if (len > max_size) {
838d484b7d0Sotto char *nptr;
839aed0ee81Snicm max_size = (len + 1024) & ~1023;
840014b1be8Sderaadt nptr = realloc(ptr, max_size);
841d484b7d0Sotto if (nptr == NULL) {
842d484b7d0Sotto i = -1;
843d484b7d0Sotto goto oomem;
844d484b7d0Sotto }
845d484b7d0Sotto ptr = nptr;
846d484b7d0Sotto }
847aed0ee81Snicm (void) strnvis(ptr, ct_encode_string(ev.str, &conv), max_size,
848aed0ee81Snicm VIS_WHITE);
849d484b7d0Sotto (void) fprintf(fp, "%s\n", ptr);
850d484b7d0Sotto }
851d484b7d0Sotto oomem:
8527b85e16bSschwarze free(ptr);
853d484b7d0Sotto done:
85428d54ee8Sschwarze return i;
8558bd3f282Sderaadt }
8568bd3f282Sderaadt
8578bd3f282Sderaadt
858d47027c4Snicm /* history_save():
859d47027c4Snicm * History save function
860d47027c4Snicm */
861ddc81437Sschwarze static int
history_save(TYPE (History)* h,const char * fname)862d47027c4Snicm history_save(TYPE(History) *h, const char *fname)
863d47027c4Snicm {
864d47027c4Snicm FILE *fp;
865d47027c4Snicm int i;
866d47027c4Snicm
867d47027c4Snicm if ((fp = fopen(fname, "w")) == NULL)
868d47027c4Snicm return -1;
869d47027c4Snicm
870d47027c4Snicm i = history_save_fp(h, fp);
871d47027c4Snicm
872d47027c4Snicm (void) fclose(fp);
873d47027c4Snicm return i;
874d47027c4Snicm }
875d47027c4Snicm
876d47027c4Snicm
877df930be7Sderaadt /* history_prev_event():
878df930be7Sderaadt * Find the previous event, with number given
879df930be7Sderaadt */
880ddc81437Sschwarze static int
history_prev_event(TYPE (History)* h,TYPE (HistEvent)* ev,int num)881aed0ee81Snicm history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
882df930be7Sderaadt {
883d484b7d0Sotto int retval;
884d484b7d0Sotto
885d484b7d0Sotto for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
886df930be7Sderaadt if (ev->num == num)
88728d54ee8Sschwarze return 0;
888d484b7d0Sotto
889d484b7d0Sotto he_seterrev(ev, _HE_NOT_FOUND);
89028d54ee8Sschwarze return -1;
891df930be7Sderaadt }
892df930be7Sderaadt
893df930be7Sderaadt
894ddc81437Sschwarze static int
history_next_evdata(TYPE (History)* h,TYPE (HistEvent)* ev,int num,void ** d)895aed0ee81Snicm history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
896aed0ee81Snicm {
897aed0ee81Snicm int retval;
898aed0ee81Snicm
899aed0ee81Snicm for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
9005f805b19Sokan if (ev->num == num) {
901aed0ee81Snicm if (d)
902aed0ee81Snicm *d = ((history_t *)h->h_ref)->cursor->data;
90328d54ee8Sschwarze return 0;
904aed0ee81Snicm }
905aed0ee81Snicm
906aed0ee81Snicm he_seterrev(ev, _HE_NOT_FOUND);
90728d54ee8Sschwarze return -1;
908aed0ee81Snicm }
909aed0ee81Snicm
910aed0ee81Snicm
911df930be7Sderaadt /* history_next_event():
912df930be7Sderaadt * Find the next event, with number given
913df930be7Sderaadt */
914ddc81437Sschwarze static int
history_next_event(TYPE (History)* h,TYPE (HistEvent)* ev,int num)915aed0ee81Snicm history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
916df930be7Sderaadt {
917d484b7d0Sotto int retval;
918d484b7d0Sotto
919d484b7d0Sotto for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
920df930be7Sderaadt if (ev->num == num)
92128d54ee8Sschwarze return 0;
922d484b7d0Sotto
923d484b7d0Sotto he_seterrev(ev, _HE_NOT_FOUND);
92428d54ee8Sschwarze return -1;
925df930be7Sderaadt }
926df930be7Sderaadt
927df930be7Sderaadt
928df930be7Sderaadt /* history_prev_string():
929df930be7Sderaadt * Find the previous event beginning with string
930df930be7Sderaadt */
931ddc81437Sschwarze static int
history_prev_string(TYPE (History)* h,TYPE (HistEvent)* ev,const Char * str)932aed0ee81Snicm history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
933df930be7Sderaadt {
934aed0ee81Snicm size_t len = Strlen(str);
935d484b7d0Sotto int retval;
936df930be7Sderaadt
937d484b7d0Sotto for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
938aed0ee81Snicm if (Strncmp(str, ev->str, len) == 0)
93928d54ee8Sschwarze return 0;
940d484b7d0Sotto
941d484b7d0Sotto he_seterrev(ev, _HE_NOT_FOUND);
94228d54ee8Sschwarze return -1;
943df930be7Sderaadt }
944df930be7Sderaadt
945df930be7Sderaadt
946df930be7Sderaadt /* history_next_string():
947df930be7Sderaadt * Find the next event beginning with string
948df930be7Sderaadt */
949ddc81437Sschwarze static int
history_next_string(TYPE (History)* h,TYPE (HistEvent)* ev,const Char * str)950aed0ee81Snicm history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
951df930be7Sderaadt {
952aed0ee81Snicm size_t len = Strlen(str);
953d484b7d0Sotto int retval;
954df930be7Sderaadt
955d484b7d0Sotto for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
956aed0ee81Snicm if (Strncmp(str, ev->str, len) == 0)
95728d54ee8Sschwarze return 0;
958d484b7d0Sotto
959d484b7d0Sotto he_seterrev(ev, _HE_NOT_FOUND);
96028d54ee8Sschwarze return -1;
961df930be7Sderaadt }
962df930be7Sderaadt
963df930be7Sderaadt
964df930be7Sderaadt /* history():
965df930be7Sderaadt * User interface to history functions.
966df930be7Sderaadt */
967d484b7d0Sotto int
FUNW(history)968aed0ee81Snicm FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
969df930be7Sderaadt {
970df930be7Sderaadt va_list va;
971aed0ee81Snicm const Char *str;
972d484b7d0Sotto int retval;
973df930be7Sderaadt
974df930be7Sderaadt va_start(va, fun);
975df930be7Sderaadt
976d484b7d0Sotto he_seterrev(ev, _HE_OK);
977d484b7d0Sotto
978df930be7Sderaadt switch (fun) {
979d484b7d0Sotto case H_GETSIZE:
980d484b7d0Sotto retval = history_getsize(h, ev);
981d484b7d0Sotto break;
982d484b7d0Sotto
983d484b7d0Sotto case H_SETSIZE:
984d484b7d0Sotto retval = history_setsize(h, ev, va_arg(va, int));
985d484b7d0Sotto break;
986d484b7d0Sotto
987d484b7d0Sotto case H_GETUNIQUE:
988d484b7d0Sotto retval = history_getunique(h, ev);
989d484b7d0Sotto break;
990d484b7d0Sotto
991d484b7d0Sotto case H_SETUNIQUE:
992d484b7d0Sotto retval = history_setunique(h, ev, va_arg(va, int));
993d484b7d0Sotto break;
994d484b7d0Sotto
995df930be7Sderaadt case H_ADD:
996aed0ee81Snicm str = va_arg(va, const Char *);
997d484b7d0Sotto retval = HADD(h, ev, str);
998df930be7Sderaadt break;
999df930be7Sderaadt
1000aed0ee81Snicm case H_DEL:
1001aed0ee81Snicm retval = HDEL(h, ev, va_arg(va, const int));
1002aed0ee81Snicm break;
1003aed0ee81Snicm
1004df930be7Sderaadt case H_ENTER:
1005aed0ee81Snicm str = va_arg(va, const Char *);
1006d484b7d0Sotto if ((retval = HENTER(h, ev, str)) != -1)
1007d484b7d0Sotto h->h_ent = ev->num;
1008d484b7d0Sotto break;
1009d484b7d0Sotto
1010d484b7d0Sotto case H_APPEND:
1011aed0ee81Snicm str = va_arg(va, const Char *);
1012d484b7d0Sotto if ((retval = HSET(h, ev, h->h_ent)) != -1)
1013d484b7d0Sotto retval = HADD(h, ev, str);
1014df930be7Sderaadt break;
1015df930be7Sderaadt
1016df930be7Sderaadt case H_FIRST:
1017d484b7d0Sotto retval = HFIRST(h, ev);
1018df930be7Sderaadt break;
1019df930be7Sderaadt
1020df930be7Sderaadt case H_NEXT:
1021d484b7d0Sotto retval = HNEXT(h, ev);
1022df930be7Sderaadt break;
1023df930be7Sderaadt
1024df930be7Sderaadt case H_LAST:
1025d484b7d0Sotto retval = HLAST(h, ev);
1026df930be7Sderaadt break;
1027df930be7Sderaadt
1028df930be7Sderaadt case H_PREV:
1029d484b7d0Sotto retval = HPREV(h, ev);
1030df930be7Sderaadt break;
1031df930be7Sderaadt
1032df930be7Sderaadt case H_CURR:
1033d484b7d0Sotto retval = HCURR(h, ev);
1034d484b7d0Sotto break;
1035d484b7d0Sotto
1036d484b7d0Sotto case H_SET:
1037d484b7d0Sotto retval = HSET(h, ev, va_arg(va, const int));
1038df930be7Sderaadt break;
1039df930be7Sderaadt
10408bd3f282Sderaadt case H_CLEAR:
1041d484b7d0Sotto HCLEAR(h, ev);
1042d484b7d0Sotto retval = 0;
10438bd3f282Sderaadt break;
10448bd3f282Sderaadt
10458bd3f282Sderaadt case H_LOAD:
1046d484b7d0Sotto retval = history_load(h, va_arg(va, const char *));
1047d484b7d0Sotto if (retval == -1)
1048d484b7d0Sotto he_seterrev(ev, _HE_HIST_READ);
10498bd3f282Sderaadt break;
10508bd3f282Sderaadt
10518bd3f282Sderaadt case H_SAVE:
1052d484b7d0Sotto retval = history_save(h, va_arg(va, const char *));
1053d484b7d0Sotto if (retval == -1)
1054d484b7d0Sotto he_seterrev(ev, _HE_HIST_WRITE);
10558bd3f282Sderaadt break;
10568bd3f282Sderaadt
1057d47027c4Snicm case H_SAVE_FP:
1058d47027c4Snicm retval = history_save_fp(h, va_arg(va, FILE *));
1059d47027c4Snicm if (retval == -1)
1060d47027c4Snicm he_seterrev(ev, _HE_HIST_WRITE);
1061d47027c4Snicm break;
1062d47027c4Snicm
1063df930be7Sderaadt case H_PREV_EVENT:
1064d484b7d0Sotto retval = history_prev_event(h, ev, va_arg(va, int));
1065df930be7Sderaadt break;
1066df930be7Sderaadt
1067df930be7Sderaadt case H_NEXT_EVENT:
1068d484b7d0Sotto retval = history_next_event(h, ev, va_arg(va, int));
1069df930be7Sderaadt break;
1070df930be7Sderaadt
1071df930be7Sderaadt case H_PREV_STR:
1072aed0ee81Snicm retval = history_prev_string(h, ev, va_arg(va, const Char *));
1073df930be7Sderaadt break;
1074df930be7Sderaadt
1075df930be7Sderaadt case H_NEXT_STR:
1076aed0ee81Snicm retval = history_next_string(h, ev, va_arg(va, const Char *));
1077df930be7Sderaadt break;
1078df930be7Sderaadt
1079df930be7Sderaadt case H_FUNC:
1080df930be7Sderaadt {
1081aed0ee81Snicm TYPE(History) hf;
1082d484b7d0Sotto
10837b85e16bSschwarze hf.h_ref = va_arg(va, void *);
1084d484b7d0Sotto h->h_ent = -1;
10858bd3f282Sderaadt hf.h_first = va_arg(va, history_gfun_t);
10868bd3f282Sderaadt hf.h_next = va_arg(va, history_gfun_t);
10878bd3f282Sderaadt hf.h_last = va_arg(va, history_gfun_t);
10888bd3f282Sderaadt hf.h_prev = va_arg(va, history_gfun_t);
10898bd3f282Sderaadt hf.h_curr = va_arg(va, history_gfun_t);
1090d484b7d0Sotto hf.h_set = va_arg(va, history_sfun_t);
10918bd3f282Sderaadt hf.h_clear = va_arg(va, history_vfun_t);
10928bd3f282Sderaadt hf.h_enter = va_arg(va, history_efun_t);
10938bd3f282Sderaadt hf.h_add = va_arg(va, history_efun_t);
1094aed0ee81Snicm hf.h_del = va_arg(va, history_sfun_t);
1095df930be7Sderaadt
1096d484b7d0Sotto if ((retval = history_set_fun(h, &hf)) == -1)
1097d484b7d0Sotto he_seterrev(ev, _HE_PARAM_MISSING);
1098df930be7Sderaadt break;
1099d484b7d0Sotto }
1100df930be7Sderaadt
1101df930be7Sderaadt case H_END:
1102aed0ee81Snicm FUN(history,end)(h);
1103d484b7d0Sotto retval = 0;
1104df930be7Sderaadt break;
1105df930be7Sderaadt
1106aed0ee81Snicm case H_NEXT_EVDATA:
1107aed0ee81Snicm {
1108aed0ee81Snicm int num = va_arg(va, int);
1109aed0ee81Snicm void **d = va_arg(va, void **);
1110aed0ee81Snicm retval = history_next_evdata(h, ev, num, d);
1111aed0ee81Snicm break;
1112aed0ee81Snicm }
1113aed0ee81Snicm
1114aed0ee81Snicm case H_DELDATA:
1115aed0ee81Snicm {
1116aed0ee81Snicm int num = va_arg(va, int);
1117aed0ee81Snicm void **d = va_arg(va, void **);
1118aed0ee81Snicm retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
1119aed0ee81Snicm break;
1120aed0ee81Snicm }
1121aed0ee81Snicm
1122aed0ee81Snicm case H_REPLACE: /* only use after H_NEXT_EVDATA */
1123aed0ee81Snicm {
1124aed0ee81Snicm const Char *line = va_arg(va, const Char *);
1125aed0ee81Snicm void *d = va_arg(va, void *);
1126aed0ee81Snicm const Char *s;
1127aed0ee81Snicm if(!line || !(s = Strdup(line))) {
1128aed0ee81Snicm retval = -1;
1129aed0ee81Snicm break;
1130aed0ee81Snicm }
1131aed0ee81Snicm ((history_t *)h->h_ref)->cursor->ev.str = s;
1132aed0ee81Snicm ((history_t *)h->h_ref)->cursor->data = d;
1133aed0ee81Snicm retval = 0;
1134aed0ee81Snicm break;
1135aed0ee81Snicm }
1136aed0ee81Snicm
1137df930be7Sderaadt default:
1138d484b7d0Sotto retval = -1;
1139d484b7d0Sotto he_seterrev(ev, _HE_UNKNOWN);
1140df930be7Sderaadt break;
1141df930be7Sderaadt }
1142df930be7Sderaadt va_end(va);
1143aed0ee81Snicm return retval;
1144df930be7Sderaadt }
1145