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