history.cxx

Go to the documentation of this file.
00001 // @(#)root/editline:$Id: history.cxx 35471 2010-09-20 16:35:01Z rdm $
00002 // Author: Mary-Louise Gill, 2009
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 /*      $NetBSD: history.c,v 1.17 2001/03/20 00:08:31 christos Exp $    */
00013 
00014 /*-
00015  * Copyright (c) 1992, 1993
00016  *      The Regents of the University of California.  All rights reserved.
00017  *
00018  * This code is derived from software contributed to Berkeley by
00019  * Christos Zoulas of Cornell University.
00020  *
00021  * Redistribution and use in source and binary forms, with or without
00022  * modification, are permitted provided that the following conditions
00023  * are met:
00024  * 1. Redistributions of source code must retain the above copyright
00025  *    notice, this list of conditions and the following disclaimer.
00026  * 2. Redistributions in binary form must reproduce the above copyright
00027  *    notice, this list of conditions and the following disclaimer in the
00028  *    documentation and/or other materials provided with the distribution.
00029  * 3. Neither the name of the University nor the names of its contributors
00030  *    may be used to endorse or promote products derived from this software
00031  *    without specific prior written permission.
00032  *
00033  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00034  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00035  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00036  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00037  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00038  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00039  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00040  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00041  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00042  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00043  * SUCH DAMAGE.
00044  */
00045 
00046 #include "compat.h"
00047 
00048 /*
00049  * hist.c: History access functions
00050  */
00051 #include "sys.h"
00052 
00053 #include <string.h>
00054 #include <stdlib.h>
00055 #include <stdarg.h>
00056 #ifdef HAVE_VIS_H
00057 # include <vis.h>
00058 #endif
00059 #include <sys/stat.h>
00060 
00061 #include <string>
00062 #include <fstream>
00063 
00064 #include "histedit.h"
00065 
00066 typedef int (*HistoryGFun_t)(ptr_t, HistEvent_t*);
00067 typedef int (*HistoryEFun_t)(ptr_t, HistEvent_t*, const char*);
00068 typedef void (*HistoryVFun_t)(ptr_t, HistEvent_t*);
00069 typedef int (*HistorySFun_t)(ptr_t, HistEvent_t*, const int);
00070 
00071 struct HistoryFcns_t {
00072    ptr_t fRef;                 /* Argument for history fcns      */
00073    int fEnt;                   /* Last entry point for history   */
00074    HistoryGFun_t fFirst;      /* Get the first element   */
00075    HistoryGFun_t fNext;       /* Get the next element            */
00076    HistoryGFun_t fLast;       /* Get the last element            */
00077    HistoryGFun_t fPrev;       /* Get the previous element        */
00078    HistoryGFun_t fCurr;       /* Get the current element         */
00079    HistorySFun_t fSet;        /* Set the current element         */
00080    HistoryVFun_t fClear;      /* Clear the history list  */
00081    HistoryEFun_t fEnter;      /* Add an element          */
00082    HistoryEFun_t fAdd;        /* Append to an element            */
00083 };
00084 #define HNEXT(h, ev) (*(h)->fNext)((h)->fRef, ev)
00085 #define HFIRST(h, ev) (*(h)->fFirst)((h)->fRef, ev)
00086 #define HPREV(h, ev) (*(h)->fPrev)((h)->fRef, ev)
00087 #define HLAST(h, ev) (*(h)->fLast)((h)->fRef, ev)
00088 #define HCURR(h, ev) (*(h)->fCurr)((h)->fRef, ev)
00089 #define HSET(h, ev, n) (*(h)->fSet)((h)->fRef, ev, n)
00090 #define HCLEAR(h, ev) (*(h)->fClear)((h)->fRef, ev)
00091 #define HENTER(h, ev, str) (*(h)->fEnter)((h)->fRef, ev, str)
00092 #define HADD(h, ev, str) (*(h)->fAdd)((h)->fRef, ev, str)
00093 
00094 #define h_malloc(a) malloc(a)
00095 #define h_realloc(a, b) realloc((a), (b))
00096 #define h_free(a) free(a)
00097 
00098 
00099 el_private int history_setsize(HistoryFcns_t*, HistEvent_t*, int);
00100 el_private int history_getsize(HistoryFcns_t*, HistEvent_t*);
00101 el_private int history_set_fun(HistoryFcns_t*, HistoryFcns_t*);
00102 el_private int history_load(HistoryFcns_t*, const char*);
00103 el_private int history_save(HistoryFcns_t*, const char*);
00104 el_private int history_prev_event(HistoryFcns_t*, HistEvent_t*, int);
00105 el_private int history_next_event(HistoryFcns_t*, HistEvent_t*, int);
00106 el_private int history_next_string(HistoryFcns_t*, HistEvent_t*, const char*);
00107 el_private int history_prev_string(HistoryFcns_t*, HistEvent_t*, const char*);
00108 
00109 
00110 /***********************************************************************/
00111 
00112 /*
00113  * Builtin- history implementation
00114  */
00115 struct HEntry_t {
00116    HistEvent_t fEv;                /* What we return             */
00117    struct HEntry_t* fNext;       /* Next entry                   */
00118    struct HEntry_t* fPrev;       /* Previous entry               */
00119 };
00120 
00121 struct History_t {
00122    HEntry_t fList;               /* Fake list header element     */
00123    HEntry_t* fCursor;            /* Current element in the list  */
00124    int fMax;                     /* Maximum number of events     */
00125    int fCur;                     /* Current number of events     */
00126    int fEventId;                 /* For generation of unique event id    */
00127 };
00128 
00129 el_private int history_def_first(ptr_t, HistEvent_t*);
00130 el_private int history_def_last(ptr_t, HistEvent_t*);
00131 el_private int history_def_next(ptr_t, HistEvent_t*);
00132 el_private int history_def_prev(ptr_t, HistEvent_t*);
00133 el_private int history_def_curr(ptr_t, HistEvent_t*);
00134 el_private int history_def_set(ptr_t, HistEvent_t *, const int n);
00135 el_private int history_def_enter(ptr_t, HistEvent_t *, const char*);
00136 el_private int history_def_add(ptr_t, HistEvent_t *, const char*);
00137 el_private void history_def_init(ptr_t*, HistEvent_t*, int);
00138 el_private void history_def_clear(ptr_t, HistEvent_t*);
00139 el_private int history_def_insert(History_t*, HistEvent_t*, const char*);
00140 el_private void history_def_delete(History_t*, HistEvent_t*, HEntry_t*);
00141 
00142 #define history_def_setsize(p, num) (void) (((History_t*) p)->fMax = (num))
00143 #define history_def_getsize(p) (((History_t*) p)->fCur)
00144 
00145 #define he_strerror(code) he_errlist[code]
00146 #define he_seterrev(evp, code) { \
00147    evp->fNum = code; \
00148    evp->fStr = he_strerror(code); \
00149 }
00150 
00151 /* error messages */
00152 static const char* const he_errlist[] = {
00153    "OK",
00154    "unknown error",
00155    "malloc() failed",
00156    "first event not found",
00157    "last event not found",
00158    "empty list",
00159    "no next event",
00160    "no previous event",
00161    "current event is invalid",
00162    "event not found",
00163    "can't read history from file",
00164    "can't write history",
00165    "required parameter(s) not supplied",
00166    "history size negative",
00167    "function not allowed with other history-functions-set the default",
00168    "bad parameters"
00169 };
00170 /* error codes */
00171 #define _HE_OK 0
00172 #define _HE_UNKNOWN 1
00173 #define _HE_MALLOC_FAILED 2
00174 #define _HE_FIRST_NOTFOUND 3
00175 #define _HE_LAST_NOTFOUND 4
00176 #define _HE_EMPTY_LIST 5
00177 #define _HE_END_REACHED 6
00178 #define _HE_START_REACHED 7
00179 #define _HE_CURR_INVALID 8
00180 #define _HE_NOT_FOUND 9
00181 #define _HE_HIST_READ 10
00182 #define _HE_HIST_WRITE 11
00183 #define _HE_PARAM_MISSING 12
00184 #define _HE_SIZE_NEGATIVE 13
00185 #define _HE_NOT_ALLOWED 14
00186 #define _HE_BAD_PARAM 15
00187 
00188 /* history_def_first():
00189  *      Default function to return the first event in the history.
00190  */
00191 el_private int
00192 history_def_first(ptr_t p, HistEvent_t* ev) {
00193    History_t* h = (History_t*) p;
00194 
00195    h->fCursor = h->fList.fNext;
00196 
00197    if (h->fCursor != &h->fList) {
00198       *ev = h->fCursor->fEv;
00199    } else {
00200       he_seterrev(ev, _HE_FIRST_NOTFOUND);
00201       return -1;
00202    }
00203 
00204    return 0;
00205 }
00206 
00207 
00208 /* history_def_last():
00209  *      Default function to return the last event in the history.
00210  */
00211 el_private int
00212 history_def_last(ptr_t p, HistEvent_t* ev) {
00213    History_t* h = (History_t*) p;
00214 
00215    h->fCursor = h->fList.fPrev;
00216 
00217    if (h->fCursor != &h->fList) {
00218       *ev = h->fCursor->fEv;
00219    } else {
00220       he_seterrev(ev, _HE_LAST_NOTFOUND);
00221       return -1;
00222    }
00223 
00224    return 0;
00225 }
00226 
00227 
00228 /* history_def_next():
00229  *      Default function to return the next event in the history.
00230  */
00231 el_private int
00232 history_def_next(ptr_t p, HistEvent_t* ev) {
00233    History_t* h = (History_t*) p;
00234 
00235    if (h->fCursor != &h->fList) {
00236       h->fCursor = h->fCursor->fNext;
00237    } else {
00238       he_seterrev(ev, _HE_EMPTY_LIST);
00239       return -1;
00240    }
00241 
00242    if (h->fCursor != &h->fList) {
00243       *ev = h->fCursor->fEv;
00244    } else {
00245       he_seterrev(ev, _HE_END_REACHED);
00246       return -1;
00247    }
00248 
00249    return 0;
00250 } // history_def_next
00251 
00252 
00253 /* history_def_prev():
00254  *      Default function to return the previous event in the history.
00255  */
00256 el_private int
00257 history_def_prev(ptr_t p, HistEvent_t* ev) {
00258    History_t* h = (History_t*) p;
00259 
00260    if (h->fCursor != &h->fList) {
00261       h->fCursor = h->fCursor->fPrev;
00262    } else {
00263       he_seterrev(ev,
00264                   (h->fCur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
00265       return -1;
00266    }
00267 
00268    if (h->fCursor != &h->fList) {
00269       *ev = h->fCursor->fEv;
00270    } else {
00271       he_seterrev(ev, _HE_START_REACHED);
00272       return -1;
00273    }
00274 
00275    return 0;
00276 } // history_def_prev
00277 
00278 
00279 /* history_def_curr():
00280  *      Default function to return the current event in the history.
00281  */
00282 el_private int
00283 history_def_curr(ptr_t p, HistEvent_t* ev) {
00284    History_t* h = (History_t*) p;
00285 
00286    if (h->fCursor != &h->fList) {
00287       *ev = h->fCursor->fEv;
00288    } else {
00289       he_seterrev(ev,
00290                   (h->fCur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
00291       return -1;
00292    }
00293 
00294    return 0;
00295 }
00296 
00297 
00298 /* history_def_set():
00299  *      Default function to set the current event in the history to the
00300  *      given one.
00301  */
00302 el_private int
00303 history_def_set(ptr_t p, HistEvent_t* ev, const int n) {
00304    History_t* h = (History_t*) p;
00305 
00306    if (h->fCur == 0) {
00307       he_seterrev(ev, _HE_EMPTY_LIST);
00308       return -1;
00309    }
00310 
00311    if (h->fCursor == &h->fList || h->fCursor->fEv.fNum != n) {
00312       for (h->fCursor = h->fList.fNext; h->fCursor != &h->fList;
00313            h->fCursor = h->fCursor->fNext) {
00314          if (h->fCursor->fEv.fNum == n) {
00315             break;
00316          }
00317       }
00318    }
00319 
00320    if (h->fCursor == &h->fList) {
00321       he_seterrev(ev, _HE_NOT_FOUND);
00322       return -1;
00323    }
00324    return 0;
00325 } // history_def_set
00326 
00327 
00328 /* history_def_add():
00329  *      Append string to element
00330  */
00331 el_private int
00332 history_def_add(ptr_t p, HistEvent_t* ev, const char* str) {
00333    History_t* h = (History_t*) p;
00334    size_t len;
00335    char* s;
00336 
00337    if (h->fCursor == &h->fList) {
00338       return history_def_enter(p, ev, str);
00339    }
00340    len = strlen(h->fCursor->fEv.fStr) + strlen(str) + 1;
00341    s = (char*) h_malloc(len);
00342 
00343    if (!s) {
00344       he_seterrev(ev, _HE_MALLOC_FAILED);
00345       return -1;
00346    }
00347    (void) strlcpy(s, h->fCursor->fEv.fStr, len);
00348    (void) strlcat(s, str, len);
00349    /* LINTED const cast */
00350    h_free((ptr_t) h->fCursor->fEv.fStr);
00351    h->fCursor->fEv.fStr = s;
00352    *ev = h->fCursor->fEv;
00353    return 0;
00354 } // history_def_add
00355 
00356 
00357 /* history_def_delete():
00358  *      Delete element hp of the h list
00359  */
00360 /* ARGSUSED */
00361 el_private void
00362 history_def_delete(History_t* h, HistEvent_t* /*ev*/, HEntry_t* hp) {
00363    if (hp == &h->fList) {
00364       abort();
00365    }
00366    hp->fPrev->fNext = hp->fNext;
00367    hp->fNext->fPrev = hp->fPrev;
00368    /* LINTED const cast */
00369    h_free((ptr_t) hp->fEv.fStr);
00370    h_free(hp);
00371    h->fCur--;
00372 }
00373 
00374 
00375 /* history_def_insert():
00376  *      Insert element with string str in the h list
00377  */
00378 el_private int
00379 history_def_insert(History_t* h, HistEvent_t* ev, const char* str) {
00380    h->fCursor = (HEntry_t*) h_malloc(sizeof(HEntry_t));
00381 
00382    if (h->fCursor) {
00383       h->fCursor->fEv.fStr = strdup(str);
00384    }
00385 
00386    if (!h->fCursor || !h->fCursor->fEv.fStr) {
00387       he_seterrev(ev, _HE_MALLOC_FAILED);
00388       return -1;
00389    }
00390    h->fCursor->fEv.fNum = ++h->fEventId;
00391    h->fCursor->fNext = h->fList.fNext;
00392    h->fCursor->fPrev = &h->fList;
00393    h->fList.fNext->fPrev = h->fCursor;
00394    h->fList.fNext = h->fCursor;
00395    h->fCur++;
00396 
00397    *ev = h->fCursor->fEv;
00398    return 0;
00399 } // history_def_insert
00400 
00401 
00402 /* history_def_enter():
00403  *      Default function to enter an item in the history
00404  */
00405 el_private int
00406 history_def_enter(ptr_t p, HistEvent_t* ev, const char* str) {
00407    History_t* h = (History_t*) p;
00408 
00409    if (history_def_insert(h, ev, str) == -1) {
00410       return -1;                /* error, keep error message */
00411 
00412    }
00413 
00414    /*
00415     * Always keep at least one entry.
00416     * This way we don't have to check for the empty list.
00417     */
00418    while (h->fCur - 1 > h->fMax)
00419       history_def_delete(h, ev, h->fList.fPrev);
00420 
00421    return 0;
00422 }
00423 
00424 
00425 /* history_def_init():
00426  *      Default history initialization function
00427  */
00428 /* ARGSUSED */
00429 el_private void
00430 history_def_init(ptr_t* p, HistEvent_t* /*ev*/, int n) {
00431    History_t* h = (History_t*) h_malloc(sizeof(History_t));
00432 
00433    if (n <= 0) {
00434       n = 0;
00435    }
00436    h->fEventId = 0;
00437    h->fCur = 0;
00438    h->fMax = n;
00439    h->fList.fNext = h->fList.fPrev = &h->fList;
00440    h->fList.fEv.fStr = NULL;
00441    h->fList.fEv.fNum = 0;
00442    h->fCursor = &h->fList;
00443    *p = (ptr_t) h;
00444 }
00445 
00446 
00447 /* history_def_clear():
00448  *      Default history cleanup function
00449  */
00450 el_private void
00451 history_def_clear(ptr_t p, HistEvent_t* ev) {
00452    History_t* h = (History_t*) p;
00453 
00454    while (h->fList.fPrev != &h->fList)
00455       history_def_delete(h, ev, h->fList.fPrev);
00456    h->fEventId = 0;
00457    h->fCur = 0;
00458 }
00459 
00460 
00461 /************************************************************************/
00462 
00463 /* history_init():
00464  *      Initialization function.
00465  */
00466 el_public HistoryFcns_t*
00467 history_init(void) {
00468    HistoryFcns_t* h = (HistoryFcns_t*) h_malloc(sizeof(HistoryFcns_t));
00469    HistEvent_t ev;
00470 
00471    history_def_init(&h->fRef, &ev, 0);
00472    h->fEnt = -1;
00473    h->fNext = history_def_next;
00474    h->fFirst = history_def_first;
00475    h->fLast = history_def_last;
00476    h->fPrev = history_def_prev;
00477    h->fCurr = history_def_curr;
00478    h->fSet = history_def_set;
00479    h->fClear = history_def_clear;
00480    h->fEnter = history_def_enter;
00481    h->fAdd = history_def_add;
00482 
00483    return h;
00484 } // history_init
00485 
00486 
00487 /* history_end():
00488  *      clean up history;
00489  */
00490 el_public void
00491 history_end(HistoryFcns_t* h) {
00492    HistEvent_t ev;
00493 
00494    if (h->fNext == history_def_next) {
00495       history_def_clear(h->fRef, &ev);
00496    }
00497 }
00498 
00499 
00500 /* history_setsize():
00501  *      Set history number of events
00502  */
00503 el_private int
00504 history_setsize(HistoryFcns_t* h, HistEvent_t* ev, int num) {
00505    if (h->fNext != history_def_next) {
00506       he_seterrev(ev, _HE_NOT_ALLOWED);
00507       return -1;
00508    }
00509 
00510    if (num < 0) {
00511       he_seterrev(ev, _HE_BAD_PARAM);
00512       return -1;
00513    }
00514    history_def_setsize(h->fRef, num);
00515    return 0;
00516 }
00517 
00518 
00519 /* history_getsize():
00520  *      Get number of events currently in history
00521  */
00522 el_private int
00523 history_getsize(HistoryFcns_t* h, HistEvent_t* ev) {
00524    int retval = 0;
00525 
00526    if (h->fNext != history_def_next) {
00527       he_seterrev(ev, _HE_NOT_ALLOWED);
00528       return -1;
00529    }
00530    retval = history_def_getsize(h->fRef);
00531 
00532    if (retval < -1) {
00533       he_seterrev(ev, _HE_SIZE_NEGATIVE);
00534       return -1;
00535    }
00536    ev->fNum = retval;
00537    return 0;
00538 }
00539 
00540 
00541 /* history_set_fun():
00542  *      Set history functions
00543  */
00544 el_private int
00545 history_set_fun(HistoryFcns_t* h, HistoryFcns_t* nh) {
00546    HistEvent_t ev;
00547 
00548    if (nh->fFirst == NULL || nh->fNext == NULL || nh->fLast == NULL ||
00549        nh->fPrev == NULL || nh->fCurr == NULL || nh->fSet == NULL ||
00550        nh->fEnter == NULL || nh->fAdd == NULL || nh->fClear == NULL ||
00551        nh->fRef == NULL) {
00552       if (h->fNext != history_def_next) {
00553          history_def_init(&h->fRef, &ev, 0);
00554          h->fFirst = history_def_first;
00555          h->fNext = history_def_next;
00556          h->fLast = history_def_last;
00557          h->fPrev = history_def_prev;
00558          h->fCurr = history_def_curr;
00559          h->fSet = history_def_set;
00560          h->fClear = history_def_clear;
00561          h->fEnter = history_def_enter;
00562          h->fAdd = history_def_add;
00563       }
00564       return -1;
00565    }
00566 
00567    if (h->fNext == history_def_next) {
00568       history_def_clear(h->fRef, &ev);
00569    }
00570 
00571    h->fEnt = -1;
00572    h->fFirst = nh->fFirst;
00573    h->fNext = nh->fNext;
00574    h->fLast = nh->fLast;
00575    h->fPrev = nh->fPrev;
00576    h->fCurr = nh->fCurr;
00577    h->fSet = nh->fSet;
00578    h->fClear = nh->fClear;
00579    h->fEnter = nh->fEnter;
00580    h->fAdd = nh->fAdd;
00581 
00582    return 0;
00583 } // history_set_fun
00584 
00585 
00586 /* history_load():
00587  *      History_t load function
00588  */
00589 el_private int
00590 history_load(HistoryFcns_t* h, const char* fname) {
00591    HistEvent_t ev;
00592 
00593    std::ifstream in(fname);
00594    if (!in) {
00595       return -1;
00596    }
00597 
00598    std::string line;
00599    int i = 0;
00600    for (; in && std::getline(in, line); i++) {
00601       HENTER(h, &ev, line.c_str());
00602    }
00603    return i;
00604 } // history_load
00605 
00606 
00607 /* history_save():
00608  *      HistoryFcns_t save function
00609  *  mod for ROOT: only append the most recent line!
00610  */
00611 el_private int
00612 history_save(HistoryFcns_t* h, const char* fname) {
00613    FILE* fp;
00614    HistEvent_t ev;
00615    int i = 0;
00616 
00617    if ((fp = fopen(fname, "a")) == NULL) {
00618       return -1;
00619    }
00620 
00621    (void) fchmod(fileno(fp), S_IRUSR | S_IWUSR);
00622 
00623    /*
00624    for (retval = HLAST(h, &ev);
00625         retval != -1;
00626         retval = HPREV(h, &ev), i++) {
00627       (void) fprintf(fp, "%s\n", ev.fStr);
00628    }
00629    */
00630    HFIRST(h, &ev);
00631    fprintf(fp, "%s\n", ev.fStr);
00632 
00633    (void) fclose(fp);
00634    return i;
00635 } // history_save
00636 
00637 
00638 /* history_prev_event():
00639  *      Find the previous event, with number given
00640  */
00641 el_private int
00642 history_prev_event(HistoryFcns_t* h, HistEvent_t* ev, int num) {
00643    int retval;
00644 
00645    for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) {
00646       if (ev->fNum == num) {
00647          return 0;
00648       }
00649    }
00650 
00651    he_seterrev(ev, _HE_NOT_FOUND);
00652    return -1;
00653 }
00654 
00655 
00656 /* history_next_event():
00657  *      Find the next event, with number given
00658  */
00659 el_private int
00660 history_next_event(HistoryFcns_t* h, HistEvent_t* ev, int num) {
00661    int retval;
00662 
00663    for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) {
00664       if (ev->fNum == num) {
00665          return 0;
00666       }
00667    }
00668 
00669    he_seterrev(ev, _HE_NOT_FOUND);
00670    return -1;
00671 }
00672 
00673 
00674 /* history_prev_string():
00675  *      Find the previous event beginning with string
00676  */
00677 el_private int
00678 history_prev_string(HistoryFcns_t* h, HistEvent_t* ev, const char* str) {
00679    size_t len = strlen(str);
00680    int retval;
00681 
00682    for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) {
00683       if (strncmp(str, ev->fStr, len) == 0) {
00684          return 0;
00685       }
00686    }
00687 
00688    he_seterrev(ev, _HE_NOT_FOUND);
00689    return -1;
00690 }
00691 
00692 
00693 /* history_next_string():
00694  *      Find the next event beginning with string
00695  */
00696 el_private int
00697 history_next_string(HistoryFcns_t* h, HistEvent_t* ev, const char* str) {
00698    size_t len = strlen(str);
00699    int retval;
00700 
00701    for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) {
00702       if (strncmp(str, ev->fStr, len) == 0) {
00703          return 0;
00704       }
00705    }
00706 
00707    he_seterrev(ev, _HE_NOT_FOUND);
00708    return -1;
00709 }
00710 
00711 
00712 /* history():
00713  *      User interface to history functions.
00714  */
00715 int
00716 history(HistoryFcns_t* h, HistEvent_t* ev, int fun, ...) {
00717    va_list va;
00718    const char* str;
00719    int retval;
00720 
00721    va_start(va, fun);
00722 
00723    he_seterrev(ev, _HE_OK);
00724 
00725    switch (fun) {
00726    case H_GETSIZE:
00727       retval = history_getsize(h, ev);
00728       break;
00729 
00730    case H_SETSIZE:
00731       retval = history_setsize(h, ev, va_arg(va, int));
00732       break;
00733 
00734    case H_ADD:
00735       str = va_arg(va, const char*);
00736       retval = HADD(h, ev, str);
00737       break;
00738 
00739    case H_ENTER:
00740       str = va_arg(va, const char*);
00741 
00742       if ((retval = HENTER(h, ev, str)) != -1) {
00743          h->fEnt = ev->fNum;
00744       }
00745       break;
00746 
00747    case H_APPEND:
00748       str = va_arg(va, const char*);
00749 
00750       if ((retval = HSET(h, ev, h->fEnt)) != -1) {
00751          retval = HADD(h, ev, str);
00752       }
00753       break;
00754 
00755    case H_FIRST:
00756       retval = HFIRST(h, ev);
00757       break;
00758 
00759    case H_NEXT:
00760       retval = HNEXT(h, ev);
00761       break;
00762 
00763    case H_LAST:
00764       retval = HLAST(h, ev);
00765       break;
00766 
00767    case H_PREV:
00768       retval = HPREV(h, ev);
00769       break;
00770 
00771    case H_CURR:
00772       retval = HCURR(h, ev);
00773       break;
00774 
00775    case H_SET:
00776       retval = HSET(h, ev, va_arg(va, int));
00777       break;
00778 
00779    case H_CLEAR:
00780       HCLEAR(h, ev);
00781       retval = 0;
00782       break;
00783 
00784    case H_LOAD:
00785       retval = history_load(h, va_arg(va, const char*));
00786 
00787       if (retval == -1) {
00788          he_seterrev(ev, _HE_HIST_READ);
00789       }
00790       break;
00791 
00792    case H_SAVE:
00793       retval = history_save(h, va_arg(va, const char*));
00794 
00795       if (retval == -1) {
00796          he_seterrev(ev, _HE_HIST_WRITE);
00797       }
00798       break;
00799 
00800    case H_PREV_EVENT:
00801       retval = history_prev_event(h, ev, va_arg(va, int));
00802       break;
00803 
00804    case H_NEXT_EVENT:
00805       retval = history_next_event(h, ev, va_arg(va, int));
00806       break;
00807 
00808    case H_PREV_STR:
00809       retval = history_prev_string(h, ev, va_arg(va, const char*));
00810       break;
00811 
00812    case H_NEXT_STR:
00813       retval = history_next_string(h, ev, va_arg(va, const char*));
00814       break;
00815 
00816    case H_FUNC:
00817       {
00818          HistoryFcns_t hf;
00819 
00820          hf.fRef = va_arg(va, ptr_t);
00821          h->fEnt = -1;
00822          hf.fFirst = va_arg(va, HistoryGFun_t);
00823          hf.fNext = va_arg(va, HistoryGFun_t);
00824          hf.fLast = va_arg(va, HistoryGFun_t);
00825          hf.fPrev = va_arg(va, HistoryGFun_t);
00826          hf.fCurr = va_arg(va, HistoryGFun_t);
00827          hf.fSet = va_arg(va, HistorySFun_t);
00828          hf.fClear = va_arg(va, HistoryVFun_t);
00829          hf.fEnter = va_arg(va, HistoryEFun_t);
00830          hf.fAdd = va_arg(va, HistoryEFun_t);
00831 
00832          if ((retval = history_set_fun(h, &hf)) == -1) {
00833             he_seterrev(ev, _HE_PARAM_MISSING);
00834          }
00835          break;
00836       }
00837 
00838    case H_END:
00839       history_end(h);
00840       retval = 0;
00841       break;
00842 
00843    default:
00844       retval = -1;
00845       he_seterrev(ev, _HE_UNKNOWN);
00846       break;
00847    } // switch
00848    va_end(va);
00849    return retval;
00850 } // history

Generated on Tue Jul 5 14:11:38 2011 for ROOT_528-00b_version by  doxygen 1.5.1