Changeset View
Changeset View
Standalone View
Standalone View
lib/libedit/hist.c
/* $NetBSD: hist.c,v 1.24 2016/02/16 22:53:14 christos Exp $ */ | /* $NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $ */ | ||||
/*- | /*- | ||||
* Copyright (c) 1992, 1993 | * Copyright (c) 1992, 1993 | ||||
* The Regents of the University of California. All rights reserved. | * The Regents of the University of California. All rights reserved. | ||||
* | * | ||||
* This code is derived from software contributed to Berkeley by | * This code is derived from software contributed to Berkeley by | ||||
* Christos Zoulas of Cornell University. | * Christos Zoulas of Cornell University. | ||||
* | * | ||||
Show All 22 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include "config.h" | #include "config.h" | ||||
#if !defined(lint) && !defined(SCCSID) | #if !defined(lint) && !defined(SCCSID) | ||||
#if 0 | #if 0 | ||||
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; | static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; | ||||
#else | #else | ||||
__RCSID("$NetBSD: hist.c,v 1.24 2016/02/16 22:53:14 christos Exp $"); | __RCSID("$NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $"); | ||||
#endif | #endif | ||||
#endif /* not lint && not SCCSID */ | #endif /* not lint && not SCCSID */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
/* | /* | ||||
* hist.c: History access functions | * hist.c: History access functions | ||||
*/ | */ | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <vis.h> | |||||
#include "el.h" | #include "el.h" | ||||
/* hist_init(): | /* hist_init(): | ||||
* Initialization function. | * Initialization function. | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
hist_init(EditLine *el) | hist_init(EditLine *el) | ||||
{ | { | ||||
el->el_history.fun = NULL; | el->el_history.fun = NULL; | ||||
el->el_history.ref = NULL; | el->el_history.ref = NULL; | ||||
el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf)); | el->el_history.buf = el_calloc(EL_BUFSIZ, sizeof(*el->el_history.buf)); | ||||
el->el_history.sz = EL_BUFSIZ; | |||||
if (el->el_history.buf == NULL) | if (el->el_history.buf == NULL) | ||||
return -1; | return -1; | ||||
el->el_history.sz = EL_BUFSIZ; | |||||
el->el_history.last = el->el_history.buf; | el->el_history.last = el->el_history.buf; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* hist_end(): | /* hist_end(): | ||||
* clean up history; | * clean up history; | ||||
*/ | */ | ||||
protected void | libedit_private void | ||||
hist_end(EditLine *el) | hist_end(EditLine *el) | ||||
{ | { | ||||
el_free(el->el_history.buf); | el_free(el->el_history.buf); | ||||
el->el_history.buf = NULL; | el->el_history.buf = NULL; | ||||
} | } | ||||
/* hist_set(): | /* hist_set(): | ||||
* Set new history interface | * Set new history interface | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
hist_set(EditLine *el, hist_fun_t fun, void *ptr) | hist_set(EditLine *el, hist_fun_t fun, void *ptr) | ||||
{ | { | ||||
el->el_history.ref = ptr; | el->el_history.ref = ptr; | ||||
el->el_history.fun = fun; | el->el_history.fun = fun; | ||||
return 0; | return 0; | ||||
} | } | ||||
/* hist_get(): | /* hist_get(): | ||||
* Get a history line and update it in the buffer. | * Get a history line and update it in the buffer. | ||||
* eventno tells us the event to get. | * eventno tells us the event to get. | ||||
*/ | */ | ||||
protected el_action_t | libedit_private el_action_t | ||||
hist_get(EditLine *el) | hist_get(EditLine *el) | ||||
{ | { | ||||
const Char *hp; | const wchar_t *hp; | ||||
int h; | int h; | ||||
size_t blen, hlen; | |||||
if (el->el_history.eventno == 0) { /* if really the current line */ | if (el->el_history.eventno == 0) { /* if really the current line */ | ||||
(void) Strncpy(el->el_line.buffer, el->el_history.buf, | (void) wcsncpy(el->el_line.buffer, el->el_history.buf, | ||||
el->el_history.sz); | el->el_history.sz); | ||||
el->el_line.lastchar = el->el_line.buffer + | el->el_line.lastchar = el->el_line.buffer + | ||||
(el->el_history.last - el->el_history.buf); | (el->el_history.last - el->el_history.buf); | ||||
#ifdef KSHVI | #ifdef KSHVI | ||||
if (el->el_map.type == MAP_VI) | if (el->el_map.type == MAP_VI) | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
else | else | ||||
#endif /* KSHVI */ | #endif /* KSHVI */ | ||||
el->el_line.cursor = el->el_line.lastchar; | el->el_line.cursor = el->el_line.lastchar; | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
} | } | ||||
if (el->el_history.ref == NULL) | if (el->el_history.ref == NULL) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
hp = HIST_FIRST(el); | hp = HIST_FIRST(el); | ||||
if (hp == NULL) | if (hp == NULL) | ||||
return CC_ERROR; | return CC_ERROR; | ||||
for (h = 1; h < el->el_history.eventno; h++) | for (h = 1; h < el->el_history.eventno; h++) | ||||
if ((hp = HIST_NEXT(el)) == NULL) { | if ((hp = HIST_NEXT(el)) == NULL) | ||||
el->el_history.eventno = h; | goto out; | ||||
return CC_ERROR; | |||||
} | |||||
(void) Strncpy(el->el_line.buffer, hp, | |||||
(size_t)(el->el_line.limit - el->el_line.buffer)); | |||||
el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = '\0'; | |||||
el->el_line.lastchar = el->el_line.buffer + Strlen(el->el_line.buffer); | |||||
hlen = wcslen(hp) + 1; | |||||
blen = (size_t)(el->el_line.limit - el->el_line.buffer); | |||||
if (hlen > blen && !ch_enlargebufs(el, hlen)) | |||||
goto out; | |||||
memcpy(el->el_line.buffer, hp, hlen * sizeof(*hp)); | |||||
el->el_line.lastchar = el->el_line.buffer + hlen - 1; | |||||
if (el->el_line.lastchar > el->el_line.buffer | if (el->el_line.lastchar > el->el_line.buffer | ||||
&& el->el_line.lastchar[-1] == '\n') | && el->el_line.lastchar[-1] == '\n') | ||||
el->el_line.lastchar--; | el->el_line.lastchar--; | ||||
if (el->el_line.lastchar > el->el_line.buffer | if (el->el_line.lastchar > el->el_line.buffer | ||||
&& el->el_line.lastchar[-1] == ' ') | && el->el_line.lastchar[-1] == ' ') | ||||
el->el_line.lastchar--; | el->el_line.lastchar--; | ||||
#ifdef KSHVI | #ifdef KSHVI | ||||
if (el->el_map.type == MAP_VI) | if (el->el_map.type == MAP_VI) | ||||
el->el_line.cursor = el->el_line.buffer; | el->el_line.cursor = el->el_line.buffer; | ||||
else | else | ||||
#endif /* KSHVI */ | #endif /* KSHVI */ | ||||
el->el_line.cursor = el->el_line.lastchar; | el->el_line.cursor = el->el_line.lastchar; | ||||
return CC_REFRESH; | return CC_REFRESH; | ||||
out: | |||||
el->el_history.eventno = h; | |||||
return CC_ERROR; | |||||
} | } | ||||
/* hist_command() | /* hist_command() | ||||
* process a history command | * process a history command | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
hist_command(EditLine *el, int argc, const Char **argv) | hist_command(EditLine *el, int argc, const wchar_t **argv) | ||||
{ | { | ||||
const Char *str; | const wchar_t *str; | ||||
int num; | int num; | ||||
TYPE(HistEvent) ev; | HistEventW ev; | ||||
if (el->el_history.ref == NULL) | if (el->el_history.ref == NULL) | ||||
return -1; | return -1; | ||||
if (argc == 1 || Strcmp(argv[1], STR("list")) == 0) { | if (argc == 1 || wcscmp(argv[1], L"list") == 0) { | ||||
size_t maxlen = 0; | |||||
char *buf = NULL; | |||||
int hno = 1; | |||||
/* List history entries */ | /* List history entries */ | ||||
for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) | for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) { | ||||
(void) fprintf(el->el_outfile, "%d %s", | char *ptr = | ||||
el->el_history.ev.num, ct_encode_string(str, &el->el_scratch)); | ct_encode_string(str, &el->el_scratch); | ||||
size_t len = strlen(ptr); | |||||
if (len > 0 && ptr[len - 1] == '\n') | |||||
ptr[--len] = '\0'; | |||||
len = len * 4 + 1; | |||||
if (len >= maxlen) { | |||||
maxlen = len + 1024; | |||||
char *nbuf = el_realloc(buf, maxlen); | |||||
if (nbuf == NULL) { | |||||
el_free(buf); | |||||
return -1; | |||||
} | |||||
buf = nbuf; | |||||
} | |||||
strvis(buf, ptr, VIS_NL); | |||||
(void) fprintf(el->el_outfile, "%d\t%s\n", | |||||
hno++, buf); | |||||
} | |||||
el_free(buf); | |||||
return 0; | return 0; | ||||
} | } | ||||
if (argc != 3) | if (argc != 3) | ||||
return -1; | return -1; | ||||
num = (int)Strtol(argv[2], NULL, 0); | num = (int)wcstol(argv[2], NULL, 0); | ||||
if (Strcmp(argv[1], STR("size")) == 0) | if (wcscmp(argv[1], L"size") == 0) | ||||
return FUNW(history)(el->el_history.ref, &ev, H_SETSIZE, num); | return history_w(el->el_history.ref, &ev, H_SETSIZE, num); | ||||
if (Strcmp(argv[1], STR("unique")) == 0) | if (wcscmp(argv[1], L"unique") == 0) | ||||
return FUNW(history)(el->el_history.ref, &ev, H_SETUNIQUE, num); | return history_w(el->el_history.ref, &ev, H_SETUNIQUE, num); | ||||
return -1; | return -1; | ||||
} | } | ||||
/* hist_enlargebuf() | /* hist_enlargebuf() | ||||
* Enlarge history buffer to specified value. Called from el_enlargebufs(). | * Enlarge history buffer to specified value. Called from el_enlargebufs(). | ||||
* Return 0 for failure, 1 for success. | * Return 0 for failure, 1 for success. | ||||
*/ | */ | ||||
protected int | libedit_private int | ||||
/*ARGSUSED*/ | /*ARGSUSED*/ | ||||
hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz) | hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz) | ||||
{ | { | ||||
Char *newbuf; | wchar_t *newbuf; | ||||
newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf)); | newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf)); | ||||
if (!newbuf) | if (!newbuf) | ||||
return 0; | return 0; | ||||
(void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf)); | (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf)); | ||||
el->el_history.last = newbuf + | el->el_history.last = newbuf + | ||||
(el->el_history.last - el->el_history.buf); | (el->el_history.last - el->el_history.buf); | ||||
el->el_history.buf = newbuf; | el->el_history.buf = newbuf; | ||||
el->el_history.sz = newsz; | el->el_history.sz = newsz; | ||||
return 1; | return 1; | ||||
} | } | ||||
#ifdef WIDECHAR | libedit_private wchar_t * | ||||
protected wchar_t * | |||||
hist_convert(EditLine *el, int fn, void *arg) | hist_convert(EditLine *el, int fn, void *arg) | ||||
{ | { | ||||
HistEventW ev; | HistEventW ev; | ||||
if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1) | if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1) | ||||
return NULL; | return NULL; | ||||
return ct_decode_string((const char *)(const void *)ev.str, | return ct_decode_string((const char *)(const void *)ev.str, | ||||
&el->el_scratch); | &el->el_scratch); | ||||
} | } | ||||
#endif |