Deleted Added
full compact
history.c (8870) history.c (26926)
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if !defined(lint) && !defined(SCCSID)
38static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
39#endif /* not lint && not SCCSID */
40
41/*
42 * hist.c: History access functions
43 */
44#include "sys.h"
45
46#include <string.h>
47#include <stdlib.h>
48#if __STDC__
49#include <stdarg.h>
50#else
51#include <varargs.h>
52#endif
53
1/*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#if !defined(lint) && !defined(SCCSID)
38static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
39#endif /* not lint && not SCCSID */
40
41/*
42 * hist.c: History access functions
43 */
44#include "sys.h"
45
46#include <string.h>
47#include <stdlib.h>
48#if __STDC__
49#include <stdarg.h>
50#else
51#include <varargs.h>
52#endif
53
54static const char hist_cookie[] = "_HiStOrY_V1_\n";
55
54#include "histedit.h"
55
56typedef const HistEvent * (*history_gfun_t) __P((ptr_t));
57typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
56#include "histedit.h"
57
58typedef const HistEvent * (*history_gfun_t) __P((ptr_t));
59typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));
60typedef void (*history_vfun_t) __P((ptr_t));
58
59struct history {
60 ptr_t h_ref; /* Argument for history fcns */
61 history_gfun_t h_first; /* Get the first element */
62 history_gfun_t h_next; /* Get the next element */
63 history_gfun_t h_last; /* Get the last element */
64 history_gfun_t h_prev; /* Get the previous element */
65 history_gfun_t h_curr; /* Get the current element */
61
62struct history {
63 ptr_t h_ref; /* Argument for history fcns */
64 history_gfun_t h_first; /* Get the first element */
65 history_gfun_t h_next; /* Get the next element */
66 history_gfun_t h_last; /* Get the last element */
67 history_gfun_t h_prev; /* Get the previous element */
68 history_gfun_t h_curr; /* Get the current element */
69 history_vfun_t h_clear; /* Clear the history list */
66 history_efun_t h_enter; /* Add an element */
67 history_efun_t h_add; /* Append to an element */
68};
69
70#define HNEXT(h) (*(h)->h_next)((h)->h_ref)
71#define HFIRST(h) (*(h)->h_first)((h)->h_ref)
72#define HPREV(h) (*(h)->h_prev)((h)->h_ref)
73#define HLAST(h) (*(h)->h_last)((h)->h_ref)
74#define HCURR(h) (*(h)->h_curr)((h)->h_ref)
70 history_efun_t h_enter; /* Add an element */
71 history_efun_t h_add; /* Append to an element */
72};
73
74#define HNEXT(h) (*(h)->h_next)((h)->h_ref)
75#define HFIRST(h) (*(h)->h_first)((h)->h_ref)
76#define HPREV(h) (*(h)->h_prev)((h)->h_ref)
77#define HLAST(h) (*(h)->h_last)((h)->h_ref)
78#define HCURR(h) (*(h)->h_curr)((h)->h_ref)
79#define HCLEAR(h) (*(h)->h_clear)((h)->h_ref)
75#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str)
76#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str)
77
78#define h_malloc(a) malloc(a)
79#define h_free(a) free(a)
80
81
82private int history_set_num __P((History *, int));
80#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str)
81#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str)
82
83#define h_malloc(a) malloc(a)
84#define h_free(a) free(a)
85
86
87private int history_set_num __P((History *, int));
83private int history_set_fun __P((History *, history_gfun_t,
84 history_gfun_t,
85 history_gfun_t,
86 history_gfun_t,
87 history_gfun_t,
88 history_efun_t,
89 history_efun_t, ptr_t));
88private int history_set_fun __P((History *, History *));
89private int history_load __P((History *, const char *));
90private int history_save __P((History *, const char *));
90private const HistEvent *history_prev_event __P((History *, int));
91private const HistEvent *history_next_event __P((History *, int));
92private const HistEvent *history_next_string __P((History *, const char *));
93private const HistEvent *history_prev_string __P((History *, const char *));
94
95
96/***********************************************************************/
97
98/*
99 * Builtin- history implementation
100 */
101typedef struct hentry_t {
102 HistEvent ev; /* What we return */
103 struct hentry_t *next; /* Next entry */
104 struct hentry_t *prev; /* Previous entry */
105} hentry_t;
106
107typedef struct history_t {
108 hentry_t list; /* Fake list header element */
109 hentry_t *cursor; /* Current element in the list */
110 int max; /* Maximum number of events */
111 int cur; /* Current number of events */
112 int eventno; /* Current event number */
113} history_t;
114
115private const HistEvent *history_def_first __P((ptr_t));
116private const HistEvent *history_def_last __P((ptr_t));
117private const HistEvent *history_def_next __P((ptr_t));
118private const HistEvent *history_def_prev __P((ptr_t));
119private const HistEvent *history_def_curr __P((ptr_t));
120private const HistEvent *history_def_enter __P((ptr_t, const char *));
121private const HistEvent *history_def_add __P((ptr_t, const char *));
122private void history_def_init __P((ptr_t *, int));
91private const HistEvent *history_prev_event __P((History *, int));
92private const HistEvent *history_next_event __P((History *, int));
93private const HistEvent *history_next_string __P((History *, const char *));
94private const HistEvent *history_prev_string __P((History *, const char *));
95
96
97/***********************************************************************/
98
99/*
100 * Builtin- history implementation
101 */
102typedef struct hentry_t {
103 HistEvent ev; /* What we return */
104 struct hentry_t *next; /* Next entry */
105 struct hentry_t *prev; /* Previous entry */
106} hentry_t;
107
108typedef struct history_t {
109 hentry_t list; /* Fake list header element */
110 hentry_t *cursor; /* Current element in the list */
111 int max; /* Maximum number of events */
112 int cur; /* Current number of events */
113 int eventno; /* Current event number */
114} history_t;
115
116private const HistEvent *history_def_first __P((ptr_t));
117private const HistEvent *history_def_last __P((ptr_t));
118private const HistEvent *history_def_next __P((ptr_t));
119private const HistEvent *history_def_prev __P((ptr_t));
120private const HistEvent *history_def_curr __P((ptr_t));
121private const HistEvent *history_def_enter __P((ptr_t, const char *));
122private const HistEvent *history_def_add __P((ptr_t, const char *));
123private void history_def_init __P((ptr_t *, int));
123private void history_def_end __P((ptr_t));
124private void history_def_clear __P((ptr_t));
124private const HistEvent *history_def_insert __P((history_t *, const char *));
125private void history_def_delete __P((history_t *, hentry_t *));
126
127#define history_def_set(p, num) (void) (((history_t *) p)->max = (num))
128
129
130/* history_def_first():
131 * Default function to return the first event in the history.
132 */
133private const HistEvent *
134history_def_first(p)
135 ptr_t p;
136{
137 history_t *h = (history_t *) p;
138 h->cursor = h->list.next;
139 if (h->cursor != &h->list)
140 return &h->cursor->ev;
141 else
142 return NULL;
143}
144
145/* history_def_last():
146 * Default function to return the last event in the history.
147 */
148private const HistEvent *
149history_def_last(p)
150 ptr_t p;
151{
152 history_t *h = (history_t *) p;
153 h->cursor = h->list.prev;
154 if (h->cursor != &h->list)
155 return &h->cursor->ev;
156 else
157 return NULL;
158}
159
160/* history_def_next():
161 * Default function to return the next event in the history.
162 */
163private const HistEvent *
164history_def_next(p)
165 ptr_t p;
166{
167 history_t *h = (history_t *) p;
168
169 if (h->cursor != &h->list)
170 h->cursor = h->cursor->next;
171 else
172 return NULL;
173
174 if (h->cursor != &h->list)
175 return &h->cursor->ev;
176 else
177 return NULL;
178}
179
180
181/* history_def_prev():
182 * Default function to return the previous event in the history.
183 */
184private const HistEvent *
185history_def_prev(p)
186 ptr_t p;
187{
188 history_t *h = (history_t *) p;
189
190 if (h->cursor != &h->list)
191 h->cursor = h->cursor->prev;
192 else
193 return NULL;
194
195 if (h->cursor != &h->list)
196 return &h->cursor->ev;
197 else
198 return NULL;
199}
200
201
202/* history_def_curr():
203 * Default function to return the current event in the history.
204 */
205private const HistEvent *
206history_def_curr(p)
207 ptr_t p;
208{
209 history_t *h = (history_t *) p;
210
211 if (h->cursor != &h->list)
212 return &h->cursor->ev;
213 else
214 return NULL;
215}
216
217
218/* history_def_add():
219 * Append string to element
220 */
221private const HistEvent *
222history_def_add(p, str)
223 ptr_t p;
224 const char *str;
225{
226 history_t *h = (history_t *) p;
227 size_t len;
228 char *s;
229
230 if (h->cursor == &h->list)
231 return (history_def_enter(p, str));
232 len = strlen(h->cursor->ev.str) + strlen(str) + 1;
233 s = (char *) h_malloc(len);
125private const HistEvent *history_def_insert __P((history_t *, const char *));
126private void history_def_delete __P((history_t *, hentry_t *));
127
128#define history_def_set(p, num) (void) (((history_t *) p)->max = (num))
129
130
131/* history_def_first():
132 * Default function to return the first event in the history.
133 */
134private const HistEvent *
135history_def_first(p)
136 ptr_t p;
137{
138 history_t *h = (history_t *) p;
139 h->cursor = h->list.next;
140 if (h->cursor != &h->list)
141 return &h->cursor->ev;
142 else
143 return NULL;
144}
145
146/* history_def_last():
147 * Default function to return the last event in the history.
148 */
149private const HistEvent *
150history_def_last(p)
151 ptr_t p;
152{
153 history_t *h = (history_t *) p;
154 h->cursor = h->list.prev;
155 if (h->cursor != &h->list)
156 return &h->cursor->ev;
157 else
158 return NULL;
159}
160
161/* history_def_next():
162 * Default function to return the next event in the history.
163 */
164private const HistEvent *
165history_def_next(p)
166 ptr_t p;
167{
168 history_t *h = (history_t *) p;
169
170 if (h->cursor != &h->list)
171 h->cursor = h->cursor->next;
172 else
173 return NULL;
174
175 if (h->cursor != &h->list)
176 return &h->cursor->ev;
177 else
178 return NULL;
179}
180
181
182/* history_def_prev():
183 * Default function to return the previous event in the history.
184 */
185private const HistEvent *
186history_def_prev(p)
187 ptr_t p;
188{
189 history_t *h = (history_t *) p;
190
191 if (h->cursor != &h->list)
192 h->cursor = h->cursor->prev;
193 else
194 return NULL;
195
196 if (h->cursor != &h->list)
197 return &h->cursor->ev;
198 else
199 return NULL;
200}
201
202
203/* history_def_curr():
204 * Default function to return the current event in the history.
205 */
206private const HistEvent *
207history_def_curr(p)
208 ptr_t p;
209{
210 history_t *h = (history_t *) p;
211
212 if (h->cursor != &h->list)
213 return &h->cursor->ev;
214 else
215 return NULL;
216}
217
218
219/* history_def_add():
220 * Append string to element
221 */
222private const HistEvent *
223history_def_add(p, str)
224 ptr_t p;
225 const char *str;
226{
227 history_t *h = (history_t *) p;
228 size_t len;
229 char *s;
230
231 if (h->cursor == &h->list)
232 return (history_def_enter(p, str));
233 len = strlen(h->cursor->ev.str) + strlen(str) + 1;
234 s = (char *) h_malloc(len);
234 (void) strcpy(s, h->cursor->ev.str);
235 (void) strcat(s, str);
235 (void)strcpy(s, h->cursor->ev.str); /* XXX strcpy is safe */
236 (void)strcat(s, str); /* XXX strcat is safe */
236 h_free((ptr_t) h->cursor->ev.str);
237 h->cursor->ev.str = s;
238 return &h->cursor->ev;
239}
240
241
242/* history_def_delete():
243 * Delete element hp of the h list
244 */
245private void
246history_def_delete(h, hp)
247 history_t *h;
248 hentry_t *hp;
249{
250 if (hp == &h->list)
251 abort();
252 hp->prev->next = hp->next;
253 hp->next->prev = hp->prev;
254 h_free((ptr_t) hp->ev.str);
255 h_free(hp);
256 h->cur--;
257}
258
259
260/* history_def_insert():
261 * Insert element with string str in the h list
262 */
263private const HistEvent *
264history_def_insert(h, str)
265 history_t *h;
266 const char *str;
267{
268 h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
269 h->cursor->ev.str = strdup(str);
270 h->cursor->next = h->list.next;
271 h->cursor->prev = &h->list;
272 h->list.next->prev = h->cursor;
273 h->list.next = h->cursor;
274 h->cur++;
275
276 return &h->cursor->ev;
277}
278
279
280/* history_def_enter():
281 * Default function to enter an item in the history
282 */
283private const HistEvent *
284history_def_enter(p, str)
285 ptr_t p;
286 const char *str;
287{
288 history_t *h = (history_t *) p;
289 const HistEvent *ev;
290
291
292 ev = history_def_insert(h, str);
293 ((HistEvent*) ev)->num = ++h->eventno;
294
295 /*
296 * Always keep at least one entry.
297 * This way we don't have to check for the empty list.
298 */
299 while (h->cur > h->max + 1)
300 history_def_delete(h, h->list.prev);
301 return ev;
302}
303
304
305/* history_def_init():
306 * Default history initialization function
307 */
308private void
309history_def_init(p, n)
310 ptr_t *p;
311 int n;
312{
313 history_t *h = (history_t *) h_malloc(sizeof(history_t));
314 if (n <= 0)
315 n = 0;
316 h->eventno = 0;
317 h->cur = 0;
318 h->max = n;
319 h->list.next = h->list.prev = &h->list;
320 h->list.ev.str = NULL;
321 h->list.ev.num = 0;
322 h->cursor = &h->list;
323 *p = (ptr_t) h;
324}
325
326
237 h_free((ptr_t) h->cursor->ev.str);
238 h->cursor->ev.str = s;
239 return &h->cursor->ev;
240}
241
242
243/* history_def_delete():
244 * Delete element hp of the h list
245 */
246private void
247history_def_delete(h, hp)
248 history_t *h;
249 hentry_t *hp;
250{
251 if (hp == &h->list)
252 abort();
253 hp->prev->next = hp->next;
254 hp->next->prev = hp->prev;
255 h_free((ptr_t) hp->ev.str);
256 h_free(hp);
257 h->cur--;
258}
259
260
261/* history_def_insert():
262 * Insert element with string str in the h list
263 */
264private const HistEvent *
265history_def_insert(h, str)
266 history_t *h;
267 const char *str;
268{
269 h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t));
270 h->cursor->ev.str = strdup(str);
271 h->cursor->next = h->list.next;
272 h->cursor->prev = &h->list;
273 h->list.next->prev = h->cursor;
274 h->list.next = h->cursor;
275 h->cur++;
276
277 return &h->cursor->ev;
278}
279
280
281/* history_def_enter():
282 * Default function to enter an item in the history
283 */
284private const HistEvent *
285history_def_enter(p, str)
286 ptr_t p;
287 const char *str;
288{
289 history_t *h = (history_t *) p;
290 const HistEvent *ev;
291
292
293 ev = history_def_insert(h, str);
294 ((HistEvent*) ev)->num = ++h->eventno;
295
296 /*
297 * Always keep at least one entry.
298 * This way we don't have to check for the empty list.
299 */
300 while (h->cur > h->max + 1)
301 history_def_delete(h, h->list.prev);
302 return ev;
303}
304
305
306/* history_def_init():
307 * Default history initialization function
308 */
309private void
310history_def_init(p, n)
311 ptr_t *p;
312 int n;
313{
314 history_t *h = (history_t *) h_malloc(sizeof(history_t));
315 if (n <= 0)
316 n = 0;
317 h->eventno = 0;
318 h->cur = 0;
319 h->max = n;
320 h->list.next = h->list.prev = &h->list;
321 h->list.ev.str = NULL;
322 h->list.ev.num = 0;
323 h->cursor = &h->list;
324 *p = (ptr_t) h;
325}
326
327
327/* history_def_end():
328/* history_def_clear():
328 * Default history cleanup function
329 */
330private void
329 * Default history cleanup function
330 */
331private void
331history_def_end(p)
332history_def_clear(p)
332 ptr_t p;
333{
334 history_t *h = (history_t *) p;
335
336 while (h->list.prev != &h->list)
337 history_def_delete(h, h->list.prev);
333 ptr_t p;
334{
335 history_t *h = (history_t *) p;
336
337 while (h->list.prev != &h->list)
338 history_def_delete(h, h->list.prev);
339 h->eventno = 0;
340 h->cur = 0;
338}
339
340/************************************************************************/
341
342/* history_init():
343 * Initialization function.
344 */
345public History *
346history_init()
347{
348 History *h = (History *) h_malloc(sizeof(History));
349
350 history_def_init(&h->h_ref, 0);
351
352 h->h_next = history_def_next;
353 h->h_first = history_def_first;
354 h->h_last = history_def_last;
355 h->h_prev = history_def_prev;
356 h->h_curr = history_def_curr;
341}
342
343/************************************************************************/
344
345/* history_init():
346 * Initialization function.
347 */
348public History *
349history_init()
350{
351 History *h = (History *) h_malloc(sizeof(History));
352
353 history_def_init(&h->h_ref, 0);
354
355 h->h_next = history_def_next;
356 h->h_first = history_def_first;
357 h->h_last = history_def_last;
358 h->h_prev = history_def_prev;
359 h->h_curr = history_def_curr;
360 h->h_clear = history_def_clear;
357 h->h_enter = history_def_enter;
358 h->h_add = history_def_add;
359
360 return h;
361}
362
363
364/* history_end():
365 * clean up history;
366 */
367public void
368history_end(h)
369 History *h;
370{
371 if (h->h_next == history_def_next)
361 h->h_enter = history_def_enter;
362 h->h_add = history_def_add;
363
364 return h;
365}
366
367
368/* history_end():
369 * clean up history;
370 */
371public void
372history_end(h)
373 History *h;
374{
375 if (h->h_next == history_def_next)
372 history_def_end(h->h_ref);
376 history_def_clear(h->h_ref);
373}
374
375
376
377/* history_set_num():
378 * Set history number of events
379 */
380private int
381history_set_num(h, num)
382 History *h;
383 int num;
384{
385 if (h->h_next != history_def_next || num < 0)
386 return -1;
387 history_def_set(h->h_ref, num);
388 return 0;
389}
390
391
392/* history_set_fun():
393 * Set history functions
394 */
395private int
377}
378
379
380
381/* history_set_num():
382 * Set history number of events
383 */
384private int
385history_set_num(h, num)
386 History *h;
387 int num;
388{
389 if (h->h_next != history_def_next || num < 0)
390 return -1;
391 history_def_set(h->h_ref, num);
392 return 0;
393}
394
395
396/* history_set_fun():
397 * Set history functions
398 */
399private int
396history_set_fun(h, first, next, last, prev, curr, enter, add, ptr)
397 History *h;
398 history_gfun_t first, next, last, prev, curr;
399 history_efun_t enter, add;
400 ptr_t ptr;
400history_set_fun(h, nh)
401 History *h, *nh;
401{
402{
402 if (first == NULL || next == NULL ||
403 last == NULL || prev == NULL || curr == NULL ||
404 enter == NULL || add == NULL ||
405 ptr == NULL ) {
403 if (nh->h_first == NULL || nh->h_next == NULL ||
404 nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL ||
405 nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
406 nh->h_ref == NULL) {
406 if (h->h_next != history_def_next) {
407 history_def_init(&h->h_ref, 0);
408 h->h_first = history_def_first;
409 h->h_next = history_def_next;
410 h->h_last = history_def_last;
411 h->h_prev = history_def_prev;
412 h->h_curr = history_def_curr;
407 if (h->h_next != history_def_next) {
408 history_def_init(&h->h_ref, 0);
409 h->h_first = history_def_first;
410 h->h_next = history_def_next;
411 h->h_last = history_def_last;
412 h->h_prev = history_def_prev;
413 h->h_curr = history_def_curr;
414 h->h_clear = history_def_clear;
413 h->h_enter = history_def_enter;
414 h->h_add = history_def_add;
415 }
416 return -1;
417 }
418
419 if (h->h_next == history_def_next)
415 h->h_enter = history_def_enter;
416 h->h_add = history_def_add;
417 }
418 return -1;
419 }
420
421 if (h->h_next == history_def_next)
420 history_def_end(h->h_ref);
422 history_def_clear(h->h_ref);
421
423
422 h->h_next = next;
423 h->h_first = first;
424 h->h_enter = enter;
425 h->h_add = add;
424 h->h_first = nh->h_first;
425 h->h_next = nh->h_next;
426 h->h_last = nh->h_last;
427 h->h_prev = nh->h_prev;
428 h->h_curr = nh->h_curr;
429 h->h_clear = nh->h_clear;
430 h->h_enter = nh->h_enter;
431 h->h_add = nh->h_add;
426 return 0;
427}
428
429
432 return 0;
433}
434
435
436/* history_load():
437 * History load function
438 */
439private int
440history_load(h, fname)
441 History *h;
442 const char *fname;
443{
444 FILE *fp;
445 char *line;
446 size_t sz;
447 int i = -1;
448
449 if ((fp = fopen(fname, "r")) == NULL)
450 return i;
451
452 if ((line = fgetln(fp, &sz)) == NULL)
453 goto done;
454
455 if (strncmp(line, hist_cookie, sz) != 0)
456 goto done;
457
458 for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
459 char c = line[sz];
460 line[sz] = '\0';
461 HENTER(h, line);
462 line[sz] = c;
463 }
464
465done:
466 (void) fclose(fp);
467 return i;
468}
469
470
471/* history_save():
472 * History save function
473 */
474private int
475history_save(h, fname)
476 History *h;
477 const char *fname;
478{
479 FILE *fp;
480 const HistEvent *ev;
481 int i = 0;
482
483 if ((fp = fopen(fname, "w")) == NULL)
484 return -1;
485
486 (void) fputs(hist_cookie, fp);
487 for (ev = HLAST(h); ev != NULL; ev = HPREV(h), i++)
488 (void) fprintf(fp, "%s", ev->str);
489 (void) fclose(fp);
490 return i;
491}
492
493
430/* history_prev_event():
431 * Find the previous event, with number given
432 */
433private const HistEvent *
434history_prev_event(h, num)
435 History *h;
436 int num;
437{
438 const HistEvent *ev;
439 for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
440 if (ev->num == num)
441 return ev;
442 return NULL;
443}
444
445
446/* history_next_event():
447 * Find the next event, with number given
448 */
449private const HistEvent *
450history_next_event(h, num)
451 History *h;
452 int num;
453{
454 const HistEvent *ev;
455 for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
456 if (ev->num == num)
457 return ev;
458 return NULL;
459}
460
461
462/* history_prev_string():
463 * Find the previous event beginning with string
464 */
465private const HistEvent *
466history_prev_string(h, str)
467 History *h;
468 const char* str;
469{
470 const HistEvent *ev;
471 size_t len = strlen(str);
472
473 for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
474 if (strncmp(str, ev->str, len) == 0)
475 return ev;
476 return NULL;
477}
478
479
480/* history_next_string():
481 * Find the next event beginning with string
482 */
483private const HistEvent *
484history_next_string(h, str)
485 History *h;
486 const char* str;
487{
488 const HistEvent *ev;
489 size_t len = strlen(str);
490
491 for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
492 if (strncmp(str, ev->str, len) == 0)
493 return ev;
494 return NULL;
495}
496
497
498/* history():
499 * User interface to history functions.
500 */
501const HistEvent *
502#if __STDC__
503history(History *h, int fun, ...)
504#else
505history(va_alist)
506 va_dcl
507#endif
508{
509 va_list va;
510 const HistEvent *ev = NULL;
511 const char *str;
494/* history_prev_event():
495 * Find the previous event, with number given
496 */
497private const HistEvent *
498history_prev_event(h, num)
499 History *h;
500 int num;
501{
502 const HistEvent *ev;
503 for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
504 if (ev->num == num)
505 return ev;
506 return NULL;
507}
508
509
510/* history_next_event():
511 * Find the next event, with number given
512 */
513private const HistEvent *
514history_next_event(h, num)
515 History *h;
516 int num;
517{
518 const HistEvent *ev;
519 for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
520 if (ev->num == num)
521 return ev;
522 return NULL;
523}
524
525
526/* history_prev_string():
527 * Find the previous event beginning with string
528 */
529private const HistEvent *
530history_prev_string(h, str)
531 History *h;
532 const char* str;
533{
534 const HistEvent *ev;
535 size_t len = strlen(str);
536
537 for (ev = HCURR(h); ev != NULL; ev = HNEXT(h))
538 if (strncmp(str, ev->str, len) == 0)
539 return ev;
540 return NULL;
541}
542
543
544/* history_next_string():
545 * Find the next event beginning with string
546 */
547private const HistEvent *
548history_next_string(h, str)
549 History *h;
550 const char* str;
551{
552 const HistEvent *ev;
553 size_t len = strlen(str);
554
555 for (ev = HCURR(h); ev != NULL; ev = HPREV(h))
556 if (strncmp(str, ev->str, len) == 0)
557 return ev;
558 return NULL;
559}
560
561
562/* history():
563 * User interface to history functions.
564 */
565const HistEvent *
566#if __STDC__
567history(History *h, int fun, ...)
568#else
569history(va_alist)
570 va_dcl
571#endif
572{
573 va_list va;
574 const HistEvent *ev = NULL;
575 const char *str;
512 static const HistEvent sev = { 0, "" };
576 static HistEvent sev = { 0, "" };
513
514#if __STDC__
515 va_start(va, fun);
516#else
517 History *h;
518 int fun;
519 va_start(va);
520 h = va_arg(va, History *);
521 fun = va_arg(va, int);
522#endif
523
524 switch (fun) {
525 case H_ADD:
526 str = va_arg(va, const char *);
527 ev = HADD(h, str);
528 break;
529
530 case H_ENTER:
531 str = va_arg(va, const char *);
532 ev = HENTER(h, str);
533 break;
534
535 case H_FIRST:
536 ev = HFIRST(h);
537 break;
538
539 case H_NEXT:
540 ev = HNEXT(h);
541 break;
542
543 case H_LAST:
544 ev = HLAST(h);
545 break;
546
547 case H_PREV:
548 ev = HPREV(h);
549 break;
550
551 case H_CURR:
552 ev = HCURR(h);
553 break;
554
577
578#if __STDC__
579 va_start(va, fun);
580#else
581 History *h;
582 int fun;
583 va_start(va);
584 h = va_arg(va, History *);
585 fun = va_arg(va, int);
586#endif
587
588 switch (fun) {
589 case H_ADD:
590 str = va_arg(va, const char *);
591 ev = HADD(h, str);
592 break;
593
594 case H_ENTER:
595 str = va_arg(va, const char *);
596 ev = HENTER(h, str);
597 break;
598
599 case H_FIRST:
600 ev = HFIRST(h);
601 break;
602
603 case H_NEXT:
604 ev = HNEXT(h);
605 break;
606
607 case H_LAST:
608 ev = HLAST(h);
609 break;
610
611 case H_PREV:
612 ev = HPREV(h);
613 break;
614
615 case H_CURR:
616 ev = HCURR(h);
617 break;
618
619 case H_CLEAR:
620 HCLEAR(h);
621 break;
622
623 case H_LOAD:
624 sev.num = history_load(h, va_arg(va, const char *));
625 ev = &sev;
626 break;
627
628 case H_SAVE:
629 sev.num = history_save(h, va_arg(va, const char *));
630 ev = &sev;
631 break;
632
555 case H_PREV_EVENT:
556 ev = history_prev_event(h, va_arg(va, int));
557 break;
558
559 case H_NEXT_EVENT:
560 ev = history_next_event(h, va_arg(va, int));
561 break;
562
563 case H_PREV_STR:
564 ev = history_prev_string(h, va_arg(va, const char*));
565 break;
566
567 case H_NEXT_STR:
568 ev = history_next_string(h, va_arg(va, const char*));
569 break;
570
571 case H_EVENT:
633 case H_PREV_EVENT:
634 ev = history_prev_event(h, va_arg(va, int));
635 break;
636
637 case H_NEXT_EVENT:
638 ev = history_next_event(h, va_arg(va, int));
639 break;
640
641 case H_PREV_STR:
642 ev = history_prev_string(h, va_arg(va, const char*));
643 break;
644
645 case H_NEXT_STR:
646 ev = history_next_string(h, va_arg(va, const char*));
647 break;
648
649 case H_EVENT:
572 if (history_set_num(h, va_arg(va, int)) == 0)
650 if (history_set_num(h, va_arg(va, int)) == 0) {
651 sev.num = -1;
573 ev = &sev;
652 ev = &sev;
653 }
574 break;
575
576 case H_FUNC:
577 {
654 break;
655
656 case H_FUNC:
657 {
578 history_gfun_t first = va_arg(va, history_gfun_t);
579 history_gfun_t next = va_arg(va, history_gfun_t);
580 history_gfun_t last = va_arg(va, history_gfun_t);
581 history_gfun_t prev = va_arg(va, history_gfun_t);
582 history_gfun_t curr = va_arg(va, history_gfun_t);
583 history_efun_t enter = va_arg(va, history_efun_t);
584 history_efun_t add = va_arg(va, history_efun_t);
585 ptr_t ptr = va_arg(va, ptr_t);
658 History hf;
659 hf.h_ref = va_arg(va, ptr_t);
660 hf.h_first = va_arg(va, history_gfun_t);
661 hf.h_next = va_arg(va, history_gfun_t);
662 hf.h_last = va_arg(va, history_gfun_t);
663 hf.h_prev = va_arg(va, history_gfun_t);
664 hf.h_curr = va_arg(va, history_gfun_t);
665 hf.h_clear = va_arg(va, history_vfun_t);
666 hf.h_enter = va_arg(va, history_efun_t);
667 hf.h_add = va_arg(va, history_efun_t);
586
668
587 if (history_set_fun(h, first, next, last, prev,
588 curr, enter, add, ptr) == 0)
669 if (history_set_fun(h, &hf) == 0) {
670 sev.num = -1;
589 ev = &sev;
671 ev = &sev;
672 }
590 }
591 break;
592
593 case H_END:
594 history_end(h);
595 break;
596
597 default:
598 break;
599 }
600 va_end(va);
601 return ev;
602}
673 }
674 break;
675
676 case H_END:
677 history_end(h);
678 break;
679
680 default:
681 break;
682 }
683 va_end(va);
684 return ev;
685}