]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libedit/hist.c
MFV r301238:
[FreeBSD/FreeBSD.git] / lib / libedit / hist.c
1 /*      $NetBSD: hist.c,v 1.20 2011/07/29 15:16:33 christos Exp $       */
2
3 /*-
4  * Copyright (c) 1992, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Christos Zoulas of Cornell University.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. Neither the name of the University nor the names of its contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34
35 #include "config.h"
36 #if !defined(lint) && !defined(SCCSID)
37 #if 0
38 static char sccsid[] = "@(#)hist.c      8.1 (Berkeley) 6/4/93";
39 #else
40 __RCSID("$NetBSD: hist.c,v 1.20 2011/07/29 15:16:33 christos Exp $");
41 #endif
42 #endif /* not lint && not SCCSID */
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 /*
47  * hist.c: History access functions
48  */
49 #include <stdlib.h>
50 #include "el.h"
51
52 /* hist_init():
53  *      Initialization function.
54  */
55 protected int
56 hist_init(EditLine *el)
57 {
58
59         el->el_history.fun = NULL;
60         el->el_history.ref = NULL;
61         el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf));
62         el->el_history.sz  = EL_BUFSIZ;
63         if (el->el_history.buf == NULL)
64                 return -1;
65         el->el_history.last = el->el_history.buf;
66         return 0;
67 }
68
69
70 /* hist_end():
71  *      clean up history;
72  */
73 protected void
74 hist_end(EditLine *el)
75 {
76
77         el_free(el->el_history.buf);
78         el->el_history.buf = NULL;
79 }
80
81
82 /* hist_set():
83  *      Set new history interface
84  */
85 protected int
86 hist_set(EditLine *el, hist_fun_t fun, void *ptr)
87 {
88
89         el->el_history.ref = ptr;
90         el->el_history.fun = fun;
91         return 0;
92 }
93
94
95 /* hist_get():
96  *      Get a history line and update it in the buffer.
97  *      eventno tells us the event to get.
98  */
99 protected el_action_t
100 hist_get(EditLine *el)
101 {
102         const Char *hp;
103         int h;
104
105         if (el->el_history.eventno == 0) {      /* if really the current line */
106                 (void) Strncpy(el->el_line.buffer, el->el_history.buf,
107                     el->el_history.sz);
108                 el->el_line.lastchar = el->el_line.buffer +
109                     (el->el_history.last - el->el_history.buf);
110
111 #ifdef KSHVI
112                 if (el->el_map.type == MAP_VI)
113                         el->el_line.cursor = el->el_line.buffer;
114                 else
115 #endif /* KSHVI */
116                         el->el_line.cursor = el->el_line.lastchar;
117
118                 return CC_REFRESH;
119         }
120         if (el->el_history.ref == NULL)
121                 return CC_ERROR;
122
123         hp = HIST_FIRST(el);
124
125         if (hp == NULL)
126                 return CC_ERROR;
127
128         for (h = 1; h < el->el_history.eventno; h++)
129                 if ((hp = HIST_NEXT(el)) == NULL) {
130                         el->el_history.eventno = h;
131                         return CC_ERROR;
132                 }
133         (void) Strncpy(el->el_line.buffer, hp,
134                         (size_t)(el->el_line.limit - el->el_line.buffer));
135         el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = '\0';
136         el->el_line.lastchar = el->el_line.buffer + Strlen(el->el_line.buffer);
137
138         if (el->el_line.lastchar > el->el_line.buffer
139             && el->el_line.lastchar[-1] == '\n')
140                 el->el_line.lastchar--;
141         if (el->el_line.lastchar > el->el_line.buffer
142             && el->el_line.lastchar[-1] == ' ')
143                 el->el_line.lastchar--;
144 #ifdef KSHVI
145         if (el->el_map.type == MAP_VI)
146                 el->el_line.cursor = el->el_line.buffer;
147         else
148 #endif /* KSHVI */
149                 el->el_line.cursor = el->el_line.lastchar;
150
151         return CC_REFRESH;
152 }
153
154
155 /* hist_command()
156  *      process a history command
157  */
158 protected int
159 hist_command(EditLine *el, int argc, const Char **argv)
160 {
161         const Char *str;
162         int num;
163         TYPE(HistEvent) ev;
164
165         if (el->el_history.ref == NULL)
166                 return -1;
167
168         if (argc == 1 || Strcmp(argv[1], STR("list")) == 0) {
169                  /* List history entries */
170
171                 for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
172                         (void) fprintf(el->el_outfile, "%d %s",
173                             el->el_history.ev.num, ct_encode_string(str, &el->el_scratch));
174                 return 0;
175         }
176
177         if (argc != 3)
178                 return -1;
179
180         num = (int)Strtol(argv[2], NULL, 0);
181
182         if (Strcmp(argv[1], STR("size")) == 0)
183                 return FUNW(history)(el->el_history.ref, &ev, H_SETSIZE, num);
184
185         if (Strcmp(argv[1], STR("unique")) == 0)
186                 return FUNW(history)(el->el_history.ref, &ev, H_SETUNIQUE, num);
187
188         return -1;
189 }
190
191 /* hist_enlargebuf()
192  *      Enlarge history buffer to specified value. Called from el_enlargebufs().
193  *      Return 0 for failure, 1 for success.
194  */
195 protected int
196 /*ARGSUSED*/
197 hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
198 {
199         Char *newbuf;
200
201         newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf));
202         if (!newbuf)
203                 return 0;
204
205         (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf));
206
207         el->el_history.last = newbuf +
208                                 (el->el_history.last - el->el_history.buf);
209         el->el_history.buf = newbuf;
210         el->el_history.sz  = newsz;
211
212         return 1;
213 }
214
215 #ifdef WIDECHAR
216 protected wchar_t *
217 hist_convert(EditLine *el, int fn, void *arg)
218 {
219         HistEventW ev;
220         if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1)
221                 return NULL;
222         return ct_decode_string((const char *)(const void *)ev.str,
223             &el->el_scratch);
224 }
225 #endif