📄 history.c
字号:
/*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Christos Zoulas of Cornell University. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#if !defined(lint) && !defined(SCCSID)static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";#endif /* not lint && not SCCSID *//* * hist.c: History access functions */#include "sys.h"#include <string.h>#include <stdlib.h>#if __STDC__#include <stdarg.h>#else#include <varargs.h>#endif#include "histedit.h"typedef const HistEvent * (*history_gfun_t) __P((ptr_t));typedef const HistEvent * (*history_efun_t) __P((ptr_t, const char *));struct history { ptr_t h_ref; /* Argument for history fcns */ history_gfun_t h_first; /* Get the first element */ history_gfun_t h_next; /* Get the next element */ history_gfun_t h_last; /* Get the last element */ history_gfun_t h_prev; /* Get the previous element */ history_gfun_t h_curr; /* Get the current element */ history_efun_t h_enter; /* Add an element */ history_efun_t h_add; /* Append to an element */};#define HNEXT(h) (*(h)->h_next)((h)->h_ref)#define HFIRST(h) (*(h)->h_first)((h)->h_ref)#define HPREV(h) (*(h)->h_prev)((h)->h_ref)#define HLAST(h) (*(h)->h_last)((h)->h_ref)#define HCURR(h) (*(h)->h_curr)((h)->h_ref)#define HENTER(h, str) (*(h)->h_enter)((h)->h_ref, str)#define HADD(h, str) (*(h)->h_add)((h)->h_ref, str)#define h_malloc(a) malloc(a)#define h_free(a) free(a)private int history_set_num __P((History *, int));private int history_set_fun __P((History *, history_gfun_t, history_gfun_t, history_gfun_t, history_gfun_t, history_gfun_t, history_efun_t, history_efun_t, ptr_t));private const HistEvent *history_prev_event __P((History *, int));private const HistEvent *history_next_event __P((History *, int));private const HistEvent *history_next_string __P((History *, const char *));private const HistEvent *history_prev_string __P((History *, const char *));/***********************************************************************//* * Builtin- history implementation */typedef struct hentry_t { HistEvent ev; /* What we return */ struct hentry_t *next; /* Next entry */ struct hentry_t *prev; /* Previous entry */} hentry_t;typedef struct history_t { hentry_t list; /* Fake list header element */ hentry_t *cursor; /* Current element in the list */ int max; /* Maximum number of events */ int cur; /* Current number of events */ int eventno; /* Current event number */} history_t;private const HistEvent *history_def_first __P((ptr_t));private const HistEvent *history_def_last __P((ptr_t));private const HistEvent *history_def_next __P((ptr_t));private const HistEvent *history_def_prev __P((ptr_t));private const HistEvent *history_def_curr __P((ptr_t));private const HistEvent *history_def_enter __P((ptr_t, const char *));private const HistEvent *history_def_add __P((ptr_t, const char *));private void history_def_init __P((ptr_t *, int));private void history_def_end __P((ptr_t));private const HistEvent *history_def_insert __P((history_t *, const char *));private void history_def_delete __P((history_t *, hentry_t *));#define history_def_set(p, num) (void) (((history_t *) p)->max = (num))/* history_def_first(): * Default function to return the first event in the history. */private const HistEvent * history_def_first(p) ptr_t p;{ history_t *h = (history_t *) p; h->cursor = h->list.next; if (h->cursor != &h->list) return &h->cursor->ev; else return NULL;}/* history_def_last(): * Default function to return the last event in the history. */private const HistEvent * history_def_last(p) ptr_t p;{ history_t *h = (history_t *) p; h->cursor = h->list.prev; if (h->cursor != &h->list) return &h->cursor->ev; else return NULL;}/* history_def_next(): * Default function to return the next event in the history. */private const HistEvent * history_def_next(p) ptr_t p;{ history_t *h = (history_t *) p; if (h->cursor != &h->list) h->cursor = h->cursor->next; else return NULL; if (h->cursor != &h->list) return &h->cursor->ev; else return NULL;}/* history_def_prev(): * Default function to return the previous event in the history. */private const HistEvent * history_def_prev(p) ptr_t p;{ history_t *h = (history_t *) p; if (h->cursor != &h->list) h->cursor = h->cursor->prev; else return NULL; if (h->cursor != &h->list) return &h->cursor->ev; else return NULL;}/* history_def_curr(): * Default function to return the current event in the history. */private const HistEvent * history_def_curr(p) ptr_t p;{ history_t *h = (history_t *) p; if (h->cursor != &h->list) return &h->cursor->ev; else return NULL;}/* history_def_add(): * Append string to element */private const HistEvent *history_def_add(p, str) ptr_t p; const char *str;{ history_t *h = (history_t *) p; size_t len; char *s; if (h->cursor == &h->list) return (history_def_enter(p, str)); len = strlen(h->cursor->ev.str) + strlen(str) + 1; s = (char *) h_malloc(len); (void) strcpy(s, h->cursor->ev.str); (void) strcat(s, str); h_free((ptr_t) h->cursor->ev.str); h->cursor->ev.str = s; return &h->cursor->ev;}/* history_def_delete(): * Delete element hp of the h list */private voidhistory_def_delete(h, hp) history_t *h; hentry_t *hp;{ if (hp == &h->list) abort(); hp->prev->next = hp->next; hp->next->prev = hp->prev; h_free((ptr_t) hp->ev.str); h_free(hp); h->cur--;}/* history_def_insert(): * Insert element with string str in the h list */private const HistEvent *history_def_insert(h, str) history_t *h; const char *str;{ h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); h->cursor->ev.str = strdup(str); h->cursor->next = h->list.next; h->cursor->prev = &h->list; h->list.next->prev = h->cursor; h->list.next = h->cursor; h->cur++; return &h->cursor->ev;}/* history_def_enter(): * Default function to enter an item in the history */private const HistEvent *history_def_enter(p, str) ptr_t p; const char *str;{ history_t *h = (history_t *) p; const HistEvent *ev; ev = history_def_insert(h, str); ((HistEvent*) ev)->num = ++h->eventno; /* * Always keep at least one entry. * This way we don't have to check for the empty list. */ while (h->cur > h->max + 1) history_def_delete(h, h->list.prev); return ev;}/* history_def_init(): * Default history initialization function */private voidhistory_def_init(p, n) ptr_t *p; int n;{ history_t *h = (history_t *) h_malloc(sizeof(history_t)); if (n <= 0) n = 0; h->eventno = 0; h->cur = 0; h->max = n; h->list.next = h->list.prev = &h->list; h->list.ev.str = NULL; h->list.ev.num = 0; h->cursor = &h->list; *p = (ptr_t) h;}/* history_def_end(): * Default history cleanup function */private voidhistory_def_end(p) ptr_t p;{ history_t *h = (history_t *) p; while (h->list.prev != &h->list) history_def_delete(h, h->list.prev);}/************************************************************************//* history_init(): * Initialization function. */public History *history_init(){ History *h = (History *) h_malloc(sizeof(History)); history_def_init(&h->h_ref, 0); h->h_next = history_def_next; h->h_first = history_def_first; h->h_last = history_def_last; h->h_prev = history_def_prev; h->h_curr = history_def_curr; h->h_enter = history_def_enter; h->h_add = history_def_add; return h;}/* history_end(): * clean up history; */public voidhistory_end(h) History *h;{ if (h->h_next == history_def_next) history_def_end(h->h_ref);}/* history_set_num(): * Set history number of events */private inthistory_set_num(h, num) History *h; int num;{ if (h->h_next != history_def_next || num < 0) return -1; history_def_set(h->h_ref, num); return 0;}/* history_set_fun(): * Set history functions */private inthistory_set_fun(h, first, next, last, prev, curr, enter, add, ptr) History *h; history_gfun_t first, next, last, prev, curr; history_efun_t enter, add; ptr_t ptr;{ if (first == NULL || next == NULL || last == NULL || prev == NULL || curr == NULL || enter == NULL || add == NULL || ptr == NULL ) { if (h->h_next != history_def_next) { history_def_init(&h->h_ref, 0); h->h_first = history_def_first; h->h_next = history_def_next; h->h_last = history_def_last; h->h_prev = history_def_prev; h->h_curr = history_def_curr; h->h_enter = history_def_enter; h->h_add = history_def_add; } return -1; } if (h->h_next == history_def_next) history_def_end(h->h_ref); h->h_next = next; h->h_first = first; h->h_enter = enter; h->h_add = add; return 0;}/* history_prev_event(): * Find the previous event, with number given */private const HistEvent *history_prev_event(h, num) History *h; int num;{ const HistEvent *ev; for (ev = HCURR(h); ev != NULL; ev = HPREV(h)) if (ev->num == num) return ev; return NULL;}/* history_next_event(): * Find the next event, with number given */private const HistEvent *history_next_event(h, num) History *h; int num;{ const HistEvent *ev; for (ev = HCURR(h); ev != NULL; ev = HNEXT(h)) if (ev->num == num) return ev; return NULL;}/* history_prev_string(): * Find the previous event beginning with string */private const HistEvent *history_prev_string(h, str) History *h; const char* str;{ const HistEvent *ev; size_t len = strlen(str); for (ev = HCURR(h); ev != NULL; ev = HNEXT(h)) if (strncmp(str, ev->str, len) == 0) return ev; return NULL;}/* history_next_string(): * Find the next event beginning with string */private const HistEvent *history_next_string(h, str) History *h; const char* str;{ const HistEvent *ev; size_t len = strlen(str); for (ev = HCURR(h); ev != NULL; ev = HPREV(h)) if (strncmp(str, ev->str, len) == 0) return ev; return NULL;}/* history(): * User interface to history functions. */const HistEvent *#if __STDC__history(History *h, int fun, ...)#elsehistory(va_alist) va_dcl#endif{ va_list va; const HistEvent *ev = NULL; const char *str; static const HistEvent sev = { 0, "" };#if __STDC__ va_start(va, fun);#else History *h; int fun; va_start(va); h = va_arg(va, History *); fun = va_arg(va, int);#endif switch (fun) { case H_ADD: str = va_arg(va, const char *); ev = HADD(h, str); break; case H_ENTER: str = va_arg(va, const char *); ev = HENTER(h, str); break; case H_FIRST: ev = HFIRST(h); break; case H_NEXT: ev = HNEXT(h); break; case H_LAST: ev = HLAST(h); break; case H_PREV: ev = HPREV(h); break; case H_CURR: ev = HCURR(h); break; case H_PREV_EVENT: ev = history_prev_event(h, va_arg(va, int)); break; case H_NEXT_EVENT: ev = history_next_event(h, va_arg(va, int)); break; case H_PREV_STR: ev = history_prev_string(h, va_arg(va, const char*)); break; case H_NEXT_STR: ev = history_next_string(h, va_arg(va, const char*)); break; case H_EVENT: if (history_set_num(h, va_arg(va, int)) == 0) ev = &sev; break; case H_FUNC: { history_gfun_t first = va_arg(va, history_gfun_t); history_gfun_t next = va_arg(va, history_gfun_t); history_gfun_t last = va_arg(va, history_gfun_t); history_gfun_t prev = va_arg(va, history_gfun_t); history_gfun_t curr = va_arg(va, history_gfun_t); history_efun_t enter = va_arg(va, history_efun_t); history_efun_t add = va_arg(va, history_efun_t); ptr_t ptr = va_arg(va, ptr_t); if (history_set_fun(h, first, next, last, prev, curr, enter, add, ptr) == 0) ev = &sev; } break; case H_END: history_end(h); break; default: break; } va_end(va); return ev;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -