hist.c revision 302408
1219820Sjeff/*	$NetBSD: hist.c,v 1.20 2011/07/29 15:16:33 christos Exp $	*/
2219820Sjeff
3219820Sjeff/*-
4219820Sjeff * Copyright (c) 1992, 1993
5219820Sjeff *	The Regents of the University of California.  All rights reserved.
6219820Sjeff *
7219820Sjeff * This code is derived from software contributed to Berkeley by
8219820Sjeff * Christos Zoulas of Cornell University.
9219820Sjeff *
10219820Sjeff * Redistribution and use in source and binary forms, with or without
11219820Sjeff * modification, are permitted provided that the following conditions
12219820Sjeff * are met:
13219820Sjeff * 1. Redistributions of source code must retain the above copyright
14219820Sjeff *    notice, this list of conditions and the following disclaimer.
15219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
16219820Sjeff *    notice, this list of conditions and the following disclaimer in the
17219820Sjeff *    documentation and/or other materials provided with the distribution.
18219820Sjeff * 3. Neither the name of the University nor the names of its contributors
19219820Sjeff *    may be used to endorse or promote products derived from this software
20219820Sjeff *    without specific prior written permission.
21219820Sjeff *
22219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25219820Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31219820Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32219820Sjeff * SUCH DAMAGE.
33219820Sjeff */
34219820Sjeff
35219820Sjeff#include "config.h"
36219820Sjeff#if !defined(lint) && !defined(SCCSID)
37219820Sjeff#if 0
38219820Sjeffstatic char sccsid[] = "@(#)hist.c	8.1 (Berkeley) 6/4/93";
39219820Sjeff#else
40219820Sjeff__RCSID("$NetBSD: hist.c,v 1.20 2011/07/29 15:16:33 christos Exp $");
41219820Sjeff#endif
42219820Sjeff#endif /* not lint && not SCCSID */
43219820Sjeff#include <sys/cdefs.h>
44219820Sjeff__FBSDID("$FreeBSD: stable/11/lib/libedit/hist.c 296435 2016-03-06 21:32:54Z pfg $");
45219820Sjeff
46219820Sjeff/*
47219820Sjeff * hist.c: History access functions
48219820Sjeff */
49219820Sjeff#include <stdlib.h>
50219820Sjeff#include "el.h"
51219820Sjeff
52219820Sjeff/* hist_init():
53219820Sjeff *	Initialization function.
54219820Sjeff */
55219820Sjeffprotected int
56219820Sjeffhist_init(EditLine *el)
57219820Sjeff{
58219820Sjeff
59219820Sjeff	el->el_history.fun = NULL;
60219820Sjeff	el->el_history.ref = NULL;
61219820Sjeff	el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf));
62219820Sjeff	el->el_history.sz  = EL_BUFSIZ;
63219820Sjeff	if (el->el_history.buf == NULL)
64219820Sjeff		return -1;
65219820Sjeff	el->el_history.last = el->el_history.buf;
66219820Sjeff	return 0;
67219820Sjeff}
68219820Sjeff
69219820Sjeff
70219820Sjeff/* hist_end():
71219820Sjeff *	clean up history;
72219820Sjeff */
73219820Sjeffprotected void
74219820Sjeffhist_end(EditLine *el)
75219820Sjeff{
76219820Sjeff
77219820Sjeff	el_free(el->el_history.buf);
78219820Sjeff	el->el_history.buf = NULL;
79219820Sjeff}
80219820Sjeff
81219820Sjeff
82219820Sjeff/* hist_set():
83219820Sjeff *	Set new history interface
84219820Sjeff */
85219820Sjeffprotected int
86219820Sjeffhist_set(EditLine *el, hist_fun_t fun, void *ptr)
87219820Sjeff{
88219820Sjeff
89219820Sjeff	el->el_history.ref = ptr;
90219820Sjeff	el->el_history.fun = fun;
91219820Sjeff	return 0;
92219820Sjeff}
93219820Sjeff
94219820Sjeff
95219820Sjeff/* hist_get():
96219820Sjeff *	Get a history line and update it in the buffer.
97219820Sjeff *	eventno tells us the event to get.
98219820Sjeff */
99219820Sjeffprotected el_action_t
100219820Sjeffhist_get(EditLine *el)
101219820Sjeff{
102219820Sjeff	const Char *hp;
103219820Sjeff	int h;
104219820Sjeff
105219820Sjeff	if (el->el_history.eventno == 0) {	/* if really the current line */
106219820Sjeff		(void) Strncpy(el->el_line.buffer, el->el_history.buf,
107219820Sjeff		    el->el_history.sz);
108219820Sjeff		el->el_line.lastchar = el->el_line.buffer +
109219820Sjeff		    (el->el_history.last - el->el_history.buf);
110219820Sjeff
111219820Sjeff#ifdef KSHVI
112219820Sjeff		if (el->el_map.type == MAP_VI)
113219820Sjeff			el->el_line.cursor = el->el_line.buffer;
114219820Sjeff		else
115219820Sjeff#endif /* KSHVI */
116219820Sjeff			el->el_line.cursor = el->el_line.lastchar;
117219820Sjeff
118219820Sjeff		return CC_REFRESH;
119219820Sjeff	}
120219820Sjeff	if (el->el_history.ref == NULL)
121219820Sjeff		return CC_ERROR;
122219820Sjeff
123219820Sjeff	hp = HIST_FIRST(el);
124219820Sjeff
125219820Sjeff	if (hp == NULL)
126219820Sjeff		return CC_ERROR;
127219820Sjeff
128219820Sjeff	for (h = 1; h < el->el_history.eventno; h++)
129219820Sjeff		if ((hp = HIST_NEXT(el)) == NULL) {
130219820Sjeff			el->el_history.eventno = h;
131219820Sjeff			return CC_ERROR;
132219820Sjeff		}
133219820Sjeff	(void) Strncpy(el->el_line.buffer, hp,
134219820Sjeff			(size_t)(el->el_line.limit - el->el_line.buffer));
135219820Sjeff	el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = '\0';
136219820Sjeff	el->el_line.lastchar = el->el_line.buffer + Strlen(el->el_line.buffer);
137219820Sjeff
138219820Sjeff	if (el->el_line.lastchar > el->el_line.buffer
139219820Sjeff	    && el->el_line.lastchar[-1] == '\n')
140219820Sjeff		el->el_line.lastchar--;
141219820Sjeff	if (el->el_line.lastchar > el->el_line.buffer
142219820Sjeff	    && el->el_line.lastchar[-1] == ' ')
143219820Sjeff		el->el_line.lastchar--;
144219820Sjeff#ifdef KSHVI
145219820Sjeff	if (el->el_map.type == MAP_VI)
146219820Sjeff		el->el_line.cursor = el->el_line.buffer;
147219820Sjeff	else
148219820Sjeff#endif /* KSHVI */
149219820Sjeff		el->el_line.cursor = el->el_line.lastchar;
150219820Sjeff
151219820Sjeff	return CC_REFRESH;
152219820Sjeff}
153219820Sjeff
154219820Sjeff
155219820Sjeff/* hist_command()
156219820Sjeff *	process a history command
157219820Sjeff */
158219820Sjeffprotected int
159219820Sjeffhist_command(EditLine *el, int argc, const Char **argv)
160219820Sjeff{
161219820Sjeff	const Char *str;
162219820Sjeff	int num;
163219820Sjeff	TYPE(HistEvent) ev;
164219820Sjeff
165219820Sjeff	if (el->el_history.ref == NULL)
166219820Sjeff		return -1;
167219820Sjeff
168219820Sjeff	if (argc == 1 || Strcmp(argv[1], STR("list")) == 0) {
169219820Sjeff		 /* List history entries */
170219820Sjeff
171219820Sjeff		for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
172219820Sjeff			(void) fprintf(el->el_outfile, "%d %s",
173219820Sjeff			    el->el_history.ev.num, ct_encode_string(str, &el->el_scratch));
174219820Sjeff		return 0;
175219820Sjeff	}
176219820Sjeff
177219820Sjeff	if (argc != 3)
178219820Sjeff		return -1;
179219820Sjeff
180219820Sjeff	num = (int)Strtol(argv[2], NULL, 0);
181219820Sjeff
182219820Sjeff	if (Strcmp(argv[1], STR("size")) == 0)
183219820Sjeff		return FUNW(history)(el->el_history.ref, &ev, H_SETSIZE, num);
184219820Sjeff
185219820Sjeff	if (Strcmp(argv[1], STR("unique")) == 0)
186219820Sjeff		return FUNW(history)(el->el_history.ref, &ev, H_SETUNIQUE, num);
187219820Sjeff
188219820Sjeff	return -1;
189219820Sjeff}
190219820Sjeff
191219820Sjeff/* hist_enlargebuf()
192219820Sjeff *	Enlarge history buffer to specified value. Called from el_enlargebufs().
193219820Sjeff *	Return 0 for failure, 1 for success.
194219820Sjeff */
195219820Sjeffprotected int
196219820Sjeff/*ARGSUSED*/
197219820Sjeffhist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
198219820Sjeff{
199219820Sjeff	Char *newbuf;
200219820Sjeff
201219820Sjeff	newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf));
202219820Sjeff	if (!newbuf)
203219820Sjeff		return 0;
204219820Sjeff
205219820Sjeff	(void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf));
206219820Sjeff
207219820Sjeff	el->el_history.last = newbuf +
208219820Sjeff				(el->el_history.last - el->el_history.buf);
209219820Sjeff	el->el_history.buf = newbuf;
210219820Sjeff	el->el_history.sz  = newsz;
211219820Sjeff
212219820Sjeff	return 1;
213219820Sjeff}
214219820Sjeff
215219820Sjeff#ifdef WIDECHAR
216219820Sjeffprotected wchar_t *
217219820Sjeffhist_convert(EditLine *el, int fn, void *arg)
218219820Sjeff{
219219820Sjeff	HistEventW ev;
220219820Sjeff	if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1)
221219820Sjeff		return NULL;
222219820Sjeff	return ct_decode_string((const char *)(const void *)ev.str,
223219820Sjeff	    &el->el_scratch);
224219820Sjeff}
225219820Sjeff#endif
226219820Sjeff