11573Srgrimes/*-
21573Srgrimes * Copyright (c) 1992, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * This code is derived from software contributed to Berkeley by
61573Srgrimes * Christos Zoulas of Cornell University.
71573Srgrimes *
81573Srgrimes * Redistribution and use in source and binary forms, with or without
91573Srgrimes * modification, are permitted provided that the following conditions
101573Srgrimes * are met:
111573Srgrimes * 1. Redistributions of source code must retain the above copyright
121573Srgrimes *    notice, this list of conditions and the following disclaimer.
131573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
141573Srgrimes *    notice, this list of conditions and the following disclaimer in the
151573Srgrimes *    documentation and/or other materials provided with the distribution.
16148834Sstefanf * 3. Neither the name of the University nor the names of its contributors
171573Srgrimes *    may be used to endorse or promote products derived from this software
181573Srgrimes *    without specific prior written permission.
191573Srgrimes *
201573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
211573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
221573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
231573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
241573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
251573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
261573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
271573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
281573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
291573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
301573Srgrimes * SUCH DAMAGE.
3184260Sobrien *
32148834Sstefanf *	$NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $
331573Srgrimes */
341573Srgrimes
351573Srgrimes#if !defined(lint) && !defined(SCCSID)
361573Srgrimesstatic char sccsid[] = "@(#)hist.c	8.1 (Berkeley) 6/4/93";
371573Srgrimes#endif /* not lint && not SCCSID */
3884260Sobrien#include <sys/cdefs.h>
3984260Sobrien__FBSDID("$FreeBSD$");
401573Srgrimes
411573Srgrimes/*
421573Srgrimes * hist.c: History access functions
431573Srgrimes */
441573Srgrimes#include "sys.h"
451573Srgrimes#include <stdlib.h>
461573Srgrimes#include "el.h"
471573Srgrimes
481573Srgrimes/* hist_init():
491573Srgrimes *	Initialization function.
501573Srgrimes */
511573Srgrimesprotected int
5284260Sobrienhist_init(EditLine *el)
531573Srgrimes{
5484260Sobrien
5584260Sobrien	el->el_history.fun = NULL;
5684260Sobrien	el->el_history.ref = NULL;
5784260Sobrien	el->el_history.buf = (char *) el_malloc(EL_BUFSIZ);
5884260Sobrien	el->el_history.sz  = EL_BUFSIZ;
5984260Sobrien	if (el->el_history.buf == NULL)
6084260Sobrien		return (-1);
6184260Sobrien	el->el_history.last = el->el_history.buf;
6284260Sobrien	return (0);
631573Srgrimes}
641573Srgrimes
651573Srgrimes
661573Srgrimes/* hist_end():
671573Srgrimes *	clean up history;
681573Srgrimes */
691573Srgrimesprotected void
7084260Sobrienhist_end(EditLine *el)
711573Srgrimes{
7284260Sobrien
7384260Sobrien	el_free((ptr_t) el->el_history.buf);
7484260Sobrien	el->el_history.buf = NULL;
751573Srgrimes}
761573Srgrimes
771573Srgrimes
781573Srgrimes/* hist_set():
791573Srgrimes *	Set new history interface
801573Srgrimes */
811573Srgrimesprotected int
8284260Sobrienhist_set(EditLine *el, hist_fun_t fun, ptr_t ptr)
8384260Sobrien{
841573Srgrimes
8584260Sobrien	el->el_history.ref = ptr;
8684260Sobrien	el->el_history.fun = fun;
8784260Sobrien	return (0);
881573Srgrimes}
891573Srgrimes
901573Srgrimes
911573Srgrimes/* hist_get():
921573Srgrimes *	Get a history line and update it in the buffer.
931573Srgrimes *	eventno tells us the event to get.
941573Srgrimes */
951573Srgrimesprotected el_action_t
9684260Sobrienhist_get(EditLine *el)
971573Srgrimes{
9884260Sobrien	const char *hp;
9984260Sobrien	int h;
1001573Srgrimes
10184260Sobrien	if (el->el_history.eventno == 0) {	/* if really the current line */
10284260Sobrien		(void) strncpy(el->el_line.buffer, el->el_history.buf,
10384260Sobrien		    el->el_history.sz);
10484260Sobrien		el->el_line.lastchar = el->el_line.buffer +
10584260Sobrien		    (el->el_history.last - el->el_history.buf);
1061573Srgrimes
1071573Srgrimes#ifdef KSHVI
10884260Sobrien		if (el->el_map.type == MAP_VI)
10984260Sobrien			el->el_line.cursor = el->el_line.buffer;
11084260Sobrien		else
1111573Srgrimes#endif /* KSHVI */
11284260Sobrien			el->el_line.cursor = el->el_line.lastchar;
1131573Srgrimes
11484260Sobrien		return (CC_REFRESH);
11584260Sobrien	}
11684260Sobrien	if (el->el_history.ref == NULL)
11784260Sobrien		return (CC_ERROR);
1181573Srgrimes
11984260Sobrien	hp = HIST_FIRST(el);
1201573Srgrimes
12184260Sobrien	if (hp == NULL)
12284260Sobrien		return (CC_ERROR);
1231573Srgrimes
12484260Sobrien	for (h = 1; h < el->el_history.eventno; h++)
12584260Sobrien		if ((hp = HIST_NEXT(el)) == NULL) {
12684260Sobrien			el->el_history.eventno = h;
12784260Sobrien			return (CC_ERROR);
12884260Sobrien		}
129148834Sstefanf	(void) strlcpy(el->el_line.buffer, hp,
13084260Sobrien			(size_t)(el->el_line.limit - el->el_line.buffer));
13184260Sobrien	el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer);
1321573Srgrimes
133148834Sstefanf	if (el->el_line.lastchar > el->el_line.buffer
134148834Sstefanf	    && el->el_line.lastchar[-1] == '\n')
135148834Sstefanf		el->el_line.lastchar--;
136148834Sstefanf	if (el->el_line.lastchar > el->el_line.buffer
137148834Sstefanf	    && el->el_line.lastchar[-1] == ' ')
138148834Sstefanf		el->el_line.lastchar--;
1391573Srgrimes#ifdef KSHVI
14084260Sobrien	if (el->el_map.type == MAP_VI)
14184260Sobrien		el->el_line.cursor = el->el_line.buffer;
14284260Sobrien	else
1431573Srgrimes#endif /* KSHVI */
14484260Sobrien		el->el_line.cursor = el->el_line.lastchar;
1451573Srgrimes
14684260Sobrien	return (CC_REFRESH);
1471573Srgrimes}
1481573Srgrimes
14984260Sobrien
150148834Sstefanf/* hist_command()
151148834Sstefanf *	process a history command
1521573Srgrimes */
1531573Srgrimesprotected int
154148834Sstefanfhist_command(EditLine *el, int argc, const char **argv)
1551573Srgrimes{
15684260Sobrien	const char *str;
157148834Sstefanf	int num;
158148834Sstefanf	HistEvent ev;
1591573Srgrimes
16084260Sobrien	if (el->el_history.ref == NULL)
16184260Sobrien		return (-1);
162148834Sstefanf
163148834Sstefanf	if (argc == 1 || strcmp(argv[1], "list") == 0) {
164148834Sstefanf		 /* List history entries */
165148834Sstefanf
166148834Sstefanf		for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
167148834Sstefanf			(void) fprintf(el->el_outfile, "%d %s",
168148834Sstefanf			    el->el_history.ev.num, str);
169148834Sstefanf		return (0);
170148834Sstefanf	}
171148834Sstefanf
172148834Sstefanf	if (argc != 3)
173148834Sstefanf		return (-1);
174148834Sstefanf
175148834Sstefanf	num = (int)strtol(argv[2], NULL, 0);
176148834Sstefanf
177148834Sstefanf	if (strcmp(argv[1], "size") == 0)
178148834Sstefanf		return history(el->el_history.ref, &ev, H_SETSIZE, num);
179148834Sstefanf
180148834Sstefanf	if (strcmp(argv[1], "unique") == 0)
181148834Sstefanf		return history(el->el_history.ref, &ev, H_SETUNIQUE, num);
182148834Sstefanf
183148834Sstefanf	return -1;
1841573Srgrimes}
18584260Sobrien
18684260Sobrien/* hist_enlargebuf()
18784260Sobrien *	Enlarge history buffer to specified value. Called from el_enlargebufs().
18884260Sobrien *	Return 0 for failure, 1 for success.
18984260Sobrien */
19084260Sobrienprotected int
19184260Sobrien/*ARGSUSED*/
19284260Sobrienhist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
19384260Sobrien{
19484260Sobrien	char *newbuf;
19584260Sobrien
19684260Sobrien	newbuf = realloc(el->el_history.buf, newsz);
19784260Sobrien	if (!newbuf)
19884260Sobrien		return 0;
19984260Sobrien
20084260Sobrien	(void) memset(&newbuf[oldsz], '\0', newsz - oldsz);
20184260Sobrien
20284260Sobrien	el->el_history.last = newbuf +
20384260Sobrien				(el->el_history.last - el->el_history.buf);
20484260Sobrien	el->el_history.buf = newbuf;
20584260Sobrien	el->el_history.sz  = newsz;
20684260Sobrien
20784260Sobrien	return 1;
20884260Sobrien}
209