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