history.c revision 1.64 1 1.64 kre /* $NetBSD: history.c,v 1.64 2024/07/11 05:41:24 kre Exp $ */
2 1.3 lukem
3 1.1 cgd /*-
4 1.1 cgd * Copyright (c) 1992, 1993
5 1.1 cgd * The Regents of the University of California. All rights reserved.
6 1.1 cgd *
7 1.1 cgd * This code is derived from software contributed to Berkeley by
8 1.1 cgd * Christos Zoulas of Cornell University.
9 1.1 cgd *
10 1.1 cgd * Redistribution and use in source and binary forms, with or without
11 1.1 cgd * modification, are permitted provided that the following conditions
12 1.1 cgd * are met:
13 1.1 cgd * 1. Redistributions of source code must retain the above copyright
14 1.1 cgd * notice, this list of conditions and the following disclaimer.
15 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 cgd * notice, this list of conditions and the following disclaimer in the
17 1.1 cgd * documentation and/or other materials provided with the distribution.
18 1.24 agc * 3. Neither the name of the University nor the names of its contributors
19 1.1 cgd * may be used to endorse or promote products derived from this software
20 1.1 cgd * without specific prior written permission.
21 1.1 cgd *
22 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 cgd * SUCH DAMAGE.
33 1.1 cgd */
34 1.1 cgd
35 1.19 christos #include "config.h"
36 1.1 cgd #if !defined(lint) && !defined(SCCSID)
37 1.6 christos #if 0
38 1.1 cgd static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
39 1.6 christos #else
40 1.64 kre __RCSID("$NetBSD: history.c,v 1.64 2024/07/11 05:41:24 kre Exp $");
41 1.6 christos #endif
42 1.1 cgd #endif /* not lint && not SCCSID */
43 1.1 cgd
44 1.1 cgd /*
45 1.35 christos * hist.c: TYPE(History) access functions
46 1.1 cgd */
47 1.52 christos #include <sys/stat.h>
48 1.64 kre #include <fcntl.h>
49 1.52 christos #include <stdarg.h>
50 1.52 christos #include <stdlib.h>
51 1.1 cgd #include <string.h>
52 1.12 christos #include <vis.h>
53 1.1 cgd
54 1.12 christos static const char hist_cookie[] = "_HiStOrY_V2_\n";
55 1.2 christos
56 1.1 cgd #include "histedit.h"
57 1.1 cgd
58 1.54 christos
59 1.54 christos #ifdef NARROWCHAR
60 1.54 christos
61 1.55 christos #define Char char
62 1.54 christos #define FUN(prefix, rest) prefix ## _ ## rest
63 1.54 christos #define FUNW(type) type
64 1.54 christos #define TYPE(type) type
65 1.54 christos #define STR(x) x
66 1.54 christos
67 1.54 christos #define Strlen(s) strlen(s)
68 1.54 christos #define Strdup(s) strdup(s)
69 1.54 christos #define Strcmp(d, s) strcmp(d, s)
70 1.54 christos #define Strncmp(d, s, n) strncmp(d, s, n)
71 1.54 christos #define Strncpy(d, s, n) strncpy(d, s, n)
72 1.54 christos #define Strncat(d, s, n) strncat(d, s, n)
73 1.56 christos #define ct_decode_string(s, b) (s)
74 1.56 christos #define ct_encode_string(s, b) (s)
75 1.54 christos
76 1.54 christos #else
77 1.56 christos #include "chartype.h"
78 1.54 christos
79 1.55 christos #define Char wchar_t
80 1.54 christos #define FUN(prefix, rest) prefix ## _w ## rest
81 1.54 christos #define FUNW(type) type ## _w
82 1.54 christos #define TYPE(type) type ## W
83 1.54 christos #define STR(x) L ## x
84 1.54 christos
85 1.54 christos #define Strlen(s) wcslen(s)
86 1.54 christos #define Strdup(s) wcsdup(s)
87 1.54 christos #define Strcmp(d, s) wcscmp(d, s)
88 1.54 christos #define Strncmp(d, s, n) wcsncmp(d, s, n)
89 1.54 christos #define Strncpy(d, s, n) wcsncpy(d, s, n)
90 1.54 christos #define Strncat(d, s, n) wcsncat(d, s, n)
91 1.54 christos
92 1.54 christos #endif
93 1.54 christos
94 1.54 christos
95 1.42 christos typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
96 1.42 christos typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
97 1.42 christos typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
98 1.42 christos typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
99 1.1 cgd
100 1.37 christos struct TYPE(history) {
101 1.42 christos void *h_ref; /* Argument for history fcns */
102 1.16 lukem int h_ent; /* Last entry point for history */
103 1.16 lukem history_gfun_t h_first; /* Get the first element */
104 1.16 lukem history_gfun_t h_next; /* Get the next element */
105 1.16 lukem history_gfun_t h_last; /* Get the last element */
106 1.16 lukem history_gfun_t h_prev; /* Get the previous element */
107 1.16 lukem history_gfun_t h_curr; /* Get the current element */
108 1.16 lukem history_sfun_t h_set; /* Set the current element */
109 1.30 christos history_sfun_t h_del; /* Set the given element */
110 1.16 lukem history_vfun_t h_clear; /* Clear the history list */
111 1.16 lukem history_efun_t h_enter; /* Add an element */
112 1.16 lukem history_efun_t h_add; /* Append to an element */
113 1.1 cgd };
114 1.22 christos
115 1.16 lukem #define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
116 1.16 lukem #define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
117 1.16 lukem #define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
118 1.16 lukem #define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
119 1.16 lukem #define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
120 1.16 lukem #define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
121 1.16 lukem #define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
122 1.7 christos #define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
123 1.7 christos #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
124 1.30 christos #define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
125 1.1 cgd
126 1.35 christos #define h_strdup(a) Strdup(a)
127 1.16 lukem #define h_malloc(a) malloc(a)
128 1.16 lukem #define h_realloc(a, b) realloc((a), (b))
129 1.16 lukem #define h_free(a) free(a)
130 1.1 cgd
131 1.19 christos typedef struct {
132 1.19 christos int num;
133 1.35 christos Char *str;
134 1.19 christos } HistEventPrivate;
135 1.19 christos
136 1.19 christos
137 1.57 christos static int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
138 1.57 christos static int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
139 1.57 christos static int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
140 1.57 christos static int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
141 1.57 christos static int history_set_fun(TYPE(History) *, TYPE(History) *);
142 1.57 christos static int history_load(TYPE(History) *, const char *);
143 1.57 christos static int history_save(TYPE(History) *, const char *);
144 1.58 christos static int history_save_fp(TYPE(History) *, size_t, FILE *);
145 1.57 christos static int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
146 1.57 christos static int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
147 1.57 christos static int history_next_string(TYPE(History) *, TYPE(HistEvent) *,
148 1.57 christos const Char *);
149 1.57 christos static int history_prev_string(TYPE(History) *, TYPE(HistEvent) *,
150 1.57 christos const Char *);
151 1.1 cgd
152 1.1 cgd
153 1.1 cgd /***********************************************************************/
154 1.1 cgd
155 1.1 cgd /*
156 1.1 cgd * Builtin- history implementation
157 1.1 cgd */
158 1.1 cgd typedef struct hentry_t {
159 1.35 christos TYPE(HistEvent) ev; /* What we return */
160 1.34 christos void *data; /* data */
161 1.16 lukem struct hentry_t *next; /* Next entry */
162 1.16 lukem struct hentry_t *prev; /* Previous entry */
163 1.22 christos } hentry_t;
164 1.1 cgd
165 1.1 cgd typedef struct history_t {
166 1.22 christos hentry_t list; /* Fake list header element */
167 1.22 christos hentry_t *cursor; /* Current element in the list */
168 1.22 christos int max; /* Maximum number of events */
169 1.22 christos int cur; /* Current number of events */
170 1.16 lukem int eventid; /* For generation of unique event id */
171 1.35 christos int flags; /* TYPE(History) flags */
172 1.22 christos #define H_UNIQUE 1 /* Store only unique elements */
173 1.22 christos } history_t;
174 1.16 lukem
175 1.57 christos static int history_def_next(void *, TYPE(HistEvent) *);
176 1.57 christos static int history_def_first(void *, TYPE(HistEvent) *);
177 1.57 christos static int history_def_prev(void *, TYPE(HistEvent) *);
178 1.57 christos static int history_def_last(void *, TYPE(HistEvent) *);
179 1.57 christos static int history_def_curr(void *, TYPE(HistEvent) *);
180 1.57 christos static int history_def_set(void *, TYPE(HistEvent) *, const int);
181 1.57 christos static void history_def_clear(void *, TYPE(HistEvent) *);
182 1.57 christos static int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
183 1.57 christos static int history_def_add(void *, TYPE(HistEvent) *, const Char *);
184 1.57 christos static int history_def_del(void *, TYPE(HistEvent) *, const int);
185 1.57 christos
186 1.57 christos static int history_def_init(void **, TYPE(HistEvent) *, int);
187 1.57 christos static int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
188 1.57 christos static void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
189 1.1 cgd
190 1.57 christos static int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
191 1.57 christos static int history_set_nth(void *, TYPE(HistEvent) *, int);
192 1.34 christos
193 1.22 christos #define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
194 1.22 christos #define history_def_getsize(p) (((history_t *)p)->cur)
195 1.22 christos #define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
196 1.22 christos #define history_def_setunique(p, uni) \
197 1.22 christos if (uni) \
198 1.22 christos (((history_t *)p)->flags) |= H_UNIQUE; \
199 1.22 christos else \
200 1.22 christos (((history_t *)p)->flags) &= ~H_UNIQUE
201 1.1 cgd
202 1.16 lukem #define he_strerror(code) he_errlist[code]
203 1.16 lukem #define he_seterrev(evp, code) {\
204 1.7 christos evp->num = code;\
205 1.7 christos evp->str = he_strerror(code);\
206 1.7 christos }
207 1.14 simonb
208 1.7 christos /* error messages */
209 1.35 christos static const Char *const he_errlist[] = {
210 1.35 christos STR("OK"),
211 1.35 christos STR("unknown error"),
212 1.35 christos STR("malloc() failed"),
213 1.35 christos STR("first event not found"),
214 1.35 christos STR("last event not found"),
215 1.35 christos STR("empty list"),
216 1.35 christos STR("no next event"),
217 1.35 christos STR("no previous event"),
218 1.35 christos STR("current event is invalid"),
219 1.35 christos STR("event not found"),
220 1.35 christos STR("can't read history from file"),
221 1.35 christos STR("can't write history"),
222 1.35 christos STR("required parameter(s) not supplied"),
223 1.35 christos STR("history size negative"),
224 1.35 christos STR("function not allowed with other history-functions-set the default"),
225 1.35 christos STR("bad parameters")
226 1.7 christos };
227 1.7 christos /* error codes */
228 1.16 lukem #define _HE_OK 0
229 1.16 lukem #define _HE_UNKNOWN 1
230 1.16 lukem #define _HE_MALLOC_FAILED 2
231 1.16 lukem #define _HE_FIRST_NOTFOUND 3
232 1.16 lukem #define _HE_LAST_NOTFOUND 4
233 1.16 lukem #define _HE_EMPTY_LIST 5
234 1.16 lukem #define _HE_END_REACHED 6
235 1.16 lukem #define _HE_START_REACHED 7
236 1.16 lukem #define _HE_CURR_INVALID 8
237 1.16 lukem #define _HE_NOT_FOUND 9
238 1.16 lukem #define _HE_HIST_READ 10
239 1.16 lukem #define _HE_HIST_WRITE 11
240 1.16 lukem #define _HE_PARAM_MISSING 12
241 1.16 lukem #define _HE_SIZE_NEGATIVE 13
242 1.16 lukem #define _HE_NOT_ALLOWED 14
243 1.16 lukem #define _HE_BAD_PARAM 15
244 1.1 cgd
245 1.1 cgd /* history_def_first():
246 1.1 cgd * Default function to return the first event in the history.
247 1.1 cgd */
248 1.57 christos static int
249 1.42 christos history_def_first(void *p, TYPE(HistEvent) *ev)
250 1.1 cgd {
251 1.16 lukem history_t *h = (history_t *) p;
252 1.7 christos
253 1.16 lukem h->cursor = h->list.next;
254 1.16 lukem if (h->cursor != &h->list)
255 1.16 lukem *ev = h->cursor->ev;
256 1.16 lukem else {
257 1.16 lukem he_seterrev(ev, _HE_FIRST_NOTFOUND);
258 1.43 christos return -1;
259 1.16 lukem }
260 1.7 christos
261 1.43 christos return 0;
262 1.1 cgd }
263 1.1 cgd
264 1.8 christos
265 1.1 cgd /* history_def_last():
266 1.1 cgd * Default function to return the last event in the history.
267 1.1 cgd */
268 1.57 christos static int
269 1.42 christos history_def_last(void *p, TYPE(HistEvent) *ev)
270 1.16 lukem {
271 1.16 lukem history_t *h = (history_t *) p;
272 1.16 lukem
273 1.16 lukem h->cursor = h->list.prev;
274 1.16 lukem if (h->cursor != &h->list)
275 1.16 lukem *ev = h->cursor->ev;
276 1.16 lukem else {
277 1.16 lukem he_seterrev(ev, _HE_LAST_NOTFOUND);
278 1.43 christos return -1;
279 1.16 lukem }
280 1.7 christos
281 1.43 christos return 0;
282 1.1 cgd }
283 1.1 cgd
284 1.8 christos
285 1.1 cgd /* history_def_next():
286 1.1 cgd * Default function to return the next event in the history.
287 1.1 cgd */
288 1.57 christos static int
289 1.42 christos history_def_next(void *p, TYPE(HistEvent) *ev)
290 1.16 lukem {
291 1.16 lukem history_t *h = (history_t *) p;
292 1.16 lukem
293 1.28 christos if (h->cursor == &h->list) {
294 1.16 lukem he_seterrev(ev, _HE_EMPTY_LIST);
295 1.43 christos return -1;
296 1.16 lukem }
297 1.1 cgd
298 1.28 christos if (h->cursor->next == &h->list) {
299 1.16 lukem he_seterrev(ev, _HE_END_REACHED);
300 1.43 christos return -1;
301 1.16 lukem }
302 1.7 christos
303 1.28 christos h->cursor = h->cursor->next;
304 1.28 christos *ev = h->cursor->ev;
305 1.28 christos
306 1.43 christos return 0;
307 1.1 cgd }
308 1.1 cgd
309 1.1 cgd
310 1.1 cgd /* history_def_prev():
311 1.1 cgd * Default function to return the previous event in the history.
312 1.1 cgd */
313 1.57 christos static int
314 1.42 christos history_def_prev(void *p, TYPE(HistEvent) *ev)
315 1.16 lukem {
316 1.16 lukem history_t *h = (history_t *) p;
317 1.16 lukem
318 1.28 christos if (h->cursor == &h->list) {
319 1.16 lukem he_seterrev(ev,
320 1.16 lukem (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
321 1.43 christos return -1;
322 1.16 lukem }
323 1.1 cgd
324 1.28 christos if (h->cursor->prev == &h->list) {
325 1.16 lukem he_seterrev(ev, _HE_START_REACHED);
326 1.43 christos return -1;
327 1.16 lukem }
328 1.7 christos
329 1.28 christos h->cursor = h->cursor->prev;
330 1.28 christos *ev = h->cursor->ev;
331 1.28 christos
332 1.43 christos return 0;
333 1.1 cgd }
334 1.1 cgd
335 1.1 cgd
336 1.1 cgd /* history_def_curr():
337 1.1 cgd * Default function to return the current event in the history.
338 1.1 cgd */
339 1.57 christos static int
340 1.42 christos history_def_curr(void *p, TYPE(HistEvent) *ev)
341 1.1 cgd {
342 1.16 lukem history_t *h = (history_t *) p;
343 1.1 cgd
344 1.16 lukem if (h->cursor != &h->list)
345 1.16 lukem *ev = h->cursor->ev;
346 1.16 lukem else {
347 1.16 lukem he_seterrev(ev,
348 1.16 lukem (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
349 1.43 christos return -1;
350 1.16 lukem }
351 1.7 christos
352 1.43 christos return 0;
353 1.1 cgd }
354 1.1 cgd
355 1.8 christos
356 1.8 christos /* history_def_set():
357 1.8 christos * Default function to set the current event in the history to the
358 1.8 christos * given one.
359 1.8 christos */
360 1.57 christos static int
361 1.42 christos history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
362 1.16 lukem {
363 1.16 lukem history_t *h = (history_t *) p;
364 1.8 christos
365 1.16 lukem if (h->cur == 0) {
366 1.16 lukem he_seterrev(ev, _HE_EMPTY_LIST);
367 1.43 christos return -1;
368 1.16 lukem }
369 1.16 lukem if (h->cursor == &h->list || h->cursor->ev.num != n) {
370 1.16 lukem for (h->cursor = h->list.next; h->cursor != &h->list;
371 1.16 lukem h->cursor = h->cursor->next)
372 1.16 lukem if (h->cursor->ev.num == n)
373 1.16 lukem break;
374 1.16 lukem }
375 1.16 lukem if (h->cursor == &h->list) {
376 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
377 1.43 christos return -1;
378 1.16 lukem }
379 1.43 christos return 0;
380 1.8 christos }
381 1.8 christos
382 1.8 christos
383 1.34 christos /* history_set_nth():
384 1.34 christos * Default function to set the current event in the history to the
385 1.34 christos * n-th one.
386 1.34 christos */
387 1.57 christos static int
388 1.42 christos history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
389 1.34 christos {
390 1.34 christos history_t *h = (history_t *) p;
391 1.34 christos
392 1.34 christos if (h->cur == 0) {
393 1.34 christos he_seterrev(ev, _HE_EMPTY_LIST);
394 1.43 christos return -1;
395 1.34 christos }
396 1.34 christos for (h->cursor = h->list.prev; h->cursor != &h->list;
397 1.34 christos h->cursor = h->cursor->prev)
398 1.34 christos if (n-- <= 0)
399 1.34 christos break;
400 1.34 christos if (h->cursor == &h->list) {
401 1.34 christos he_seterrev(ev, _HE_NOT_FOUND);
402 1.43 christos return -1;
403 1.34 christos }
404 1.43 christos return 0;
405 1.34 christos }
406 1.34 christos
407 1.34 christos
408 1.1 cgd /* history_def_add():
409 1.1 cgd * Append string to element
410 1.1 cgd */
411 1.57 christos static int
412 1.42 christos history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
413 1.16 lukem {
414 1.16 lukem history_t *h = (history_t *) p;
415 1.63 christos size_t len, elen, slen;
416 1.35 christos Char *s;
417 1.19 christos HistEventPrivate *evp = (void *)&h->cursor->ev;
418 1.16 lukem
419 1.16 lukem if (h->cursor == &h->list)
420 1.43 christos return history_def_enter(p, ev, str);
421 1.63 christos elen = Strlen(evp->str);
422 1.63 christos slen = Strlen(str);
423 1.63 christos len = elen + slen + 1;
424 1.35 christos s = h_malloc(len * sizeof(*s));
425 1.21 christos if (s == NULL) {
426 1.16 lukem he_seterrev(ev, _HE_MALLOC_FAILED);
427 1.43 christos return -1;
428 1.16 lukem }
429 1.63 christos memcpy(s, evp->str, elen * sizeof(*s));
430 1.63 christos memcpy(s + elen, str, slen * sizeof(*s));
431 1.35 christos s[len - 1] = '\0';
432 1.42 christos h_free(evp->str);
433 1.19 christos evp->str = s;
434 1.16 lukem *ev = h->cursor->ev;
435 1.43 christos return 0;
436 1.1 cgd }
437 1.1 cgd
438 1.1 cgd
439 1.57 christos static int
440 1.35 christos history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
441 1.34 christos int num, void **data)
442 1.34 christos {
443 1.34 christos if (history_set_nth(h, ev, num) != 0)
444 1.43 christos return -1;
445 1.34 christos /* magic value to skip delete (just set to n-th history) */
446 1.34 christos if (data == (void **)-1)
447 1.43 christos return 0;
448 1.35 christos ev->str = Strdup(h->cursor->ev.str);
449 1.34 christos ev->num = h->cursor->ev.num;
450 1.34 christos if (data)
451 1.34 christos *data = h->cursor->data;
452 1.34 christos history_def_delete(h, ev, h->cursor);
453 1.43 christos return 0;
454 1.34 christos }
455 1.34 christos
456 1.34 christos
457 1.30 christos /* history_def_del():
458 1.30 christos * Delete element hp of the h list
459 1.30 christos */
460 1.30 christos /* ARGSUSED */
461 1.57 christos static int
462 1.42 christos history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
463 1.30 christos const int num)
464 1.30 christos {
465 1.30 christos history_t *h = (history_t *) p;
466 1.30 christos if (history_def_set(h, ev, num) != 0)
467 1.43 christos return -1;
468 1.35 christos ev->str = Strdup(h->cursor->ev.str);
469 1.30 christos ev->num = h->cursor->ev.num;
470 1.30 christos history_def_delete(h, ev, h->cursor);
471 1.43 christos return 0;
472 1.30 christos }
473 1.30 christos
474 1.30 christos
475 1.1 cgd /* history_def_delete():
476 1.1 cgd * Delete element hp of the h list
477 1.1 cgd */
478 1.11 christos /* ARGSUSED */
479 1.57 christos static void
480 1.52 christos history_def_delete(history_t *h,
481 1.35 christos TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
482 1.16 lukem {
483 1.19 christos HistEventPrivate *evp = (void *)&hp->ev;
484 1.16 lukem if (hp == &h->list)
485 1.16 lukem abort();
486 1.34 christos if (h->cursor == hp) {
487 1.30 christos h->cursor = hp->prev;
488 1.34 christos if (h->cursor == &h->list)
489 1.34 christos h->cursor = hp->next;
490 1.34 christos }
491 1.16 lukem hp->prev->next = hp->next;
492 1.16 lukem hp->next->prev = hp->prev;
493 1.42 christos h_free(evp->str);
494 1.16 lukem h_free(hp);
495 1.16 lukem h->cur--;
496 1.1 cgd }
497 1.1 cgd
498 1.1 cgd
499 1.1 cgd /* history_def_insert():
500 1.1 cgd * Insert element with string str in the h list
501 1.1 cgd */
502 1.57 christos static int
503 1.35 christos history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
504 1.16 lukem {
505 1.39 christos hentry_t *c;
506 1.16 lukem
507 1.39 christos c = h_malloc(sizeof(*c));
508 1.39 christos if (c == NULL)
509 1.21 christos goto oomem;
510 1.39 christos if ((c->ev.str = h_strdup(str)) == NULL) {
511 1.42 christos h_free(c);
512 1.21 christos goto oomem;
513 1.16 lukem }
514 1.39 christos c->data = NULL;
515 1.39 christos c->ev.num = ++h->eventid;
516 1.39 christos c->next = h->list.next;
517 1.39 christos c->prev = &h->list;
518 1.39 christos h->list.next->prev = c;
519 1.39 christos h->list.next = c;
520 1.16 lukem h->cur++;
521 1.39 christos h->cursor = c;
522 1.1 cgd
523 1.39 christos *ev = c->ev;
524 1.43 christos return 0;
525 1.21 christos oomem:
526 1.21 christos he_seterrev(ev, _HE_MALLOC_FAILED);
527 1.43 christos return -1;
528 1.1 cgd }
529 1.1 cgd
530 1.1 cgd
531 1.1 cgd /* history_def_enter():
532 1.1 cgd * Default function to enter an item in the history
533 1.1 cgd */
534 1.57 christos static int
535 1.42 christos history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
536 1.16 lukem {
537 1.16 lukem history_t *h = (history_t *) p;
538 1.16 lukem
539 1.22 christos if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
540 1.35 christos Strcmp(h->list.next->ev.str, str) == 0)
541 1.43 christos return 0;
542 1.22 christos
543 1.16 lukem if (history_def_insert(h, ev, str) == -1)
544 1.43 christos return -1; /* error, keep error message */
545 1.16 lukem
546 1.16 lukem /*
547 1.16 lukem * Always keep at least one entry.
548 1.16 lukem * This way we don't have to check for the empty list.
549 1.16 lukem */
550 1.18 jdolecek while (h->cur > h->max && h->cur > 0)
551 1.16 lukem history_def_delete(h, ev, h->list.prev);
552 1.7 christos
553 1.43 christos return 1;
554 1.1 cgd }
555 1.1 cgd
556 1.1 cgd
557 1.1 cgd /* history_def_init():
558 1.1 cgd * Default history initialization function
559 1.1 cgd */
560 1.11 christos /* ARGSUSED */
561 1.57 christos static int
562 1.42 christos history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
563 1.16 lukem {
564 1.42 christos history_t *h = (history_t *) h_malloc(sizeof(*h));
565 1.21 christos if (h == NULL)
566 1.21 christos return -1;
567 1.16 lukem
568 1.16 lukem if (n <= 0)
569 1.16 lukem n = 0;
570 1.16 lukem h->eventid = 0;
571 1.16 lukem h->cur = 0;
572 1.16 lukem h->max = n;
573 1.16 lukem h->list.next = h->list.prev = &h->list;
574 1.16 lukem h->list.ev.str = NULL;
575 1.16 lukem h->list.ev.num = 0;
576 1.16 lukem h->cursor = &h->list;
577 1.22 christos h->flags = 0;
578 1.42 christos *p = h;
579 1.21 christos return 0;
580 1.1 cgd }
581 1.1 cgd
582 1.1 cgd
583 1.2 christos /* history_def_clear():
584 1.1 cgd * Default history cleanup function
585 1.1 cgd */
586 1.57 christos static void
587 1.42 christos history_def_clear(void *p, TYPE(HistEvent) *ev)
588 1.16 lukem {
589 1.16 lukem history_t *h = (history_t *) p;
590 1.16 lukem
591 1.16 lukem while (h->list.prev != &h->list)
592 1.16 lukem history_def_delete(h, ev, h->list.prev);
593 1.39 christos h->cursor = &h->list;
594 1.16 lukem h->eventid = 0;
595 1.16 lukem h->cur = 0;
596 1.1 cgd }
597 1.1 cgd
598 1.2 christos
599 1.2 christos
600 1.2 christos
601 1.1 cgd /************************************************************************/
602 1.1 cgd
603 1.1 cgd /* history_init():
604 1.1 cgd * Initialization function.
605 1.1 cgd */
606 1.57 christos TYPE(History) *
607 1.35 christos FUN(history,init)(void)
608 1.1 cgd {
609 1.35 christos TYPE(HistEvent) ev;
610 1.42 christos TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
611 1.21 christos if (h == NULL)
612 1.21 christos return NULL;
613 1.1 cgd
614 1.21 christos if (history_def_init(&h->h_ref, &ev, 0) == -1) {
615 1.42 christos h_free(h);
616 1.21 christos return NULL;
617 1.21 christos }
618 1.16 lukem h->h_ent = -1;
619 1.16 lukem h->h_next = history_def_next;
620 1.16 lukem h->h_first = history_def_first;
621 1.16 lukem h->h_last = history_def_last;
622 1.16 lukem h->h_prev = history_def_prev;
623 1.16 lukem h->h_curr = history_def_curr;
624 1.16 lukem h->h_set = history_def_set;
625 1.16 lukem h->h_clear = history_def_clear;
626 1.16 lukem h->h_enter = history_def_enter;
627 1.16 lukem h->h_add = history_def_add;
628 1.31 christos h->h_del = history_def_del;
629 1.1 cgd
630 1.43 christos return h;
631 1.1 cgd }
632 1.1 cgd
633 1.1 cgd
634 1.1 cgd /* history_end():
635 1.1 cgd * clean up history;
636 1.1 cgd */
637 1.57 christos void
638 1.35 christos FUN(history,end)(TYPE(History) *h)
639 1.1 cgd {
640 1.35 christos TYPE(HistEvent) ev;
641 1.16 lukem
642 1.16 lukem if (h->h_next == history_def_next)
643 1.16 lukem history_def_clear(h->h_ref, &ev);
644 1.32 christos h_free(h->h_ref);
645 1.29 christos h_free(h);
646 1.1 cgd }
647 1.1 cgd
648 1.1 cgd
649 1.1 cgd
650 1.12 christos /* history_setsize():
651 1.1 cgd * Set history number of events
652 1.1 cgd */
653 1.57 christos static int
654 1.35 christos history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
655 1.16 lukem {
656 1.7 christos
657 1.16 lukem if (h->h_next != history_def_next) {
658 1.16 lukem he_seterrev(ev, _HE_NOT_ALLOWED);
659 1.43 christos return -1;
660 1.16 lukem }
661 1.16 lukem if (num < 0) {
662 1.16 lukem he_seterrev(ev, _HE_BAD_PARAM);
663 1.43 christos return -1;
664 1.16 lukem }
665 1.16 lukem history_def_setsize(h->h_ref, num);
666 1.43 christos return 0;
667 1.1 cgd }
668 1.1 cgd
669 1.16 lukem
670 1.12 christos /* history_getsize():
671 1.7 christos * Get number of events currently in history
672 1.7 christos */
673 1.57 christos static int
674 1.35 christos history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
675 1.16 lukem {
676 1.22 christos if (h->h_next != history_def_next) {
677 1.22 christos he_seterrev(ev, _HE_NOT_ALLOWED);
678 1.43 christos return -1;
679 1.22 christos }
680 1.22 christos ev->num = history_def_getsize(h->h_ref);
681 1.22 christos if (ev->num < -1) {
682 1.22 christos he_seterrev(ev, _HE_SIZE_NEGATIVE);
683 1.43 christos return -1;
684 1.22 christos }
685 1.43 christos return 0;
686 1.22 christos }
687 1.22 christos
688 1.22 christos
689 1.22 christos /* history_setunique():
690 1.22 christos * Set if adjacent equal events should not be entered in history.
691 1.22 christos */
692 1.57 christos static int
693 1.35 christos history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
694 1.22 christos {
695 1.7 christos
696 1.16 lukem if (h->h_next != history_def_next) {
697 1.16 lukem he_seterrev(ev, _HE_NOT_ALLOWED);
698 1.43 christos return -1;
699 1.16 lukem }
700 1.22 christos history_def_setunique(h->h_ref, uni);
701 1.43 christos return 0;
702 1.22 christos }
703 1.22 christos
704 1.22 christos
705 1.22 christos /* history_getunique():
706 1.22 christos * Get if adjacent equal events should not be entered in history.
707 1.22 christos */
708 1.57 christos static int
709 1.35 christos history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
710 1.22 christos {
711 1.22 christos if (h->h_next != history_def_next) {
712 1.22 christos he_seterrev(ev, _HE_NOT_ALLOWED);
713 1.43 christos return -1;
714 1.16 lukem }
715 1.22 christos ev->num = history_def_getunique(h->h_ref);
716 1.43 christos return 0;
717 1.7 christos }
718 1.1 cgd
719 1.16 lukem
720 1.1 cgd /* history_set_fun():
721 1.1 cgd * Set history functions
722 1.1 cgd */
723 1.57 christos static int
724 1.35 christos history_set_fun(TYPE(History) *h, TYPE(History) *nh)
725 1.16 lukem {
726 1.35 christos TYPE(HistEvent) ev;
727 1.16 lukem
728 1.16 lukem if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
729 1.16 lukem nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
730 1.16 lukem nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
731 1.30 christos nh->h_del == NULL || nh->h_ref == NULL) {
732 1.16 lukem if (h->h_next != history_def_next) {
733 1.46 christos if (history_def_init(&h->h_ref, &ev, 0) == -1)
734 1.46 christos return -1;
735 1.16 lukem h->h_first = history_def_first;
736 1.16 lukem h->h_next = history_def_next;
737 1.16 lukem h->h_last = history_def_last;
738 1.16 lukem h->h_prev = history_def_prev;
739 1.16 lukem h->h_curr = history_def_curr;
740 1.16 lukem h->h_set = history_def_set;
741 1.16 lukem h->h_clear = history_def_clear;
742 1.16 lukem h->h_enter = history_def_enter;
743 1.16 lukem h->h_add = history_def_add;
744 1.30 christos h->h_del = history_def_del;
745 1.16 lukem }
746 1.43 christos return -1;
747 1.16 lukem }
748 1.16 lukem if (h->h_next == history_def_next)
749 1.16 lukem history_def_clear(h->h_ref, &ev);
750 1.16 lukem
751 1.16 lukem h->h_ent = -1;
752 1.16 lukem h->h_first = nh->h_first;
753 1.16 lukem h->h_next = nh->h_next;
754 1.16 lukem h->h_last = nh->h_last;
755 1.16 lukem h->h_prev = nh->h_prev;
756 1.16 lukem h->h_curr = nh->h_curr;
757 1.16 lukem h->h_set = nh->h_set;
758 1.16 lukem h->h_clear = nh->h_clear;
759 1.16 lukem h->h_enter = nh->h_enter;
760 1.16 lukem h->h_add = nh->h_add;
761 1.30 christos h->h_del = nh->h_del;
762 1.1 cgd
763 1.43 christos return 0;
764 1.1 cgd }
765 1.1 cgd
766 1.1 cgd
767 1.2 christos /* history_load():
768 1.35 christos * TYPE(History) load function
769 1.2 christos */
770 1.57 christos static int
771 1.35 christos history_load(TYPE(History) *h, const char *fname)
772 1.16 lukem {
773 1.16 lukem FILE *fp;
774 1.16 lukem char *line;
775 1.50 christos size_t llen;
776 1.50 christos ssize_t sz;
777 1.50 christos size_t max_size;
778 1.16 lukem char *ptr;
779 1.16 lukem int i = -1;
780 1.35 christos TYPE(HistEvent) ev;
781 1.60 christos Char *decode_result;
782 1.53 christos #ifndef NARROWCHAR
783 1.36 christos static ct_buffer_t conv;
784 1.35 christos #endif
785 1.16 lukem
786 1.16 lukem if ((fp = fopen(fname, "r")) == NULL)
787 1.43 christos return i;
788 1.16 lukem
789 1.50 christos line = NULL;
790 1.50 christos llen = 0;
791 1.50 christos if ((sz = getline(&line, &llen, fp)) == -1)
792 1.16 lukem goto done;
793 1.16 lukem
794 1.50 christos if (strncmp(line, hist_cookie, (size_t)sz) != 0)
795 1.16 lukem goto done;
796 1.16 lukem
797 1.42 christos ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
798 1.21 christos if (ptr == NULL)
799 1.21 christos goto done;
800 1.50 christos for (i = 0; (sz = getline(&line, &llen, fp)) != -1; i++) {
801 1.50 christos if (sz > 0 && line[sz - 1] == '\n')
802 1.50 christos line[--sz] = '\0';
803 1.50 christos if (max_size < (size_t)sz) {
804 1.21 christos char *nptr;
805 1.50 christos max_size = ((size_t)sz + 1024) & (size_t)~1023;
806 1.42 christos nptr = h_realloc(ptr, max_size * sizeof(*ptr));
807 1.21 christos if (nptr == NULL) {
808 1.21 christos i = -1;
809 1.21 christos goto oomem;
810 1.21 christos }
811 1.21 christos ptr = nptr;
812 1.16 lukem }
813 1.16 lukem (void) strunvis(ptr, line);
814 1.60 christos decode_result = ct_decode_string(ptr, &conv);
815 1.60 christos if (decode_result == NULL)
816 1.60 christos continue;
817 1.62 kre if (HENTER(h, &ev, decode_result) == -1) {
818 1.33 sketch i = -1;
819 1.33 sketch goto oomem;
820 1.21 christos }
821 1.16 lukem }
822 1.21 christos oomem:
823 1.42 christos h_free(ptr);
824 1.2 christos done:
825 1.48 christos free(line);
826 1.16 lukem (void) fclose(fp);
827 1.43 christos return i;
828 1.2 christos }
829 1.2 christos
830 1.2 christos
831 1.47 christos /* history_save_fp():
832 1.35 christos * TYPE(History) save function
833 1.2 christos */
834 1.57 christos static int
835 1.58 christos history_save_fp(TYPE(History) *h, size_t nelem, FILE *fp)
836 1.16 lukem {
837 1.35 christos TYPE(HistEvent) ev;
838 1.21 christos int i = -1, retval;
839 1.16 lukem size_t len, max_size;
840 1.40 christos char *ptr;
841 1.40 christos const char *str;
842 1.53 christos #ifndef NARROWCHAR
843 1.36 christos static ct_buffer_t conv;
844 1.35 christos #endif
845 1.16 lukem
846 1.58 christos if (ftell(fp) == 0 && fputs(hist_cookie, fp) == EOF)
847 1.21 christos goto done;
848 1.42 christos ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
849 1.21 christos if (ptr == NULL)
850 1.21 christos goto done;
851 1.58 christos if (nelem != (size_t)-1) {
852 1.58 christos for (retval = HFIRST(h, &ev); retval != -1 && nelem-- > 0;
853 1.58 christos retval = HNEXT(h, &ev))
854 1.58 christos continue;
855 1.58 christos } else
856 1.58 christos retval = -1;
857 1.58 christos
858 1.58 christos if (retval == -1)
859 1.58 christos retval = HLAST(h, &ev);
860 1.58 christos
861 1.58 christos for (i = 0; retval != -1; retval = HPREV(h, &ev), i++) {
862 1.39 christos str = ct_encode_string(ev.str, &conv);
863 1.49 christos len = strlen(str) * 4 + 1;
864 1.49 christos if (len > max_size) {
865 1.21 christos char *nptr;
866 1.45 christos max_size = (len + 1024) & (size_t)~1023;
867 1.42 christos nptr = h_realloc(ptr, max_size * sizeof(*ptr));
868 1.21 christos if (nptr == NULL) {
869 1.21 christos i = -1;
870 1.21 christos goto oomem;
871 1.21 christos }
872 1.21 christos ptr = nptr;
873 1.16 lukem }
874 1.39 christos (void) strvis(ptr, str, VIS_WHITE);
875 1.20 christos (void) fprintf(fp, "%s\n", ptr);
876 1.16 lukem }
877 1.21 christos oomem:
878 1.42 christos h_free(ptr);
879 1.21 christos done:
880 1.43 christos return i;
881 1.2 christos }
882 1.2 christos
883 1.2 christos
884 1.47 christos /* history_save():
885 1.47 christos * History save function
886 1.47 christos */
887 1.57 christos static int
888 1.47 christos history_save(TYPE(History) *h, const char *fname)
889 1.47 christos {
890 1.47 christos FILE *fp;
891 1.47 christos int i;
892 1.47 christos
893 1.64 kre if ((i = open(fname, O_WRONLY|O_CREAT|O_TRUNC,
894 1.64 kre S_IRUSR|S_IWUSR)) == -1)
895 1.64 kre return -1;
896 1.64 kre
897 1.64 kre if ((fp = fdopen(i, "w")) == NULL)
898 1.47 christos return -1;
899 1.47 christos
900 1.58 christos i = history_save_fp(h, (size_t)-1, fp);
901 1.47 christos
902 1.47 christos (void) fclose(fp);
903 1.47 christos return i;
904 1.47 christos }
905 1.47 christos
906 1.47 christos
907 1.1 cgd /* history_prev_event():
908 1.1 cgd * Find the previous event, with number given
909 1.1 cgd */
910 1.57 christos static int
911 1.35 christos history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
912 1.16 lukem {
913 1.16 lukem int retval;
914 1.7 christos
915 1.16 lukem for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
916 1.16 lukem if (ev->num == num)
917 1.43 christos return 0;
918 1.16 lukem
919 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
920 1.43 christos return -1;
921 1.1 cgd }
922 1.1 cgd
923 1.1 cgd
924 1.57 christos static int
925 1.35 christos history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
926 1.34 christos {
927 1.34 christos int retval;
928 1.34 christos
929 1.34 christos for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
930 1.38 christos if (ev->num == num) {
931 1.34 christos if (d)
932 1.34 christos *d = ((history_t *)h->h_ref)->cursor->data;
933 1.43 christos return 0;
934 1.34 christos }
935 1.34 christos
936 1.34 christos he_seterrev(ev, _HE_NOT_FOUND);
937 1.43 christos return -1;
938 1.34 christos }
939 1.34 christos
940 1.34 christos
941 1.1 cgd /* history_next_event():
942 1.1 cgd * Find the next event, with number given
943 1.1 cgd */
944 1.57 christos static int
945 1.35 christos history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
946 1.16 lukem {
947 1.16 lukem int retval;
948 1.16 lukem
949 1.16 lukem for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
950 1.16 lukem if (ev->num == num)
951 1.43 christos return 0;
952 1.7 christos
953 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
954 1.43 christos return -1;
955 1.1 cgd }
956 1.1 cgd
957 1.1 cgd
958 1.1 cgd /* history_prev_string():
959 1.1 cgd * Find the previous event beginning with string
960 1.1 cgd */
961 1.57 christos static int
962 1.35 christos history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
963 1.16 lukem {
964 1.35 christos size_t len = Strlen(str);
965 1.16 lukem int retval;
966 1.7 christos
967 1.16 lukem for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
968 1.35 christos if (Strncmp(str, ev->str, len) == 0)
969 1.43 christos return 0;
970 1.16 lukem
971 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
972 1.43 christos return -1;
973 1.1 cgd }
974 1.1 cgd
975 1.1 cgd
976 1.1 cgd /* history_next_string():
977 1.1 cgd * Find the next event beginning with string
978 1.1 cgd */
979 1.57 christos static int
980 1.35 christos history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
981 1.16 lukem {
982 1.35 christos size_t len = Strlen(str);
983 1.16 lukem int retval;
984 1.16 lukem
985 1.16 lukem for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
986 1.35 christos if (Strncmp(str, ev->str, len) == 0)
987 1.43 christos return 0;
988 1.7 christos
989 1.16 lukem he_seterrev(ev, _HE_NOT_FOUND);
990 1.43 christos return -1;
991 1.1 cgd }
992 1.1 cgd
993 1.1 cgd
994 1.1 cgd /* history():
995 1.1 cgd * User interface to history functions.
996 1.1 cgd */
997 1.7 christos int
998 1.35 christos FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
999 1.1 cgd {
1000 1.16 lukem va_list va;
1001 1.35 christos const Char *str;
1002 1.16 lukem int retval;
1003 1.16 lukem
1004 1.16 lukem va_start(va, fun);
1005 1.16 lukem
1006 1.16 lukem he_seterrev(ev, _HE_OK);
1007 1.16 lukem
1008 1.16 lukem switch (fun) {
1009 1.16 lukem case H_GETSIZE:
1010 1.16 lukem retval = history_getsize(h, ev);
1011 1.16 lukem break;
1012 1.16 lukem
1013 1.16 lukem case H_SETSIZE:
1014 1.16 lukem retval = history_setsize(h, ev, va_arg(va, int));
1015 1.22 christos break;
1016 1.22 christos
1017 1.22 christos case H_GETUNIQUE:
1018 1.22 christos retval = history_getunique(h, ev);
1019 1.22 christos break;
1020 1.22 christos
1021 1.22 christos case H_SETUNIQUE:
1022 1.22 christos retval = history_setunique(h, ev, va_arg(va, int));
1023 1.16 lukem break;
1024 1.16 lukem
1025 1.16 lukem case H_ADD:
1026 1.35 christos str = va_arg(va, const Char *);
1027 1.16 lukem retval = HADD(h, ev, str);
1028 1.16 lukem break;
1029 1.16 lukem
1030 1.30 christos case H_DEL:
1031 1.30 christos retval = HDEL(h, ev, va_arg(va, const int));
1032 1.30 christos break;
1033 1.30 christos
1034 1.16 lukem case H_ENTER:
1035 1.35 christos str = va_arg(va, const Char *);
1036 1.16 lukem if ((retval = HENTER(h, ev, str)) != -1)
1037 1.16 lukem h->h_ent = ev->num;
1038 1.16 lukem break;
1039 1.16 lukem
1040 1.16 lukem case H_APPEND:
1041 1.35 christos str = va_arg(va, const Char *);
1042 1.16 lukem if ((retval = HSET(h, ev, h->h_ent)) != -1)
1043 1.16 lukem retval = HADD(h, ev, str);
1044 1.16 lukem break;
1045 1.16 lukem
1046 1.16 lukem case H_FIRST:
1047 1.16 lukem retval = HFIRST(h, ev);
1048 1.16 lukem break;
1049 1.1 cgd
1050 1.16 lukem case H_NEXT:
1051 1.16 lukem retval = HNEXT(h, ev);
1052 1.16 lukem break;
1053 1.16 lukem
1054 1.16 lukem case H_LAST:
1055 1.16 lukem retval = HLAST(h, ev);
1056 1.16 lukem break;
1057 1.16 lukem
1058 1.16 lukem case H_PREV:
1059 1.16 lukem retval = HPREV(h, ev);
1060 1.16 lukem break;
1061 1.16 lukem
1062 1.16 lukem case H_CURR:
1063 1.16 lukem retval = HCURR(h, ev);
1064 1.16 lukem break;
1065 1.16 lukem
1066 1.16 lukem case H_SET:
1067 1.16 lukem retval = HSET(h, ev, va_arg(va, const int));
1068 1.16 lukem break;
1069 1.16 lukem
1070 1.16 lukem case H_CLEAR:
1071 1.16 lukem HCLEAR(h, ev);
1072 1.16 lukem retval = 0;
1073 1.16 lukem break;
1074 1.16 lukem
1075 1.16 lukem case H_LOAD:
1076 1.16 lukem retval = history_load(h, va_arg(va, const char *));
1077 1.16 lukem if (retval == -1)
1078 1.16 lukem he_seterrev(ev, _HE_HIST_READ);
1079 1.16 lukem break;
1080 1.16 lukem
1081 1.16 lukem case H_SAVE:
1082 1.16 lukem retval = history_save(h, va_arg(va, const char *));
1083 1.16 lukem if (retval == -1)
1084 1.16 lukem he_seterrev(ev, _HE_HIST_WRITE);
1085 1.16 lukem break;
1086 1.16 lukem
1087 1.47 christos case H_SAVE_FP:
1088 1.58 christos retval = history_save_fp(h, (size_t)-1, va_arg(va, FILE *));
1089 1.58 christos if (retval == -1)
1090 1.58 christos he_seterrev(ev, _HE_HIST_WRITE);
1091 1.58 christos break;
1092 1.58 christos
1093 1.58 christos case H_NSAVE_FP:
1094 1.59 uwe {
1095 1.59 uwe size_t sz = va_arg(va, size_t);
1096 1.59 uwe retval = history_save_fp(h, sz, va_arg(va, FILE *));
1097 1.47 christos if (retval == -1)
1098 1.47 christos he_seterrev(ev, _HE_HIST_WRITE);
1099 1.47 christos break;
1100 1.59 uwe }
1101 1.47 christos
1102 1.16 lukem case H_PREV_EVENT:
1103 1.16 lukem retval = history_prev_event(h, ev, va_arg(va, int));
1104 1.16 lukem break;
1105 1.16 lukem
1106 1.16 lukem case H_NEXT_EVENT:
1107 1.16 lukem retval = history_next_event(h, ev, va_arg(va, int));
1108 1.16 lukem break;
1109 1.1 cgd
1110 1.16 lukem case H_PREV_STR:
1111 1.35 christos retval = history_prev_string(h, ev, va_arg(va, const Char *));
1112 1.16 lukem break;
1113 1.7 christos
1114 1.16 lukem case H_NEXT_STR:
1115 1.35 christos retval = history_next_string(h, ev, va_arg(va, const Char *));
1116 1.16 lukem break;
1117 1.1 cgd
1118 1.16 lukem case H_FUNC:
1119 1.1 cgd {
1120 1.35 christos TYPE(History) hf;
1121 1.16 lukem
1122 1.42 christos hf.h_ref = va_arg(va, void *);
1123 1.16 lukem h->h_ent = -1;
1124 1.16 lukem hf.h_first = va_arg(va, history_gfun_t);
1125 1.16 lukem hf.h_next = va_arg(va, history_gfun_t);
1126 1.16 lukem hf.h_last = va_arg(va, history_gfun_t);
1127 1.16 lukem hf.h_prev = va_arg(va, history_gfun_t);
1128 1.16 lukem hf.h_curr = va_arg(va, history_gfun_t);
1129 1.16 lukem hf.h_set = va_arg(va, history_sfun_t);
1130 1.16 lukem hf.h_clear = va_arg(va, history_vfun_t);
1131 1.16 lukem hf.h_enter = va_arg(va, history_efun_t);
1132 1.16 lukem hf.h_add = va_arg(va, history_efun_t);
1133 1.30 christos hf.h_del = va_arg(va, history_sfun_t);
1134 1.8 christos
1135 1.16 lukem if ((retval = history_set_fun(h, &hf)) == -1)
1136 1.16 lukem he_seterrev(ev, _HE_PARAM_MISSING);
1137 1.16 lukem break;
1138 1.16 lukem }
1139 1.16 lukem
1140 1.16 lukem case H_END:
1141 1.36 christos FUN(history,end)(h);
1142 1.16 lukem retval = 0;
1143 1.16 lukem break;
1144 1.16 lukem
1145 1.34 christos case H_NEXT_EVDATA:
1146 1.34 christos {
1147 1.34 christos int num = va_arg(va, int);
1148 1.34 christos void **d = va_arg(va, void **);
1149 1.34 christos retval = history_next_evdata(h, ev, num, d);
1150 1.34 christos break;
1151 1.34 christos }
1152 1.34 christos
1153 1.34 christos case H_DELDATA:
1154 1.34 christos {
1155 1.34 christos int num = va_arg(va, int);
1156 1.34 christos void **d = va_arg(va, void **);
1157 1.34 christos retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
1158 1.34 christos break;
1159 1.34 christos }
1160 1.34 christos
1161 1.34 christos case H_REPLACE: /* only use after H_NEXT_EVDATA */
1162 1.34 christos {
1163 1.35 christos const Char *line = va_arg(va, const Char *);
1164 1.34 christos void *d = va_arg(va, void *);
1165 1.35 christos const Char *s;
1166 1.35 christos if(!line || !(s = Strdup(line))) {
1167 1.34 christos retval = -1;
1168 1.34 christos break;
1169 1.34 christos }
1170 1.34 christos ((history_t *)h->h_ref)->cursor->ev.str = s;
1171 1.34 christos ((history_t *)h->h_ref)->cursor->data = d;
1172 1.34 christos retval = 0;
1173 1.34 christos break;
1174 1.34 christos }
1175 1.34 christos
1176 1.16 lukem default:
1177 1.16 lukem retval = -1;
1178 1.16 lukem he_seterrev(ev, _HE_UNKNOWN);
1179 1.16 lukem break;
1180 1.16 lukem }
1181 1.16 lukem va_end(va);
1182 1.34 christos return retval;
1183 1.1 cgd }
1184