Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libedit/hist.c
39475 views
1
/* $NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 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.34 2019/07/23 10:19:35 christos Exp $");
41
#endif
42
#endif /* not lint && not SCCSID */
43
44
/*
45
* hist.c: History access functions
46
*/
47
#include <stdlib.h>
48
#include <string.h>
49
#include <vis.h>
50
51
#include "el.h"
52
53
/* hist_init():
54
* Initialization function.
55
*/
56
libedit_private int
57
hist_init(EditLine *el)
58
{
59
60
el->el_history.fun = NULL;
61
el->el_history.ref = NULL;
62
el->el_history.buf = el_calloc(EL_BUFSIZ, sizeof(*el->el_history.buf));
63
if (el->el_history.buf == NULL)
64
return -1;
65
el->el_history.sz = EL_BUFSIZ;
66
el->el_history.last = el->el_history.buf;
67
return 0;
68
}
69
70
71
/* hist_end():
72
* clean up history;
73
*/
74
libedit_private void
75
hist_end(EditLine *el)
76
{
77
78
el_free(el->el_history.buf);
79
el->el_history.buf = NULL;
80
}
81
82
83
/* hist_set():
84
* Set new history interface
85
*/
86
libedit_private int
87
hist_set(EditLine *el, hist_fun_t fun, void *ptr)
88
{
89
90
el->el_history.ref = ptr;
91
el->el_history.fun = fun;
92
return 0;
93
}
94
95
96
/* hist_get():
97
* Get a history line and update it in the buffer.
98
* eventno tells us the event to get.
99
*/
100
libedit_private el_action_t
101
hist_get(EditLine *el)
102
{
103
const wchar_t *hp;
104
int h;
105
size_t blen, hlen;
106
107
if (el->el_history.eventno == 0) { /* if really the current line */
108
(void) wcsncpy(el->el_line.buffer, el->el_history.buf,
109
el->el_history.sz);
110
el->el_line.lastchar = el->el_line.buffer +
111
(el->el_history.last - el->el_history.buf);
112
113
#ifdef KSHVI
114
if (el->el_map.type == MAP_VI)
115
el->el_line.cursor = el->el_line.buffer;
116
else
117
#endif /* KSHVI */
118
el->el_line.cursor = el->el_line.lastchar;
119
120
return CC_REFRESH;
121
}
122
if (el->el_history.ref == NULL)
123
return CC_ERROR;
124
125
hp = HIST_FIRST(el);
126
127
if (hp == NULL)
128
return CC_ERROR;
129
130
for (h = 1; h < el->el_history.eventno; h++)
131
if ((hp = HIST_NEXT(el)) == NULL)
132
goto out;
133
134
hlen = wcslen(hp) + 1;
135
blen = (size_t)(el->el_line.limit - el->el_line.buffer);
136
if (hlen > blen && !ch_enlargebufs(el, hlen))
137
goto out;
138
139
memcpy(el->el_line.buffer, hp, hlen * sizeof(*hp));
140
el->el_line.lastchar = el->el_line.buffer + hlen - 1;
141
142
if (el->el_line.lastchar > el->el_line.buffer
143
&& el->el_line.lastchar[-1] == '\n')
144
el->el_line.lastchar--;
145
if (el->el_line.lastchar > el->el_line.buffer
146
&& el->el_line.lastchar[-1] == ' ')
147
el->el_line.lastchar--;
148
#ifdef KSHVI
149
if (el->el_map.type == MAP_VI)
150
el->el_line.cursor = el->el_line.buffer;
151
else
152
#endif /* KSHVI */
153
el->el_line.cursor = el->el_line.lastchar;
154
155
return CC_REFRESH;
156
out:
157
el->el_history.eventno = h;
158
return CC_ERROR;
159
160
}
161
162
163
/* hist_command()
164
* process a history command
165
*/
166
libedit_private int
167
hist_command(EditLine *el, int argc, const wchar_t **argv)
168
{
169
const wchar_t *str;
170
int num;
171
HistEventW ev;
172
173
if (el->el_history.ref == NULL)
174
return -1;
175
176
if (argc == 1 || wcscmp(argv[1], L"list") == 0) {
177
size_t maxlen = 0;
178
char *buf = NULL;
179
int hno = 1;
180
/* List history entries */
181
182
for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) {
183
char *ptr =
184
ct_encode_string(str, &el->el_scratch);
185
size_t len = strlen(ptr);
186
if (len > 0 && ptr[len - 1] == '\n')
187
ptr[--len] = '\0';
188
len = len * 4 + 1;
189
if (len >= maxlen) {
190
maxlen = len + 1024;
191
char *nbuf = el_realloc(buf, maxlen);
192
if (nbuf == NULL) {
193
el_free(buf);
194
return -1;
195
}
196
buf = nbuf;
197
}
198
strvis(buf, ptr, VIS_NL);
199
(void) fprintf(el->el_outfile, "%d\t%s\n",
200
hno++, buf);
201
}
202
el_free(buf);
203
return 0;
204
}
205
206
if (argc != 3)
207
return -1;
208
209
num = (int)wcstol(argv[2], NULL, 0);
210
211
if (wcscmp(argv[1], L"size") == 0)
212
return history_w(el->el_history.ref, &ev, H_SETSIZE, num);
213
214
if (wcscmp(argv[1], L"unique") == 0)
215
return history_w(el->el_history.ref, &ev, H_SETUNIQUE, num);
216
217
return -1;
218
}
219
220
/* hist_enlargebuf()
221
* Enlarge history buffer to specified value. Called from el_enlargebufs().
222
* Return 0 for failure, 1 for success.
223
*/
224
libedit_private int
225
/*ARGSUSED*/
226
hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
227
{
228
wchar_t *newbuf;
229
230
newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf));
231
if (!newbuf)
232
return 0;
233
234
(void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf));
235
236
el->el_history.last = newbuf +
237
(el->el_history.last - el->el_history.buf);
238
el->el_history.buf = newbuf;
239
el->el_history.sz = newsz;
240
241
return 1;
242
}
243
244
libedit_private wchar_t *
245
hist_convert(EditLine *el, int fn, void *arg)
246
{
247
HistEventW ev;
248
if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1)
249
return NULL;
250
return ct_decode_string((const char *)(const void *)ev.str,
251
&el->el_scratch);
252
}
253
254