Wed Jul 27 02:23:30 2011 UTC ()
- don't leave cursor dangling on memory failure or after clearing the list
- compute the string length to be strvis'ed after the string is encoded


(christos)
diff -r1.38 -r1.39 src/lib/libedit/history.c

cvs diff -r1.38 -r1.39 src/lib/libedit/history.c (switch to unified diff)

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