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