Fri Jul 29 20:58:07 2011 UTC ()
- fix unused params
- unconditionalize vis.h


(christos)
diff -r1.27 -r1.28 src/lib/libedit/common.c
diff -r1.27 -r1.28 src/lib/libedit/filecomplete.c
diff -r1.43 -r1.44 src/lib/libedit/history.c
diff -r1.96 -r1.97 src/lib/libedit/readline.c
diff -r1.37 -r1.38 src/lib/libedit/vi.c

cvs diff -r1.27 -r1.28 src/lib/libedit/common.c (switch to unified diff)

--- src/lib/libedit/common.c 2011/07/29 15:20:39 1.27
+++ src/lib/libedit/common.c 2011/07/29 20:58:07 1.28
@@ -1,921 +1,922 @@ @@ -1,921 +1,922 @@
1/* $NetBSD: common.c,v 1.27 2011/07/29 15:20:39 christos Exp $ */ 1/* $NetBSD: common.c,v 1.28 2011/07/29 20:58:07 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University. 8 * Christos Zoulas of Cornell University.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 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 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include "config.h" 35#include "config.h"
36#if !defined(lint) && !defined(SCCSID) 36#if !defined(lint) && !defined(SCCSID)
37#if 0 37#if 0
38static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; 38static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
39#else 39#else
40__RCSID("$NetBSD: common.c,v 1.27 2011/07/29 15:20:39 christos Exp $"); 40__RCSID("$NetBSD: common.c,v 1.28 2011/07/29 20:58:07 christos Exp $");
41#endif 41#endif
42#endif /* not lint && not SCCSID */ 42#endif /* not lint && not SCCSID */
43 43
44/* 44/*
45 * common.c: Common Editor functions 45 * common.c: Common Editor functions
46 */ 46 */
47#include "el.h" 47#include "el.h"
48 48
49/* ed_end_of_file(): 49/* ed_end_of_file():
50 * Indicate end of file 50 * Indicate end of file
51 * [^D] 51 * [^D]
52 */ 52 */
53protected el_action_t 53protected el_action_t
54/*ARGSUSED*/ 54/*ARGSUSED*/
55ed_end_of_file(EditLine *el, Int c __attribute__((__unused__))) 55ed_end_of_file(EditLine *el, Int c __attribute__((__unused__)))
56{ 56{
57 57
58 re_goto_bottom(el); 58 re_goto_bottom(el);
59 *el->el_line.lastchar = '\0'; 59 *el->el_line.lastchar = '\0';
60 return CC_EOF; 60 return CC_EOF;
61} 61}
62 62
63 63
64/* ed_insert(): 64/* ed_insert():
65 * Add character to the line 65 * Add character to the line
66 * Insert a character [bound to all insert keys] 66 * Insert a character [bound to all insert keys]
67 */ 67 */
68protected el_action_t 68protected el_action_t
69ed_insert(EditLine *el, Int c) 69ed_insert(EditLine *el, Int c)
70{ 70{
71 int count = el->el_state.argument; 71 int count = el->el_state.argument;
72 72
73 if (c == '\0') 73 if (c == '\0')
74 return CC_ERROR; 74 return CC_ERROR;
75 75
76 if (el->el_line.lastchar + el->el_state.argument >= 76 if (el->el_line.lastchar + el->el_state.argument >=
77 el->el_line.limit) { 77 el->el_line.limit) {
78 /* end of buffer space, try to allocate more */ 78 /* end of buffer space, try to allocate more */
79 if (!ch_enlargebufs(el, (size_t) count)) 79 if (!ch_enlargebufs(el, (size_t) count))
80 return CC_ERROR; /* error allocating more */ 80 return CC_ERROR; /* error allocating more */
81 } 81 }
82 82
83 if (count == 1) { 83 if (count == 1) {
84 if (el->el_state.inputmode == MODE_INSERT 84 if (el->el_state.inputmode == MODE_INSERT
85 || el->el_line.cursor >= el->el_line.lastchar) 85 || el->el_line.cursor >= el->el_line.lastchar)
86 c_insert(el, 1); 86 c_insert(el, 1);
87 87
88 *el->el_line.cursor++ = c; 88 *el->el_line.cursor++ = c;
89 re_fastaddc(el); /* fast refresh for one char. */ 89 re_fastaddc(el); /* fast refresh for one char. */
90 } else { 90 } else {
91 if (el->el_state.inputmode != MODE_REPLACE_1) 91 if (el->el_state.inputmode != MODE_REPLACE_1)
92 c_insert(el, el->el_state.argument); 92 c_insert(el, el->el_state.argument);
93 93
94 while (count-- && el->el_line.cursor < el->el_line.lastchar) 94 while (count-- && el->el_line.cursor < el->el_line.lastchar)
95 *el->el_line.cursor++ = c; 95 *el->el_line.cursor++ = c;
96 re_refresh(el); 96 re_refresh(el);
97 } 97 }
98 98
99 if (el->el_state.inputmode == MODE_REPLACE_1) 99 if (el->el_state.inputmode == MODE_REPLACE_1)
100 return vi_command_mode(el, 0); 100 return vi_command_mode(el, 0);
101 101
102 return CC_NORM; 102 return CC_NORM;
103} 103}
104 104
105 105
106/* ed_delete_prev_word(): 106/* ed_delete_prev_word():
107 * Delete from beginning of current word to cursor 107 * Delete from beginning of current word to cursor
108 * [M-^?] [^W] 108 * [M-^?] [^W]
109 */ 109 */
110protected el_action_t 110protected el_action_t
111/*ARGSUSED*/ 111/*ARGSUSED*/
112ed_delete_prev_word(EditLine *el, Int c __attribute__((__unused__))) 112ed_delete_prev_word(EditLine *el, Int c __attribute__((__unused__)))
113{ 113{
114 Char *cp, *p, *kp; 114 Char *cp, *p, *kp;
115 115
116 if (el->el_line.cursor == el->el_line.buffer) 116 if (el->el_line.cursor == el->el_line.buffer)
117 return CC_ERROR; 117 return CC_ERROR;
118 118
119 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, 119 cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
120 el->el_state.argument, ce__isword); 120 el->el_state.argument, ce__isword);
121 121
122 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++) 122 for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
123 *kp++ = *p; 123 *kp++ = *p;
124 el->el_chared.c_kill.last = kp; 124 el->el_chared.c_kill.last = kp;
125 125
126 c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */ 126 c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */
127 el->el_line.cursor = cp; 127 el->el_line.cursor = cp;
128 if (el->el_line.cursor < el->el_line.buffer) 128 if (el->el_line.cursor < el->el_line.buffer)
129 el->el_line.cursor = el->el_line.buffer; /* bounds check */ 129 el->el_line.cursor = el->el_line.buffer; /* bounds check */
130 return CC_REFRESH; 130 return CC_REFRESH;
131} 131}
132 132
133 133
134/* ed_delete_next_char(): 134/* ed_delete_next_char():
135 * Delete character under cursor 135 * Delete character under cursor
136 * [^D] [x] 136 * [^D] [x]
137 */ 137 */
138protected el_action_t 138protected el_action_t
139/*ARGSUSED*/ 139/*ARGSUSED*/
140ed_delete_next_char(EditLine *el, Int c) 140ed_delete_next_char(EditLine *el, Int c __attribute__((__unused__)))
141{ 141{
142#ifdef DEBUG_EDIT 142#ifdef DEBUG_EDIT
143#define EL el->el_line 143#define EL el->el_line
144 (void) fprintf(el->el_errlfile, 144 (void) fprintf(el->el_errlfile,
145 "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n", 145 "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n",
146 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar, 146 EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
147 EL.lastchar, EL.limit, EL.limit); 147 EL.lastchar, EL.limit, EL.limit);
148#endif 148#endif
149 if (el->el_line.cursor == el->el_line.lastchar) { 149 if (el->el_line.cursor == el->el_line.lastchar) {
150 /* if I'm at the end */ 150 /* if I'm at the end */
151 if (el->el_map.type == MAP_VI) { 151 if (el->el_map.type == MAP_VI) {
152 if (el->el_line.cursor == el->el_line.buffer) { 152 if (el->el_line.cursor == el->el_line.buffer) {
153 /* if I'm also at the beginning */ 153 /* if I'm also at the beginning */
154#ifdef KSHVI 154#ifdef KSHVI
155 return CC_ERROR; 155 return CC_ERROR;
156#else 156#else
157 /* then do an EOF */ 157 /* then do an EOF */
158 terminal_writec(el, c); 158 terminal_writec(el, c);
159 return CC_EOF; 159 return CC_EOF;
160#endif 160#endif
161 } else { 161 } else {
162#ifdef KSHVI 162#ifdef KSHVI
163 el->el_line.cursor--; 163 el->el_line.cursor--;
164#else 164#else
165 return CC_ERROR; 165 return CC_ERROR;
166#endif 166#endif
167 } 167 }
168 } else { 168 } else {
169 if (el->el_line.cursor != el->el_line.buffer) 169 if (el->el_line.cursor != el->el_line.buffer)
170 el->el_line.cursor--; 170 el->el_line.cursor--;
171 else 171 else
172 return CC_ERROR; 172 return CC_ERROR;
173 } 173 }
174 } 174 }
175 c_delafter(el, el->el_state.argument); /* delete after dot */ 175 c_delafter(el, el->el_state.argument); /* delete after dot */
176 if (el->el_line.cursor >= el->el_line.lastchar && 176 if (el->el_line.cursor >= el->el_line.lastchar &&
177 el->el_line.cursor > el->el_line.buffer) 177 el->el_line.cursor > el->el_line.buffer)
178 /* bounds check */ 178 /* bounds check */
179 el->el_line.cursor = el->el_line.lastchar - 1; 179 el->el_line.cursor = el->el_line.lastchar - 1;
180 return CC_REFRESH; 180 return CC_REFRESH;
181} 181}
182 182
183 183
184/* ed_kill_line(): 184/* ed_kill_line():
185 * Cut to the end of line 185 * Cut to the end of line
186 * [^K] [^K] 186 * [^K] [^K]
187 */ 187 */
188protected el_action_t 188protected el_action_t
189/*ARGSUSED*/ 189/*ARGSUSED*/
190ed_kill_line(EditLine *el, Int c __attribute__((__unused__))) 190ed_kill_line(EditLine *el, Int c __attribute__((__unused__)))
191{ 191{
192 Char *kp, *cp; 192 Char *kp, *cp;
193 193
194 cp = el->el_line.cursor; 194 cp = el->el_line.cursor;
195 kp = el->el_chared.c_kill.buf; 195 kp = el->el_chared.c_kill.buf;
196 while (cp < el->el_line.lastchar) 196 while (cp < el->el_line.lastchar)
197 *kp++ = *cp++; /* copy it */ 197 *kp++ = *cp++; /* copy it */
198 el->el_chared.c_kill.last = kp; 198 el->el_chared.c_kill.last = kp;
199 /* zap! -- delete to end */ 199 /* zap! -- delete to end */
200 el->el_line.lastchar = el->el_line.cursor; 200 el->el_line.lastchar = el->el_line.cursor;
201 return CC_REFRESH; 201 return CC_REFRESH;
202} 202}
203 203
204 204
205/* ed_move_to_end(): 205/* ed_move_to_end():
206 * Move cursor to the end of line 206 * Move cursor to the end of line
207 * [^E] [^E] 207 * [^E] [^E]
208 */ 208 */
209protected el_action_t 209protected el_action_t
210/*ARGSUSED*/ 210/*ARGSUSED*/
211ed_move_to_end(EditLine *el, Int c __attribute__((__unused__))) 211ed_move_to_end(EditLine *el, Int c __attribute__((__unused__)))
212{ 212{
213 213
214 el->el_line.cursor = el->el_line.lastchar; 214 el->el_line.cursor = el->el_line.lastchar;
215 if (el->el_map.type == MAP_VI) { 215 if (el->el_map.type == MAP_VI) {
216 if (el->el_chared.c_vcmd.action != NOP) { 216 if (el->el_chared.c_vcmd.action != NOP) {
217 cv_delfini(el); 217 cv_delfini(el);
218 return CC_REFRESH; 218 return CC_REFRESH;
219 } 219 }
220#ifdef VI_MOVE 220#ifdef VI_MOVE
221 el->el_line.cursor--; 221 el->el_line.cursor--;
222#endif 222#endif
223 } 223 }
224 return CC_CURSOR; 224 return CC_CURSOR;
225} 225}
226 226
227 227
228/* ed_move_to_beg(): 228/* ed_move_to_beg():
229 * Move cursor to the beginning of line 229 * Move cursor to the beginning of line
230 * [^A] [^A] 230 * [^A] [^A]
231 */ 231 */
232protected el_action_t 232protected el_action_t
233/*ARGSUSED*/ 233/*ARGSUSED*/
234ed_move_to_beg(EditLine *el, Int c __attribute__((__unused__))) 234ed_move_to_beg(EditLine *el, Int c __attribute__((__unused__)))
235{ 235{
236 236
237 el->el_line.cursor = el->el_line.buffer; 237 el->el_line.cursor = el->el_line.buffer;
238 238
239 if (el->el_map.type == MAP_VI) { 239 if (el->el_map.type == MAP_VI) {
240 /* We want FIRST non space character */ 240 /* We want FIRST non space character */
241 while (Isspace(*el->el_line.cursor)) 241 while (Isspace(*el->el_line.cursor))
242 el->el_line.cursor++; 242 el->el_line.cursor++;
243 if (el->el_chared.c_vcmd.action != NOP) { 243 if (el->el_chared.c_vcmd.action != NOP) {
244 cv_delfini(el); 244 cv_delfini(el);
245 return CC_REFRESH; 245 return CC_REFRESH;
246 } 246 }
247 } 247 }
248 return CC_CURSOR; 248 return CC_CURSOR;
249} 249}
250 250
251 251
252/* ed_transpose_chars(): 252/* ed_transpose_chars():
253 * Exchange the character to the left of the cursor with the one under it 253 * Exchange the character to the left of the cursor with the one under it
254 * [^T] [^T] 254 * [^T] [^T]
255 */ 255 */
256protected el_action_t 256protected el_action_t
257ed_transpose_chars(EditLine *el, Int c) 257ed_transpose_chars(EditLine *el, Int c)
258{ 258{
259 259
260 if (el->el_line.cursor < el->el_line.lastchar) { 260 if (el->el_line.cursor < el->el_line.lastchar) {
261 if (el->el_line.lastchar <= &el->el_line.buffer[1]) 261 if (el->el_line.lastchar <= &el->el_line.buffer[1])
262 return CC_ERROR; 262 return CC_ERROR;
263 else 263 else
264 el->el_line.cursor++; 264 el->el_line.cursor++;
265 } 265 }
266 if (el->el_line.cursor > &el->el_line.buffer[1]) { 266 if (el->el_line.cursor > &el->el_line.buffer[1]) {
267 /* must have at least two chars entered */ 267 /* must have at least two chars entered */
268 c = el->el_line.cursor[-2]; 268 c = el->el_line.cursor[-2];
269 el->el_line.cursor[-2] = el->el_line.cursor[-1]; 269 el->el_line.cursor[-2] = el->el_line.cursor[-1];
270 el->el_line.cursor[-1] = c; 270 el->el_line.cursor[-1] = c;
271 return CC_REFRESH; 271 return CC_REFRESH;
272 } else 272 } else
273 return CC_ERROR; 273 return CC_ERROR;
274} 274}
275 275
276 276
277/* ed_next_char(): 277/* ed_next_char():
278 * Move to the right one character 278 * Move to the right one character
279 * [^F] [^F] 279 * [^F] [^F]
280 */ 280 */
281protected el_action_t 281protected el_action_t
282/*ARGSUSED*/ 282/*ARGSUSED*/
283ed_next_char(EditLine *el, Int c __attribute__((__unused__))) 283ed_next_char(EditLine *el, Int c __attribute__((__unused__)))
284{ 284{
285 Char *lim = el->el_line.lastchar; 285 Char *lim = el->el_line.lastchar;
286 286
287 if (el->el_line.cursor >= lim || 287 if (el->el_line.cursor >= lim ||
288 (el->el_line.cursor == lim - 1 && 288 (el->el_line.cursor == lim - 1 &&
289 el->el_map.type == MAP_VI && 289 el->el_map.type == MAP_VI &&
290 el->el_chared.c_vcmd.action == NOP)) 290 el->el_chared.c_vcmd.action == NOP))
291 return CC_ERROR; 291 return CC_ERROR;
292 292
293 el->el_line.cursor += el->el_state.argument; 293 el->el_line.cursor += el->el_state.argument;
294 if (el->el_line.cursor > lim) 294 if (el->el_line.cursor > lim)
295 el->el_line.cursor = lim; 295 el->el_line.cursor = lim;
296 296
297 if (el->el_map.type == MAP_VI) 297 if (el->el_map.type == MAP_VI)
298 if (el->el_chared.c_vcmd.action != NOP) { 298 if (el->el_chared.c_vcmd.action != NOP) {
299 cv_delfini(el); 299 cv_delfini(el);
300 return CC_REFRESH; 300 return CC_REFRESH;
301 } 301 }
302 return CC_CURSOR; 302 return CC_CURSOR;
303} 303}
304 304
305 305
306/* ed_prev_word(): 306/* ed_prev_word():
307 * Move to the beginning of the current word 307 * Move to the beginning of the current word
308 * [M-b] [b] 308 * [M-b] [b]
309 */ 309 */
310protected el_action_t 310protected el_action_t
311/*ARGSUSED*/ 311/*ARGSUSED*/
312ed_prev_word(EditLine *el, Int c __attribute__((__unused__))) 312ed_prev_word(EditLine *el, Int c __attribute__((__unused__)))
313{ 313{
314 314
315 if (el->el_line.cursor == el->el_line.buffer) 315 if (el->el_line.cursor == el->el_line.buffer)
316 return CC_ERROR; 316 return CC_ERROR;
317 317
318 el->el_line.cursor = c__prev_word(el->el_line.cursor, 318 el->el_line.cursor = c__prev_word(el->el_line.cursor,
319 el->el_line.buffer, 319 el->el_line.buffer,
320 el->el_state.argument, 320 el->el_state.argument,
321 ce__isword); 321 ce__isword);
322 322
323 if (el->el_map.type == MAP_VI) 323 if (el->el_map.type == MAP_VI)
324 if (el->el_chared.c_vcmd.action != NOP) { 324 if (el->el_chared.c_vcmd.action != NOP) {
325 cv_delfini(el); 325 cv_delfini(el);
326 return CC_REFRESH; 326 return CC_REFRESH;
327 } 327 }
328 return CC_CURSOR; 328 return CC_CURSOR;
329} 329}
330 330
331 331
332/* ed_prev_char(): 332/* ed_prev_char():
333 * Move to the left one character 333 * Move to the left one character
334 * [^B] [^B] 334 * [^B] [^B]
335 */ 335 */
336protected el_action_t 336protected el_action_t
337/*ARGSUSED*/ 337/*ARGSUSED*/
338ed_prev_char(EditLine *el, Int c __attribute__((__unused__))) 338ed_prev_char(EditLine *el, Int c __attribute__((__unused__)))
339{ 339{
340 340
341 if (el->el_line.cursor > el->el_line.buffer) { 341 if (el->el_line.cursor > el->el_line.buffer) {
342 el->el_line.cursor -= el->el_state.argument; 342 el->el_line.cursor -= el->el_state.argument;
343 if (el->el_line.cursor < el->el_line.buffer) 343 if (el->el_line.cursor < el->el_line.buffer)
344 el->el_line.cursor = el->el_line.buffer; 344 el->el_line.cursor = el->el_line.buffer;
345 345
346 if (el->el_map.type == MAP_VI) 346 if (el->el_map.type == MAP_VI)
347 if (el->el_chared.c_vcmd.action != NOP) { 347 if (el->el_chared.c_vcmd.action != NOP) {
348 cv_delfini(el); 348 cv_delfini(el);
349 return CC_REFRESH; 349 return CC_REFRESH;
350 } 350 }
351 return CC_CURSOR; 351 return CC_CURSOR;
352 } else 352 } else
353 return CC_ERROR; 353 return CC_ERROR;
354} 354}
355 355
356 356
357/* ed_quoted_insert(): 357/* ed_quoted_insert():
358 * Add the next character typed verbatim 358 * Add the next character typed verbatim
359 * [^V] [^V] 359 * [^V] [^V]
360 */ 360 */
361protected el_action_t 361protected el_action_t
362ed_quoted_insert(EditLine *el, Int c) 362ed_quoted_insert(EditLine *el, Int c)
363{ 363{
364 int num; 364 int num;
365 Char tc; 365 Char tc;
366 366
367 tty_quotemode(el); 367 tty_quotemode(el);
368 num = FUN(el,getc)(el, &tc); 368 num = FUN(el,getc)(el, &tc);
369 c = tc; 369 c = tc;
370 tty_noquotemode(el); 370 tty_noquotemode(el);
371 if (num == 1) 371 if (num == 1)
372 return ed_insert(el, c); 372 return ed_insert(el, c);
373 else 373 else
374 return ed_end_of_file(el, 0); 374 return ed_end_of_file(el, 0);
375} 375}
376 376
377 377
378/* ed_digit(): 378/* ed_digit():
379 * Adds to argument or enters a digit 379 * Adds to argument or enters a digit
380 */ 380 */
381protected el_action_t 381protected el_action_t
382ed_digit(EditLine *el, Int c) 382ed_digit(EditLine *el, Int c)
383{ 383{
384 384
385 if (!Isdigit(c)) 385 if (!Isdigit(c))
386 return CC_ERROR; 386 return CC_ERROR;
387 387
388 if (el->el_state.doingarg) { 388 if (el->el_state.doingarg) {
389 /* if doing an arg, add this in... */ 389 /* if doing an arg, add this in... */
390 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT) 390 if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
391 el->el_state.argument = c - '0'; 391 el->el_state.argument = c - '0';
392 else { 392 else {
393 if (el->el_state.argument > 1000000) 393 if (el->el_state.argument > 1000000)
394 return CC_ERROR; 394 return CC_ERROR;
395 el->el_state.argument = 395 el->el_state.argument =
396 (el->el_state.argument * 10) + (c - '0'); 396 (el->el_state.argument * 10) + (c - '0');
397 } 397 }
398 return CC_ARGHACK; 398 return CC_ARGHACK;
399 } 399 }
400 400
401 return ed_insert(el, c); 401 return ed_insert(el, c);
402} 402}
403 403
404 404
405/* ed_argument_digit(): 405/* ed_argument_digit():
406 * Digit that starts argument 406 * Digit that starts argument
407 * For ESC-n 407 * For ESC-n
408 */ 408 */
409protected el_action_t 409protected el_action_t
410ed_argument_digit(EditLine *el, Int c) 410ed_argument_digit(EditLine *el, Int c)
411{ 411{
412 412
413 if (!Isdigit(c)) 413 if (!Isdigit(c))
414 return CC_ERROR; 414 return CC_ERROR;
415 415
416 if (el->el_state.doingarg) { 416 if (el->el_state.doingarg) {
417 if (el->el_state.argument > 1000000) 417 if (el->el_state.argument > 1000000)
418 return CC_ERROR; 418 return CC_ERROR;
419 el->el_state.argument = (el->el_state.argument * 10) + 419 el->el_state.argument = (el->el_state.argument * 10) +
420 (c - '0'); 420 (c - '0');
421 } else { /* else starting an argument */ 421 } else { /* else starting an argument */
422 el->el_state.argument = c - '0'; 422 el->el_state.argument = c - '0';
423 el->el_state.doingarg = 1; 423 el->el_state.doingarg = 1;
424 } 424 }
425 return CC_ARGHACK; 425 return CC_ARGHACK;
426} 426}
427 427
428 428
429/* ed_unassigned(): 429/* ed_unassigned():
430 * Indicates unbound character 430 * Indicates unbound character
431 * Bound to keys that are not assigned 431 * Bound to keys that are not assigned
432 */ 432 */
433protected el_action_t 433protected el_action_t
434/*ARGSUSED*/ 434/*ARGSUSED*/
435ed_unassigned(EditLine *el, Int c __attribute__((__unused__))) 435ed_unassigned(EditLine *el __attribute__((__unused__)),
 436 Int c __attribute__((__unused__)))
436{ 437{
437 438
438 return CC_ERROR; 439 return CC_ERROR;
439} 440}
440 441
441 442
442/** 443/**
443 ** TTY key handling. 444 ** TTY key handling.
444 **/ 445 **/
445 446
446/* ed_tty_sigint(): 447/* ed_tty_sigint():
447 * Tty interrupt character 448 * Tty interrupt character
448 * [^C] 449 * [^C]
449 */ 450 */
450protected el_action_t 451protected el_action_t
451/*ARGSUSED*/ 452/*ARGSUSED*/
452ed_tty_sigint(EditLine *el __attribute__((__unused__)),  453ed_tty_sigint(EditLine *el __attribute__((__unused__)),
453 Int c __attribute__((__unused__))) 454 Int c __attribute__((__unused__)))
454{ 455{
455 456
456 return CC_NORM; 457 return CC_NORM;
457} 458}
458 459
459 460
460/* ed_tty_dsusp(): 461/* ed_tty_dsusp():
461 * Tty delayed suspend character 462 * Tty delayed suspend character
462 * [^Y] 463 * [^Y]
463 */ 464 */
464protected el_action_t 465protected el_action_t
465/*ARGSUSED*/ 466/*ARGSUSED*/
466ed_tty_dsusp(EditLine *el __attribute__((__unused__)),  467ed_tty_dsusp(EditLine *el __attribute__((__unused__)),
467 Int c __attribute__((__unused__))) 468 Int c __attribute__((__unused__)))
468{ 469{
469 470
470 return CC_NORM; 471 return CC_NORM;
471} 472}
472 473
473 474
474/* ed_tty_flush_output(): 475/* ed_tty_flush_output():
475 * Tty flush output characters 476 * Tty flush output characters
476 * [^O] 477 * [^O]
477 */ 478 */
478protected el_action_t 479protected el_action_t
479/*ARGSUSED*/ 480/*ARGSUSED*/
480ed_tty_flush_output(EditLine *el __attribute__((__unused__)),  481ed_tty_flush_output(EditLine *el __attribute__((__unused__)),
481 Int c __attribute__((__unused__))) 482 Int c __attribute__((__unused__)))
482{ 483{
483 484
484 return CC_NORM; 485 return CC_NORM;
485} 486}
486 487
487 488
488/* ed_tty_sigquit(): 489/* ed_tty_sigquit():
489 * Tty quit character 490 * Tty quit character
490 * [^\] 491 * [^\]
491 */ 492 */
492protected el_action_t 493protected el_action_t
493/*ARGSUSED*/ 494/*ARGSUSED*/
494ed_tty_sigquit(EditLine *el __attribute__((__unused__)),  495ed_tty_sigquit(EditLine *el __attribute__((__unused__)),
495 Int c __attribute__((__unused__))) 496 Int c __attribute__((__unused__)))
496{ 497{
497 498
498 return CC_NORM; 499 return CC_NORM;
499} 500}
500 501
501 502
502/* ed_tty_sigtstp(): 503/* ed_tty_sigtstp():
503 * Tty suspend character 504 * Tty suspend character
504 * [^Z] 505 * [^Z]
505 */ 506 */
506protected el_action_t 507protected el_action_t
507/*ARGSUSED*/ 508/*ARGSUSED*/
508ed_tty_sigtstp(EditLine *el __attribute__((__unused__)),  509ed_tty_sigtstp(EditLine *el __attribute__((__unused__)),
509 Int c __attribute__((__unused__))) 510 Int c __attribute__((__unused__)))
510{ 511{
511 512
512 return CC_NORM; 513 return CC_NORM;
513} 514}
514 515
515 516
516/* ed_tty_stop_output(): 517/* ed_tty_stop_output():
517 * Tty disallow output characters 518 * Tty disallow output characters
518 * [^S] 519 * [^S]
519 */ 520 */
520protected el_action_t 521protected el_action_t
521/*ARGSUSED*/ 522/*ARGSUSED*/
522ed_tty_stop_output(EditLine *el __attribute__((__unused__)),  523ed_tty_stop_output(EditLine *el __attribute__((__unused__)),
523 Int c __attribute__((__unused__))) 524 Int c __attribute__((__unused__)))
524{ 525{
525 526
526 return CC_NORM; 527 return CC_NORM;
527} 528}
528 529
529 530
530/* ed_tty_start_output(): 531/* ed_tty_start_output():
531 * Tty allow output characters 532 * Tty allow output characters
532 * [^Q] 533 * [^Q]
533 */ 534 */
534protected el_action_t 535protected el_action_t
535/*ARGSUSED*/ 536/*ARGSUSED*/
536ed_tty_start_output(EditLine *el __attribute__((__unused__)),  537ed_tty_start_output(EditLine *el __attribute__((__unused__)),
537 Int c __attribute__((__unused__))) 538 Int c __attribute__((__unused__)))
538{ 539{
539 540
540 return CC_NORM; 541 return CC_NORM;
541} 542}
542 543
543 544
544/* ed_newline(): 545/* ed_newline():
545 * Execute command 546 * Execute command
546 * [^J] 547 * [^J]
547 */ 548 */
548protected el_action_t 549protected el_action_t
549/*ARGSUSED*/ 550/*ARGSUSED*/
550ed_newline(EditLine *el, Int c __attribute__((__unused__))) 551ed_newline(EditLine *el, Int c __attribute__((__unused__)))
551{ 552{
552 553
553 re_goto_bottom(el); 554 re_goto_bottom(el);
554 *el->el_line.lastchar++ = '\n'; 555 *el->el_line.lastchar++ = '\n';
555 *el->el_line.lastchar = '\0'; 556 *el->el_line.lastchar = '\0';
556 return CC_NEWLINE; 557 return CC_NEWLINE;
557} 558}
558 559
559 560
560/* ed_delete_prev_char(): 561/* ed_delete_prev_char():
561 * Delete the character to the left of the cursor 562 * Delete the character to the left of the cursor
562 * [^?] 563 * [^?]
563 */ 564 */
564protected el_action_t 565protected el_action_t
565/*ARGSUSED*/ 566/*ARGSUSED*/
566ed_delete_prev_char(EditLine *el, Int c __attribute__((__unused__))) 567ed_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
567{ 568{
568 569
569 if (el->el_line.cursor <= el->el_line.buffer) 570 if (el->el_line.cursor <= el->el_line.buffer)
570 return CC_ERROR; 571 return CC_ERROR;
571 572
572 c_delbefore(el, el->el_state.argument); 573 c_delbefore(el, el->el_state.argument);
573 el->el_line.cursor -= el->el_state.argument; 574 el->el_line.cursor -= el->el_state.argument;
574 if (el->el_line.cursor < el->el_line.buffer) 575 if (el->el_line.cursor < el->el_line.buffer)
575 el->el_line.cursor = el->el_line.buffer; 576 el->el_line.cursor = el->el_line.buffer;
576 return CC_REFRESH; 577 return CC_REFRESH;
577} 578}
578 579
579 580
580/* ed_clear_screen(): 581/* ed_clear_screen():
581 * Clear screen leaving current line at the top 582 * Clear screen leaving current line at the top
582 * [^L] 583 * [^L]
583 */ 584 */
584protected el_action_t 585protected el_action_t
585/*ARGSUSED*/ 586/*ARGSUSED*/
586ed_clear_screen(EditLine *el, Int c __attribute__((__unused__))) 587ed_clear_screen(EditLine *el, Int c __attribute__((__unused__)))
587{ 588{
588 589
589 terminal_clear_screen(el); /* clear the whole real screen */ 590 terminal_clear_screen(el); /* clear the whole real screen */
590 re_clear_display(el); /* reset everything */ 591 re_clear_display(el); /* reset everything */
591 return CC_REFRESH; 592 return CC_REFRESH;
592} 593}
593 594
594 595
595/* ed_redisplay(): 596/* ed_redisplay():
596 * Redisplay everything 597 * Redisplay everything
597 * ^R 598 * ^R
598 */ 599 */
599protected el_action_t 600protected el_action_t
600/*ARGSUSED*/ 601/*ARGSUSED*/
601ed_redisplay(EditLine *el __attribute__((__unused__)),  602ed_redisplay(EditLine *el __attribute__((__unused__)),
602 Int c __attribute__((__unused__))) 603 Int c __attribute__((__unused__)))
603{ 604{
604 605
605 return CC_REDISPLAY; 606 return CC_REDISPLAY;
606} 607}
607 608
608 609
609/* ed_start_over(): 610/* ed_start_over():
610 * Erase current line and start from scratch 611 * Erase current line and start from scratch
611 * [^G] 612 * [^G]
612 */ 613 */
613protected el_action_t 614protected el_action_t
614/*ARGSUSED*/ 615/*ARGSUSED*/
615ed_start_over(EditLine *el, Int c __attribute__((__unused__))) 616ed_start_over(EditLine *el, Int c __attribute__((__unused__)))
616{ 617{
617 618
618 ch_reset(el, 0); 619 ch_reset(el, 0);
619 return CC_REFRESH; 620 return CC_REFRESH;
620} 621}
621 622
622 623
623/* ed_sequence_lead_in(): 624/* ed_sequence_lead_in():
624 * First character in a bound sequence 625 * First character in a bound sequence
625 * Placeholder for external keys 626 * Placeholder for external keys
626 */ 627 */
627protected el_action_t 628protected el_action_t
628/*ARGSUSED*/ 629/*ARGSUSED*/
629ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),  630ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
630 Int c __attribute__((__unused__))) 631 Int c __attribute__((__unused__)))
631{ 632{
632 633
633 return CC_NORM; 634 return CC_NORM;
634} 635}
635 636
636 637
637/* ed_prev_history(): 638/* ed_prev_history():
638 * Move to the previous history line 639 * Move to the previous history line
639 * [^P] [k] 640 * [^P] [k]
640 */ 641 */
641protected el_action_t 642protected el_action_t
642/*ARGSUSED*/ 643/*ARGSUSED*/
643ed_prev_history(EditLine *el, Int c __attribute__((__unused__))) 644ed_prev_history(EditLine *el, Int c __attribute__((__unused__)))
644{ 645{
645 char beep = 0; 646 char beep = 0;
646 int sv_event = el->el_history.eventno; 647 int sv_event = el->el_history.eventno;
647 648
648 el->el_chared.c_undo.len = -1; 649 el->el_chared.c_undo.len = -1;
649 *el->el_line.lastchar = '\0'; /* just in case */ 650 *el->el_line.lastchar = '\0'; /* just in case */
650 651
651 if (el->el_history.eventno == 0) { /* save the current buffer 652 if (el->el_history.eventno == 0) { /* save the current buffer
652 * away */ 653 * away */
653 (void) Strncpy(el->el_history.buf, el->el_line.buffer, 654 (void) Strncpy(el->el_history.buf, el->el_line.buffer,
654 EL_BUFSIZ); 655 EL_BUFSIZ);
655 el->el_history.last = el->el_history.buf + 656 el->el_history.last = el->el_history.buf +
656 (el->el_line.lastchar - el->el_line.buffer); 657 (el->el_line.lastchar - el->el_line.buffer);
657 } 658 }
658 el->el_history.eventno += el->el_state.argument; 659 el->el_history.eventno += el->el_state.argument;
659 660
660 if (hist_get(el) == CC_ERROR) { 661 if (hist_get(el) == CC_ERROR) {
661 if (el->el_map.type == MAP_VI) { 662 if (el->el_map.type == MAP_VI) {
662 el->el_history.eventno = sv_event; 663 el->el_history.eventno = sv_event;
663  664
664 } 665 }
665 beep = 1; 666 beep = 1;
666 /* el->el_history.eventno was fixed by first call */ 667 /* el->el_history.eventno was fixed by first call */
667 (void) hist_get(el); 668 (void) hist_get(el);
668 } 669 }
669 if (beep) 670 if (beep)
670 return CC_REFRESH_BEEP; 671 return CC_REFRESH_BEEP;
671 return CC_REFRESH; 672 return CC_REFRESH;
672} 673}
673 674
674 675
675/* ed_next_history(): 676/* ed_next_history():
676 * Move to the next history line 677 * Move to the next history line
677 * [^N] [j] 678 * [^N] [j]
678 */ 679 */
679protected el_action_t 680protected el_action_t
680/*ARGSUSED*/ 681/*ARGSUSED*/
681ed_next_history(EditLine *el, Int c __attribute__((__unused__))) 682ed_next_history(EditLine *el, Int c __attribute__((__unused__)))
682{ 683{
683 el_action_t beep = CC_REFRESH, rval; 684 el_action_t beep = CC_REFRESH, rval;
684 685
685 el->el_chared.c_undo.len = -1; 686 el->el_chared.c_undo.len = -1;
686 *el->el_line.lastchar = '\0'; /* just in case */ 687 *el->el_line.lastchar = '\0'; /* just in case */
687 688
688 el->el_history.eventno -= el->el_state.argument; 689 el->el_history.eventno -= el->el_state.argument;
689 690
690 if (el->el_history.eventno < 0) { 691 if (el->el_history.eventno < 0) {
691 el->el_history.eventno = 0; 692 el->el_history.eventno = 0;
692 beep = CC_REFRESH_BEEP; 693 beep = CC_REFRESH_BEEP;
693 } 694 }
694 rval = hist_get(el); 695 rval = hist_get(el);
695 if (rval == CC_REFRESH) 696 if (rval == CC_REFRESH)
696 return beep; 697 return beep;
697 return rval; 698 return rval;
698 699
699} 700}
700 701
701 702
702/* ed_search_prev_history(): 703/* ed_search_prev_history():
703 * Search previous in history for a line matching the current 704 * Search previous in history for a line matching the current
704 * next search history [M-P] [K] 705 * next search history [M-P] [K]
705 */ 706 */
706protected el_action_t 707protected el_action_t
707/*ARGSUSED*/ 708/*ARGSUSED*/
708ed_search_prev_history(EditLine *el, Int c __attribute__((__unused__))) 709ed_search_prev_history(EditLine *el, Int c __attribute__((__unused__)))
709{ 710{
710 const Char *hp; 711 const Char *hp;
711 int h; 712 int h;
712 bool_t found = 0; 713 bool_t found = 0;
713 714
714 el->el_chared.c_vcmd.action = NOP; 715 el->el_chared.c_vcmd.action = NOP;
715 el->el_chared.c_undo.len = -1; 716 el->el_chared.c_undo.len = -1;
716 *el->el_line.lastchar = '\0'; /* just in case */ 717 *el->el_line.lastchar = '\0'; /* just in case */
717 if (el->el_history.eventno < 0) { 718 if (el->el_history.eventno < 0) {
718#ifdef DEBUG_EDIT 719#ifdef DEBUG_EDIT
719 (void) fprintf(el->el_errfile, 720 (void) fprintf(el->el_errfile,
720 "e_prev_search_hist(): eventno < 0;\n"); 721 "e_prev_search_hist(): eventno < 0;\n");
721#endif 722#endif
722 el->el_history.eventno = 0; 723 el->el_history.eventno = 0;
723 return CC_ERROR; 724 return CC_ERROR;
724 } 725 }
725 if (el->el_history.eventno == 0) { 726 if (el->el_history.eventno == 0) {
726 (void) Strncpy(el->el_history.buf, el->el_line.buffer, 727 (void) Strncpy(el->el_history.buf, el->el_line.buffer,
727 EL_BUFSIZ); 728 EL_BUFSIZ);
728 el->el_history.last = el->el_history.buf + 729 el->el_history.last = el->el_history.buf +
729 (el->el_line.lastchar - el->el_line.buffer); 730 (el->el_line.lastchar - el->el_line.buffer);
730 } 731 }
731 if (el->el_history.ref == NULL) 732 if (el->el_history.ref == NULL)
732 return CC_ERROR; 733 return CC_ERROR;
733 734
734 hp = HIST_FIRST(el); 735 hp = HIST_FIRST(el);
735 if (hp == NULL) 736 if (hp == NULL)
736 return CC_ERROR; 737 return CC_ERROR;
737 738
738 c_setpat(el); /* Set search pattern !! */ 739 c_setpat(el); /* Set search pattern !! */
739 740
740 for (h = 1; h <= el->el_history.eventno; h++) 741 for (h = 1; h <= el->el_history.eventno; h++)
741 hp = HIST_NEXT(el); 742 hp = HIST_NEXT(el);
742 743
743 while (hp != NULL) { 744 while (hp != NULL) {
744#ifdef SDEBUG 745#ifdef SDEBUG
745 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 746 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
746#endif 747#endif
747 if ((Strncmp(hp, el->el_line.buffer, (size_t) 748 if ((Strncmp(hp, el->el_line.buffer, (size_t)
748 (el->el_line.lastchar - el->el_line.buffer)) || 749 (el->el_line.lastchar - el->el_line.buffer)) ||
749 hp[el->el_line.lastchar - el->el_line.buffer]) && 750 hp[el->el_line.lastchar - el->el_line.buffer]) &&
750 c_hmatch(el, hp)) { 751 c_hmatch(el, hp)) {
751 found++; 752 found++;
752 break; 753 break;
753 } 754 }
754 h++; 755 h++;
755 hp = HIST_NEXT(el); 756 hp = HIST_NEXT(el);
756 } 757 }
757 758
758 if (!found) { 759 if (!found) {
759#ifdef SDEBUG 760#ifdef SDEBUG
760 (void) fprintf(el->el_errfile, "not found\n"); 761 (void) fprintf(el->el_errfile, "not found\n");
761#endif 762#endif
762 return CC_ERROR; 763 return CC_ERROR;
763 } 764 }
764 el->el_history.eventno = h; 765 el->el_history.eventno = h;
765 766
766 return hist_get(el); 767 return hist_get(el);
767} 768}
768 769
769 770
770/* ed_search_next_history(): 771/* ed_search_next_history():
771 * Search next in history for a line matching the current 772 * Search next in history for a line matching the current
772 * [M-N] [J] 773 * [M-N] [J]
773 */ 774 */
774protected el_action_t 775protected el_action_t
775/*ARGSUSED*/ 776/*ARGSUSED*/
776ed_search_next_history(EditLine *el, Int c __attribute__((__unused__))) 777ed_search_next_history(EditLine *el, Int c __attribute__((__unused__)))
777{ 778{
778 const Char *hp; 779 const Char *hp;
779 int h; 780 int h;
780 bool_t found = 0; 781 bool_t found = 0;
781 782
782 el->el_chared.c_vcmd.action = NOP; 783 el->el_chared.c_vcmd.action = NOP;
783 el->el_chared.c_undo.len = -1; 784 el->el_chared.c_undo.len = -1;
784 *el->el_line.lastchar = '\0'; /* just in case */ 785 *el->el_line.lastchar = '\0'; /* just in case */
785 786
786 if (el->el_history.eventno == 0) 787 if (el->el_history.eventno == 0)
787 return CC_ERROR; 788 return CC_ERROR;
788 789
789 if (el->el_history.ref == NULL) 790 if (el->el_history.ref == NULL)
790 return CC_ERROR; 791 return CC_ERROR;
791 792
792 hp = HIST_FIRST(el); 793 hp = HIST_FIRST(el);
793 if (hp == NULL) 794 if (hp == NULL)
794 return CC_ERROR; 795 return CC_ERROR;
795 796
796 c_setpat(el); /* Set search pattern !! */ 797 c_setpat(el); /* Set search pattern !! */
797 798
798 for (h = 1; h < el->el_history.eventno && hp; h++) { 799 for (h = 1; h < el->el_history.eventno && hp; h++) {
799#ifdef SDEBUG 800#ifdef SDEBUG
800 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); 801 (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
801#endif 802#endif
802 if ((Strncmp(hp, el->el_line.buffer, (size_t) 803 if ((Strncmp(hp, el->el_line.buffer, (size_t)
803 (el->el_line.lastchar - el->el_line.buffer)) || 804 (el->el_line.lastchar - el->el_line.buffer)) ||
804 hp[el->el_line.lastchar - el->el_line.buffer]) && 805 hp[el->el_line.lastchar - el->el_line.buffer]) &&
805 c_hmatch(el, hp)) 806 c_hmatch(el, hp))
806 found = h; 807 found = h;
807 hp = HIST_NEXT(el); 808 hp = HIST_NEXT(el);
808 } 809 }
809 810
810 if (!found) { /* is it the current history number? */ 811 if (!found) { /* is it the current history number? */
811 if (!c_hmatch(el, el->el_history.buf)) { 812 if (!c_hmatch(el, el->el_history.buf)) {
812#ifdef SDEBUG 813#ifdef SDEBUG
813 (void) fprintf(el->el_errfile, "not found\n"); 814 (void) fprintf(el->el_errfile, "not found\n");
814#endif 815#endif
815 return CC_ERROR; 816 return CC_ERROR;
816 } 817 }
817 } 818 }
818 el->el_history.eventno = found; 819 el->el_history.eventno = found;
819 820
820 return hist_get(el); 821 return hist_get(el);
821} 822}
822 823
823 824
824/* ed_prev_line(): 825/* ed_prev_line():
825 * Move up one line 826 * Move up one line
826 * Could be [k] [^p] 827 * Could be [k] [^p]
827 */ 828 */
828protected el_action_t 829protected el_action_t
829/*ARGSUSED*/ 830/*ARGSUSED*/
830ed_prev_line(EditLine *el, Int c __attribute__((__unused__))) 831ed_prev_line(EditLine *el, Int c __attribute__((__unused__)))
831{ 832{
832 Char *ptr; 833 Char *ptr;
833 int nchars = c_hpos(el); 834 int nchars = c_hpos(el);
834 835
835 /* 836 /*
836 * Move to the line requested 837 * Move to the line requested
837 */ 838 */
838 if (*(ptr = el->el_line.cursor) == '\n') 839 if (*(ptr = el->el_line.cursor) == '\n')
839 ptr--; 840 ptr--;
840 841
841 for (; ptr >= el->el_line.buffer; ptr--) 842 for (; ptr >= el->el_line.buffer; ptr--)
842 if (*ptr == '\n' && --el->el_state.argument <= 0) 843 if (*ptr == '\n' && --el->el_state.argument <= 0)
843 break; 844 break;
844 845
845 if (el->el_state.argument > 0) 846 if (el->el_state.argument > 0)
846 return CC_ERROR; 847 return CC_ERROR;
847 848
848 /* 849 /*
849 * Move to the beginning of the line 850 * Move to the beginning of the line
850 */ 851 */
851 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--) 852 for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
852 continue; 853 continue;
853 854
854 /* 855 /*
855 * Move to the character requested 856 * Move to the character requested
856 */ 857 */
857 for (ptr++; 858 for (ptr++;
858 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 859 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
859 ptr++) 860 ptr++)
860 continue; 861 continue;
861 862
862 el->el_line.cursor = ptr; 863 el->el_line.cursor = ptr;
863 return CC_CURSOR; 864 return CC_CURSOR;
864} 865}
865 866
866 867
867/* ed_next_line(): 868/* ed_next_line():
868 * Move down one line 869 * Move down one line
869 * Could be [j] [^n] 870 * Could be [j] [^n]
870 */ 871 */
871protected el_action_t 872protected el_action_t
872/*ARGSUSED*/ 873/*ARGSUSED*/
873ed_next_line(EditLine *el, Int c __attribute__((__unused__))) 874ed_next_line(EditLine *el, Int c __attribute__((__unused__)))
874{ 875{
875 Char *ptr; 876 Char *ptr;
876 int nchars = c_hpos(el); 877 int nchars = c_hpos(el);
877 878
878 /* 879 /*
879 * Move to the line requested 880 * Move to the line requested
880 */ 881 */
881 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++) 882 for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
882 if (*ptr == '\n' && --el->el_state.argument <= 0) 883 if (*ptr == '\n' && --el->el_state.argument <= 0)
883 break; 884 break;
884 885
885 if (el->el_state.argument > 0) 886 if (el->el_state.argument > 0)
886 return CC_ERROR; 887 return CC_ERROR;
887 888
888 /* 889 /*
889 * Move to the character requested 890 * Move to the character requested
890 */ 891 */
891 for (ptr++; 892 for (ptr++;
892 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n'; 893 nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
893 ptr++) 894 ptr++)
894 continue; 895 continue;
895 896
896 el->el_line.cursor = ptr; 897 el->el_line.cursor = ptr;
897 return CC_CURSOR; 898 return CC_CURSOR;
898} 899}
899 900
900 901
901/* ed_command(): 902/* ed_command():
902 * Editline extended command 903 * Editline extended command
903 * [M-X] [:] 904 * [M-X] [:]
904 */ 905 */
905protected el_action_t 906protected el_action_t
906/*ARGSUSED*/ 907/*ARGSUSED*/
907ed_command(EditLine *el, Int c __attribute__((__unused__))) 908ed_command(EditLine *el, Int c __attribute__((__unused__)))
908{ 909{
909 Char tmpbuf[EL_BUFSIZ]; 910 Char tmpbuf[EL_BUFSIZ];
910 int tmplen; 911 int tmplen;
911 912
912 tmplen = c_gets(el, tmpbuf, STR("\n: ")); 913 tmplen = c_gets(el, tmpbuf, STR("\n: "));
913 terminal__putc(el, '\n'); 914 terminal__putc(el, '\n');
914 915
915 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) 916 if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
916 terminal_beep(el); 917 terminal_beep(el);
917 918
918 el->el_map.current = el->el_map.key; 919 el->el_map.current = el->el_map.key;
919 re_clear_display(el); 920 re_clear_display(el);
920 return CC_REFRESH; 921 return CC_REFRESH;
921} 922}

cvs diff -r1.27 -r1.28 src/lib/libedit/filecomplete.c (switch to unified diff)

--- src/lib/libedit/filecomplete.c 2011/07/29 15:16:33 1.27
+++ src/lib/libedit/filecomplete.c 2011/07/29 20:58:07 1.28
@@ -1,581 +1,577 @@ @@ -1,581 +1,577 @@
1/* $NetBSD: filecomplete.c,v 1.27 2011/07/29 15:16:33 christos Exp $ */ 1/* $NetBSD: filecomplete.c,v 1.28 2011/07/29 20:58:07 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jaromir Dolecek. 8 * by Jaromir Dolecek.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include "config.h" 32#include "config.h"
33#if !defined(lint) && !defined(SCCSID) 33#if !defined(lint) && !defined(SCCSID)
34__RCSID("$NetBSD: filecomplete.c,v 1.27 2011/07/29 15:16:33 christos Exp $"); 34__RCSID("$NetBSD: filecomplete.c,v 1.28 2011/07/29 20:58:07 christos Exp $");
35#endif /* not lint && not SCCSID */ 35#endif /* not lint && not SCCSID */
36 36
37#include <sys/types.h> 37#include <sys/types.h>
38#include <sys/stat.h> 38#include <sys/stat.h>
39#include <stdio.h> 39#include <stdio.h>
40#include <dirent.h> 40#include <dirent.h>
41#include <string.h> 41#include <string.h>
42#include <pwd.h> 42#include <pwd.h>
43#include <ctype.h> 43#include <ctype.h>
44#include <stdlib.h> 44#include <stdlib.h>
45#include <unistd.h> 45#include <unistd.h>
46#include <limits.h> 46#include <limits.h>
47#include <errno.h> 47#include <errno.h>
48#include <fcntl.h> 48#include <fcntl.h>
49#ifdef HAVE_VIS_H 49
50#include <vis.h> 
51#else 
52#include "vis.h" 
53#endif 
54#include "el.h" 50#include "el.h"
55#include "fcns.h" /* for EL_NUM_FCNS */ 51#include "fcns.h" /* for EL_NUM_FCNS */
56#include "histedit.h" 52#include "histedit.h"
57#include "filecomplete.h" 53#include "filecomplete.h"
58 54
59static const Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', 55static const Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@',
60 '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; 56 '$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
61 57
62 58
63/********************************/ 59/********************************/
64/* completion functions */ 60/* completion functions */
65 61
66/* 62/*
67 * does tilde expansion of strings of type ``~user/foo'' 63 * does tilde expansion of strings of type ``~user/foo''
68 * if ``user'' isn't valid user name or ``txt'' doesn't start 64 * if ``user'' isn't valid user name or ``txt'' doesn't start
69 * w/ '~', returns pointer to strdup()ed copy of ``txt'' 65 * w/ '~', returns pointer to strdup()ed copy of ``txt''
70 * 66 *
71 * it's callers's responsibility to free() returned string 67 * it's callers's responsibility to free() returned string
72 */ 68 */
73char * 69char *
74fn_tilde_expand(const char *txt) 70fn_tilde_expand(const char *txt)
75{ 71{
76#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) 72#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
77 struct passwd pwres; 73 struct passwd pwres;
78 char pwbuf[1024]; 74 char pwbuf[1024];
79#endif 75#endif
80 struct passwd *pass; 76 struct passwd *pass;
81 char *temp; 77 char *temp;
82 size_t len = 0; 78 size_t len = 0;
83 79
84 if (txt[0] != '~') 80 if (txt[0] != '~')
85 return strdup(txt); 81 return strdup(txt);
86 82
87 temp = strchr(txt + 1, '/'); 83 temp = strchr(txt + 1, '/');
88 if (temp == NULL) { 84 if (temp == NULL) {
89 temp = strdup(txt + 1); 85 temp = strdup(txt + 1);
90 if (temp == NULL) 86 if (temp == NULL)
91 return NULL; 87 return NULL;
92 } else { 88 } else {
93 len = temp - txt + 1; /* text until string after slash */ 89 len = temp - txt + 1; /* text until string after slash */
94 temp = el_malloc(len * sizeof(*temp)); 90 temp = el_malloc(len * sizeof(*temp));
95 if (temp == NULL) 91 if (temp == NULL)
96 return NULL; 92 return NULL;
97 (void)strncpy(temp, txt + 1, len - 2); 93 (void)strncpy(temp, txt + 1, len - 2);
98 temp[len - 2] = '\0'; 94 temp[len - 2] = '\0';
99 } 95 }
100 if (temp[0] == 0) { 96 if (temp[0] == 0) {
101#ifdef HAVE_GETPW_R_POSIX 97#ifdef HAVE_GETPW_R_POSIX
102 if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), 98 if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
103 &pass) != 0) 99 &pass) != 0)
104 pass = NULL; 100 pass = NULL;
105#elif HAVE_GETPW_R_DRAFT 101#elif HAVE_GETPW_R_DRAFT
106 pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf)); 102 pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf));
107#else 103#else
108 pass = getpwuid(getuid()); 104 pass = getpwuid(getuid());
109#endif 105#endif
110 } else { 106 } else {
111#ifdef HAVE_GETPW_R_POSIX 107#ifdef HAVE_GETPW_R_POSIX
112 if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0) 108 if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
113 pass = NULL; 109 pass = NULL;
114#elif HAVE_GETPW_R_DRAFT 110#elif HAVE_GETPW_R_DRAFT
115 pass = getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf)); 111 pass = getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf));
116#else 112#else
117 pass = getpwnam(temp); 113 pass = getpwnam(temp);
118#endif 114#endif
119 } 115 }
120 el_free(temp); /* value no more needed */ 116 el_free(temp); /* value no more needed */
121 if (pass == NULL) 117 if (pass == NULL)
122 return strdup(txt); 118 return strdup(txt);
123 119
124 /* update pointer txt to point at string immedially following */ 120 /* update pointer txt to point at string immedially following */
125 /* first slash */ 121 /* first slash */
126 txt += len; 122 txt += len;
127 123
128 len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1; 124 len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1;
129 temp = el_malloc(len * sizeof(*temp)); 125 temp = el_malloc(len * sizeof(*temp));
130 if (temp == NULL) 126 if (temp == NULL)
131 return NULL; 127 return NULL;
132 (void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt); 128 (void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt);
133 129
134 return temp; 130 return temp;
135} 131}
136 132
137 133
138/* 134/*
139 * return first found file name starting by the ``text'' or NULL if no 135 * return first found file name starting by the ``text'' or NULL if no
140 * such file can be found 136 * such file can be found
141 * value of ``state'' is ignored 137 * value of ``state'' is ignored
142 * 138 *
143 * it's caller's responsibility to free returned string 139 * it's caller's responsibility to free returned string
144 */ 140 */
145char * 141char *
146fn_filename_completion_function(const char *text, int state) 142fn_filename_completion_function(const char *text, int state)
147{ 143{
148 static DIR *dir = NULL; 144 static DIR *dir = NULL;
149 static char *filename = NULL, *dirname = NULL, *dirpath = NULL; 145 static char *filename = NULL, *dirname = NULL, *dirpath = NULL;
150 static size_t filename_len = 0; 146 static size_t filename_len = 0;
151 struct dirent *entry; 147 struct dirent *entry;
152 char *temp; 148 char *temp;
153 size_t len; 149 size_t len;
154 150
155 if (state == 0 || dir == NULL) { 151 if (state == 0 || dir == NULL) {
156 temp = strrchr(text, '/'); 152 temp = strrchr(text, '/');
157 if (temp) { 153 if (temp) {
158 char *nptr; 154 char *nptr;
159 temp++; 155 temp++;
160 nptr = el_realloc(filename, (strlen(temp) + 1) * 156 nptr = el_realloc(filename, (strlen(temp) + 1) *
161 sizeof(*nptr)); 157 sizeof(*nptr));
162 if (nptr == NULL) { 158 if (nptr == NULL) {
163 el_free(filename); 159 el_free(filename);
164 filename = NULL; 160 filename = NULL;
165 return NULL; 161 return NULL;
166 } 162 }
167 filename = nptr; 163 filename = nptr;
168 (void)strcpy(filename, temp); 164 (void)strcpy(filename, temp);
169 len = temp - text; /* including last slash */ 165 len = temp - text; /* including last slash */
170 166
171 nptr = el_realloc(dirname, (len + 1) * 167 nptr = el_realloc(dirname, (len + 1) *
172 sizeof(*nptr)); 168 sizeof(*nptr));
173 if (nptr == NULL) { 169 if (nptr == NULL) {
174 el_free(dirname); 170 el_free(dirname);
175 dirname = NULL; 171 dirname = NULL;
176 return NULL; 172 return NULL;
177 } 173 }
178 dirname = nptr; 174 dirname = nptr;
179 (void)strncpy(dirname, text, len); 175 (void)strncpy(dirname, text, len);
180 dirname[len] = '\0'; 176 dirname[len] = '\0';
181 } else { 177 } else {
182 el_free(filename); 178 el_free(filename);
183 if (*text == 0) 179 if (*text == 0)
184 filename = NULL; 180 filename = NULL;
185 else { 181 else {
186 filename = strdup(text); 182 filename = strdup(text);
187 if (filename == NULL) 183 if (filename == NULL)
188 return NULL; 184 return NULL;
189 } 185 }
190 el_free(dirname); 186 el_free(dirname);
191 dirname = NULL; 187 dirname = NULL;
192 } 188 }
193 189
194 if (dir != NULL) { 190 if (dir != NULL) {
195 (void)closedir(dir); 191 (void)closedir(dir);
196 dir = NULL; 192 dir = NULL;
197 } 193 }
198 194
199 /* support for ``~user'' syntax */ 195 /* support for ``~user'' syntax */
200 196
201 el_free(dirpath); 197 el_free(dirpath);
202 dirpath = NULL; 198 dirpath = NULL;
203 if (dirname == NULL) { 199 if (dirname == NULL) {
204 if ((dirname = strdup("")) == NULL) 200 if ((dirname = strdup("")) == NULL)
205 return NULL; 201 return NULL;
206 dirpath = strdup("./"); 202 dirpath = strdup("./");
207 } else if (*dirname == '~') 203 } else if (*dirname == '~')
208 dirpath = fn_tilde_expand(dirname); 204 dirpath = fn_tilde_expand(dirname);
209 else 205 else
210 dirpath = strdup(dirname); 206 dirpath = strdup(dirname);
211 207
212 if (dirpath == NULL) 208 if (dirpath == NULL)
213 return NULL; 209 return NULL;
214 210
215 dir = opendir(dirpath); 211 dir = opendir(dirpath);
216 if (!dir) 212 if (!dir)
217 return NULL; /* cannot open the directory */ 213 return NULL; /* cannot open the directory */
218 214
219 /* will be used in cycle */ 215 /* will be used in cycle */
220 filename_len = filename ? strlen(filename) : 0; 216 filename_len = filename ? strlen(filename) : 0;
221 } 217 }
222 218
223 /* find the match */ 219 /* find the match */
224 while ((entry = readdir(dir)) != NULL) { 220 while ((entry = readdir(dir)) != NULL) {
225 /* skip . and .. */ 221 /* skip . and .. */
226 if (entry->d_name[0] == '.' && (!entry->d_name[1] 222 if (entry->d_name[0] == '.' && (!entry->d_name[1]
227 || (entry->d_name[1] == '.' && !entry->d_name[2]))) 223 || (entry->d_name[1] == '.' && !entry->d_name[2])))
228 continue; 224 continue;
229 if (filename_len == 0) 225 if (filename_len == 0)
230 break; 226 break;
231 /* otherwise, get first entry where first */ 227 /* otherwise, get first entry where first */
232 /* filename_len characters are equal */ 228 /* filename_len characters are equal */
233 if (entry->d_name[0] == filename[0] 229 if (entry->d_name[0] == filename[0]
234#if HAVE_STRUCT_DIRENT_D_NAMLEN 230#if HAVE_STRUCT_DIRENT_D_NAMLEN
235 && entry->d_namlen >= filename_len 231 && entry->d_namlen >= filename_len
236#else 232#else
237 && strlen(entry->d_name) >= filename_len 233 && strlen(entry->d_name) >= filename_len
238#endif 234#endif
239 && strncmp(entry->d_name, filename, 235 && strncmp(entry->d_name, filename,
240 filename_len) == 0) 236 filename_len) == 0)
241 break; 237 break;
242 } 238 }
243 239
244 if (entry) { /* match found */ 240 if (entry) { /* match found */
245 241
246#if HAVE_STRUCT_DIRENT_D_NAMLEN 242#if HAVE_STRUCT_DIRENT_D_NAMLEN
247 len = entry->d_namlen; 243 len = entry->d_namlen;
248#else 244#else
249 len = strlen(entry->d_name); 245 len = strlen(entry->d_name);
250#endif 246#endif
251 247
252 len = strlen(dirname) + len + 1; 248 len = strlen(dirname) + len + 1;
253 temp = el_malloc(len * sizeof(*temp)); 249 temp = el_malloc(len * sizeof(*temp));
254 if (temp == NULL) 250 if (temp == NULL)
255 return NULL; 251 return NULL;
256 (void)snprintf(temp, len, "%s%s", dirname, entry->d_name); 252 (void)snprintf(temp, len, "%s%s", dirname, entry->d_name);
257 } else { 253 } else {
258 (void)closedir(dir); 254 (void)closedir(dir);
259 dir = NULL; 255 dir = NULL;
260 temp = NULL; 256 temp = NULL;
261 } 257 }
262 258
263 return temp; 259 return temp;
264} 260}
265 261
266 262
267static const char * 263static const char *
268append_char_function(const char *name) 264append_char_function(const char *name)
269{ 265{
270 struct stat stbuf; 266 struct stat stbuf;
271 char *expname = *name == '~' ? fn_tilde_expand(name) : NULL; 267 char *expname = *name == '~' ? fn_tilde_expand(name) : NULL;
272 const char *rs = " "; 268 const char *rs = " ";
273 269
274 if (stat(expname ? expname : name, &stbuf) == -1) 270 if (stat(expname ? expname : name, &stbuf) == -1)
275 goto out; 271 goto out;
276 if (S_ISDIR(stbuf.st_mode)) 272 if (S_ISDIR(stbuf.st_mode))
277 rs = "/"; 273 rs = "/";
278out: 274out:
279 if (expname) 275 if (expname)
280 el_free(expname); 276 el_free(expname);
281 return rs; 277 return rs;
282} 278}
283/* 279/*
284 * returns list of completions for text given 280 * returns list of completions for text given
285 * non-static for readline. 281 * non-static for readline.
286 */ 282 */
287char ** completion_matches(const char *, char *(*)(const char *, int)); 283char ** completion_matches(const char *, char *(*)(const char *, int));
288char ** 284char **
289completion_matches(const char *text, char *(*genfunc)(const char *, int)) 285completion_matches(const char *text, char *(*genfunc)(const char *, int))
290{ 286{
291 char **match_list = NULL, *retstr, *prevstr; 287 char **match_list = NULL, *retstr, *prevstr;
292 size_t match_list_len, max_equal, which, i; 288 size_t match_list_len, max_equal, which, i;
293 size_t matches; 289 size_t matches;
294 290
295 matches = 0; 291 matches = 0;
296 match_list_len = 1; 292 match_list_len = 1;
297 while ((retstr = (*genfunc) (text, (int)matches)) != NULL) { 293 while ((retstr = (*genfunc) (text, (int)matches)) != NULL) {
298 /* allow for list terminator here */ 294 /* allow for list terminator here */
299 if (matches + 3 >= match_list_len) { 295 if (matches + 3 >= match_list_len) {
300 char **nmatch_list; 296 char **nmatch_list;
301 while (matches + 3 >= match_list_len) 297 while (matches + 3 >= match_list_len)
302 match_list_len <<= 1; 298 match_list_len <<= 1;
303 nmatch_list = el_realloc(match_list, 299 nmatch_list = el_realloc(match_list,
304 match_list_len * sizeof(*nmatch_list)); 300 match_list_len * sizeof(*nmatch_list));
305 if (nmatch_list == NULL) { 301 if (nmatch_list == NULL) {
306 el_free(match_list); 302 el_free(match_list);
307 return NULL; 303 return NULL;
308 } 304 }
309 match_list = nmatch_list; 305 match_list = nmatch_list;
310 306
311 } 307 }
312 match_list[++matches] = retstr; 308 match_list[++matches] = retstr;
313 } 309 }
314 310
315 if (!match_list) 311 if (!match_list)
316 return NULL; /* nothing found */ 312 return NULL; /* nothing found */
317 313
318 /* find least denominator and insert it to match_list[0] */ 314 /* find least denominator and insert it to match_list[0] */
319 which = 2; 315 which = 2;
320 prevstr = match_list[1]; 316 prevstr = match_list[1];
321 max_equal = strlen(prevstr); 317 max_equal = strlen(prevstr);
322 for (; which <= matches; which++) { 318 for (; which <= matches; which++) {
323 for (i = 0; i < max_equal && 319 for (i = 0; i < max_equal &&
324 prevstr[i] == match_list[which][i]; i++) 320 prevstr[i] == match_list[which][i]; i++)
325 continue; 321 continue;
326 max_equal = i; 322 max_equal = i;
327 } 323 }
328 324
329 retstr = el_malloc((max_equal + 1) * sizeof(*retstr)); 325 retstr = el_malloc((max_equal + 1) * sizeof(*retstr));
330 if (retstr == NULL) { 326 if (retstr == NULL) {
331 el_free(match_list); 327 el_free(match_list);
332 return NULL; 328 return NULL;
333 } 329 }
334 (void)strncpy(retstr, match_list[1], max_equal); 330 (void)strncpy(retstr, match_list[1], max_equal);
335 retstr[max_equal] = '\0'; 331 retstr[max_equal] = '\0';
336 match_list[0] = retstr; 332 match_list[0] = retstr;
337 333
338 /* add NULL as last pointer to the array */ 334 /* add NULL as last pointer to the array */
339 match_list[matches + 1] = (char *) NULL; 335 match_list[matches + 1] = (char *) NULL;
340 336
341 return match_list; 337 return match_list;
342} 338}
343 339
344/* 340/*
345 * Sort function for qsort(). Just wrapper around strcasecmp(). 341 * Sort function for qsort(). Just wrapper around strcasecmp().
346 */ 342 */
347static int 343static int
348_fn_qsort_string_compare(const void *i1, const void *i2) 344_fn_qsort_string_compare(const void *i1, const void *i2)
349{ 345{
350 const char *s1 = ((const char * const *)i1)[0]; 346 const char *s1 = ((const char * const *)i1)[0];
351 const char *s2 = ((const char * const *)i2)[0]; 347 const char *s2 = ((const char * const *)i2)[0];
352 348
353 return strcasecmp(s1, s2); 349 return strcasecmp(s1, s2);
354} 350}
355 351
356/* 352/*
357 * Display list of strings in columnar format on readline's output stream. 353 * Display list of strings in columnar format on readline's output stream.
358 * 'matches' is list of strings, 'num' is number of strings in 'matches', 354 * 'matches' is list of strings, 'num' is number of strings in 'matches',
359 * 'width' is maximum length of string in 'matches'. 355 * 'width' is maximum length of string in 'matches'.
360 * 356 *
361 * matches[0] is not one of the match strings, but it is counted in 357 * matches[0] is not one of the match strings, but it is counted in
362 * num, so the strings are matches[1] *through* matches[num-1]. 358 * num, so the strings are matches[1] *through* matches[num-1].
363 */ 359 */
364void 360void
365fn_display_match_list (EditLine *el, char **matches, size_t num, size_t width) 361fn_display_match_list (EditLine *el, char **matches, size_t num, size_t width)
366{ 362{
367 size_t line, lines, col, cols, thisguy; 363 size_t line, lines, col, cols, thisguy;
368 int screenwidth = el->el_terminal.t_size.h; 364 int screenwidth = el->el_terminal.t_size.h;
369 365
370 /* Ignore matches[0]. Avoid 1-based array logic below. */ 366 /* Ignore matches[0]. Avoid 1-based array logic below. */
371 matches++; 367 matches++;
372 num--; 368 num--;
373 369
374 /* 370 /*
375 * Find out how many entries can be put on one line; count 371 * Find out how many entries can be put on one line; count
376 * with one space between strings the same way it's printed. 372 * with one space between strings the same way it's printed.
377 */ 373 */
378 cols = screenwidth / (width + 1); 374 cols = screenwidth / (width + 1);
379 if (cols == 0) 375 if (cols == 0)
380 cols = 1; 376 cols = 1;
381 377
382 /* how many lines of output, rounded up */ 378 /* how many lines of output, rounded up */
383 lines = (num + cols - 1) / cols; 379 lines = (num + cols - 1) / cols;
384 380
385 /* Sort the items. */ 381 /* Sort the items. */
386 qsort(matches, num, sizeof(char *), _fn_qsort_string_compare); 382 qsort(matches, num, sizeof(char *), _fn_qsort_string_compare);
387 383
388 /* 384 /*
389 * On the ith line print elements i, i+lines, i+lines*2, etc. 385 * On the ith line print elements i, i+lines, i+lines*2, etc.
390 */ 386 */
391 for (line = 0; line < lines; line++) { 387 for (line = 0; line < lines; line++) {
392 for (col = 0; col < cols; col++) { 388 for (col = 0; col < cols; col++) {
393 thisguy = line + col * lines; 389 thisguy = line + col * lines;
394 if (thisguy >= num) 390 if (thisguy >= num)
395 break; 391 break;
396 (void)fprintf(el->el_outfile, "%s%-*s", 392 (void)fprintf(el->el_outfile, "%s%-*s",
397 col == 0 ? "" : " ", (int)width, matches[thisguy]); 393 col == 0 ? "" : " ", (int)width, matches[thisguy]);
398 } 394 }
399 (void)fprintf(el->el_outfile, "\n"); 395 (void)fprintf(el->el_outfile, "\n");
400 } 396 }
401} 397}
402 398
403/* 399/*
404 * Complete the word at or before point, 400 * Complete the word at or before point,
405 * 'what_to_do' says what to do with the completion. 401 * 'what_to_do' says what to do with the completion.
406 * \t means do standard completion. 402 * \t means do standard completion.
407 * `?' means list the possible completions. 403 * `?' means list the possible completions.
408 * `*' means insert all of the possible completions. 404 * `*' means insert all of the possible completions.
409 * `!' means to do standard completion, and list all possible completions if 405 * `!' means to do standard completion, and list all possible completions if
410 * there is more than one. 406 * there is more than one.
411 * 407 *
412 * Note: '*' support is not implemented 408 * Note: '*' support is not implemented
413 * '!' could never be invoked 409 * '!' could never be invoked
414 */ 410 */
415int 411int
416fn_complete(EditLine *el, 412fn_complete(EditLine *el,
417 char *(*complet_func)(const char *, int), 413 char *(*complet_func)(const char *, int),
418 char **(*attempted_completion_function)(const char *, int, int), 414 char **(*attempted_completion_function)(const char *, int, int),
419 const Char *word_break, const Char *special_prefixes, 415 const Char *word_break, const Char *special_prefixes,
420 const char *(*app_func)(const char *), size_t query_items, 416 const char *(*app_func)(const char *), size_t query_items,
421 int *completion_type, int *over, int *point, int *end) 417 int *completion_type, int *over, int *point, int *end)
422{ 418{
423 const TYPE(LineInfo) *li; 419 const TYPE(LineInfo) *li;
424 Char *temp; 420 Char *temp;
425 char **matches; 421 char **matches;
426 const Char *ctemp; 422 const Char *ctemp;
427 size_t len; 423 size_t len;
428 int what_to_do = '\t'; 424 int what_to_do = '\t';
429 int retval = CC_NORM; 425 int retval = CC_NORM;
430 426
431 if (el->el_state.lastcmd == el->el_state.thiscmd) 427 if (el->el_state.lastcmd == el->el_state.thiscmd)
432 what_to_do = '?'; 428 what_to_do = '?';
433 429
434 /* readline's rl_complete() has to be told what we did... */ 430 /* readline's rl_complete() has to be told what we did... */
435 if (completion_type != NULL) 431 if (completion_type != NULL)
436 *completion_type = what_to_do; 432 *completion_type = what_to_do;
437 433
438 if (!complet_func) 434 if (!complet_func)
439 complet_func = fn_filename_completion_function; 435 complet_func = fn_filename_completion_function;
440 if (!app_func) 436 if (!app_func)
441 app_func = append_char_function; 437 app_func = append_char_function;
442 438
443 /* We now look backwards for the start of a filename/variable word */ 439 /* We now look backwards for the start of a filename/variable word */
444 li = FUN(el,line)(el); 440 li = FUN(el,line)(el);
445 ctemp = li->cursor; 441 ctemp = li->cursor;
446 while (ctemp > li->buffer 442 while (ctemp > li->buffer
447 && !Strchr(word_break, ctemp[-1]) 443 && !Strchr(word_break, ctemp[-1])
448 && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) ) 444 && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) )
449 ctemp--; 445 ctemp--;
450 446
451 len = li->cursor - ctemp; 447 len = li->cursor - ctemp;
452 temp = el_malloc((len + 1) * sizeof(*temp)); 448 temp = el_malloc((len + 1) * sizeof(*temp));
453 (void)Strncpy(temp, ctemp, len); 449 (void)Strncpy(temp, ctemp, len);
454 temp[len] = '\0'; 450 temp[len] = '\0';
455 451
456 /* these can be used by function called in completion_matches() */ 452 /* these can be used by function called in completion_matches() */
457 /* or (*attempted_completion_function)() */ 453 /* or (*attempted_completion_function)() */
458 if (point != 0) 454 if (point != 0)
459 *point = (int)(li->cursor - li->buffer); 455 *point = (int)(li->cursor - li->buffer);
460 if (end != NULL) 456 if (end != NULL)
461 *end = (int)(li->lastchar - li->buffer); 457 *end = (int)(li->lastchar - li->buffer);
462 458
463 if (attempted_completion_function) { 459 if (attempted_completion_function) {
464 int cur_off = (int)(li->cursor - li->buffer); 460 int cur_off = (int)(li->cursor - li->buffer);
465 matches = (*attempted_completion_function) (ct_encode_string(temp, &el->el_scratch), 461 matches = (*attempted_completion_function) (ct_encode_string(temp, &el->el_scratch),
466 (int)(cur_off - len), cur_off); 462 (int)(cur_off - len), cur_off);
467 } else 463 } else
468 matches = 0; 464 matches = 0;
469 if (!attempted_completion_function ||  465 if (!attempted_completion_function ||
470 (over != NULL && !*over && !matches)) 466 (over != NULL && !*over && !matches))
471 matches = completion_matches(ct_encode_string(temp, &el->el_scratch), complet_func); 467 matches = completion_matches(ct_encode_string(temp, &el->el_scratch), complet_func);
472 468
473 if (over != NULL) 469 if (over != NULL)
474 *over = 0; 470 *over = 0;
475 471
476 if (matches) { 472 if (matches) {
477 int i; 473 int i;
478 size_t matches_num, maxlen, match_len, match_display=1; 474 size_t matches_num, maxlen, match_len, match_display=1;
479 475
480 retval = CC_REFRESH; 476 retval = CC_REFRESH;
481 /* 477 /*
482 * Only replace the completed string with common part of 478 * Only replace the completed string with common part of
483 * possible matches if there is possible completion. 479 * possible matches if there is possible completion.
484 */ 480 */
485 if (matches[0][0] != '\0') { 481 if (matches[0][0] != '\0') {
486 el_deletestr(el, (int) len); 482 el_deletestr(el, (int) len);
487 FUN(el,insertstr)(el, 483 FUN(el,insertstr)(el,
488 ct_decode_string(matches[0], &el->el_scratch)); 484 ct_decode_string(matches[0], &el->el_scratch));
489 } 485 }
490 486
491 if (what_to_do == '?') 487 if (what_to_do == '?')
492 goto display_matches; 488 goto display_matches;
493 489
494 if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { 490 if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
495 /* 491 /*
496 * We found exact match. Add a space after 492 * We found exact match. Add a space after
497 * it, unless we do filename completion and the 493 * it, unless we do filename completion and the
498 * object is a directory. 494 * object is a directory.
499 */ 495 */
500 FUN(el,insertstr)(el, 496 FUN(el,insertstr)(el,
501 ct_decode_string((*app_func)(matches[0]), 497 ct_decode_string((*app_func)(matches[0]),
502 &el->el_scratch)); 498 &el->el_scratch));
503 } else if (what_to_do == '!') { 499 } else if (what_to_do == '!') {
504 display_matches: 500 display_matches:
505 /* 501 /*
506 * More than one match and requested to list possible 502 * More than one match and requested to list possible
507 * matches. 503 * matches.
508 */ 504 */
509 505
510 for(i = 1, maxlen = 0; matches[i]; i++) { 506 for(i = 1, maxlen = 0; matches[i]; i++) {
511 match_len = strlen(matches[i]); 507 match_len = strlen(matches[i]);
512 if (match_len > maxlen) 508 if (match_len > maxlen)
513 maxlen = match_len; 509 maxlen = match_len;
514 } 510 }
515 /* matches[1] through matches[i-1] are available */ 511 /* matches[1] through matches[i-1] are available */
516 matches_num = i - 1; 512 matches_num = i - 1;
517  513
518 /* newline to get on next line from command line */ 514 /* newline to get on next line from command line */
519 (void)fprintf(el->el_outfile, "\n"); 515 (void)fprintf(el->el_outfile, "\n");
520 516
521 /* 517 /*
522 * If there are too many items, ask user for display 518 * If there are too many items, ask user for display
523 * confirmation. 519 * confirmation.
524 */ 520 */
525 if (matches_num > query_items) { 521 if (matches_num > query_items) {
526 (void)fprintf(el->el_outfile, 522 (void)fprintf(el->el_outfile,
527 "Display all %zu possibilities? (y or n) ", 523 "Display all %zu possibilities? (y or n) ",
528 matches_num); 524 matches_num);
529 (void)fflush(el->el_outfile); 525 (void)fflush(el->el_outfile);
530 if (getc(stdin) != 'y') 526 if (getc(stdin) != 'y')
531 match_display = 0; 527 match_display = 0;
532 (void)fprintf(el->el_outfile, "\n"); 528 (void)fprintf(el->el_outfile, "\n");
533 } 529 }
534 530
535 if (match_display) { 531 if (match_display) {
536 /* 532 /*
537 * Interface of this function requires the 533 * Interface of this function requires the
538 * strings be matches[1..num-1] for compat. 534 * strings be matches[1..num-1] for compat.
539 * We have matches_num strings not counting 535 * We have matches_num strings not counting
540 * the prefix in matches[0], so we need to 536 * the prefix in matches[0], so we need to
541 * add 1 to matches_num for the call. 537 * add 1 to matches_num for the call.
542 */ 538 */
543 fn_display_match_list(el, matches, 539 fn_display_match_list(el, matches,
544 matches_num+1, maxlen); 540 matches_num+1, maxlen);
545 } 541 }
546 retval = CC_REDISPLAY; 542 retval = CC_REDISPLAY;
547 } else if (matches[0][0]) { 543 } else if (matches[0][0]) {
548 /* 544 /*
549 * There was some common match, but the name was 545 * There was some common match, but the name was
550 * not complete enough. Next tab will print possible 546 * not complete enough. Next tab will print possible
551 * completions. 547 * completions.
552 */ 548 */
553 el_beep(el); 549 el_beep(el);
554 } else { 550 } else {
555 /* lcd is not a valid object - further specification */ 551 /* lcd is not a valid object - further specification */
556 /* is needed */ 552 /* is needed */
557 el_beep(el); 553 el_beep(el);
558 retval = CC_NORM; 554 retval = CC_NORM;
559 } 555 }
560 556
561 /* free elements of array and the array itself */ 557 /* free elements of array and the array itself */
562 for (i = 0; matches[i]; i++) 558 for (i = 0; matches[i]; i++)
563 el_free(matches[i]); 559 el_free(matches[i]);
564 el_free(matches); 560 el_free(matches);
565 matches = NULL; 561 matches = NULL;
566 } 562 }
567 el_free(temp); 563 el_free(temp);
568 return retval; 564 return retval;
569} 565}
570 566
571/* 567/*
572 * el-compatible wrapper around rl_complete; needed for key binding 568 * el-compatible wrapper around rl_complete; needed for key binding
573 */ 569 */
574/* ARGSUSED */ 570/* ARGSUSED */
575unsigned char 571unsigned char
576_el_fn_complete(EditLine *el, int ch __attribute__((__unused__))) 572_el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
577{ 573{
578 return (unsigned char)fn_complete(el, NULL, NULL, 574 return (unsigned char)fn_complete(el, NULL, NULL,
579 break_chars, NULL, NULL, 100, 575 break_chars, NULL, NULL, 100,
580 NULL, NULL, NULL, NULL); 576 NULL, NULL, NULL, NULL);
581} 577}

cvs diff -r1.43 -r1.44 src/lib/libedit/history.c (switch to unified diff)

--- src/lib/libedit/history.c 2011/07/29 15:16:33 1.43
+++ src/lib/libedit/history.c 2011/07/29 20:58:07 1.44
@@ -1,1053 +1,1049 @@ @@ -1,1053 +1,1049 @@
1/* $NetBSD: history.c,v 1.43 2011/07/29 15:16:33 christos Exp $ */ 1/* $NetBSD: history.c,v 1.44 2011/07/29 20:58:07 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University. 8 * Christos Zoulas of Cornell University.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 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 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include "config.h" 35#include "config.h"
36#if !defined(lint) && !defined(SCCSID) 36#if !defined(lint) && !defined(SCCSID)
37#if 0 37#if 0
38static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; 38static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
39#else 39#else
40__RCSID("$NetBSD: history.c,v 1.43 2011/07/29 15:16:33 christos Exp $"); 40__RCSID("$NetBSD: history.c,v 1.44 2011/07/29 20:58:07 christos Exp $");
41#endif 41#endif
42#endif /* not lint && not SCCSID */ 42#endif /* not lint && not SCCSID */
43 43
44/* 44/*
45 * hist.c: TYPE(History) access functions 45 * hist.c: TYPE(History) access functions
46 */ 46 */
47#include <string.h> 47#include <string.h>
48#include <stdlib.h> 48#include <stdlib.h>
49#include <stdarg.h> 49#include <stdarg.h>
50#ifdef HAVE_VIS_H 
51#include <vis.h> 50#include <vis.h>
52#else 
53#include "vis.h" 
54#endif 
55#include <sys/stat.h> 51#include <sys/stat.h>
56 52
57static const char hist_cookie[] = "_HiStOrY_V2_\n"; 53static const char hist_cookie[] = "_HiStOrY_V2_\n";
58 54
59#include "histedit.h" 55#include "histedit.h"
60#include "chartype.h" 56#include "chartype.h"
61 57
62typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *); 58typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
63typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *); 59typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
64typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *); 60typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
65typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int); 61typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
66 62
67struct TYPE(history) { 63struct TYPE(history) {
68 void *h_ref; /* Argument for history fcns */ 64 void *h_ref; /* Argument for history fcns */
69 int h_ent; /* Last entry point for history */ 65 int h_ent; /* Last entry point for history */
70 history_gfun_t h_first; /* Get the first element */ 66 history_gfun_t h_first; /* Get the first element */
71 history_gfun_t h_next; /* Get the next element */ 67 history_gfun_t h_next; /* Get the next element */
72 history_gfun_t h_last; /* Get the last element */ 68 history_gfun_t h_last; /* Get the last element */
73 history_gfun_t h_prev; /* Get the previous element */ 69 history_gfun_t h_prev; /* Get the previous element */
74 history_gfun_t h_curr; /* Get the current element */ 70 history_gfun_t h_curr; /* Get the current element */
75 history_sfun_t h_set; /* Set the current element */ 71 history_sfun_t h_set; /* Set the current element */
76 history_sfun_t h_del; /* Set the given element */ 72 history_sfun_t h_del; /* Set the given element */
77 history_vfun_t h_clear; /* Clear the history list */ 73 history_vfun_t h_clear; /* Clear the history list */
78 history_efun_t h_enter; /* Add an element */ 74 history_efun_t h_enter; /* Add an element */
79 history_efun_t h_add; /* Append to an element */ 75 history_efun_t h_add; /* Append to an element */
80}; 76};
81 77
82#define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev) 78#define HNEXT(h, ev) (*(h)->h_next)((h)->h_ref, ev)
83#define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev) 79#define HFIRST(h, ev) (*(h)->h_first)((h)->h_ref, ev)
84#define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev) 80#define HPREV(h, ev) (*(h)->h_prev)((h)->h_ref, ev)
85#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev) 81#define HLAST(h, ev) (*(h)->h_last)((h)->h_ref, ev)
86#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev) 82#define HCURR(h, ev) (*(h)->h_curr)((h)->h_ref, ev)
87#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n) 83#define HSET(h, ev, n) (*(h)->h_set)((h)->h_ref, ev, n)
88#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev) 84#define HCLEAR(h, ev) (*(h)->h_clear)((h)->h_ref, ev)
89#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str) 85#define HENTER(h, ev, str) (*(h)->h_enter)((h)->h_ref, ev, str)
90#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str) 86#define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str)
91#define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n) 87#define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n)
92 88
93#define h_strdup(a) Strdup(a) 89#define h_strdup(a) Strdup(a)
94#define h_malloc(a) malloc(a) 90#define h_malloc(a) malloc(a)
95#define h_realloc(a, b) realloc((a), (b)) 91#define h_realloc(a, b) realloc((a), (b))
96#define h_free(a) free(a) 92#define h_free(a) free(a)
97 93
98typedef struct { 94typedef struct {
99 int num; 95 int num;
100 Char *str; 96 Char *str;
101} HistEventPrivate; 97} HistEventPrivate;
102 98
103 99
104 100
105private int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int); 101private int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
106private int history_getsize(TYPE(History) *, TYPE(HistEvent) *); 102private int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
107private int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int); 103private int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
108private int history_getunique(TYPE(History) *, TYPE(HistEvent) *); 104private int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
109private int history_set_fun(TYPE(History) *, TYPE(History) *); 105private int history_set_fun(TYPE(History) *, TYPE(History) *);
110private int history_load(TYPE(History) *, const char *); 106private int history_load(TYPE(History) *, const char *);
111private int history_save(TYPE(History) *, const char *); 107private int history_save(TYPE(History) *, const char *);
112private int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int); 108private int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
113private int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int); 109private int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
114private int history_next_string(TYPE(History) *, TYPE(HistEvent) *, const Char *); 110private int history_next_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
115private int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, const Char *); 111private int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
116 112
117 113
118/***********************************************************************/ 114/***********************************************************************/
119 115
120/* 116/*
121 * Builtin- history implementation 117 * Builtin- history implementation
122 */ 118 */
123typedef struct hentry_t { 119typedef struct hentry_t {
124 TYPE(HistEvent) ev; /* What we return */ 120 TYPE(HistEvent) ev; /* What we return */
125 void *data; /* data */ 121 void *data; /* data */
126 struct hentry_t *next; /* Next entry */ 122 struct hentry_t *next; /* Next entry */
127 struct hentry_t *prev; /* Previous entry */ 123 struct hentry_t *prev; /* Previous entry */
128} hentry_t; 124} hentry_t;
129 125
130typedef struct history_t { 126typedef struct history_t {
131 hentry_t list; /* Fake list header element */ 127 hentry_t list; /* Fake list header element */
132 hentry_t *cursor; /* Current element in the list */ 128 hentry_t *cursor; /* Current element in the list */
133 int max; /* Maximum number of events */ 129 int max; /* Maximum number of events */
134 int cur; /* Current number of events */ 130 int cur; /* Current number of events */
135 int eventid; /* For generation of unique event id */ 131 int eventid; /* For generation of unique event id */
136 int flags; /* TYPE(History) flags */ 132 int flags; /* TYPE(History) flags */
137#define H_UNIQUE 1 /* Store only unique elements */ 133#define H_UNIQUE 1 /* Store only unique elements */
138} history_t; 134} history_t;
139 135
140private int history_def_next(void *, TYPE(HistEvent) *); 136private int history_def_next(void *, TYPE(HistEvent) *);
141private int history_def_first(void *, TYPE(HistEvent) *); 137private int history_def_first(void *, TYPE(HistEvent) *);
142private int history_def_prev(void *, TYPE(HistEvent) *); 138private int history_def_prev(void *, TYPE(HistEvent) *);
143private int history_def_last(void *, TYPE(HistEvent) *); 139private int history_def_last(void *, TYPE(HistEvent) *);
144private int history_def_curr(void *, TYPE(HistEvent) *); 140private int history_def_curr(void *, TYPE(HistEvent) *);
145private int history_def_set(void *, TYPE(HistEvent) *, const int); 141private int history_def_set(void *, TYPE(HistEvent) *, const int);
146private void history_def_clear(void *, TYPE(HistEvent) *); 142private void history_def_clear(void *, TYPE(HistEvent) *);
147private int history_def_enter(void *, TYPE(HistEvent) *, const Char *); 143private int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
148private int history_def_add(void *, TYPE(HistEvent) *, const Char *); 144private int history_def_add(void *, TYPE(HistEvent) *, const Char *);
149private int history_def_del(void *, TYPE(HistEvent) *, const int); 145private int history_def_del(void *, TYPE(HistEvent) *, const int);
150 146
151private int history_def_init(void **, TYPE(HistEvent) *, int); 147private int history_def_init(void **, TYPE(HistEvent) *, int);
152private int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *); 148private int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
153private void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *); 149private void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
154 150
155private int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **); 151private int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
156private int history_set_nth(void *, TYPE(HistEvent) *, int); 152private int history_set_nth(void *, TYPE(HistEvent) *, int);
157 153
158#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num)) 154#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
159#define history_def_getsize(p) (((history_t *)p)->cur) 155#define history_def_getsize(p) (((history_t *)p)->cur)
160#define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0) 156#define history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0)
161#define history_def_setunique(p, uni) \ 157#define history_def_setunique(p, uni) \
162 if (uni) \ 158 if (uni) \
163 (((history_t *)p)->flags) |= H_UNIQUE; \ 159 (((history_t *)p)->flags) |= H_UNIQUE; \
164 else \ 160 else \
165 (((history_t *)p)->flags) &= ~H_UNIQUE 161 (((history_t *)p)->flags) &= ~H_UNIQUE
166 162
167#define he_strerror(code) he_errlist[code] 163#define he_strerror(code) he_errlist[code]
168#define he_seterrev(evp, code) {\ 164#define he_seterrev(evp, code) {\
169 evp->num = code;\ 165 evp->num = code;\
170 evp->str = he_strerror(code);\ 166 evp->str = he_strerror(code);\
171 } 167 }
172 168
173/* error messages */ 169/* error messages */
174static const Char *const he_errlist[] = { 170static const Char *const he_errlist[] = {
175 STR("OK"), 171 STR("OK"),
176 STR("unknown error"), 172 STR("unknown error"),
177 STR("malloc() failed"), 173 STR("malloc() failed"),
178 STR("first event not found"), 174 STR("first event not found"),
179 STR("last event not found"), 175 STR("last event not found"),
180 STR("empty list"), 176 STR("empty list"),
181 STR("no next event"), 177 STR("no next event"),
182 STR("no previous event"), 178 STR("no previous event"),
183 STR("current event is invalid"), 179 STR("current event is invalid"),
184 STR("event not found"), 180 STR("event not found"),
185 STR("can't read history from file"), 181 STR("can't read history from file"),
186 STR("can't write history"), 182 STR("can't write history"),
187 STR("required parameter(s) not supplied"), 183 STR("required parameter(s) not supplied"),
188 STR("history size negative"), 184 STR("history size negative"),
189 STR("function not allowed with other history-functions-set the default"), 185 STR("function not allowed with other history-functions-set the default"),
190 STR("bad parameters") 186 STR("bad parameters")
191}; 187};
192/* error codes */ 188/* error codes */
193#define _HE_OK 0 189#define _HE_OK 0
194#define _HE_UNKNOWN 1 190#define _HE_UNKNOWN 1
195#define _HE_MALLOC_FAILED 2 191#define _HE_MALLOC_FAILED 2
196#define _HE_FIRST_NOTFOUND 3 192#define _HE_FIRST_NOTFOUND 3
197#define _HE_LAST_NOTFOUND 4 193#define _HE_LAST_NOTFOUND 4
198#define _HE_EMPTY_LIST 5 194#define _HE_EMPTY_LIST 5
199#define _HE_END_REACHED 6 195#define _HE_END_REACHED 6
200#define _HE_START_REACHED 7 196#define _HE_START_REACHED 7
201#define _HE_CURR_INVALID 8 197#define _HE_CURR_INVALID 8
202#define _HE_NOT_FOUND 9 198#define _HE_NOT_FOUND 9
203#define _HE_HIST_READ 10 199#define _HE_HIST_READ 10
204#define _HE_HIST_WRITE 11 200#define _HE_HIST_WRITE 11
205#define _HE_PARAM_MISSING 12 201#define _HE_PARAM_MISSING 12
206#define _HE_SIZE_NEGATIVE 13 202#define _HE_SIZE_NEGATIVE 13
207#define _HE_NOT_ALLOWED 14 203#define _HE_NOT_ALLOWED 14
208#define _HE_BAD_PARAM 15 204#define _HE_BAD_PARAM 15
209 205
210/* history_def_first(): 206/* history_def_first():
211 * Default function to return the first event in the history. 207 * Default function to return the first event in the history.
212 */ 208 */
213private int 209private int
214history_def_first(void *p, TYPE(HistEvent) *ev) 210history_def_first(void *p, TYPE(HistEvent) *ev)
215{ 211{
216 history_t *h = (history_t *) p; 212 history_t *h = (history_t *) p;
217 213
218 h->cursor = h->list.next; 214 h->cursor = h->list.next;
219 if (h->cursor != &h->list) 215 if (h->cursor != &h->list)
220 *ev = h->cursor->ev; 216 *ev = h->cursor->ev;
221 else { 217 else {
222 he_seterrev(ev, _HE_FIRST_NOTFOUND); 218 he_seterrev(ev, _HE_FIRST_NOTFOUND);
223 return -1; 219 return -1;
224 } 220 }
225 221
226 return 0; 222 return 0;
227} 223}
228 224
229 225
230/* history_def_last(): 226/* history_def_last():
231 * Default function to return the last event in the history. 227 * Default function to return the last event in the history.
232 */ 228 */
233private int 229private int
234history_def_last(void *p, TYPE(HistEvent) *ev) 230history_def_last(void *p, TYPE(HistEvent) *ev)
235{ 231{
236 history_t *h = (history_t *) p; 232 history_t *h = (history_t *) p;
237 233
238 h->cursor = h->list.prev; 234 h->cursor = h->list.prev;
239 if (h->cursor != &h->list) 235 if (h->cursor != &h->list)
240 *ev = h->cursor->ev; 236 *ev = h->cursor->ev;
241 else { 237 else {
242 he_seterrev(ev, _HE_LAST_NOTFOUND); 238 he_seterrev(ev, _HE_LAST_NOTFOUND);
243 return -1; 239 return -1;
244 } 240 }
245 241
246 return 0; 242 return 0;
247} 243}
248 244
249 245
250/* history_def_next(): 246/* history_def_next():
251 * Default function to return the next event in the history. 247 * Default function to return the next event in the history.
252 */ 248 */
253private int 249private int
254history_def_next(void *p, TYPE(HistEvent) *ev) 250history_def_next(void *p, TYPE(HistEvent) *ev)
255{ 251{
256 history_t *h = (history_t *) p; 252 history_t *h = (history_t *) p;
257 253
258 if (h->cursor == &h->list) { 254 if (h->cursor == &h->list) {
259 he_seterrev(ev, _HE_EMPTY_LIST); 255 he_seterrev(ev, _HE_EMPTY_LIST);
260 return -1; 256 return -1;
261 } 257 }
262 258
263 if (h->cursor->next == &h->list) { 259 if (h->cursor->next == &h->list) {
264 he_seterrev(ev, _HE_END_REACHED); 260 he_seterrev(ev, _HE_END_REACHED);
265 return -1; 261 return -1;
266 } 262 }
267 263
268 h->cursor = h->cursor->next; 264 h->cursor = h->cursor->next;
269 *ev = h->cursor->ev; 265 *ev = h->cursor->ev;
270 266
271 return 0; 267 return 0;
272} 268}
273 269
274 270
275/* history_def_prev(): 271/* history_def_prev():
276 * Default function to return the previous event in the history. 272 * Default function to return the previous event in the history.
277 */ 273 */
278private int 274private int
279history_def_prev(void *p, TYPE(HistEvent) *ev) 275history_def_prev(void *p, TYPE(HistEvent) *ev)
280{ 276{
281 history_t *h = (history_t *) p; 277 history_t *h = (history_t *) p;
282 278
283 if (h->cursor == &h->list) { 279 if (h->cursor == &h->list) {
284 he_seterrev(ev, 280 he_seterrev(ev,
285 (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST); 281 (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
286 return -1; 282 return -1;
287 } 283 }
288 284
289 if (h->cursor->prev == &h->list) { 285 if (h->cursor->prev == &h->list) {
290 he_seterrev(ev, _HE_START_REACHED); 286 he_seterrev(ev, _HE_START_REACHED);
291 return -1; 287 return -1;
292 } 288 }
293 289
294 h->cursor = h->cursor->prev; 290 h->cursor = h->cursor->prev;
295 *ev = h->cursor->ev; 291 *ev = h->cursor->ev;
296 292
297 return 0; 293 return 0;
298} 294}
299 295
300 296
301/* history_def_curr(): 297/* history_def_curr():
302 * Default function to return the current event in the history. 298 * Default function to return the current event in the history.
303 */ 299 */
304private int 300private int
305history_def_curr(void *p, TYPE(HistEvent) *ev) 301history_def_curr(void *p, TYPE(HistEvent) *ev)
306{ 302{
307 history_t *h = (history_t *) p; 303 history_t *h = (history_t *) p;
308 304
309 if (h->cursor != &h->list) 305 if (h->cursor != &h->list)
310 *ev = h->cursor->ev; 306 *ev = h->cursor->ev;
311 else { 307 else {
312 he_seterrev(ev, 308 he_seterrev(ev,
313 (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST); 309 (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
314 return -1; 310 return -1;
315 } 311 }
316 312
317 return 0; 313 return 0;
318} 314}
319 315
320 316
321/* history_def_set(): 317/* history_def_set():
322 * Default function to set the current event in the history to the 318 * Default function to set the current event in the history to the
323 * given one. 319 * given one.
324 */ 320 */
325private int 321private int
326history_def_set(void *p, TYPE(HistEvent) *ev, const int n) 322history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
327{ 323{
328 history_t *h = (history_t *) p; 324 history_t *h = (history_t *) p;
329 325
330 if (h->cur == 0) { 326 if (h->cur == 0) {
331 he_seterrev(ev, _HE_EMPTY_LIST); 327 he_seterrev(ev, _HE_EMPTY_LIST);
332 return -1; 328 return -1;
333 } 329 }
334 if (h->cursor == &h->list || h->cursor->ev.num != n) { 330 if (h->cursor == &h->list || h->cursor->ev.num != n) {
335 for (h->cursor = h->list.next; h->cursor != &h->list; 331 for (h->cursor = h->list.next; h->cursor != &h->list;
336 h->cursor = h->cursor->next) 332 h->cursor = h->cursor->next)
337 if (h->cursor->ev.num == n) 333 if (h->cursor->ev.num == n)
338 break; 334 break;
339 } 335 }
340 if (h->cursor == &h->list) { 336 if (h->cursor == &h->list) {
341 he_seterrev(ev, _HE_NOT_FOUND); 337 he_seterrev(ev, _HE_NOT_FOUND);
342 return -1; 338 return -1;
343 } 339 }
344 return 0; 340 return 0;
345} 341}
346 342
347 343
348/* history_set_nth(): 344/* history_set_nth():
349 * Default function to set the current event in the history to the 345 * Default function to set the current event in the history to the
350 * n-th one. 346 * n-th one.
351 */ 347 */
352private int 348private int
353history_set_nth(void *p, TYPE(HistEvent) *ev, int n) 349history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
354{ 350{
355 history_t *h = (history_t *) p; 351 history_t *h = (history_t *) p;
356 352
357 if (h->cur == 0) { 353 if (h->cur == 0) {
358 he_seterrev(ev, _HE_EMPTY_LIST); 354 he_seterrev(ev, _HE_EMPTY_LIST);
359 return -1; 355 return -1;
360 } 356 }
361 for (h->cursor = h->list.prev; h->cursor != &h->list; 357 for (h->cursor = h->list.prev; h->cursor != &h->list;
362 h->cursor = h->cursor->prev) 358 h->cursor = h->cursor->prev)
363 if (n-- <= 0) 359 if (n-- <= 0)
364 break; 360 break;
365 if (h->cursor == &h->list) { 361 if (h->cursor == &h->list) {
366 he_seterrev(ev, _HE_NOT_FOUND); 362 he_seterrev(ev, _HE_NOT_FOUND);
367 return -1; 363 return -1;
368 } 364 }
369 return 0; 365 return 0;
370} 366}
371 367
372 368
373/* history_def_add(): 369/* history_def_add():
374 * Append string to element 370 * Append string to element
375 */ 371 */
376private int 372private int
377history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str) 373history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
378{ 374{
379 history_t *h = (history_t *) p; 375 history_t *h = (history_t *) p;
380 size_t len; 376 size_t len;
381 Char *s; 377 Char *s;
382 HistEventPrivate *evp = (void *)&h->cursor->ev; 378 HistEventPrivate *evp = (void *)&h->cursor->ev;
383 379
384 if (h->cursor == &h->list) 380 if (h->cursor == &h->list)
385 return history_def_enter(p, ev, str); 381 return history_def_enter(p, ev, str);
386 len = Strlen(evp->str) + Strlen(str) + 1; 382 len = Strlen(evp->str) + Strlen(str) + 1;
387 s = h_malloc(len * sizeof(*s)); 383 s = h_malloc(len * sizeof(*s));
388 if (s == NULL) { 384 if (s == NULL) {
389 he_seterrev(ev, _HE_MALLOC_FAILED); 385 he_seterrev(ev, _HE_MALLOC_FAILED);
390 return -1; 386 return -1;
391 } 387 }
392 (void) Strncpy(s, h->cursor->ev.str, len); 388 (void) Strncpy(s, h->cursor->ev.str, len);
393 s[len - 1] = '\0'; 389 s[len - 1] = '\0';
394 (void) Strncat(s, str, len - Strlen(s) - 1); 390 (void) Strncat(s, str, len - Strlen(s) - 1);
395 h_free(evp->str); 391 h_free(evp->str);
396 evp->str = s; 392 evp->str = s;
397 *ev = h->cursor->ev; 393 *ev = h->cursor->ev;
398 return 0; 394 return 0;
399} 395}
400 396
401 397
402private int 398private int
403history_deldata_nth(history_t *h, TYPE(HistEvent) *ev, 399history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
404 int num, void **data) 400 int num, void **data)
405{ 401{
406 if (history_set_nth(h, ev, num) != 0) 402 if (history_set_nth(h, ev, num) != 0)
407 return -1; 403 return -1;
408 /* magic value to skip delete (just set to n-th history) */ 404 /* magic value to skip delete (just set to n-th history) */
409 if (data == (void **)-1) 405 if (data == (void **)-1)
410 return 0; 406 return 0;
411 ev->str = Strdup(h->cursor->ev.str); 407 ev->str = Strdup(h->cursor->ev.str);
412 ev->num = h->cursor->ev.num; 408 ev->num = h->cursor->ev.num;
413 if (data) 409 if (data)
414 *data = h->cursor->data; 410 *data = h->cursor->data;
415 history_def_delete(h, ev, h->cursor); 411 history_def_delete(h, ev, h->cursor);
416 return 0; 412 return 0;
417} 413}
418 414
419 415
420/* history_def_del(): 416/* history_def_del():
421 * Delete element hp of the h list 417 * Delete element hp of the h list
422 */ 418 */
423/* ARGSUSED */ 419/* ARGSUSED */
424private int 420private int
425history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)), 421history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
426 const int num) 422 const int num)
427{ 423{
428 history_t *h = (history_t *) p; 424 history_t *h = (history_t *) p;
429 if (history_def_set(h, ev, num) != 0) 425 if (history_def_set(h, ev, num) != 0)
430 return -1; 426 return -1;
431 ev->str = Strdup(h->cursor->ev.str); 427 ev->str = Strdup(h->cursor->ev.str);
432 ev->num = h->cursor->ev.num; 428 ev->num = h->cursor->ev.num;
433 history_def_delete(h, ev, h->cursor); 429 history_def_delete(h, ev, h->cursor);
434 return 0; 430 return 0;
435} 431}
436 432
437 433
438/* history_def_delete(): 434/* history_def_delete():
439 * Delete element hp of the h list 435 * Delete element hp of the h list
440 */ 436 */
441/* ARGSUSED */ 437/* ARGSUSED */
442private void 438private void
443history_def_delete(history_t *h,  439history_def_delete(history_t *h,
444 TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp) 440 TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
445{ 441{
446 HistEventPrivate *evp = (void *)&hp->ev; 442 HistEventPrivate *evp = (void *)&hp->ev;
447 if (hp == &h->list) 443 if (hp == &h->list)
448 abort(); 444 abort();
449 if (h->cursor == hp) { 445 if (h->cursor == hp) {
450 h->cursor = hp->prev; 446 h->cursor = hp->prev;
451 if (h->cursor == &h->list) 447 if (h->cursor == &h->list)
452 h->cursor = hp->next; 448 h->cursor = hp->next;
453 } 449 }
454 hp->prev->next = hp->next; 450 hp->prev->next = hp->next;
455 hp->next->prev = hp->prev; 451 hp->next->prev = hp->prev;
456 h_free(evp->str); 452 h_free(evp->str);
457 h_free(hp); 453 h_free(hp);
458 h->cur--; 454 h->cur--;
459} 455}
460 456
461 457
462/* history_def_insert(): 458/* history_def_insert():
463 * Insert element with string str in the h list 459 * Insert element with string str in the h list
464 */ 460 */
465private int 461private int
466history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str) 462history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
467{ 463{
468 hentry_t *c; 464 hentry_t *c;
469 465
470 c = h_malloc(sizeof(*c)); 466 c = h_malloc(sizeof(*c));
471 if (c == NULL) 467 if (c == NULL)
472 goto oomem; 468 goto oomem;
473 if ((c->ev.str = h_strdup(str)) == NULL) { 469 if ((c->ev.str = h_strdup(str)) == NULL) {
474 h_free(c); 470 h_free(c);
475 goto oomem; 471 goto oomem;
476 } 472 }
477 c->data = NULL; 473 c->data = NULL;
478 c->ev.num = ++h->eventid; 474 c->ev.num = ++h->eventid;
479 c->next = h->list.next; 475 c->next = h->list.next;
480 c->prev = &h->list; 476 c->prev = &h->list;
481 h->list.next->prev = c; 477 h->list.next->prev = c;
482 h->list.next = c; 478 h->list.next = c;
483 h->cur++; 479 h->cur++;
484 h->cursor = c; 480 h->cursor = c;
485 481
486 *ev = c->ev; 482 *ev = c->ev;
487 return 0; 483 return 0;
488oomem: 484oomem:
489 he_seterrev(ev, _HE_MALLOC_FAILED); 485 he_seterrev(ev, _HE_MALLOC_FAILED);
490 return -1; 486 return -1;
491} 487}
492 488
493 489
494/* history_def_enter(): 490/* history_def_enter():
495 * Default function to enter an item in the history 491 * Default function to enter an item in the history
496 */ 492 */
497private int 493private int
498history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str) 494history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
499{ 495{
500 history_t *h = (history_t *) p; 496 history_t *h = (history_t *) p;
501 497
502 if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list && 498 if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list &&
503 Strcmp(h->list.next->ev.str, str) == 0) 499 Strcmp(h->list.next->ev.str, str) == 0)
504 return 0; 500 return 0;
505 501
506 if (history_def_insert(h, ev, str) == -1) 502 if (history_def_insert(h, ev, str) == -1)
507 return -1; /* error, keep error message */ 503 return -1; /* error, keep error message */
508 504
509 /* 505 /*
510 * Always keep at least one entry. 506 * Always keep at least one entry.
511 * This way we don't have to check for the empty list. 507 * This way we don't have to check for the empty list.
512 */ 508 */
513 while (h->cur > h->max && h->cur > 0) 509 while (h->cur > h->max && h->cur > 0)
514 history_def_delete(h, ev, h->list.prev); 510 history_def_delete(h, ev, h->list.prev);
515 511
516 return 1; 512 return 1;
517} 513}
518 514
519 515
520/* history_def_init(): 516/* history_def_init():
521 * Default history initialization function 517 * Default history initialization function
522 */ 518 */
523/* ARGSUSED */ 519/* ARGSUSED */
524private int 520private int
525history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n) 521history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
526{ 522{
527 history_t *h = (history_t *) h_malloc(sizeof(*h)); 523 history_t *h = (history_t *) h_malloc(sizeof(*h));
528 if (h == NULL) 524 if (h == NULL)
529 return -1; 525 return -1;
530 526
531 if (n <= 0) 527 if (n <= 0)
532 n = 0; 528 n = 0;
533 h->eventid = 0; 529 h->eventid = 0;
534 h->cur = 0; 530 h->cur = 0;
535 h->max = n; 531 h->max = n;
536 h->list.next = h->list.prev = &h->list; 532 h->list.next = h->list.prev = &h->list;
537 h->list.ev.str = NULL; 533 h->list.ev.str = NULL;
538 h->list.ev.num = 0; 534 h->list.ev.num = 0;
539 h->cursor = &h->list; 535 h->cursor = &h->list;
540 h->flags = 0; 536 h->flags = 0;
541 *p = h; 537 *p = h;
542 return 0; 538 return 0;
543} 539}
544 540
545 541
546/* history_def_clear(): 542/* history_def_clear():
547 * Default history cleanup function 543 * Default history cleanup function
548 */ 544 */
549private void 545private void
550history_def_clear(void *p, TYPE(HistEvent) *ev) 546history_def_clear(void *p, TYPE(HistEvent) *ev)
551{ 547{
552 history_t *h = (history_t *) p; 548 history_t *h = (history_t *) p;
553 549
554 while (h->list.prev != &h->list) 550 while (h->list.prev != &h->list)
555 history_def_delete(h, ev, h->list.prev); 551 history_def_delete(h, ev, h->list.prev);
556 h->cursor = &h->list; 552 h->cursor = &h->list;
557 h->eventid = 0; 553 h->eventid = 0;
558 h->cur = 0; 554 h->cur = 0;
559} 555}
560 556
561 557
562 558
563 559
564/************************************************************************/ 560/************************************************************************/
565 561
566/* history_init(): 562/* history_init():
567 * Initialization function. 563 * Initialization function.
568 */ 564 */
569public TYPE(History) * 565public TYPE(History) *
570FUN(history,init)(void) 566FUN(history,init)(void)
571{ 567{
572 TYPE(HistEvent) ev; 568 TYPE(HistEvent) ev;
573 TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h)); 569 TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
574 if (h == NULL) 570 if (h == NULL)
575 return NULL; 571 return NULL;
576 572
577 if (history_def_init(&h->h_ref, &ev, 0) == -1) { 573 if (history_def_init(&h->h_ref, &ev, 0) == -1) {
578 h_free(h); 574 h_free(h);
579 return NULL; 575 return NULL;
580 } 576 }
581 h->h_ent = -1; 577 h->h_ent = -1;
582 h->h_next = history_def_next; 578 h->h_next = history_def_next;
583 h->h_first = history_def_first; 579 h->h_first = history_def_first;
584 h->h_last = history_def_last; 580 h->h_last = history_def_last;
585 h->h_prev = history_def_prev; 581 h->h_prev = history_def_prev;
586 h->h_curr = history_def_curr; 582 h->h_curr = history_def_curr;
587 h->h_set = history_def_set; 583 h->h_set = history_def_set;
588 h->h_clear = history_def_clear; 584 h->h_clear = history_def_clear;
589 h->h_enter = history_def_enter; 585 h->h_enter = history_def_enter;
590 h->h_add = history_def_add; 586 h->h_add = history_def_add;
591 h->h_del = history_def_del; 587 h->h_del = history_def_del;
592 588
593 return h; 589 return h;
594} 590}
595 591
596 592
597/* history_end(): 593/* history_end():
598 * clean up history; 594 * clean up history;
599 */ 595 */
600public void 596public void
601FUN(history,end)(TYPE(History) *h) 597FUN(history,end)(TYPE(History) *h)
602{ 598{
603 TYPE(HistEvent) ev; 599 TYPE(HistEvent) ev;
604 600
605 if (h->h_next == history_def_next) 601 if (h->h_next == history_def_next)
606 history_def_clear(h->h_ref, &ev); 602 history_def_clear(h->h_ref, &ev);
607 h_free(h->h_ref); 603 h_free(h->h_ref);
608 h_free(h); 604 h_free(h);
609} 605}
610 606
611 607
612 608
613/* history_setsize(): 609/* history_setsize():
614 * Set history number of events 610 * Set history number of events
615 */ 611 */
616private int 612private int
617history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num) 613history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
618{ 614{
619 615
620 if (h->h_next != history_def_next) { 616 if (h->h_next != history_def_next) {
621 he_seterrev(ev, _HE_NOT_ALLOWED); 617 he_seterrev(ev, _HE_NOT_ALLOWED);
622 return -1; 618 return -1;
623 } 619 }
624 if (num < 0) { 620 if (num < 0) {
625 he_seterrev(ev, _HE_BAD_PARAM); 621 he_seterrev(ev, _HE_BAD_PARAM);
626 return -1; 622 return -1;
627 } 623 }
628 history_def_setsize(h->h_ref, num); 624 history_def_setsize(h->h_ref, num);
629 return 0; 625 return 0;
630} 626}
631 627
632 628
633/* history_getsize(): 629/* history_getsize():
634 * Get number of events currently in history 630 * Get number of events currently in history
635 */ 631 */
636private int 632private int
637history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev) 633history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
638{ 634{
639 if (h->h_next != history_def_next) { 635 if (h->h_next != history_def_next) {
640 he_seterrev(ev, _HE_NOT_ALLOWED); 636 he_seterrev(ev, _HE_NOT_ALLOWED);
641 return -1; 637 return -1;
642 } 638 }
643 ev->num = history_def_getsize(h->h_ref); 639 ev->num = history_def_getsize(h->h_ref);
644 if (ev->num < -1) { 640 if (ev->num < -1) {
645 he_seterrev(ev, _HE_SIZE_NEGATIVE); 641 he_seterrev(ev, _HE_SIZE_NEGATIVE);
646 return -1; 642 return -1;
647 } 643 }
648 return 0; 644 return 0;
649} 645}
650 646
651 647
652/* history_setunique(): 648/* history_setunique():
653 * Set if adjacent equal events should not be entered in history. 649 * Set if adjacent equal events should not be entered in history.
654 */ 650 */
655private int 651private int
656history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni) 652history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
657{ 653{
658 654
659 if (h->h_next != history_def_next) { 655 if (h->h_next != history_def_next) {
660 he_seterrev(ev, _HE_NOT_ALLOWED); 656 he_seterrev(ev, _HE_NOT_ALLOWED);
661 return -1; 657 return -1;
662 } 658 }
663 history_def_setunique(h->h_ref, uni); 659 history_def_setunique(h->h_ref, uni);
664 return 0; 660 return 0;
665} 661}
666 662
667 663
668/* history_getunique(): 664/* history_getunique():
669 * Get if adjacent equal events should not be entered in history. 665 * Get if adjacent equal events should not be entered in history.
670 */ 666 */
671private int 667private int
672history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev) 668history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
673{ 669{
674 if (h->h_next != history_def_next) { 670 if (h->h_next != history_def_next) {
675 he_seterrev(ev, _HE_NOT_ALLOWED); 671 he_seterrev(ev, _HE_NOT_ALLOWED);
676 return -1; 672 return -1;
677 } 673 }
678 ev->num = history_def_getunique(h->h_ref); 674 ev->num = history_def_getunique(h->h_ref);
679 return 0; 675 return 0;
680} 676}
681 677
682 678
683/* history_set_fun(): 679/* history_set_fun():
684 * Set history functions 680 * Set history functions
685 */ 681 */
686private int 682private int
687history_set_fun(TYPE(History) *h, TYPE(History) *nh) 683history_set_fun(TYPE(History) *h, TYPE(History) *nh)
688{ 684{
689 TYPE(HistEvent) ev; 685 TYPE(HistEvent) ev;
690 686
691 if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL || 687 if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||
692 nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL || 688 nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||
693 nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || 689 nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL ||
694 nh->h_del == NULL || nh->h_ref == NULL) { 690 nh->h_del == NULL || nh->h_ref == NULL) {
695 if (h->h_next != history_def_next) { 691 if (h->h_next != history_def_next) {
696 history_def_init(&h->h_ref, &ev, 0); 692 history_def_init(&h->h_ref, &ev, 0);
697 h->h_first = history_def_first; 693 h->h_first = history_def_first;
698 h->h_next = history_def_next; 694 h->h_next = history_def_next;
699 h->h_last = history_def_last; 695 h->h_last = history_def_last;
700 h->h_prev = history_def_prev; 696 h->h_prev = history_def_prev;
701 h->h_curr = history_def_curr; 697 h->h_curr = history_def_curr;
702 h->h_set = history_def_set; 698 h->h_set = history_def_set;
703 h->h_clear = history_def_clear; 699 h->h_clear = history_def_clear;
704 h->h_enter = history_def_enter; 700 h->h_enter = history_def_enter;
705 h->h_add = history_def_add; 701 h->h_add = history_def_add;
706 h->h_del = history_def_del; 702 h->h_del = history_def_del;
707 } 703 }
708 return -1; 704 return -1;
709 } 705 }
710 if (h->h_next == history_def_next) 706 if (h->h_next == history_def_next)
711 history_def_clear(h->h_ref, &ev); 707 history_def_clear(h->h_ref, &ev);
712 708
713 h->h_ent = -1; 709 h->h_ent = -1;
714 h->h_first = nh->h_first; 710 h->h_first = nh->h_first;
715 h->h_next = nh->h_next; 711 h->h_next = nh->h_next;
716 h->h_last = nh->h_last; 712 h->h_last = nh->h_last;
717 h->h_prev = nh->h_prev; 713 h->h_prev = nh->h_prev;
718 h->h_curr = nh->h_curr; 714 h->h_curr = nh->h_curr;
719 h->h_set = nh->h_set; 715 h->h_set = nh->h_set;
720 h->h_clear = nh->h_clear; 716 h->h_clear = nh->h_clear;
721 h->h_enter = nh->h_enter; 717 h->h_enter = nh->h_enter;
722 h->h_add = nh->h_add; 718 h->h_add = nh->h_add;
723 h->h_del = nh->h_del; 719 h->h_del = nh->h_del;
724 720
725 return 0; 721 return 0;
726} 722}
727 723
728 724
729/* history_load(): 725/* history_load():
730 * TYPE(History) load function 726 * TYPE(History) load function
731 */ 727 */
732private int 728private int
733history_load(TYPE(History) *h, const char *fname) 729history_load(TYPE(History) *h, const char *fname)
734{ 730{
735 FILE *fp; 731 FILE *fp;
736 char *line; 732 char *line;
737 size_t sz, max_size; 733 size_t sz, max_size;
738 char *ptr; 734 char *ptr;
739 int i = -1; 735 int i = -1;
740 TYPE(HistEvent) ev; 736 TYPE(HistEvent) ev;
741#ifdef WIDECHAR 737#ifdef WIDECHAR
742 static ct_buffer_t conv; 738 static ct_buffer_t conv;
743#endif 739#endif
744 740
745 if ((fp = fopen(fname, "r")) == NULL) 741 if ((fp = fopen(fname, "r")) == NULL)
746 return i; 742 return i;
747 743
748 if ((line = fgetln(fp, &sz)) == NULL) 744 if ((line = fgetln(fp, &sz)) == NULL)
749 goto done; 745 goto done;
750 746
751 if (strncmp(line, hist_cookie, sz) != 0) 747 if (strncmp(line, hist_cookie, sz) != 0)
752 goto done; 748 goto done;
753 749
754 ptr = h_malloc((max_size = 1024) * sizeof(*ptr)); 750 ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
755 if (ptr == NULL) 751 if (ptr == NULL)
756 goto done; 752 goto done;
757 for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) { 753 for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
758 char c = line[sz]; 754 char c = line[sz];
759 755
760 if (sz != 0 && line[sz - 1] == '\n') 756 if (sz != 0 && line[sz - 1] == '\n')
761 line[--sz] = '\0'; 757 line[--sz] = '\0';
762 else 758 else
763 line[sz] = '\0'; 759 line[sz] = '\0';
764 760
765 if (max_size < sz) { 761 if (max_size < sz) {
766 char *nptr; 762 char *nptr;
767 max_size = (sz + 1024) & ~1023; 763 max_size = (sz + 1024) & ~1023;
768 nptr = h_realloc(ptr, max_size * sizeof(*ptr)); 764 nptr = h_realloc(ptr, max_size * sizeof(*ptr));
769 if (nptr == NULL) { 765 if (nptr == NULL) {
770 i = -1; 766 i = -1;
771 goto oomem; 767 goto oomem;
772 } 768 }
773 ptr = nptr; 769 ptr = nptr;
774 } 770 }
775 (void) strunvis(ptr, line); 771 (void) strunvis(ptr, line);
776 line[sz] = c; 772 line[sz] = c;
777 if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) { 773 if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) {
778 i = -1; 774 i = -1;
779 goto oomem; 775 goto oomem;
780 } 776 }
781 } 777 }
782oomem: 778oomem:
783 h_free(ptr); 779 h_free(ptr);
784done: 780done:
785 (void) fclose(fp); 781 (void) fclose(fp);
786 return i; 782 return i;
787} 783}
788 784
789 785
790/* history_save(): 786/* history_save():
791 * TYPE(History) save function 787 * TYPE(History) save function
792 */ 788 */
793private int 789private int
794history_save(TYPE(History) *h, const char *fname) 790history_save(TYPE(History) *h, const char *fname)
795{ 791{
796 FILE *fp; 792 FILE *fp;
797 TYPE(HistEvent) ev; 793 TYPE(HistEvent) ev;
798 int i = -1, retval; 794 int i = -1, retval;
799 size_t len, max_size; 795 size_t len, max_size;
800 char *ptr; 796 char *ptr;
801 const char *str; 797 const char *str;
802#ifdef WIDECHAR 798#ifdef WIDECHAR
803 static ct_buffer_t conv; 799 static ct_buffer_t conv;
804#endif 800#endif
805 801
806 if ((fp = fopen(fname, "w")) == NULL) 802 if ((fp = fopen(fname, "w")) == NULL)
807 return -1; 803 return -1;
808 804
809 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) 805 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
810 goto done; 806 goto done;
811 if (fputs(hist_cookie, fp) == EOF) 807 if (fputs(hist_cookie, fp) == EOF)
812 goto done; 808 goto done;
813 ptr = h_malloc((max_size = 1024) * sizeof(*ptr)); 809 ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
814 if (ptr == NULL) 810 if (ptr == NULL)
815 goto done; 811 goto done;
816 for (i = 0, retval = HLAST(h, &ev); 812 for (i = 0, retval = HLAST(h, &ev);
817 retval != -1; 813 retval != -1;
818 retval = HPREV(h, &ev), i++) { 814 retval = HPREV(h, &ev), i++) {
819 str = ct_encode_string(ev.str, &conv); 815 str = ct_encode_string(ev.str, &conv);
820 len = strlen(str) * 4; 816 len = strlen(str) * 4;
821 if (len >= max_size) { 817 if (len >= max_size) {
822 char *nptr; 818 char *nptr;
823 max_size = (len + 1024) & ~1023; 819 max_size = (len + 1024) & ~1023;
824 nptr = h_realloc(ptr, max_size * sizeof(*ptr)); 820 nptr = h_realloc(ptr, max_size * sizeof(*ptr));
825 if (nptr == NULL) { 821 if (nptr == NULL) {
826 i = -1; 822 i = -1;
827 goto oomem; 823 goto oomem;
828 } 824 }
829 ptr = nptr; 825 ptr = nptr;
830 } 826 }
831 (void) strvis(ptr, str, VIS_WHITE); 827 (void) strvis(ptr, str, VIS_WHITE);
832 (void) fprintf(fp, "%s\n", ptr); 828 (void) fprintf(fp, "%s\n", ptr);
833 } 829 }
834oomem: 830oomem:
835 h_free(ptr); 831 h_free(ptr);
836done: 832done:
837 (void) fclose(fp); 833 (void) fclose(fp);
838 return i; 834 return i;
839} 835}
840 836
841 837
842/* history_prev_event(): 838/* history_prev_event():
843 * Find the previous event, with number given 839 * Find the previous event, with number given
844 */ 840 */
845private int 841private int
846history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num) 842history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
847{ 843{
848 int retval; 844 int retval;
849 845
850 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) 846 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
851 if (ev->num == num) 847 if (ev->num == num)
852 return 0; 848 return 0;
853 849
854 he_seterrev(ev, _HE_NOT_FOUND); 850 he_seterrev(ev, _HE_NOT_FOUND);
855 return -1; 851 return -1;
856} 852}
857 853
858 854
859private int 855private int
860history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d) 856history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
861{ 857{
862 int retval; 858 int retval;
863 859
864 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) 860 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
865 if (ev->num == num) { 861 if (ev->num == num) {
866 if (d) 862 if (d)
867 *d = ((history_t *)h->h_ref)->cursor->data; 863 *d = ((history_t *)h->h_ref)->cursor->data;
868 return 0; 864 return 0;
869 } 865 }
870 866
871 he_seterrev(ev, _HE_NOT_FOUND); 867 he_seterrev(ev, _HE_NOT_FOUND);
872 return -1; 868 return -1;
873} 869}
874 870
875 871
876/* history_next_event(): 872/* history_next_event():
877 * Find the next event, with number given 873 * Find the next event, with number given
878 */ 874 */
879private int 875private int
880history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num) 876history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
881{ 877{
882 int retval; 878 int retval;
883 879
884 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) 880 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
885 if (ev->num == num) 881 if (ev->num == num)
886 return 0; 882 return 0;
887 883
888 he_seterrev(ev, _HE_NOT_FOUND); 884 he_seterrev(ev, _HE_NOT_FOUND);
889 return -1; 885 return -1;
890} 886}
891 887
892 888
893/* history_prev_string(): 889/* history_prev_string():
894 * Find the previous event beginning with string 890 * Find the previous event beginning with string
895 */ 891 */
896private int 892private int
897history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str) 893history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
898{ 894{
899 size_t len = Strlen(str); 895 size_t len = Strlen(str);
900 int retval; 896 int retval;
901 897
902 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) 898 for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
903 if (Strncmp(str, ev->str, len) == 0) 899 if (Strncmp(str, ev->str, len) == 0)
904 return 0; 900 return 0;
905 901
906 he_seterrev(ev, _HE_NOT_FOUND); 902 he_seterrev(ev, _HE_NOT_FOUND);
907 return -1; 903 return -1;
908} 904}
909 905
910 906
911/* history_next_string(): 907/* history_next_string():
912 * Find the next event beginning with string 908 * Find the next event beginning with string
913 */ 909 */
914private int 910private int
915history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str) 911history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
916{ 912{
917 size_t len = Strlen(str); 913 size_t len = Strlen(str);
918 int retval; 914 int retval;
919 915
920 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) 916 for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
921 if (Strncmp(str, ev->str, len) == 0) 917 if (Strncmp(str, ev->str, len) == 0)
922 return 0; 918 return 0;
923 919
924 he_seterrev(ev, _HE_NOT_FOUND); 920 he_seterrev(ev, _HE_NOT_FOUND);
925 return -1; 921 return -1;
926} 922}
927 923
928 924
929/* history(): 925/* history():
930 * User interface to history functions. 926 * User interface to history functions.
931 */ 927 */
932int 928int
933FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...) 929FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
934{ 930{
935 va_list va; 931 va_list va;
936 const Char *str; 932 const Char *str;
937 int retval; 933 int retval;
938 934
939 va_start(va, fun); 935 va_start(va, fun);
940 936
941 he_seterrev(ev, _HE_OK); 937 he_seterrev(ev, _HE_OK);
942 938
943 switch (fun) { 939 switch (fun) {
944 case H_GETSIZE: 940 case H_GETSIZE:
945 retval = history_getsize(h, ev); 941 retval = history_getsize(h, ev);
946 break; 942 break;
947 943
948 case H_SETSIZE: 944 case H_SETSIZE:
949 retval = history_setsize(h, ev, va_arg(va, int)); 945 retval = history_setsize(h, ev, va_arg(va, int));
950 break; 946 break;
951 947
952 case H_GETUNIQUE: 948 case H_GETUNIQUE:
953 retval = history_getunique(h, ev); 949 retval = history_getunique(h, ev);
954 break; 950 break;
955 951
956 case H_SETUNIQUE: 952 case H_SETUNIQUE:
957 retval = history_setunique(h, ev, va_arg(va, int)); 953 retval = history_setunique(h, ev, va_arg(va, int));
958 break; 954 break;
959 955
960 case H_ADD: 956 case H_ADD:
961 str = va_arg(va, const Char *); 957 str = va_arg(va, const Char *);
962 retval = HADD(h, ev, str); 958 retval = HADD(h, ev, str);
963 break; 959 break;
964 960
965 case H_DEL: 961 case H_DEL:
966 retval = HDEL(h, ev, va_arg(va, const int)); 962 retval = HDEL(h, ev, va_arg(va, const int));
967 break; 963 break;
968 964
969 case H_ENTER: 965 case H_ENTER:
970 str = va_arg(va, const Char *); 966 str = va_arg(va, const Char *);
971 if ((retval = HENTER(h, ev, str)) != -1) 967 if ((retval = HENTER(h, ev, str)) != -1)
972 h->h_ent = ev->num; 968 h->h_ent = ev->num;
973 break; 969 break;
974 970
975 case H_APPEND: 971 case H_APPEND:
976 str = va_arg(va, const Char *); 972 str = va_arg(va, const Char *);
977 if ((retval = HSET(h, ev, h->h_ent)) != -1) 973 if ((retval = HSET(h, ev, h->h_ent)) != -1)
978 retval = HADD(h, ev, str); 974 retval = HADD(h, ev, str);
979 break; 975 break;
980 976
981 case H_FIRST: 977 case H_FIRST:
982 retval = HFIRST(h, ev); 978 retval = HFIRST(h, ev);
983 break; 979 break;
984 980
985 case H_NEXT: 981 case H_NEXT:
986 retval = HNEXT(h, ev); 982 retval = HNEXT(h, ev);
987 break; 983 break;
988 984
989 case H_LAST: 985 case H_LAST:
990 retval = HLAST(h, ev); 986 retval = HLAST(h, ev);
991 break; 987 break;
992 988
993 case H_PREV: 989 case H_PREV:
994 retval = HPREV(h, ev); 990 retval = HPREV(h, ev);
995 break; 991 break;
996 992
997 case H_CURR: 993 case H_CURR:
998 retval = HCURR(h, ev); 994 retval = HCURR(h, ev);
999 break; 995 break;
1000 996
1001 case H_SET: 997 case H_SET:
1002 retval = HSET(h, ev, va_arg(va, const int)); 998 retval = HSET(h, ev, va_arg(va, const int));
1003 break; 999 break;
1004 1000
1005 case H_CLEAR: 1001 case H_CLEAR:
1006 HCLEAR(h, ev); 1002 HCLEAR(h, ev);
1007 retval = 0; 1003 retval = 0;
1008 break; 1004 break;
1009 1005
1010 case H_LOAD: 1006 case H_LOAD:
1011 retval = history_load(h, va_arg(va, const char *)); 1007 retval = history_load(h, va_arg(va, const char *));
1012 if (retval == -1) 1008 if (retval == -1)
1013 he_seterrev(ev, _HE_HIST_READ); 1009 he_seterrev(ev, _HE_HIST_READ);
1014 break; 1010 break;
1015 1011
1016 case H_SAVE: 1012 case H_SAVE:
1017 retval = history_save(h, va_arg(va, const char *)); 1013 retval = history_save(h, va_arg(va, const char *));
1018 if (retval == -1) 1014 if (retval == -1)
1019 he_seterrev(ev, _HE_HIST_WRITE); 1015 he_seterrev(ev, _HE_HIST_WRITE);
1020 break; 1016 break;
1021 1017
1022 case H_PREV_EVENT: 1018 case H_PREV_EVENT:
1023 retval = history_prev_event(h, ev, va_arg(va, int)); 1019 retval = history_prev_event(h, ev, va_arg(va, int));
1024 break; 1020 break;
1025 1021
1026 case H_NEXT_EVENT: 1022 case H_NEXT_EVENT:
1027 retval = history_next_event(h, ev, va_arg(va, int)); 1023 retval = history_next_event(h, ev, va_arg(va, int));
1028 break; 1024 break;
1029 1025
1030 case H_PREV_STR: 1026 case H_PREV_STR:
1031 retval = history_prev_string(h, ev, va_arg(va, const Char *)); 1027 retval = history_prev_string(h, ev, va_arg(va, const Char *));
1032 break; 1028 break;
1033 1029
1034 case H_NEXT_STR: 1030 case H_NEXT_STR:
1035 retval = history_next_string(h, ev, va_arg(va, const Char *)); 1031 retval = history_next_string(h, ev, va_arg(va, const Char *));
1036 break; 1032 break;
1037 1033
1038 case H_FUNC: 1034 case H_FUNC:
1039 { 1035 {
1040 TYPE(History) hf; 1036 TYPE(History) hf;
1041 1037
1042 hf.h_ref = va_arg(va, void *); 1038 hf.h_ref = va_arg(va, void *);
1043 h->h_ent = -1; 1039 h->h_ent = -1;
1044 hf.h_first = va_arg(va, history_gfun_t); 1040 hf.h_first = va_arg(va, history_gfun_t);
1045 hf.h_next = va_arg(va, history_gfun_t); 1041 hf.h_next = va_arg(va, history_gfun_t);
1046 hf.h_last = va_arg(va, history_gfun_t); 1042 hf.h_last = va_arg(va, history_gfun_t);
1047 hf.h_prev = va_arg(va, history_gfun_t); 1043 hf.h_prev = va_arg(va, history_gfun_t);
1048 hf.h_curr = va_arg(va, history_gfun_t); 1044 hf.h_curr = va_arg(va, history_gfun_t);
1049 hf.h_set = va_arg(va, history_sfun_t); 1045 hf.h_set = va_arg(va, history_sfun_t);
1050 hf.h_clear = va_arg(va, history_vfun_t); 1046 hf.h_clear = va_arg(va, history_vfun_t);
1051 hf.h_enter = va_arg(va, history_efun_t); 1047 hf.h_enter = va_arg(va, history_efun_t);
1052 hf.h_add = va_arg(va, history_efun_t); 1048 hf.h_add = va_arg(va, history_efun_t);
1053 hf.h_del = va_arg(va, history_sfun_t); 1049 hf.h_del = va_arg(va, history_sfun_t);

cvs diff -r1.96 -r1.97 src/lib/libedit/readline.c (switch to unified diff)

--- src/lib/libedit/readline.c 2011/07/29 15:16:33 1.96
+++ src/lib/libedit/readline.c 2011/07/29 20:58:07 1.97
@@ -1,2257 +1,2261 @@ @@ -1,2257 +1,2261 @@
1/* $NetBSD: readline.c,v 1.96 2011/07/29 15:16:33 christos Exp $ */ 1/* $NetBSD: readline.c,v 1.97 2011/07/29 20:58:07 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jaromir Dolecek. 8 * by Jaromir Dolecek.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include "config.h" 32#include "config.h"
33#if !defined(lint) && !defined(SCCSID) 33#if !defined(lint) && !defined(SCCSID)
34__RCSID("$NetBSD: readline.c,v 1.96 2011/07/29 15:16:33 christos Exp $"); 34__RCSID("$NetBSD: readline.c,v 1.97 2011/07/29 20:58:07 christos Exp $");
35#endif /* not lint && not SCCSID */ 35#endif /* not lint && not SCCSID */
36 36
37#include <sys/types.h> 37#include <sys/types.h>
38#include <sys/stat.h> 38#include <sys/stat.h>
39#include <stdio.h> 39#include <stdio.h>
40#include <dirent.h> 40#include <dirent.h>
41#include <string.h> 41#include <string.h>
42#include <pwd.h> 42#include <pwd.h>
43#include <ctype.h> 43#include <ctype.h>
44#include <stdlib.h> 44#include <stdlib.h>
45#include <unistd.h> 45#include <unistd.h>
46#include <limits.h> 46#include <limits.h>
47#include <errno.h> 47#include <errno.h>
48#include <fcntl.h> 48#include <fcntl.h>
49#include <setjmp.h> 49#include <setjmp.h>
50#ifdef HAVE_VIS_H 
51#include <vis.h> 50#include <vis.h>
52#else 51
53#include "vis.h" 
54#endif 
55#include "readline/readline.h" 52#include "readline/readline.h"
56#include "el.h" 53#include "el.h"
57#include "fcns.h" /* for EL_NUM_FCNS */ 54#include "fcns.h" /* for EL_NUM_FCNS */
58#include "histedit.h" 55#include "histedit.h"
59#include "filecomplete.h" 56#include "filecomplete.h"
60 57
61void rl_prep_terminal(int); 58void rl_prep_terminal(int);
62void rl_deprep_terminal(void); 59void rl_deprep_terminal(void);
63 60
64/* for rl_complete() */ 61/* for rl_complete() */
65#define TAB '\r' 62#define TAB '\r'
66 63
67/* see comment at the #ifdef for sense of this */ 64/* see comment at the #ifdef for sense of this */
68/* #define GDB_411_HACK */ 65/* #define GDB_411_HACK */
69 66
70/* readline compatibility stuff - look at readline sources/documentation */ 67/* readline compatibility stuff - look at readline sources/documentation */
71/* to see what these variables mean */ 68/* to see what these variables mean */
72const char *rl_library_version = "EditLine wrapper"; 69const char *rl_library_version = "EditLine wrapper";
73int rl_readline_version = RL_READLINE_VERSION; 70int rl_readline_version = RL_READLINE_VERSION;
74static char empty[] = { '\0' }; 71static char empty[] = { '\0' };
75static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; 72static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
76static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', 73static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
77 '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; 74 '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
78char *rl_readline_name = empty; 75char *rl_readline_name = empty;
79FILE *rl_instream = NULL; 76FILE *rl_instream = NULL;
80FILE *rl_outstream = NULL; 77FILE *rl_outstream = NULL;
81int rl_point = 0; 78int rl_point = 0;
82int rl_end = 0; 79int rl_end = 0;
83char *rl_line_buffer = NULL; 80char *rl_line_buffer = NULL;
84VCPFunction *rl_linefunc = NULL; 81VCPFunction *rl_linefunc = NULL;
85int rl_done = 0; 82int rl_done = 0;
86VFunction *rl_event_hook = NULL; 83VFunction *rl_event_hook = NULL;
87KEYMAP_ENTRY_ARRAY emacs_standard_keymap, 84KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
88 emacs_meta_keymap, 85 emacs_meta_keymap,
89 emacs_ctlx_keymap; 86 emacs_ctlx_keymap;
90 87
91int history_base = 1; /* probably never subject to change */ 88int history_base = 1; /* probably never subject to change */
92int history_length = 0; 89int history_length = 0;
93int max_input_history = 0; 90int max_input_history = 0;
94char history_expansion_char = '!'; 91char history_expansion_char = '!';
95char history_subst_char = '^'; 92char history_subst_char = '^';
96char *history_no_expand_chars = expand_chars; 93char *history_no_expand_chars = expand_chars;
97Function *history_inhibit_expansion_function = NULL; 94Function *history_inhibit_expansion_function = NULL;
98char *history_arg_extract(int start, int end, const char *str); 95char *history_arg_extract(int start, int end, const char *str);
99 96
100int rl_inhibit_completion = 0; 97int rl_inhibit_completion = 0;
101int rl_attempted_completion_over = 0; 98int rl_attempted_completion_over = 0;
102char *rl_basic_word_break_characters = break_chars; 99char *rl_basic_word_break_characters = break_chars;
103char *rl_completer_word_break_characters = NULL; 100char *rl_completer_word_break_characters = NULL;
104char *rl_completer_quote_characters = NULL; 101char *rl_completer_quote_characters = NULL;
105Function *rl_completion_entry_function = NULL; 102Function *rl_completion_entry_function = NULL;
106CPPFunction *rl_attempted_completion_function = NULL; 103CPPFunction *rl_attempted_completion_function = NULL;
107Function *rl_pre_input_hook = NULL; 104Function *rl_pre_input_hook = NULL;
108Function *rl_startup1_hook = NULL; 105Function *rl_startup1_hook = NULL;
109int (*rl_getc_function)(FILE *) = NULL; 106int (*rl_getc_function)(FILE *) = NULL;
110char *rl_terminal_name = NULL; 107char *rl_terminal_name = NULL;
111int rl_already_prompted = 0; 108int rl_already_prompted = 0;
112int rl_filename_completion_desired = 0; 109int rl_filename_completion_desired = 0;
113int rl_ignore_completion_duplicates = 0; 110int rl_ignore_completion_duplicates = 0;
114int rl_catch_signals = 1; 111int rl_catch_signals = 1;
115int readline_echoing_p = 1; 112int readline_echoing_p = 1;
116int _rl_print_completions_horizontally = 0; 113int _rl_print_completions_horizontally = 0;
117VFunction *rl_redisplay_function = NULL; 114VFunction *rl_redisplay_function = NULL;
118Function *rl_startup_hook = NULL; 115Function *rl_startup_hook = NULL;
119VFunction *rl_completion_display_matches_hook = NULL; 116VFunction *rl_completion_display_matches_hook = NULL;
120VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal; 117VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
121VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal; 118VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
122KEYMAP_ENTRY_ARRAY emacs_meta_keymap; 119KEYMAP_ENTRY_ARRAY emacs_meta_keymap;
123 120
124/* 121/*
125 * The current prompt string. 122 * The current prompt string.
126 */ 123 */
127char *rl_prompt = NULL; 124char *rl_prompt = NULL;
128/* 125/*
129 * This is set to character indicating type of completion being done by 126 * This is set to character indicating type of completion being done by
130 * rl_complete_internal(); this is available for application completion 127 * rl_complete_internal(); this is available for application completion
131 * functions. 128 * functions.
132 */ 129 */
133int rl_completion_type = 0; 130int rl_completion_type = 0;
134 131
135/* 132/*
136 * If more than this number of items results from query for possible 133 * If more than this number of items results from query for possible
137 * completions, we ask user if they are sure to really display the list. 134 * completions, we ask user if they are sure to really display the list.
138 */ 135 */
139int rl_completion_query_items = 100; 136int rl_completion_query_items = 100;
140 137
141/* 138/*
142 * List of characters which are word break characters, but should be left 139 * List of characters which are word break characters, but should be left
143 * in the parsed text when it is passed to the completion function. 140 * in the parsed text when it is passed to the completion function.
144 * Shell uses this to help determine what kind of completing to do. 141 * Shell uses this to help determine what kind of completing to do.
145 */ 142 */
146char *rl_special_prefixes = NULL; 143char *rl_special_prefixes = NULL;
147 144
148/* 145/*
149 * This is the character appended to the completed words if at the end of 146 * This is the character appended to the completed words if at the end of
150 * the line. Default is ' ' (a space). 147 * the line. Default is ' ' (a space).
151 */ 148 */
152int rl_completion_append_character = ' '; 149int rl_completion_append_character = ' ';
153 150
154/* stuff below is used internally by libedit for readline emulation */ 151/* stuff below is used internally by libedit for readline emulation */
155 152
156static History *h = NULL; 153static History *h = NULL;
157static EditLine *e = NULL; 154static EditLine *e = NULL;
158static Function *map[256]; 155static Function *map[256];
159static jmp_buf topbuf; 156static jmp_buf topbuf;
160 157
161/* internal functions */ 158/* internal functions */
162static unsigned char _el_rl_complete(EditLine *, int); 159static unsigned char _el_rl_complete(EditLine *, int);
163static unsigned char _el_rl_tstp(EditLine *, int); 160static unsigned char _el_rl_tstp(EditLine *, int);
164static char *_get_prompt(EditLine *); 161static char *_get_prompt(EditLine *);
165static int _getc_function(EditLine *, char *); 162static int _getc_function(EditLine *, char *);
166static HIST_ENTRY *_move_history(int); 163static HIST_ENTRY *_move_history(int);
167static int _history_expand_command(const char *, size_t, size_t, 164static int _history_expand_command(const char *, size_t, size_t,
168 char **); 165 char **);
169static char *_rl_compat_sub(const char *, const char *, 166static char *_rl_compat_sub(const char *, const char *,
170 const char *, int); 167 const char *, int);
171static int _rl_event_read_char(EditLine *, char *); 168static int _rl_event_read_char(EditLine *, char *);
172static void _rl_update_pos(void); 169static void _rl_update_pos(void);
173 170
174 171
175/* ARGSUSED */ 172/* ARGSUSED */
176static char * 173static char *
177_get_prompt(EditLine *el __attribute__((__unused__))) 174_get_prompt(EditLine *el __attribute__((__unused__)))
178{ 175{
179 rl_already_prompted = 1; 176 rl_already_prompted = 1;
180 return rl_prompt; 177 return rl_prompt;
181} 178}
182 179
183 180
184/* 181/*
185 * generic function for moving around history 182 * generic function for moving around history
186 */ 183 */
187static HIST_ENTRY * 184static HIST_ENTRY *
188_move_history(int op) 185_move_history(int op)
189{ 186{
190 HistEvent ev; 187 HistEvent ev;
191 static HIST_ENTRY rl_he; 188 static HIST_ENTRY rl_he;
192 189
193 if (history(h, &ev, op) != 0) 190 if (history(h, &ev, op) != 0)
194 return NULL; 191 return NULL;
195 192
196 rl_he.line = ev.str; 193 rl_he.line = ev.str;
197 rl_he.data = NULL; 194 rl_he.data = NULL;
198 195
199 return &rl_he; 196 return &rl_he;
200} 197}
201 198
202 199
203/* 200/*
204 * read one key from user defined input function 201 * read one key from user defined input function
205 */ 202 */
206static int 203static int
207/*ARGSUSED*/ 204/*ARGSUSED*/
208_getc_function(EditLine *el, char *c) 205_getc_function(EditLine *el __attribute__((__unused__)), char *c)
209{ 206{
210 int i; 207 int i;
211 208
212 i = (*rl_getc_function)(NULL); 209 i = (*rl_getc_function)(NULL);
213 if (i == -1) 210 if (i == -1)
214 return 0; 211 return 0;
215 *c = i; 212 *c = i;
216 return 1; 213 return 1;
217} 214}
218 215
219static void 216static void
220_resize_fun(EditLine *el, void *a) 217_resize_fun(EditLine *el, void *a)
221{ 218{
222 const LineInfo *li; 219 const LineInfo *li;
223 char **ap = a; 220 char **ap = a;
224 221
225 li = el_line(el); 222 li = el_line(el);
226 /* a cheesy way to get rid of const cast. */ 223 /* a cheesy way to get rid of const cast. */
227 *ap = memchr(li->buffer, *li->buffer, 1); 224 *ap = memchr(li->buffer, *li->buffer, 1);
228} 225}
229 226
230static const char _dothistory[] = "/.history"; 227static const char _dothistory[] = "/.history";
231 228
232static const char * 229static const char *
233_default_history_file(void) 230_default_history_file(void)
234{ 231{
235 struct passwd *p; 232 struct passwd *p;
236 static char path[PATH_MAX]; 233 static char path[PATH_MAX];
237 234
238 if (*path) 235 if (*path)
239 return path; 236 return path;
240 if ((p = getpwuid(getuid())) == NULL) 237 if ((p = getpwuid(getuid())) == NULL)
241 return NULL; 238 return NULL;
242 strlcpy(path, p->pw_dir, PATH_MAX); 239 strlcpy(path, p->pw_dir, PATH_MAX);
243 strlcat(path, _dothistory, PATH_MAX); 240 strlcat(path, _dothistory, PATH_MAX);
244 return path; 241 return path;
245} 242}
246 243
247/* 244/*
248 * READLINE compatibility stuff 245 * READLINE compatibility stuff
249 */ 246 */
250 247
251/* 248/*
252 * Set the prompt 249 * Set the prompt
253 */ 250 */
254int 251int
255rl_set_prompt(const char *prompt) 252rl_set_prompt(const char *prompt)
256{ 253{
257 char *p; 254 char *p;
258 255
259 if (!prompt) 256 if (!prompt)
260 prompt = ""; 257 prompt = "";
261 if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)  258 if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0)
262 return 0; 259 return 0;
263 if (rl_prompt) 260 if (rl_prompt)
264 el_free(rl_prompt); 261 el_free(rl_prompt);
265 rl_prompt = strdup(prompt); 262 rl_prompt = strdup(prompt);
266 if (rl_prompt == NULL) 263 if (rl_prompt == NULL)
267 return -1; 264 return -1;
268 265
269 while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) 266 while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL)
270 *p = RL_PROMPT_START_IGNORE; 267 *p = RL_PROMPT_START_IGNORE;
271 268
272 return 0; 269 return 0;
273} 270}
274 271
275/* 272/*
276 * initialize rl compat stuff 273 * initialize rl compat stuff
277 */ 274 */
278int 275int
279rl_initialize(void) 276rl_initialize(void)
280{ 277{
281 HistEvent ev; 278 HistEvent ev;
282 int editmode = 1; 279 int editmode = 1;
283 struct termios t; 280 struct termios t;
284 281
285 if (e != NULL) 282 if (e != NULL)
286 el_end(e); 283 el_end(e);
287 if (h != NULL) 284 if (h != NULL)
288 history_end(h); 285 history_end(h);
289 286
290 if (!rl_instream) 287 if (!rl_instream)
291 rl_instream = stdin; 288 rl_instream = stdin;
292 if (!rl_outstream) 289 if (!rl_outstream)
293 rl_outstream = stdout; 290 rl_outstream = stdout;
294 291
295 /* 292 /*
296 * See if we don't really want to run the editor 293 * See if we don't really want to run the editor
297 */ 294 */
298 if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0) 295 if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
299 editmode = 0; 296 editmode = 0;
300 297
301 e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr); 298 e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
302 299
303 if (!editmode) 300 if (!editmode)
304 el_set(e, EL_EDITMODE, 0); 301 el_set(e, EL_EDITMODE, 0);
305 302
306 h = history_init(); 303 h = history_init();
307 if (!e || !h) 304 if (!e || !h)
308 return -1; 305 return -1;
309 306
310 history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ 307 history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */
311 history_length = 0; 308 history_length = 0;
312 max_input_history = INT_MAX; 309 max_input_history = INT_MAX;
313 el_set(e, EL_HIST, history, h); 310 el_set(e, EL_HIST, history, h);
314 311
315 /* Setup resize function */ 312 /* Setup resize function */
316 el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer); 313 el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer);
317 314
318 /* setup getc function if valid */ 315 /* setup getc function if valid */
319 if (rl_getc_function) 316 if (rl_getc_function)
320 el_set(e, EL_GETCFN, _getc_function); 317 el_set(e, EL_GETCFN, _getc_function);
321 318
322 /* for proper prompt printing in readline() */ 319 /* for proper prompt printing in readline() */
323 if (rl_set_prompt("") == -1) { 320 if (rl_set_prompt("") == -1) {
324 history_end(h); 321 history_end(h);
325 el_end(e); 322 el_end(e);
326 return -1; 323 return -1;
327 } 324 }
328 el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE); 325 el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE);
329 el_set(e, EL_SIGNAL, rl_catch_signals); 326 el_set(e, EL_SIGNAL, rl_catch_signals);
330 327
331 /* set default mode to "emacs"-style and read setting afterwards */ 328 /* set default mode to "emacs"-style and read setting afterwards */
332 /* so this can be overriden */ 329 /* so this can be overriden */
333 el_set(e, EL_EDITOR, "emacs"); 330 el_set(e, EL_EDITOR, "emacs");
334 if (rl_terminal_name != NULL) 331 if (rl_terminal_name != NULL)
335 el_set(e, EL_TERMINAL, rl_terminal_name); 332 el_set(e, EL_TERMINAL, rl_terminal_name);
336 else 333 else
337 el_get(e, EL_TERMINAL, &rl_terminal_name); 334 el_get(e, EL_TERMINAL, &rl_terminal_name);
338 335
339 /* 336 /*
340 * Word completion - this has to go AFTER rebinding keys 337 * Word completion - this has to go AFTER rebinding keys
341 * to emacs-style. 338 * to emacs-style.
342 */ 339 */
343 el_set(e, EL_ADDFN, "rl_complete", 340 el_set(e, EL_ADDFN, "rl_complete",
344 "ReadLine compatible completion function", 341 "ReadLine compatible completion function",
345 _el_rl_complete); 342 _el_rl_complete);
346 el_set(e, EL_BIND, "^I", "rl_complete", NULL); 343 el_set(e, EL_BIND, "^I", "rl_complete", NULL);
347 344
348 /* 345 /*
349 * Send TSTP when ^Z is pressed. 346 * Send TSTP when ^Z is pressed.
350 */ 347 */
351 el_set(e, EL_ADDFN, "rl_tstp", 348 el_set(e, EL_ADDFN, "rl_tstp",
352 "ReadLine compatible suspend function", 349 "ReadLine compatible suspend function",
353 _el_rl_tstp); 350 _el_rl_tstp);
354 el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); 351 el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);
355  352
356 /* read settings from configuration file */ 353 /* read settings from configuration file */
357 el_source(e, NULL); 354 el_source(e, NULL);
358 355
359 /* 356 /*
360 * Unfortunately, some applications really do use rl_point 357 * Unfortunately, some applications really do use rl_point
361 * and rl_line_buffer directly. 358 * and rl_line_buffer directly.
362 */ 359 */
363 _resize_fun(e, &rl_line_buffer); 360 _resize_fun(e, &rl_line_buffer);
364 _rl_update_pos(); 361 _rl_update_pos();
365 362
366 if (rl_startup_hook) 363 if (rl_startup_hook)
367 (*rl_startup_hook)(NULL, 0); 364 (*rl_startup_hook)(NULL, 0);
368 365
369 return 0; 366 return 0;
370} 367}
371 368
372 369
373/* 370/*
374 * read one line from input stream and return it, chomping 371 * read one line from input stream and return it, chomping
375 * trailing newline (if there is any) 372 * trailing newline (if there is any)
376 */ 373 */
377char * 374char *
378readline(const char *p) 375readline(const char *p)
379{ 376{
380 HistEvent ev; 377 HistEvent ev;
381 const char * volatile prompt = p; 378 const char * volatile prompt = p;
382 int count; 379 int count;
383 const char *ret; 380 const char *ret;
384 char *buf; 381 char *buf;
385 static int used_event_hook; 382 static int used_event_hook;
386 383
387 if (e == NULL || h == NULL) 384 if (e == NULL || h == NULL)
388 rl_initialize(); 385 rl_initialize();
389 386
390 rl_done = 0; 387 rl_done = 0;
391 388
392 (void)setjmp(topbuf); 389 (void)setjmp(topbuf);
393 390
394 /* update prompt accordingly to what has been passed */ 391 /* update prompt accordingly to what has been passed */
395 if (rl_set_prompt(prompt) == -1) 392 if (rl_set_prompt(prompt) == -1)
396 return NULL; 393 return NULL;
397 394
398 if (rl_pre_input_hook) 395 if (rl_pre_input_hook)
399 (*rl_pre_input_hook)(NULL, 0); 396 (*rl_pre_input_hook)(NULL, 0);
400 397
401 if (rl_event_hook && !(e->el_flags&NO_TTY)) { 398 if (rl_event_hook && !(e->el_flags&NO_TTY)) {
402 el_set(e, EL_GETCFN, _rl_event_read_char); 399 el_set(e, EL_GETCFN, _rl_event_read_char);
403 used_event_hook = 1; 400 used_event_hook = 1;
404 } 401 }
405 402
406 if (!rl_event_hook && used_event_hook) { 403 if (!rl_event_hook && used_event_hook) {
407 el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN); 404 el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN);
408 used_event_hook = 0; 405 used_event_hook = 0;
409 } 406 }
410 407
411 rl_already_prompted = 0; 408 rl_already_prompted = 0;
412 409
413 /* get one line from input stream */ 410 /* get one line from input stream */
414 ret = el_gets(e, &count); 411 ret = el_gets(e, &count);
415 412
416 if (ret && count > 0) { 413 if (ret && count > 0) {
417 int lastidx; 414 int lastidx;
418 415
419 buf = strdup(ret); 416 buf = strdup(ret);
420 if (buf == NULL) 417 if (buf == NULL)
421 return NULL; 418 return NULL;
422 lastidx = count - 1; 419 lastidx = count - 1;
423 if (buf[lastidx] == '\n') 420 if (buf[lastidx] == '\n')
424 buf[lastidx] = '\0'; 421 buf[lastidx] = '\0';
425 } else 422 } else
426 buf = NULL; 423 buf = NULL;
427 424
428 history(h, &ev, H_GETSIZE); 425 history(h, &ev, H_GETSIZE);
429 history_length = ev.num; 426 history_length = ev.num;
430 427
431 return buf; 428 return buf;
432} 429}
433 430
434/* 431/*
435 * history functions 432 * history functions
436 */ 433 */
437 434
438/* 435/*
439 * is normally called before application starts to use 436 * is normally called before application starts to use
440 * history expansion functions 437 * history expansion functions
441 */ 438 */
442void 439void
443using_history(void) 440using_history(void)
444{ 441{
445 if (h == NULL || e == NULL) 442 if (h == NULL || e == NULL)
446 rl_initialize(); 443 rl_initialize();
447} 444}
448 445
449 446
450/* 447/*
451 * substitute ``what'' with ``with'', returning resulting string; if 448 * substitute ``what'' with ``with'', returning resulting string; if
452 * globally == 1, substitutes all occurrences of what, otherwise only the 449 * globally == 1, substitutes all occurrences of what, otherwise only the
453 * first one 450 * first one
454 */ 451 */
455static char * 452static char *
456_rl_compat_sub(const char *str, const char *what, const char *with, 453_rl_compat_sub(const char *str, const char *what, const char *with,
457 int globally) 454 int globally)
458{ 455{
459 const char *s; 456 const char *s;
460 char *r, *result; 457 char *r, *result;
461 size_t len, with_len, what_len; 458 size_t len, with_len, what_len;
462 459
463 len = strlen(str); 460 len = strlen(str);
464 with_len = strlen(with); 461 with_len = strlen(with);
465 what_len = strlen(what); 462 what_len = strlen(what);
466 463
467 /* calculate length we need for result */ 464 /* calculate length we need for result */
468 s = str; 465 s = str;
469 while (*s) { 466 while (*s) {
470 if (*s == *what && !strncmp(s, what, what_len)) { 467 if (*s == *what && !strncmp(s, what, what_len)) {
471 len += with_len - what_len; 468 len += with_len - what_len;
472 if (!globally) 469 if (!globally)
473 break; 470 break;
474 s += what_len; 471 s += what_len;
475 } else 472 } else
476 s++; 473 s++;
477 } 474 }
478 r = result = el_malloc((len + 1) * sizeof(*r)); 475 r = result = el_malloc((len + 1) * sizeof(*r));
479 if (result == NULL) 476 if (result == NULL)
480 return NULL; 477 return NULL;
481 s = str; 478 s = str;
482 while (*s) { 479 while (*s) {
483 if (*s == *what && !strncmp(s, what, what_len)) { 480 if (*s == *what && !strncmp(s, what, what_len)) {
484 (void)strncpy(r, with, with_len); 481 (void)strncpy(r, with, with_len);
485 r += with_len; 482 r += with_len;
486 s += what_len; 483 s += what_len;
487 if (!globally) { 484 if (!globally) {
488 (void)strcpy(r, s); 485 (void)strcpy(r, s);
489 return result; 486 return result;
490 } 487 }
491 } else 488 } else
492 *r++ = *s++; 489 *r++ = *s++;
493 } 490 }
494 *r = '\0'; 491 *r = '\0';
495 return result; 492 return result;
496} 493}
497 494
498static char *last_search_pat; /* last !?pat[?] search pattern */ 495static char *last_search_pat; /* last !?pat[?] search pattern */
499static char *last_search_match; /* last !?pat[?] that matched */ 496static char *last_search_match; /* last !?pat[?] that matched */
500 497
501const char * 498const char *
502get_history_event(const char *cmd, int *cindex, int qchar) 499get_history_event(const char *cmd, int *cindex, int qchar)
503{ 500{
504 int idx, sign, sub, num, begin, ret; 501 int idx, sign, sub, num, begin, ret;
505 size_t len; 502 size_t len;
506 char *pat; 503 char *pat;
507 const char *rptr; 504 const char *rptr;
508 HistEvent ev; 505 HistEvent ev;
509 506
510 idx = *cindex; 507 idx = *cindex;
511 if (cmd[idx++] != history_expansion_char) 508 if (cmd[idx++] != history_expansion_char)
512 return NULL; 509 return NULL;
513 510
514 /* find out which event to take */ 511 /* find out which event to take */
515 if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { 512 if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') {
516 if (history(h, &ev, H_FIRST) != 0) 513 if (history(h, &ev, H_FIRST) != 0)
517 return NULL; 514 return NULL;
518 *cindex = cmd[idx]? (idx + 1):idx; 515 *cindex = cmd[idx]? (idx + 1):idx;
519 return ev.str; 516 return ev.str;
520 } 517 }
521 sign = 0; 518 sign = 0;
522 if (cmd[idx] == '-') { 519 if (cmd[idx] == '-') {
523 sign = 1; 520 sign = 1;
524 idx++; 521 idx++;
525 } 522 }
526 523
527 if ('0' <= cmd[idx] && cmd[idx] <= '9') { 524 if ('0' <= cmd[idx] && cmd[idx] <= '9') {
528 HIST_ENTRY *rl_he; 525 HIST_ENTRY *rl_he;
529 526
530 num = 0; 527 num = 0;
531 while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') { 528 while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
532 num = num * 10 + cmd[idx] - '0'; 529 num = num * 10 + cmd[idx] - '0';
533 idx++; 530 idx++;
534 } 531 }
535 if (sign) 532 if (sign)
536 num = history_length - num + 1; 533 num = history_length - num + 1;
537 534
538 if (!(rl_he = history_get(num))) 535 if (!(rl_he = history_get(num)))
539 return NULL; 536 return NULL;
540 537
541 *cindex = idx; 538 *cindex = idx;
542 return rl_he->line; 539 return rl_he->line;
543 } 540 }
544 sub = 0; 541 sub = 0;
545 if (cmd[idx] == '?') { 542 if (cmd[idx] == '?') {
546 sub = 1; 543 sub = 1;
547 idx++; 544 idx++;
548 } 545 }
549 begin = idx; 546 begin = idx;
550 while (cmd[idx]) { 547 while (cmd[idx]) {
551 if (cmd[idx] == '\n') 548 if (cmd[idx] == '\n')
552 break; 549 break;
553 if (sub && cmd[idx] == '?') 550 if (sub && cmd[idx] == '?')
554 break; 551 break;
555 if (!sub && (cmd[idx] == ':' || cmd[idx] == ' ' 552 if (!sub && (cmd[idx] == ':' || cmd[idx] == ' '
556 || cmd[idx] == '\t' || cmd[idx] == qchar)) 553 || cmd[idx] == '\t' || cmd[idx] == qchar))
557 break; 554 break;
558 idx++; 555 idx++;
559 } 556 }
560 len = idx - begin; 557 len = idx - begin;
561 if (sub && cmd[idx] == '?') 558 if (sub && cmd[idx] == '?')
562 idx++; 559 idx++;
563 if (sub && len == 0 && last_search_pat && *last_search_pat) 560 if (sub && len == 0 && last_search_pat && *last_search_pat)
564 pat = last_search_pat; 561 pat = last_search_pat;
565 else if (len == 0) 562 else if (len == 0)
566 return NULL; 563 return NULL;
567 else { 564 else {
568 if ((pat = el_malloc((len + 1) * sizeof(*pat))) == NULL) 565 if ((pat = el_malloc((len + 1) * sizeof(*pat))) == NULL)
569 return NULL; 566 return NULL;
570 (void)strncpy(pat, cmd + begin, len); 567 (void)strncpy(pat, cmd + begin, len);
571 pat[len] = '\0'; 568 pat[len] = '\0';
572 } 569 }
573 570
574 if (history(h, &ev, H_CURR) != 0) { 571 if (history(h, &ev, H_CURR) != 0) {
575 if (pat != last_search_pat) 572 if (pat != last_search_pat)
576 el_free(pat); 573 el_free(pat);
577 return NULL; 574 return NULL;
578 } 575 }
579 num = ev.num; 576 num = ev.num;
580 577
581 if (sub) { 578 if (sub) {
582 if (pat != last_search_pat) { 579 if (pat != last_search_pat) {
583 if (last_search_pat) 580 if (last_search_pat)
584 el_free(last_search_pat); 581 el_free(last_search_pat);
585 last_search_pat = pat; 582 last_search_pat = pat;
586 } 583 }
587 ret = history_search(pat, -1); 584 ret = history_search(pat, -1);
588 } else 585 } else
589 ret = history_search_prefix(pat, -1); 586 ret = history_search_prefix(pat, -1);
590 587
591 if (ret == -1) { 588 if (ret == -1) {
592 /* restore to end of list on failed search */ 589 /* restore to end of list on failed search */
593 history(h, &ev, H_FIRST); 590 history(h, &ev, H_FIRST);
594 (void)fprintf(rl_outstream, "%s: Event not found\n", pat); 591 (void)fprintf(rl_outstream, "%s: Event not found\n", pat);
595 if (pat != last_search_pat) 592 if (pat != last_search_pat)
596 el_free(pat); 593 el_free(pat);
597 return NULL; 594 return NULL;
598 } 595 }
599 596
600 if (sub && len) { 597 if (sub && len) {
601 if (last_search_match && last_search_match != pat) 598 if (last_search_match && last_search_match != pat)
602 el_free(last_search_match); 599 el_free(last_search_match);
603 last_search_match = pat; 600 last_search_match = pat;
604 } 601 }
605 602
606 if (pat != last_search_pat) 603 if (pat != last_search_pat)
607 el_free(pat); 604 el_free(pat);
608 605
609 if (history(h, &ev, H_CURR) != 0) 606 if (history(h, &ev, H_CURR) != 0)
610 return NULL; 607 return NULL;
611 *cindex = idx; 608 *cindex = idx;
612 rptr = ev.str; 609 rptr = ev.str;
613 610
614 /* roll back to original position */ 611 /* roll back to original position */
615 (void)history(h, &ev, H_SET, num); 612 (void)history(h, &ev, H_SET, num);
616 613
617 return rptr; 614 return rptr;
618} 615}
619 616
620/* 617/*
621 * the real function doing history expansion - takes as argument command 618 * the real function doing history expansion - takes as argument command
622 * to do and data upon which the command should be executed 619 * to do and data upon which the command should be executed
623 * does expansion the way I've understood readline documentation 620 * does expansion the way I've understood readline documentation
624 * 621 *
625 * returns 0 if data was not modified, 1 if it was and 2 if the string 622 * returns 0 if data was not modified, 1 if it was and 2 if the string
626 * should be only printed and not executed; in case of error, 623 * should be only printed and not executed; in case of error,
627 * returns -1 and *result points to NULL 624 * returns -1 and *result points to NULL
628 * it's callers responsibility to free() string returned in *result 625 * it's callers responsibility to free() string returned in *result
629 */ 626 */
630static int 627static int
631_history_expand_command(const char *command, size_t offs, size_t cmdlen, 628_history_expand_command(const char *command, size_t offs, size_t cmdlen,
632 char **result) 629 char **result)
633{ 630{
634 char *tmp, *search = NULL, *aptr; 631 char *tmp, *search = NULL, *aptr;
635 const char *ptr, *cmd; 632 const char *ptr, *cmd;
636 static char *from = NULL, *to = NULL; 633 static char *from = NULL, *to = NULL;
637 int start, end, idx, has_mods = 0; 634 int start, end, idx, has_mods = 0;
638 int p_on = 0, g_on = 0; 635 int p_on = 0, g_on = 0;
639 636
640 *result = NULL; 637 *result = NULL;
641 aptr = NULL; 638 aptr = NULL;
642 ptr = NULL; 639 ptr = NULL;
643 640
644 /* First get event specifier */ 641 /* First get event specifier */
645 idx = 0; 642 idx = 0;
646 643
647 if (strchr(":^*$", command[offs + 1])) { 644 if (strchr(":^*$", command[offs + 1])) {
648 char str[4]; 645 char str[4];
649 /* 646 /*
650 * "!:" is shorthand for "!!:". 647 * "!:" is shorthand for "!!:".
651 * "!^", "!*" and "!$" are shorthand for 648 * "!^", "!*" and "!$" are shorthand for
652 * "!!:^", "!!:*" and "!!:$" respectively. 649 * "!!:^", "!!:*" and "!!:$" respectively.
653 */ 650 */
654 str[0] = str[1] = '!'; 651 str[0] = str[1] = '!';
655 str[2] = '0'; 652 str[2] = '0';
656 ptr = get_history_event(str, &idx, 0); 653 ptr = get_history_event(str, &idx, 0);
657 idx = (command[offs + 1] == ':')? 1:0; 654 idx = (command[offs + 1] == ':')? 1:0;
658 has_mods = 1; 655 has_mods = 1;
659 } else { 656 } else {
660 if (command[offs + 1] == '#') { 657 if (command[offs + 1] == '#') {
661 /* use command so far */ 658 /* use command so far */
662 if ((aptr = el_malloc((offs + 1) * sizeof(*aptr))) 659 if ((aptr = el_malloc((offs + 1) * sizeof(*aptr)))
663 == NULL) 660 == NULL)
664 return -1; 661 return -1;
665 (void)strncpy(aptr, command, offs); 662 (void)strncpy(aptr, command, offs);
666 aptr[offs] = '\0'; 663 aptr[offs] = '\0';
667 idx = 1; 664 idx = 1;
668 } else { 665 } else {
669 int qchar; 666 int qchar;
670 667
671 qchar = (offs > 0 && command[offs - 1] == '"')? '"':0; 668 qchar = (offs > 0 && command[offs - 1] == '"')? '"':0;
672 ptr = get_history_event(command + offs, &idx, qchar); 669 ptr = get_history_event(command + offs, &idx, qchar);
673 } 670 }
674 has_mods = command[offs + idx] == ':'; 671 has_mods = command[offs + idx] == ':';
675 } 672 }
676 673
677 if (ptr == NULL && aptr == NULL) 674 if (ptr == NULL && aptr == NULL)
678 return -1; 675 return -1;
679 676
680 if (!has_mods) { 677 if (!has_mods) {
681 *result = strdup(aptr ? aptr : ptr); 678 *result = strdup(aptr ? aptr : ptr);
682 if (aptr) 679 if (aptr)
683 el_free(aptr); 680 el_free(aptr);
684 if (*result == NULL) 681 if (*result == NULL)
685 return -1; 682 return -1;
686 return 1; 683 return 1;
687 } 684 }
688 685
689 cmd = command + offs + idx + 1; 686 cmd = command + offs + idx + 1;
690 687
691 /* Now parse any word designators */ 688 /* Now parse any word designators */
692 689
693 if (*cmd == '%') /* last word matched by ?pat? */ 690 if (*cmd == '%') /* last word matched by ?pat? */
694 tmp = strdup(last_search_match? last_search_match:""); 691 tmp = strdup(last_search_match? last_search_match:"");
695 else if (strchr("^*$-0123456789", *cmd)) { 692 else if (strchr("^*$-0123456789", *cmd)) {
696 start = end = -1; 693 start = end = -1;
697 if (*cmd == '^') 694 if (*cmd == '^')
698 start = end = 1, cmd++; 695 start = end = 1, cmd++;
699 else if (*cmd == '$') 696 else if (*cmd == '$')
700 start = -1, cmd++; 697 start = -1, cmd++;
701 else if (*cmd == '*') 698 else if (*cmd == '*')
702 start = 1, cmd++; 699 start = 1, cmd++;
703 else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { 700 else if (*cmd == '-' || isdigit((unsigned char) *cmd)) {
704 start = 0; 701 start = 0;
705 while (*cmd && '0' <= *cmd && *cmd <= '9') 702 while (*cmd && '0' <= *cmd && *cmd <= '9')
706 start = start * 10 + *cmd++ - '0'; 703 start = start * 10 + *cmd++ - '0';
707 704
708 if (*cmd == '-') { 705 if (*cmd == '-') {
709 if (isdigit((unsigned char) cmd[1])) { 706 if (isdigit((unsigned char) cmd[1])) {
710 cmd++; 707 cmd++;
711 end = 0; 708 end = 0;
712 while (*cmd && '0' <= *cmd && *cmd <= '9') 709 while (*cmd && '0' <= *cmd && *cmd <= '9')
713 end = end * 10 + *cmd++ - '0'; 710 end = end * 10 + *cmd++ - '0';
714 } else if (cmd[1] == '$') { 711 } else if (cmd[1] == '$') {
715 cmd += 2; 712 cmd += 2;
716 end = -1; 713 end = -1;
717 } else { 714 } else {
718 cmd++; 715 cmd++;
719 end = -2; 716 end = -2;
720 } 717 }
721 } else if (*cmd == '*') 718 } else if (*cmd == '*')
722 end = -1, cmd++; 719 end = -1, cmd++;
723 else 720 else
724 end = start; 721 end = start;
725 } 722 }
726 tmp = history_arg_extract(start, end, aptr? aptr:ptr); 723 tmp = history_arg_extract(start, end, aptr? aptr:ptr);
727 if (tmp == NULL) { 724 if (tmp == NULL) {
728 (void)fprintf(rl_outstream, "%s: Bad word specifier", 725 (void)fprintf(rl_outstream, "%s: Bad word specifier",
729 command + offs + idx); 726 command + offs + idx);
730 if (aptr) 727 if (aptr)
731 el_free(aptr); 728 el_free(aptr);
732 return -1; 729 return -1;
733 } 730 }
734 } else 731 } else
735 tmp = strdup(aptr? aptr:ptr); 732 tmp = strdup(aptr? aptr:ptr);
736 733
737 if (aptr) 734 if (aptr)
738 el_free(aptr); 735 el_free(aptr);
739 736
740 if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { 737 if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) {
741 *result = tmp; 738 *result = tmp;
742 return 1; 739 return 1;
743 } 740 }
744 741
745 for (; *cmd; cmd++) { 742 for (; *cmd; cmd++) {
746 if (*cmd == ':') 743 if (*cmd == ':')
747 continue; 744 continue;
748 else if (*cmd == 'h') { /* remove trailing path */ 745 else if (*cmd == 'h') { /* remove trailing path */
749 if ((aptr = strrchr(tmp, '/')) != NULL) 746 if ((aptr = strrchr(tmp, '/')) != NULL)
750 *aptr = '\0'; 747 *aptr = '\0';
751 } else if (*cmd == 't') { /* remove leading path */ 748 } else if (*cmd == 't') { /* remove leading path */
752 if ((aptr = strrchr(tmp, '/')) != NULL) { 749 if ((aptr = strrchr(tmp, '/')) != NULL) {
753 aptr = strdup(aptr + 1); 750 aptr = strdup(aptr + 1);
754 el_free(tmp); 751 el_free(tmp);
755 tmp = aptr; 752 tmp = aptr;
756 } 753 }
757 } else if (*cmd == 'r') { /* remove trailing suffix */ 754 } else if (*cmd == 'r') { /* remove trailing suffix */
758 if ((aptr = strrchr(tmp, '.')) != NULL) 755 if ((aptr = strrchr(tmp, '.')) != NULL)
759 *aptr = '\0'; 756 *aptr = '\0';
760 } else if (*cmd == 'e') { /* remove all but suffix */ 757 } else if (*cmd == 'e') { /* remove all but suffix */
761 if ((aptr = strrchr(tmp, '.')) != NULL) { 758 if ((aptr = strrchr(tmp, '.')) != NULL) {
762 aptr = strdup(aptr); 759 aptr = strdup(aptr);
763 el_free(tmp); 760 el_free(tmp);
764 tmp = aptr; 761 tmp = aptr;
765 } 762 }
766 } else if (*cmd == 'p') /* print only */ 763 } else if (*cmd == 'p') /* print only */
767 p_on = 1; 764 p_on = 1;
768 else if (*cmd == 'g') 765 else if (*cmd == 'g')
769 g_on = 2; 766 g_on = 2;
770 else if (*cmd == 's' || *cmd == '&') { 767 else if (*cmd == 's' || *cmd == '&') {
771 char *what, *with, delim; 768 char *what, *with, delim;
772 size_t len, from_len; 769 size_t len, from_len;
773 size_t size; 770 size_t size;
774 771
775 if (*cmd == '&' && (from == NULL || to == NULL)) 772 if (*cmd == '&' && (from == NULL || to == NULL))
776 continue; 773 continue;
777 else if (*cmd == 's') { 774 else if (*cmd == 's') {
778 delim = *(++cmd), cmd++; 775 delim = *(++cmd), cmd++;
779 size = 16; 776 size = 16;
780 what = el_realloc(from, size * sizeof(*what)); 777 what = el_realloc(from, size * sizeof(*what));
781 if (what == NULL) { 778 if (what == NULL) {
782 el_free(from); 779 el_free(from);
783 el_free(tmp); 780 el_free(tmp);
784 return 0; 781 return 0;
785 } 782 }
786 len = 0; 783 len = 0;
787 for (; *cmd && *cmd != delim; cmd++) { 784 for (; *cmd && *cmd != delim; cmd++) {
788 if (*cmd == '\\' && cmd[1] == delim) 785 if (*cmd == '\\' && cmd[1] == delim)
789 cmd++; 786 cmd++;
790 if (len >= size) { 787 if (len >= size) {
791 char *nwhat; 788 char *nwhat;
792 nwhat = el_realloc(what, 789 nwhat = el_realloc(what,
793 (size <<= 1) * 790 (size <<= 1) *
794 sizeof(*nwhat)); 791 sizeof(*nwhat));
795 if (nwhat == NULL) { 792 if (nwhat == NULL) {
796 el_free(what); 793 el_free(what);
797 el_free(tmp); 794 el_free(tmp);
798 return 0; 795 return 0;
799 } 796 }
800 what = nwhat; 797 what = nwhat;
801 } 798 }
802 what[len++] = *cmd; 799 what[len++] = *cmd;
803 } 800 }
804 what[len] = '\0'; 801 what[len] = '\0';
805 from = what; 802 from = what;
806 if (*what == '\0') { 803 if (*what == '\0') {
807 el_free(what); 804 el_free(what);
808 if (search) { 805 if (search) {
809 from = strdup(search); 806 from = strdup(search);
810 if (from == NULL) { 807 if (from == NULL) {
811 el_free(tmp); 808 el_free(tmp);
812 return 0; 809 return 0;
813 } 810 }
814 } else { 811 } else {
815 from = NULL; 812 from = NULL;
816 el_free(tmp); 813 el_free(tmp);
817 return -1; 814 return -1;
818 } 815 }
819 } 816 }
820 cmd++; /* shift after delim */ 817 cmd++; /* shift after delim */
821 if (!*cmd) 818 if (!*cmd)
822 continue; 819 continue;
823 820
824 size = 16; 821 size = 16;
825 with = el_realloc(to, size * sizeof(*with)); 822 with = el_realloc(to, size * sizeof(*with));
826 if (with == NULL) { 823 if (with == NULL) {
827 el_free(to); 824 el_free(to);
828 el_free(tmp); 825 el_free(tmp);
829 return -1; 826 return -1;
830 } 827 }
831 len = 0; 828 len = 0;
832 from_len = strlen(from); 829 from_len = strlen(from);
833 for (; *cmd && *cmd != delim; cmd++) { 830 for (; *cmd && *cmd != delim; cmd++) {
834 if (len + from_len + 1 >= size) { 831 if (len + from_len + 1 >= size) {
835 char *nwith; 832 char *nwith;
836 size += from_len + 1; 833 size += from_len + 1;
837 nwith = el_realloc(with, 834 nwith = el_realloc(with,
838 size * sizeof(*nwith)); 835 size * sizeof(*nwith));
839 if (nwith == NULL) { 836 if (nwith == NULL) {
840 el_free(with); 837 el_free(with);
841 el_free(tmp); 838 el_free(tmp);
842 return -1; 839 return -1;
843 } 840 }
844 with = nwith; 841 with = nwith;
845 } 842 }
846 if (*cmd == '&') { 843 if (*cmd == '&') {
847 /* safe */ 844 /* safe */
848 (void)strcpy(&with[len], from); 845 (void)strcpy(&with[len], from);
849 len += from_len; 846 len += from_len;
850 continue; 847 continue;
851 } 848 }
852 if (*cmd == '\\' 849 if (*cmd == '\\'
853 && (*(cmd + 1) == delim 850 && (*(cmd + 1) == delim
854 || *(cmd + 1) == '&')) 851 || *(cmd + 1) == '&'))
855 cmd++; 852 cmd++;
856 with[len++] = *cmd; 853 with[len++] = *cmd;
857 } 854 }
858 with[len] = '\0'; 855 with[len] = '\0';
859 to = with; 856 to = with;
860 } 857 }
861 858
862 aptr = _rl_compat_sub(tmp, from, to, g_on); 859 aptr = _rl_compat_sub(tmp, from, to, g_on);
863 if (aptr) { 860 if (aptr) {
864 el_free(tmp); 861 el_free(tmp);
865 tmp = aptr; 862 tmp = aptr;
866 } 863 }
867 g_on = 0; 864 g_on = 0;
868 } 865 }
869 } 866 }
870 *result = tmp; 867 *result = tmp;
871 return p_on? 2:1; 868 return p_on? 2:1;
872} 869}
873 870
874 871
875/* 872/*
876 * csh-style history expansion 873 * csh-style history expansion
877 */ 874 */
878int 875int
879history_expand(char *str, char **output) 876history_expand(char *str, char **output)
880{ 877{
881 int ret = 0; 878 int ret = 0;
882 size_t idx, i, size; 879 size_t idx, i, size;
883 char *tmp, *result; 880 char *tmp, *result;
884 881
885 if (h == NULL || e == NULL) 882 if (h == NULL || e == NULL)
886 rl_initialize(); 883 rl_initialize();
887 884
888 if (history_expansion_char == 0) { 885 if (history_expansion_char == 0) {
889 *output = strdup(str); 886 *output = strdup(str);
890 return 0; 887 return 0;
891 } 888 }
892 889
893 *output = NULL; 890 *output = NULL;
894 if (str[0] == history_subst_char) { 891 if (str[0] == history_subst_char) {
895 /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ 892 /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
896 *output = el_malloc((strlen(str) + 4 + 1) * sizeof(*output)); 893 *output = el_malloc((strlen(str) + 4 + 1) * sizeof(*output));
897 if (*output == NULL) 894 if (*output == NULL)
898 return 0; 895 return 0;
899 (*output)[0] = (*output)[1] = history_expansion_char; 896 (*output)[0] = (*output)[1] = history_expansion_char;
900 (*output)[2] = ':'; 897 (*output)[2] = ':';
901 (*output)[3] = 's'; 898 (*output)[3] = 's';
902 (void)strcpy((*output) + 4, str); 899 (void)strcpy((*output) + 4, str);
903 str = *output; 900 str = *output;
904 } else { 901 } else {
905 *output = strdup(str); 902 *output = strdup(str);
906 if (*output == NULL) 903 if (*output == NULL)
907 return 0; 904 return 0;
908 } 905 }
909 906
910#define ADD_STRING(what, len, fr) \ 907#define ADD_STRING(what, len, fr) \
911 { \ 908 { \
912 if (idx + len + 1 > size) { \ 909 if (idx + len + 1 > size) { \
913 char *nresult = el_realloc(result, \ 910 char *nresult = el_realloc(result, \
914 (size += len + 1) * sizeof(*nresult)); \ 911 (size += len + 1) * sizeof(*nresult)); \
915 if (nresult == NULL) { \ 912 if (nresult == NULL) { \
916 el_free(*output); \ 913 el_free(*output); \
917 if (/*CONSTCOND*/fr) \ 914 if (/*CONSTCOND*/fr) \
918 el_free(tmp); \ 915 el_free(tmp); \
919 return 0; \ 916 return 0; \
920 } \ 917 } \
921 result = nresult; \ 918 result = nresult; \
922 } \ 919 } \
923 (void)strncpy(&result[idx], what, len); \ 920 (void)strncpy(&result[idx], what, len); \
924 idx += len; \ 921 idx += len; \
925 result[idx] = '\0'; \ 922 result[idx] = '\0'; \
926 } 923 }
927 924
928 result = NULL; 925 result = NULL;
929 size = idx = 0; 926 size = idx = 0;
930 tmp = NULL; 927 tmp = NULL;
931 for (i = 0; str[i];) { 928 for (i = 0; str[i];) {
932 int qchar, loop_again; 929 int qchar, loop_again;
933 size_t len, start, j; 930 size_t len, start, j;
934 931
935 qchar = 0; 932 qchar = 0;
936 loop_again = 1; 933 loop_again = 1;
937 start = j = i; 934 start = j = i;
938loop: 935loop:
939 for (; str[j]; j++) { 936 for (; str[j]; j++) {
940 if (str[j] == '\\' && 937 if (str[j] == '\\' &&
941 str[j + 1] == history_expansion_char) { 938 str[j + 1] == history_expansion_char) {
942 (void)strcpy(&str[j], &str[j + 1]); 939 (void)strcpy(&str[j], &str[j + 1]);
943 continue; 940 continue;
944 } 941 }
945 if (!loop_again) { 942 if (!loop_again) {
946 if (isspace((unsigned char) str[j]) 943 if (isspace((unsigned char) str[j])
947 || str[j] == qchar) 944 || str[j] == qchar)
948 break; 945 break;
949 } 946 }
950 if (str[j] == history_expansion_char 947 if (str[j] == history_expansion_char
951 && !strchr(history_no_expand_chars, str[j + 1]) 948 && !strchr(history_no_expand_chars, str[j + 1])
952 && (!history_inhibit_expansion_function || 949 && (!history_inhibit_expansion_function ||
953 (*history_inhibit_expansion_function)(str, 950 (*history_inhibit_expansion_function)(str,
954 (int)j) == 0)) 951 (int)j) == 0))
955 break; 952 break;
956 } 953 }
957 954
958 if (str[j] && loop_again) { 955 if (str[j] && loop_again) {
959 i = j; 956 i = j;
960 qchar = (j > 0 && str[j - 1] == '"' )? '"':0; 957 qchar = (j > 0 && str[j - 1] == '"' )? '"':0;
961 j++; 958 j++;
962 if (str[j] == history_expansion_char) 959 if (str[j] == history_expansion_char)
963 j++; 960 j++;
964 loop_again = 0; 961 loop_again = 0;
965 goto loop; 962 goto loop;
966 } 963 }
967 len = i - start; 964 len = i - start;
968 ADD_STRING(&str[start], len, 0); 965 ADD_STRING(&str[start], len, 0);
969 966
970 if (str[i] == '\0' || str[i] != history_expansion_char) { 967 if (str[i] == '\0' || str[i] != history_expansion_char) {
971 len = j - i; 968 len = j - i;
972 ADD_STRING(&str[i], len, 0); 969 ADD_STRING(&str[i], len, 0);
973 if (start == 0) 970 if (start == 0)
974 ret = 0; 971 ret = 0;
975 else 972 else
976 ret = 1; 973 ret = 1;
977 break; 974 break;
978 } 975 }
979 ret = _history_expand_command (str, i, (j - i), &tmp); 976 ret = _history_expand_command (str, i, (j - i), &tmp);
980 if (ret > 0 && tmp) { 977 if (ret > 0 && tmp) {
981 len = strlen(tmp); 978 len = strlen(tmp);
982 ADD_STRING(tmp, len, 1); 979 ADD_STRING(tmp, len, 1);
983 } 980 }
984 if (tmp) { 981 if (tmp) {
985 el_free(tmp); 982 el_free(tmp);
986 tmp = NULL; 983 tmp = NULL;
987 } 984 }
988 i = j; 985 i = j;
989 } 986 }
990 987
991 /* ret is 2 for "print only" option */ 988 /* ret is 2 for "print only" option */
992 if (ret == 2) { 989 if (ret == 2) {
993 add_history(result); 990 add_history(result);
994#ifdef GDB_411_HACK 991#ifdef GDB_411_HACK
995 /* gdb 4.11 has been shipped with readline, where */ 992 /* gdb 4.11 has been shipped with readline, where */
996 /* history_expand() returned -1 when the line */ 993 /* history_expand() returned -1 when the line */
997 /* should not be executed; in readline 2.1+ */ 994 /* should not be executed; in readline 2.1+ */
998 /* it should return 2 in such a case */ 995 /* it should return 2 in such a case */
999 ret = -1; 996 ret = -1;
1000#endif 997#endif
1001 } 998 }
1002 el_free(*output); 999 el_free(*output);
1003 *output = result; 1000 *output = result;
1004 1001
1005 return ret; 1002 return ret;
1006} 1003}
1007 1004
1008/* 1005/*
1009* Return a string consisting of arguments of "str" from "start" to "end". 1006* Return a string consisting of arguments of "str" from "start" to "end".
1010*/ 1007*/
1011char * 1008char *
1012history_arg_extract(int start, int end, const char *str) 1009history_arg_extract(int start, int end, const char *str)
1013{ 1010{
1014 size_t i, len, max; 1011 size_t i, len, max;
1015 char **arr, *result = NULL; 1012 char **arr, *result = NULL;
1016 1013
1017 arr = history_tokenize(str); 1014 arr = history_tokenize(str);
1018 if (!arr) 1015 if (!arr)
1019 return NULL; 1016 return NULL;
1020 if (arr && *arr == NULL) 1017 if (arr && *arr == NULL)
1021 goto out; 1018 goto out;
1022 1019
1023 for (max = 0; arr[max]; max++) 1020 for (max = 0; arr[max]; max++)
1024 continue; 1021 continue;
1025 max--; 1022 max--;
1026 1023
1027 if (start == '$') 1024 if (start == '$')
1028 start = (int)max; 1025 start = (int)max;
1029 if (end == '$') 1026 if (end == '$')
1030 end = (int)max; 1027 end = (int)max;
1031 if (end < 0) 1028 if (end < 0)
1032 end = (int)max + end + 1; 1029 end = (int)max + end + 1;
1033 if (start < 0) 1030 if (start < 0)
1034 start = end; 1031 start = end;
1035 1032
1036 if (start < 0 || end < 0 || (size_t)start > max || 1033 if (start < 0 || end < 0 || (size_t)start > max ||
1037 (size_t)end > max || start > end) 1034 (size_t)end > max || start > end)
1038 goto out; 1035 goto out;
1039 1036
1040 for (i = start, len = 0; i <= (size_t)end; i++) 1037 for (i = start, len = 0; i <= (size_t)end; i++)
1041 len += strlen(arr[i]) + 1; 1038 len += strlen(arr[i]) + 1;
1042 len++; 1039 len++;
1043 result = el_malloc(len * sizeof(*result)); 1040 result = el_malloc(len * sizeof(*result));
1044 if (result == NULL) 1041 if (result == NULL)
1045 goto out; 1042 goto out;
1046 1043
1047 for (i = start, len = 0; i <= (size_t)end; i++) { 1044 for (i = start, len = 0; i <= (size_t)end; i++) {
1048 (void)strcpy(result + len, arr[i]); 1045 (void)strcpy(result + len, arr[i]);
1049 len += strlen(arr[i]); 1046 len += strlen(arr[i]);
1050 if (i < (size_t)end) 1047 if (i < (size_t)end)
1051 result[len++] = ' '; 1048 result[len++] = ' ';
1052 } 1049 }
1053 result[len] = '\0'; 1050 result[len] = '\0';
1054 1051
1055out: 1052out:
1056 for (i = 0; arr[i]; i++) 1053 for (i = 0; arr[i]; i++)
1057 el_free(arr[i]); 1054 el_free(arr[i]);
1058 el_free(arr); 1055 el_free(arr);
1059 1056
1060 return result; 1057 return result;
1061} 1058}
1062 1059
1063/* 1060/*
1064 * Parse the string into individual tokens, 1061 * Parse the string into individual tokens,
1065 * similar to how shell would do it. 1062 * similar to how shell would do it.
1066 */ 1063 */
1067char ** 1064char **
1068history_tokenize(const char *str) 1065history_tokenize(const char *str)
1069{ 1066{
1070 int size = 1, idx = 0, i, start; 1067 int size = 1, idx = 0, i, start;
1071 size_t len; 1068 size_t len;
1072 char **result = NULL, *temp, delim = '\0'; 1069 char **result = NULL, *temp, delim = '\0';
1073 1070
1074 for (i = 0; str[i];) { 1071 for (i = 0; str[i];) {
1075 while (isspace((unsigned char) str[i])) 1072 while (isspace((unsigned char) str[i]))
1076 i++; 1073 i++;
1077 start = i; 1074 start = i;
1078 for (; str[i];) { 1075 for (; str[i];) {
1079 if (str[i] == '\\') { 1076 if (str[i] == '\\') {
1080 if (str[i+1] != '\0') 1077 if (str[i+1] != '\0')
1081 i++; 1078 i++;
1082 } else if (str[i] == delim) 1079 } else if (str[i] == delim)
1083 delim = '\0'; 1080 delim = '\0';
1084 else if (!delim && 1081 else if (!delim &&
1085 (isspace((unsigned char) str[i]) || 1082 (isspace((unsigned char) str[i]) ||
1086 strchr("()<>;&|$", str[i]))) 1083 strchr("()<>;&|$", str[i])))
1087 break; 1084 break;
1088 else if (!delim && strchr("'`\"", str[i])) 1085 else if (!delim && strchr("'`\"", str[i]))
1089 delim = str[i]; 1086 delim = str[i];
1090 if (str[i]) 1087 if (str[i])
1091 i++; 1088 i++;
1092 } 1089 }
1093 1090
1094 if (idx + 2 >= size) { 1091 if (idx + 2 >= size) {
1095 char **nresult; 1092 char **nresult;
1096 size <<= 1; 1093 size <<= 1;
1097 nresult = el_realloc(result, size * sizeof(*nresult)); 1094 nresult = el_realloc(result, size * sizeof(*nresult));
1098 if (nresult == NULL) { 1095 if (nresult == NULL) {
1099 el_free(result); 1096 el_free(result);
1100 return NULL; 1097 return NULL;
1101 } 1098 }
1102 result = nresult; 1099 result = nresult;
1103 } 1100 }
1104 len = i - start; 1101 len = i - start;
1105 temp = el_malloc((len + 1) * sizeof(*temp)); 1102 temp = el_malloc((len + 1) * sizeof(*temp));
1106 if (temp == NULL) { 1103 if (temp == NULL) {
1107 for (i = 0; i < idx; i++) 1104 for (i = 0; i < idx; i++)
1108 el_free(result[i]); 1105 el_free(result[i]);
1109 el_free(result); 1106 el_free(result);
1110 return NULL; 1107 return NULL;
1111 } 1108 }
1112 (void)strncpy(temp, &str[start], len); 1109 (void)strncpy(temp, &str[start], len);
1113 temp[len] = '\0'; 1110 temp[len] = '\0';
1114 result[idx++] = temp; 1111 result[idx++] = temp;
1115 result[idx] = NULL; 1112 result[idx] = NULL;
1116 if (str[i]) 1113 if (str[i])
1117 i++; 1114 i++;
1118 } 1115 }
1119 return result; 1116 return result;
1120} 1117}
1121 1118
1122 1119
1123/* 1120/*
1124 * limit size of history record to ``max'' events 1121 * limit size of history record to ``max'' events
1125 */ 1122 */
1126void 1123void
1127stifle_history(int max) 1124stifle_history(int max)
1128{ 1125{
1129 HistEvent ev; 1126 HistEvent ev;
1130 1127
1131 if (h == NULL || e == NULL) 1128 if (h == NULL || e == NULL)
1132 rl_initialize(); 1129 rl_initialize();
1133 1130
1134 if (history(h, &ev, H_SETSIZE, max) == 0) 1131 if (history(h, &ev, H_SETSIZE, max) == 0)
1135 max_input_history = max; 1132 max_input_history = max;
1136} 1133}
1137 1134
1138 1135
1139/* 1136/*
1140 * "unlimit" size of history - set the limit to maximum allowed int value 1137 * "unlimit" size of history - set the limit to maximum allowed int value
1141 */ 1138 */
1142int 1139int
1143unstifle_history(void) 1140unstifle_history(void)
1144{ 1141{
1145 HistEvent ev; 1142 HistEvent ev;
1146 int omax; 1143 int omax;
1147 1144
1148 history(h, &ev, H_SETSIZE, INT_MAX); 1145 history(h, &ev, H_SETSIZE, INT_MAX);
1149 omax = max_input_history; 1146 omax = max_input_history;
1150 max_input_history = INT_MAX; 1147 max_input_history = INT_MAX;
1151 return omax; /* some value _must_ be returned */ 1148 return omax; /* some value _must_ be returned */
1152} 1149}
1153 1150
1154 1151
1155int 1152int
1156history_is_stifled(void) 1153history_is_stifled(void)
1157{ 1154{
1158 1155
1159 /* cannot return true answer */ 1156 /* cannot return true answer */
1160 return max_input_history != INT_MAX; 1157 return max_input_history != INT_MAX;
1161} 1158}
1162 1159
1163static const char _history_tmp_template[] = "/tmp/.historyXXXXXX"; 1160static const char _history_tmp_template[] = "/tmp/.historyXXXXXX";
1164 1161
1165int 1162int
1166history_truncate_file (const char *filename, int nlines) 1163history_truncate_file (const char *filename, int nlines)
1167{ 1164{
1168 int ret = 0; 1165 int ret = 0;
1169 FILE *fp, *tp; 1166 FILE *fp, *tp;
1170 char template[sizeof(_history_tmp_template)]; 1167 char template[sizeof(_history_tmp_template)];
1171 char buf[4096]; 1168 char buf[4096];
1172 int fd; 1169 int fd;
1173 char *cp; 1170 char *cp;
1174 off_t off; 1171 off_t off;
1175 int count = 0; 1172 int count = 0;
1176 ssize_t left = 0; 1173 ssize_t left = 0;
1177 1174
1178 if (filename == NULL && (filename = _default_history_file()) == NULL) 1175 if (filename == NULL && (filename = _default_history_file()) == NULL)
1179 return errno; 1176 return errno;
1180 if ((fp = fopen(filename, "r+")) == NULL) 1177 if ((fp = fopen(filename, "r+")) == NULL)
1181 return errno; 1178 return errno;
1182 strcpy(template, _history_tmp_template); 1179 strcpy(template, _history_tmp_template);
1183 if ((fd = mkstemp(template)) == -1) { 1180 if ((fd = mkstemp(template)) == -1) {
1184 ret = errno; 1181 ret = errno;
1185 goto out1; 1182 goto out1;
1186 } 1183 }
1187 1184
1188 if ((tp = fdopen(fd, "r+")) == NULL) { 1185 if ((tp = fdopen(fd, "r+")) == NULL) {
1189 close(fd); 1186 close(fd);
1190 ret = errno; 1187 ret = errno;
1191 goto out2; 1188 goto out2;
1192 } 1189 }
1193 1190
1194 for(;;) { 1191 for(;;) {
1195 if (fread(buf, sizeof(buf), 1, fp) != 1) { 1192 if (fread(buf, sizeof(buf), 1, fp) != 1) {
1196 if (ferror(fp)) { 1193 if (ferror(fp)) {
1197 ret = errno; 1194 ret = errno;
1198 break; 1195 break;
1199 } 1196 }
1200 if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) == 1197 if (fseeko(fp, (off_t)sizeof(buf) * count, SEEK_SET) ==
1201 (off_t)-1) { 1198 (off_t)-1) {
1202 ret = errno; 1199 ret = errno;
1203 break; 1200 break;
1204 } 1201 }
1205 left = fread(buf, 1, sizeof(buf), fp); 1202 left = fread(buf, 1, sizeof(buf), fp);
1206 if (ferror(fp)) { 1203 if (ferror(fp)) {
1207 ret = errno; 1204 ret = errno;
1208 break; 1205 break;
1209 } 1206 }
1210 if (left == 0) { 1207 if (left == 0) {
1211 count--; 1208 count--;
1212 left = sizeof(buf); 1209 left = sizeof(buf);
1213 } else if (fwrite(buf, (size_t)left, 1, tp) != 1) { 1210 } else if (fwrite(buf, (size_t)left, 1, tp) != 1) {
1214 ret = errno; 1211 ret = errno;
1215 break; 1212 break;
1216 } 1213 }
1217 fflush(tp); 1214 fflush(tp);
1218 break; 1215 break;
1219 } 1216 }
1220 if (fwrite(buf, sizeof(buf), 1, tp) != 1) { 1217 if (fwrite(buf, sizeof(buf), 1, tp) != 1) {
1221 ret = errno; 1218 ret = errno;
1222 break; 1219 break;
1223 } 1220 }
1224 count++; 1221 count++;
1225 } 1222 }
1226 if (ret) 1223 if (ret)
1227 goto out3; 1224 goto out3;
1228 cp = buf + left - 1; 1225 cp = buf + left - 1;
1229 if(*cp != '\n') 1226 if(*cp != '\n')
1230 cp++; 1227 cp++;
1231 for(;;) { 1228 for(;;) {
1232 while (--cp >= buf) { 1229 while (--cp >= buf) {
1233 if (*cp == '\n') { 1230 if (*cp == '\n') {
1234 if (--nlines == 0) { 1231 if (--nlines == 0) {
1235 if (++cp >= buf + sizeof(buf)) { 1232 if (++cp >= buf + sizeof(buf)) {
1236 count++; 1233 count++;
1237 cp = buf; 1234 cp = buf;
1238 } 1235 }
1239 break; 1236 break;
1240 } 1237 }
1241 } 1238 }
1242 } 1239 }
1243 if (nlines <= 0 || count == 0) 1240 if (nlines <= 0 || count == 0)
1244 break; 1241 break;
1245 count--; 1242 count--;
1246 if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) { 1243 if (fseeko(tp, (off_t)sizeof(buf) * count, SEEK_SET) < 0) {
1247 ret = errno; 1244 ret = errno;
1248 break; 1245 break;
1249 } 1246 }
1250 if (fread(buf, sizeof(buf), 1, tp) != 1) { 1247 if (fread(buf, sizeof(buf), 1, tp) != 1) {
1251 if (ferror(tp)) { 1248 if (ferror(tp)) {
1252 ret = errno; 1249 ret = errno;
1253 break; 1250 break;
1254 } 1251 }
1255 ret = EAGAIN; 1252 ret = EAGAIN;
1256 break; 1253 break;
1257 } 1254 }
1258 cp = buf + sizeof(buf); 1255 cp = buf + sizeof(buf);
1259 } 1256 }
1260 1257
1261 if (ret || nlines > 0) 1258 if (ret || nlines > 0)
1262 goto out3; 1259 goto out3;
1263 1260
1264 if (fseeko(fp, 0, SEEK_SET) == (off_t)-1) { 1261 if (fseeko(fp, 0, SEEK_SET) == (off_t)-1) {
1265 ret = errno; 1262 ret = errno;
1266 goto out3; 1263 goto out3;
1267 } 1264 }
1268 1265
1269 if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) == 1266 if (fseeko(tp, (off_t)sizeof(buf) * count + (cp - buf), SEEK_SET) ==
1270 (off_t)-1) { 1267 (off_t)-1) {
1271 ret = errno; 1268 ret = errno;
1272 goto out3; 1269 goto out3;
1273 } 1270 }
1274 1271
1275 for(;;) { 1272 for(;;) {
1276 if ((left = fread(buf, 1, sizeof(buf), tp)) == 0) { 1273 if ((left = fread(buf, 1, sizeof(buf), tp)) == 0) {
1277 if (ferror(fp)) 1274 if (ferror(fp))
1278 ret = errno; 1275 ret = errno;
1279 break; 1276 break;
1280 } 1277 }
1281 if (fwrite(buf, (size_t)left, 1, fp) != 1) { 1278 if (fwrite(buf, (size_t)left, 1, fp) != 1) {
1282 ret = errno; 1279 ret = errno;
1283 break; 1280 break;
1284 } 1281 }
1285 } 1282 }
1286 fflush(fp); 1283 fflush(fp);
1287 if((off = ftello(fp)) > 0) 1284 if((off = ftello(fp)) > 0)
1288 (void)ftruncate(fileno(fp), off); 1285 (void)ftruncate(fileno(fp), off);
1289out3: 1286out3:
1290 fclose(tp); 1287 fclose(tp);
1291out2: 1288out2:
1292 unlink(template); 1289 unlink(template);
1293out1: 1290out1:
1294 fclose(fp); 1291 fclose(fp);
1295 1292
1296 return ret; 1293 return ret;
1297} 1294}
1298 1295
1299 1296
1300/* 1297/*
1301 * read history from a file given 1298 * read history from a file given
1302 */ 1299 */
1303int 1300int
1304read_history(const char *filename) 1301read_history(const char *filename)
1305{ 1302{
1306 HistEvent ev; 1303 HistEvent ev;
1307 1304
1308 if (h == NULL || e == NULL) 1305 if (h == NULL || e == NULL)
1309 rl_initialize(); 1306 rl_initialize();
1310 if (filename == NULL && (filename = _default_history_file()) == NULL) 1307 if (filename == NULL && (filename = _default_history_file()) == NULL)
1311 return errno; 1308 return errno;
1312 return history(h, &ev, H_LOAD, filename) == -1 ? 1309 return history(h, &ev, H_LOAD, filename) == -1 ?
1313 (errno ? errno : EINVAL) : 0; 1310 (errno ? errno : EINVAL) : 0;
1314} 1311}
1315 1312
1316 1313
1317/* 1314/*
1318 * write history to a file given 1315 * write history to a file given
1319 */ 1316 */
1320int 1317int
1321write_history(const char *filename) 1318write_history(const char *filename)
1322{ 1319{
1323 HistEvent ev; 1320 HistEvent ev;
1324 1321
1325 if (h == NULL || e == NULL) 1322 if (h == NULL || e == NULL)
1326 rl_initialize(); 1323 rl_initialize();
1327 if (filename == NULL && (filename = _default_history_file()) == NULL) 1324 if (filename == NULL && (filename = _default_history_file()) == NULL)
1328 return errno; 1325 return errno;
1329 return history(h, &ev, H_SAVE, filename) == -1 ? 1326 return history(h, &ev, H_SAVE, filename) == -1 ?
1330 (errno ? errno : EINVAL) : 0; 1327 (errno ? errno : EINVAL) : 0;
1331} 1328}
1332 1329
1333 1330
1334/* 1331/*
1335 * returns history ``num''th event 1332 * returns history ``num''th event
1336 * 1333 *
1337 * returned pointer points to static variable 1334 * returned pointer points to static variable
1338 */ 1335 */
1339HIST_ENTRY * 1336HIST_ENTRY *
1340history_get(int num) 1337history_get(int num)
1341{ 1338{
1342 static HIST_ENTRY she; 1339 static HIST_ENTRY she;
1343 HistEvent ev; 1340 HistEvent ev;
1344 int curr_num; 1341 int curr_num;
1345 1342
1346 if (h == NULL || e == NULL) 1343 if (h == NULL || e == NULL)
1347 rl_initialize(); 1344 rl_initialize();
1348 1345
1349 /* save current position */ 1346 /* save current position */
1350 if (history(h, &ev, H_CURR) != 0) 1347 if (history(h, &ev, H_CURR) != 0)
1351 return NULL; 1348 return NULL;
1352 curr_num = ev.num; 1349 curr_num = ev.num;
1353 1350
1354 /* start from the oldest */ 1351 /* start from the oldest */
1355 if (history(h, &ev, H_LAST) != 0) 1352 if (history(h, &ev, H_LAST) != 0)
1356 return NULL; /* error */ 1353 return NULL; /* error */
1357 1354
1358 /* look forwards for event matching specified offset */ 1355 /* look forwards for event matching specified offset */
1359 if (history(h, &ev, H_NEXT_EVDATA, num, &she.data)) 1356 if (history(h, &ev, H_NEXT_EVDATA, num, &she.data))
1360 return NULL; 1357 return NULL;
1361 1358
1362 she.line = ev.str; 1359 she.line = ev.str;
1363 1360
1364 /* restore pointer to where it was */ 1361 /* restore pointer to where it was */
1365 (void)history(h, &ev, H_SET, curr_num); 1362 (void)history(h, &ev, H_SET, curr_num);
1366 1363
1367 return &she; 1364 return &she;
1368} 1365}
1369 1366
1370 1367
1371/* 1368/*
1372 * add the line to history table 1369 * add the line to history table
1373 */ 1370 */
1374int 1371int
1375add_history(const char *line) 1372add_history(const char *line)
1376{ 1373{
1377 HistEvent ev; 1374 HistEvent ev;
1378 1375
1379 if (h == NULL || e == NULL) 1376 if (h == NULL || e == NULL)
1380 rl_initialize(); 1377 rl_initialize();
1381 1378
1382 (void)history(h, &ev, H_ENTER, line); 1379 (void)history(h, &ev, H_ENTER, line);
1383 if (history(h, &ev, H_GETSIZE) == 0) 1380 if (history(h, &ev, H_GETSIZE) == 0)
1384 history_length = ev.num; 1381 history_length = ev.num;
1385 1382
1386 return !(history_length > 0); /* return 0 if all is okay */ 1383 return !(history_length > 0); /* return 0 if all is okay */
1387} 1384}
1388 1385
1389 1386
1390/* 1387/*
1391 * remove the specified entry from the history list and return it. 1388 * remove the specified entry from the history list and return it.
1392 */ 1389 */
1393HIST_ENTRY * 1390HIST_ENTRY *
1394remove_history(int num) 1391remove_history(int num)
1395{ 1392{
1396 HIST_ENTRY *he; 1393 HIST_ENTRY *he;
1397 HistEvent ev; 1394 HistEvent ev;
1398 1395
1399 if (h == NULL || e == NULL) 1396 if (h == NULL || e == NULL)
1400 rl_initialize(); 1397 rl_initialize();
1401 1398
1402 if ((he = el_malloc(sizeof(*he))) == NULL) 1399 if ((he = el_malloc(sizeof(*he))) == NULL)
1403 return NULL; 1400 return NULL;
1404 1401
1405 if (history(h, &ev, H_DELDATA, num, &he->data) != 0) { 1402 if (history(h, &ev, H_DELDATA, num, &he->data) != 0) {
1406 el_free(he); 1403 el_free(he);
1407 return NULL; 1404 return NULL;
1408 } 1405 }
1409 1406
1410 he->line = ev.str; 1407 he->line = ev.str;
1411 if (history(h, &ev, H_GETSIZE) == 0) 1408 if (history(h, &ev, H_GETSIZE) == 0)
1412 history_length = ev.num; 1409 history_length = ev.num;
1413 1410
1414 return he; 1411 return he;
1415} 1412}
1416 1413
1417 1414
1418/* 1415/*
1419 * replace the line and data of the num-th entry 1416 * replace the line and data of the num-th entry
1420 */ 1417 */
1421HIST_ENTRY * 1418HIST_ENTRY *
1422replace_history_entry(int num, const char *line, histdata_t data) 1419replace_history_entry(int num, const char *line, histdata_t data)
1423{ 1420{
1424 HIST_ENTRY *he; 1421 HIST_ENTRY *he;
1425 HistEvent ev; 1422 HistEvent ev;
1426 int curr_num; 1423 int curr_num;
1427 1424
1428 if (h == NULL || e == NULL) 1425 if (h == NULL || e == NULL)
1429 rl_initialize(); 1426 rl_initialize();
1430 1427
1431 /* save current position */ 1428 /* save current position */
1432 if (history(h, &ev, H_CURR) != 0) 1429 if (history(h, &ev, H_CURR) != 0)
1433 return NULL; 1430 return NULL;
1434 curr_num = ev.num; 1431 curr_num = ev.num;
1435 1432
1436 /* start from the oldest */ 1433 /* start from the oldest */
1437 if (history(h, &ev, H_LAST) != 0) 1434 if (history(h, &ev, H_LAST) != 0)
1438 return NULL; /* error */ 1435 return NULL; /* error */
1439 1436
1440 if ((he = el_malloc(sizeof(*he))) == NULL) 1437 if ((he = el_malloc(sizeof(*he))) == NULL)
1441 return NULL; 1438 return NULL;
1442 1439
1443 /* look forwards for event matching specified offset */ 1440 /* look forwards for event matching specified offset */
1444 if (history(h, &ev, H_NEXT_EVDATA, num, &he->data)) 1441 if (history(h, &ev, H_NEXT_EVDATA, num, &he->data))
1445 goto out; 1442 goto out;
1446 1443
1447 he->line = strdup(ev.str); 1444 he->line = strdup(ev.str);
1448 if (he->line == NULL) 1445 if (he->line == NULL)
1449 goto out; 1446 goto out;
1450 1447
1451 if (history(h, &ev, H_REPLACE, line, data)) 1448 if (history(h, &ev, H_REPLACE, line, data))
1452 goto out; 1449 goto out;
1453 1450
1454 /* restore pointer to where it was */ 1451 /* restore pointer to where it was */
1455 if (history(h, &ev, H_SET, curr_num)) 1452 if (history(h, &ev, H_SET, curr_num))
1456 goto out; 1453 goto out;
1457 1454
1458 return he; 1455 return he;
1459out: 1456out:
1460 el_free(he); 1457 el_free(he);
1461 return NULL; 1458 return NULL;
1462} 1459}
1463 1460
1464/* 1461/*
1465 * clear the history list - delete all entries 1462 * clear the history list - delete all entries
1466 */ 1463 */
1467void 1464void
1468clear_history(void) 1465clear_history(void)
1469{ 1466{
1470 HistEvent ev; 1467 HistEvent ev;
1471 1468
1472 (void)history(h, &ev, H_CLEAR); 1469 (void)history(h, &ev, H_CLEAR);
1473 history_length = 0; 1470 history_length = 0;
1474} 1471}
1475 1472
1476 1473
1477/* 1474/*
1478 * returns offset of the current history event 1475 * returns offset of the current history event
1479 */ 1476 */
1480int 1477int
1481where_history(void) 1478where_history(void)
1482{ 1479{
1483 HistEvent ev; 1480 HistEvent ev;
1484 int curr_num, off; 1481 int curr_num, off;
1485 1482
1486 if (history(h, &ev, H_CURR) != 0) 1483 if (history(h, &ev, H_CURR) != 0)
1487 return 0; 1484 return 0;
1488 curr_num = ev.num; 1485 curr_num = ev.num;
1489 1486
1490 (void)history(h, &ev, H_FIRST); 1487 (void)history(h, &ev, H_FIRST);
1491 off = 1; 1488 off = 1;
1492 while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) 1489 while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
1493 off++; 1490 off++;
1494 1491
1495 return off; 1492 return off;
1496} 1493}
1497 1494
1498 1495
1499/* 1496/*
1500 * returns current history event or NULL if there is no such event 1497 * returns current history event or NULL if there is no such event
1501 */ 1498 */
1502HIST_ENTRY * 1499HIST_ENTRY *
1503current_history(void) 1500current_history(void)
1504{ 1501{
1505 1502
1506 return _move_history(H_CURR); 1503 return _move_history(H_CURR);
1507} 1504}
1508 1505
1509 1506
1510/* 1507/*
1511 * returns total number of bytes history events' data are using 1508 * returns total number of bytes history events' data are using
1512 */ 1509 */
1513int 1510int
1514history_total_bytes(void) 1511history_total_bytes(void)
1515{ 1512{
1516 HistEvent ev; 1513 HistEvent ev;
1517 int curr_num; 1514 int curr_num;
1518 size_t size; 1515 size_t size;
1519 1516
1520 if (history(h, &ev, H_CURR) != 0) 1517 if (history(h, &ev, H_CURR) != 0)
1521 return -1; 1518 return -1;
1522 curr_num = ev.num; 1519 curr_num = ev.num;
1523 1520
1524 (void)history(h, &ev, H_FIRST); 1521 (void)history(h, &ev, H_FIRST);
1525 size = 0; 1522 size = 0;
1526 do 1523 do
1527 size += strlen(ev.str) * sizeof(*ev.str); 1524 size += strlen(ev.str) * sizeof(*ev.str);
1528 while (history(h, &ev, H_NEXT) == 0); 1525 while (history(h, &ev, H_NEXT) == 0);
1529 1526
1530 /* get to the same position as before */ 1527 /* get to the same position as before */
1531 history(h, &ev, H_PREV_EVENT, curr_num); 1528 history(h, &ev, H_PREV_EVENT, curr_num);
1532 1529
1533 return (int)size; 1530 return (int)size;
1534} 1531}
1535 1532
1536 1533
1537/* 1534/*
1538 * sets the position in the history list to ``pos'' 1535 * sets the position in the history list to ``pos''
1539 */ 1536 */
1540int 1537int
1541history_set_pos(int pos) 1538history_set_pos(int pos)
1542{ 1539{
1543 HistEvent ev; 1540 HistEvent ev;
1544 int curr_num; 1541 int curr_num;
1545 1542
1546 if (pos >= history_length || pos < 0) 1543 if (pos >= history_length || pos < 0)
1547 return -1; 1544 return -1;
1548 1545
1549 (void)history(h, &ev, H_CURR); 1546 (void)history(h, &ev, H_CURR);
1550 curr_num = ev.num; 1547 curr_num = ev.num;
1551 1548
1552 /* 1549 /*
1553 * use H_DELDATA to set to nth history (without delete) by passing 1550 * use H_DELDATA to set to nth history (without delete) by passing
1554 * (void **)-1 1551 * (void **)-1
1555 */ 1552 */
1556 if (history(h, &ev, H_DELDATA, pos, (void **)-1)) { 1553 if (history(h, &ev, H_DELDATA, pos, (void **)-1)) {
1557 (void)history(h, &ev, H_SET, curr_num); 1554 (void)history(h, &ev, H_SET, curr_num);
1558 return -1; 1555 return -1;
1559 } 1556 }
1560 return 0; 1557 return 0;
1561} 1558}
1562 1559
1563 1560
1564/* 1561/*
1565 * returns previous event in history and shifts pointer accordingly 1562 * returns previous event in history and shifts pointer accordingly
1566 */ 1563 */
1567HIST_ENTRY * 1564HIST_ENTRY *
1568previous_history(void) 1565previous_history(void)
1569{ 1566{
1570 1567
1571 return _move_history(H_PREV); 1568 return _move_history(H_PREV);
1572} 1569}
1573 1570
1574 1571
1575/* 1572/*
1576 * returns next event in history and shifts pointer accordingly 1573 * returns next event in history and shifts pointer accordingly
1577 */ 1574 */
1578HIST_ENTRY * 1575HIST_ENTRY *
1579next_history(void) 1576next_history(void)
1580{ 1577{
1581 1578
1582 return _move_history(H_NEXT); 1579 return _move_history(H_NEXT);
1583} 1580}
1584 1581
1585 1582
1586/* 1583/*
1587 * searches for first history event containing the str 1584 * searches for first history event containing the str
1588 */ 1585 */
1589int 1586int
1590history_search(const char *str, int direction) 1587history_search(const char *str, int direction)
1591{ 1588{
1592 HistEvent ev; 1589 HistEvent ev;
1593 const char *strp; 1590 const char *strp;
1594 int curr_num; 1591 int curr_num;
1595 1592
1596 if (history(h, &ev, H_CURR) != 0) 1593 if (history(h, &ev, H_CURR) != 0)
1597 return -1; 1594 return -1;
1598 curr_num = ev.num; 1595 curr_num = ev.num;
1599 1596
1600 for (;;) { 1597 for (;;) {
1601 if ((strp = strstr(ev.str, str)) != NULL) 1598 if ((strp = strstr(ev.str, str)) != NULL)
1602 return (int)(strp - ev.str); 1599 return (int)(strp - ev.str);
1603 if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0) 1600 if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)
1604 break; 1601 break;
1605 } 1602 }
1606 (void)history(h, &ev, H_SET, curr_num); 1603 (void)history(h, &ev, H_SET, curr_num);
1607 return -1; 1604 return -1;
1608} 1605}
1609 1606
1610 1607
1611/* 1608/*
1612 * searches for first history event beginning with str 1609 * searches for first history event beginning with str
1613 */ 1610 */
1614int 1611int
1615history_search_prefix(const char *str, int direction) 1612history_search_prefix(const char *str, int direction)
1616{ 1613{
1617 HistEvent ev; 1614 HistEvent ev;
1618 1615
1619 return (history(h, &ev, direction < 0 ? 1616 return (history(h, &ev, direction < 0 ?
1620 H_PREV_STR : H_NEXT_STR, str)); 1617 H_PREV_STR : H_NEXT_STR, str));
1621} 1618}
1622 1619
1623 1620
1624/* 1621/*
1625 * search for event in history containing str, starting at offset 1622 * search for event in history containing str, starting at offset
1626 * abs(pos); continue backward, if pos<0, forward otherwise 1623 * abs(pos); continue backward, if pos<0, forward otherwise
1627 */ 1624 */
1628/* ARGSUSED */ 1625/* ARGSUSED */
1629int 1626int
1630history_search_pos(const char *str, 1627history_search_pos(const char *str,
1631 int direction __attribute__((__unused__)), int pos) 1628 int direction __attribute__((__unused__)), int pos)
1632{ 1629{
1633 HistEvent ev; 1630 HistEvent ev;
1634 int curr_num, off; 1631 int curr_num, off;
1635 1632
1636 off = (pos > 0) ? pos : -pos; 1633 off = (pos > 0) ? pos : -pos;
1637 pos = (pos > 0) ? 1 : -1; 1634 pos = (pos > 0) ? 1 : -1;
1638 1635
1639 if (history(h, &ev, H_CURR) != 0) 1636 if (history(h, &ev, H_CURR) != 0)
1640 return -1; 1637 return -1;
1641 curr_num = ev.num; 1638 curr_num = ev.num;
1642 1639
1643 if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) 1640 if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
1644 return -1; 1641 return -1;
1645 1642
1646 for (;;) { 1643 for (;;) {
1647 if (strstr(ev.str, str)) 1644 if (strstr(ev.str, str))
1648 return off; 1645 return off;
1649 if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) 1646 if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0)
1650 break; 1647 break;
1651 } 1648 }
1652 1649
1653 /* set "current" pointer back to previous state */ 1650 /* set "current" pointer back to previous state */
1654 (void)history(h, &ev, 1651 (void)history(h, &ev,
1655 pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); 1652 pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num);
1656 1653
1657 return -1; 1654 return -1;
1658} 1655}
1659 1656
1660 1657
1661/********************************/ 1658/********************************/
1662/* completion functions */ 1659/* completion functions */
1663 1660
1664char * 1661char *
1665tilde_expand(char *name) 1662tilde_expand(char *name)
1666{ 1663{
1667 return fn_tilde_expand(name); 1664 return fn_tilde_expand(name);
1668} 1665}
1669 1666
1670char * 1667char *
1671filename_completion_function(const char *name, int state) 1668filename_completion_function(const char *name, int state)
1672{ 1669{
1673 return fn_filename_completion_function(name, state); 1670 return fn_filename_completion_function(name, state);
1674} 1671}
1675 1672
1676/* 1673/*
1677 * a completion generator for usernames; returns _first_ username 1674 * a completion generator for usernames; returns _first_ username
1678 * which starts with supplied text 1675 * which starts with supplied text
1679 * text contains a partial username preceded by random character 1676 * text contains a partial username preceded by random character
1680 * (usually '~'); state resets search from start (??? should we do that anyway) 1677 * (usually '~'); state resets search from start (??? should we do that anyway)
1681 * it's callers responsibility to free returned value 1678 * it's callers responsibility to free returned value
1682 */ 1679 */
1683char * 1680char *
1684username_completion_function(const char *text, int state) 1681username_completion_function(const char *text, int state)
1685{ 1682{
1686#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) 1683#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1687 struct passwd pwres; 1684 struct passwd pwres;
1688 char pwbuf[1024]; 1685 char pwbuf[1024];
1689#endif 1686#endif
1690 struct passwd *pass = NULL; 1687 struct passwd *pass = NULL;
1691 1688
1692 if (text[0] == '\0') 1689 if (text[0] == '\0')
1693 return NULL; 1690 return NULL;
1694 1691
1695 if (*text == '~') 1692 if (*text == '~')
1696 text++; 1693 text++;
1697 1694
1698 if (state == 0) 1695 if (state == 0)
1699 setpwent(); 1696 setpwent();
1700 1697
1701 while ( 1698 while (
1702#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) 1699#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
1703 getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL 1700 getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pass) == 0 && pass != NULL
1704#else 1701#else
1705 (pass = getpwent()) != NULL 1702 (pass = getpwent()) != NULL
1706#endif 1703#endif
1707 && text[0] == pass->pw_name[0] 1704 && text[0] == pass->pw_name[0]
1708 && strcmp(text, pass->pw_name) == 0) 1705 && strcmp(text, pass->pw_name) == 0)
1709 continue; 1706 continue;
1710 1707
1711 if (pass == NULL) { 1708 if (pass == NULL) {
1712 endpwent(); 1709 endpwent();
1713 return NULL; 1710 return NULL;
1714 } 1711 }
1715 return strdup(pass->pw_name); 1712 return strdup(pass->pw_name);
1716} 1713}
1717 1714
1718 1715
1719/* 1716/*
1720 * el-compatible wrapper to send TSTP on ^Z 1717 * el-compatible wrapper to send TSTP on ^Z
1721 */ 1718 */
1722/* ARGSUSED */ 1719/* ARGSUSED */
1723static unsigned char 1720static unsigned char
1724_el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__))) 1721_el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))
1725{ 1722{
1726 (void)kill(0, SIGTSTP); 1723 (void)kill(0, SIGTSTP);
1727 return CC_NORM; 1724 return CC_NORM;
1728} 1725}
1729 1726
1730/* 1727/*
1731 * Display list of strings in columnar format on readline's output stream. 1728 * Display list of strings in columnar format on readline's output stream.
1732 * 'matches' is list of strings, 'len' is number of strings in 'matches', 1729 * 'matches' is list of strings, 'len' is number of strings in 'matches',
1733 * 'max' is maximum length of string in 'matches'. 1730 * 'max' is maximum length of string in 'matches'.
1734 */ 1731 */
1735void 1732void
1736rl_display_match_list(char **matches, int len, int max) 1733rl_display_match_list(char **matches, int len, int max)
1737{ 1734{
1738 1735
1739 fn_display_match_list(e, matches, (size_t)len, (size_t)max); 1736 fn_display_match_list(e, matches, (size_t)len, (size_t)max);
1740} 1737}
1741 1738
1742static const char * 1739static const char *
1743/*ARGSUSED*/ 1740/*ARGSUSED*/
1744_rl_completion_append_character_function(const char *dummy 1741_rl_completion_append_character_function(const char *dummy
1745 __attribute__((__unused__))) 1742 __attribute__((__unused__)))
1746{ 1743{
1747 static char buf[2]; 1744 static char buf[2];
1748 buf[0] = rl_completion_append_character; 1745 buf[0] = rl_completion_append_character;
1749 buf[1] = '\0'; 1746 buf[1] = '\0';
1750 return buf; 1747 return buf;
1751} 1748}
1752 1749
1753 1750
1754/* 1751/*
1755 * complete word at current point 1752 * complete word at current point
1756 */ 1753 */
1757/* ARGSUSED */ 1754/* ARGSUSED */
1758int 1755int
1759rl_complete(int ignore __attribute__((__unused__)), int invoking_key) 1756rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
1760{ 1757{
1761#ifdef WIDECHAR 1758#ifdef WIDECHAR
1762 static ct_buffer_t wbreak_conv, sprefix_conv; 1759 static ct_buffer_t wbreak_conv, sprefix_conv;
1763#endif 1760#endif
1764 1761
1765 if (h == NULL || e == NULL) 1762 if (h == NULL || e == NULL)
1766 rl_initialize(); 1763 rl_initialize();
1767 1764
1768 if (rl_inhibit_completion) { 1765 if (rl_inhibit_completion) {
1769 char arr[2]; 1766 char arr[2];
1770 arr[0] = (char)invoking_key; 1767 arr[0] = (char)invoking_key;
1771 arr[1] = '\0'; 1768 arr[1] = '\0';
1772 el_insertstr(e, arr); 1769 el_insertstr(e, arr);
1773 return CC_REFRESH; 1770 return CC_REFRESH;
1774 } 1771 }
1775 1772
1776 /* Just look at how many global variables modify this operation! */ 1773 /* Just look at how many global variables modify this operation! */
1777 return fn_complete(e, 1774 return fn_complete(e,
1778 (CPFunction *)rl_completion_entry_function, 1775 (CPFunction *)rl_completion_entry_function,
1779 rl_attempted_completion_function, 1776 rl_attempted_completion_function,
1780 ct_decode_string(rl_basic_word_break_characters, &wbreak_conv), 1777 ct_decode_string(rl_basic_word_break_characters, &wbreak_conv),
1781 ct_decode_string(rl_special_prefixes, &sprefix_conv), 1778 ct_decode_string(rl_special_prefixes, &sprefix_conv),
1782 _rl_completion_append_character_function, 1779 _rl_completion_append_character_function,
1783 (size_t)rl_completion_query_items, 1780 (size_t)rl_completion_query_items,
1784 &rl_completion_type, &rl_attempted_completion_over, 1781 &rl_completion_type, &rl_attempted_completion_over,
1785 &rl_point, &rl_end); 1782 &rl_point, &rl_end);
1786 1783
1787 1784
1788} 1785}
1789 1786
1790 1787
1791/* ARGSUSED */ 1788/* ARGSUSED */
1792static unsigned char 1789static unsigned char
1793_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch) 1790_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch)
1794{ 1791{
1795 return (unsigned char)rl_complete(0, ch); 1792 return (unsigned char)rl_complete(0, ch);
1796} 1793}
1797 1794
1798/* 1795/*
1799 * misc other functions 1796 * misc other functions
1800 */ 1797 */
1801 1798
1802/* 1799/*
1803 * bind key c to readline-type function func 1800 * bind key c to readline-type function func
1804 */ 1801 */
1805int 1802int
1806rl_bind_key(int c, rl_command_func_t *func) 1803rl_bind_key(int c, rl_command_func_t *func)
1807{ 1804{
1808 int retval = -1; 1805 int retval = -1;
1809 1806
1810 if (h == NULL || e == NULL) 1807 if (h == NULL || e == NULL)
1811 rl_initialize(); 1808 rl_initialize();
1812 1809
1813 if (func == rl_insert) { 1810 if (func == rl_insert) {
1814 /* XXX notice there is no range checking of ``c'' */ 1811 /* XXX notice there is no range checking of ``c'' */
1815 e->el_map.key[c] = ED_INSERT; 1812 e->el_map.key[c] = ED_INSERT;
1816 retval = 0; 1813 retval = 0;
1817 } 1814 }
1818 return retval; 1815 return retval;
1819} 1816}
1820 1817
1821 1818
1822/* 1819/*
1823 * read one key from input - handles chars pushed back 1820 * read one key from input - handles chars pushed back
1824 * to input stream also 1821 * to input stream also
1825 */ 1822 */
1826int 1823int
1827rl_read_key(void) 1824rl_read_key(void)
1828{ 1825{
1829 char fooarr[2 * sizeof(int)]; 1826 char fooarr[2 * sizeof(int)];
1830 1827
1831 if (e == NULL || h == NULL) 1828 if (e == NULL || h == NULL)
1832 rl_initialize(); 1829 rl_initialize();
1833 1830
1834 return el_getc(e, fooarr); 1831 return el_getc(e, fooarr);
1835} 1832}
1836 1833
1837 1834
1838/* 1835/*
1839 * reset the terminal 1836 * reset the terminal
1840 */ 1837 */
1841/* ARGSUSED */ 1838/* ARGSUSED */
1842void 1839void
1843rl_reset_terminal(const char *p __attribute__((__unused__))) 1840rl_reset_terminal(const char *p __attribute__((__unused__)))
1844{ 1841{
1845 1842
1846 if (h == NULL || e == NULL) 1843 if (h == NULL || e == NULL)
1847 rl_initialize(); 1844 rl_initialize();
1848 el_reset(e); 1845 el_reset(e);
1849} 1846}
1850 1847
1851 1848
1852/* 1849/*
1853 * insert character ``c'' back into input stream, ``count'' times 1850 * insert character ``c'' back into input stream, ``count'' times
1854 */ 1851 */
1855int 1852int
1856rl_insert(int count, int c) 1853rl_insert(int count, int c)
1857{ 1854{
1858 char arr[2]; 1855 char arr[2];
1859 1856
1860 if (h == NULL || e == NULL) 1857 if (h == NULL || e == NULL)
1861 rl_initialize(); 1858 rl_initialize();
1862 1859
1863 /* XXX - int -> char conversion can lose on multichars */ 1860 /* XXX - int -> char conversion can lose on multichars */
1864 arr[0] = c; 1861 arr[0] = c;
1865 arr[1] = '\0'; 1862 arr[1] = '\0';
1866 1863
1867 for (; count > 0; count--) 1864 for (; count > 0; count--)
1868 el_push(e, arr); 1865 el_push(e, arr);
1869 1866
1870 return 0; 1867 return 0;
1871} 1868}
1872 1869
1873int 1870int
1874rl_insert_text(const char *text) 1871rl_insert_text(const char *text)
1875{ 1872{
1876 if (!text || *text == 0) 1873 if (!text || *text == 0)
1877 return 0; 1874 return 0;
1878 1875
1879 if (h == NULL || e == NULL) 1876 if (h == NULL || e == NULL)
1880 rl_initialize(); 1877 rl_initialize();
1881 1878
1882 if (el_insertstr(e, text) < 0) 1879 if (el_insertstr(e, text) < 0)
1883 return 0; 1880 return 0;
1884 return (int)strlen(text); 1881 return (int)strlen(text);
1885} 1882}
1886 1883
1887/*ARGSUSED*/ 1884/*ARGSUSED*/
1888int 1885int
1889rl_newline(int count, int c) 1886rl_newline(int count __attribute__((__unused__)),
 1887 int c __attribute__((__unused__)))
1890{ 1888{
1891 /* 1889 /*
1892 * Readline-4.0 appears to ignore the args. 1890 * Readline-4.0 appears to ignore the args.
1893 */ 1891 */
1894 return rl_insert(1, '\n'); 1892 return rl_insert(1, '\n');
1895} 1893}
1896 1894
1897/*ARGSUSED*/ 1895/*ARGSUSED*/
1898static unsigned char 1896static unsigned char
1899rl_bind_wrapper(EditLine *el, unsigned char c) 1897rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c)
1900{ 1898{
1901 if (map[c] == NULL) 1899 if (map[c] == NULL)
1902 return CC_ERROR; 1900 return CC_ERROR;
1903 1901
1904 _rl_update_pos(); 1902 _rl_update_pos();
1905 1903
1906 (*map[c])(NULL, c); 1904 (*map[c])(NULL, c);
1907 1905
1908 /* If rl_done was set by the above call, deal with it here */ 1906 /* If rl_done was set by the above call, deal with it here */
1909 if (rl_done) 1907 if (rl_done)
1910 return CC_EOF; 1908 return CC_EOF;
1911 1909
1912 return CC_NORM; 1910 return CC_NORM;
1913} 1911}
1914 1912
1915int 1913int
1916rl_add_defun(const char *name, Function *fun, int c) 1914rl_add_defun(const char *name, Function *fun, int c)
1917{ 1915{
1918 char dest[8]; 1916 char dest[8];
1919 if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0) 1917 if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0)
1920 return -1; 1918 return -1;
1921 map[(unsigned char)c] = fun; 1919 map[(unsigned char)c] = fun;
1922 el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); 1920 el_set(e, EL_ADDFN, name, name, rl_bind_wrapper);
1923 vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0); 1921 vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0);
1924 el_set(e, EL_BIND, dest, name); 1922 el_set(e, EL_BIND, dest, name);
1925 return 0; 1923 return 0;
1926} 1924}
1927 1925
1928void 1926void
1929rl_callback_read_char() 1927rl_callback_read_char()
1930{ 1928{
1931 int count = 0, done = 0; 1929 int count = 0, done = 0;
1932 const char *buf = el_gets(e, &count); 1930 const char *buf = el_gets(e, &count);
1933 char *wbuf; 1931 char *wbuf;
1934 1932
1935 if (buf == NULL || count-- <= 0) 1933 if (buf == NULL || count-- <= 0)
1936 return; 1934 return;
1937 if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF]) 1935 if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF])
1938 done = 1; 1936 done = 1;
1939 if (buf[count] == '\n' || buf[count] == '\r') 1937 if (buf[count] == '\n' || buf[count] == '\r')
1940 done = 2; 1938 done = 2;
1941 1939
1942 if (done && rl_linefunc != NULL) { 1940 if (done && rl_linefunc != NULL) {
1943 el_set(e, EL_UNBUFFERED, 0); 1941 el_set(e, EL_UNBUFFERED, 0);
1944 if (done == 2) { 1942 if (done == 2) {
1945 if ((wbuf = strdup(buf)) != NULL) 1943 if ((wbuf = strdup(buf)) != NULL)
1946 wbuf[count] = '\0'; 1944 wbuf[count] = '\0';
1947 } else 1945 } else
1948 wbuf = NULL; 1946 wbuf = NULL;
1949 (*(void (*)(const char *))rl_linefunc)(wbuf); 1947 (*(void (*)(const char *))rl_linefunc)(wbuf);
1950 //el_set(e, EL_UNBUFFERED, 1); 1948 //el_set(e, EL_UNBUFFERED, 1);
1951 } 1949 }
1952} 1950}
1953 1951
1954void  1952void
1955rl_callback_handler_install(const char *prompt, VCPFunction *linefunc) 1953rl_callback_handler_install(const char *prompt, VCPFunction *linefunc)
1956{ 1954{
1957 if (e == NULL) { 1955 if (e == NULL) {
1958 rl_initialize(); 1956 rl_initialize();
1959 } 1957 }
1960 (void)rl_set_prompt(prompt); 1958 (void)rl_set_prompt(prompt);
1961 rl_linefunc = linefunc; 1959 rl_linefunc = linefunc;
1962 el_set(e, EL_UNBUFFERED, 1); 1960 el_set(e, EL_UNBUFFERED, 1);
1963}  1961}
1964 1962
1965void  1963void
1966rl_callback_handler_remove(void) 1964rl_callback_handler_remove(void)
1967{ 1965{
1968 el_set(e, EL_UNBUFFERED, 0); 1966 el_set(e, EL_UNBUFFERED, 0);
1969 rl_linefunc = NULL; 1967 rl_linefunc = NULL;
1970} 1968}
1971 1969
1972void 1970void
1973rl_redisplay(void) 1971rl_redisplay(void)
1974{ 1972{
1975 char a[2]; 1973 char a[2];
1976 a[0] = e->el_tty.t_c[TS_IO][C_REPRINT]; 1974 a[0] = e->el_tty.t_c[TS_IO][C_REPRINT];
1977 a[1] = '\0'; 1975 a[1] = '\0';
1978 el_push(e, a); 1976 el_push(e, a);
1979} 1977}
1980 1978
1981int 1979int
1982rl_get_previous_history(int count, int key) 1980rl_get_previous_history(int count, int key)
1983{ 1981{
1984 char a[2]; 1982 char a[2];
1985 a[0] = key; 1983 a[0] = key;
1986 a[1] = '\0'; 1984 a[1] = '\0';
1987 while (count--) 1985 while (count--)
1988 el_push(e, a); 1986 el_push(e, a);
1989 return 0; 1987 return 0;
1990} 1988}
1991 1989
1992void 1990void
1993/*ARGSUSED*/ 1991/*ARGSUSED*/
1994rl_prep_terminal(int meta_flag) 1992rl_prep_terminal(int meta_flag __attribute__((__unused__)))
1995{ 1993{
1996 el_set(e, EL_PREP_TERM, 1); 1994 el_set(e, EL_PREP_TERM, 1);
1997} 1995}
1998 1996
1999void 1997void
2000rl_deprep_terminal(void) 1998rl_deprep_terminal(void)
2001{ 1999{
2002 el_set(e, EL_PREP_TERM, 0); 2000 el_set(e, EL_PREP_TERM, 0);
2003} 2001}
2004 2002
2005int 2003int
2006rl_read_init_file(const char *s) 2004rl_read_init_file(const char *s)
2007{ 2005{
2008 return el_source(e, s); 2006 return el_source(e, s);
2009} 2007}
2010 2008
2011int 2009int
2012rl_parse_and_bind(const char *line) 2010rl_parse_and_bind(const char *line)
2013{ 2011{
2014 const char **argv; 2012 const char **argv;
2015 int argc; 2013 int argc;
2016 Tokenizer *tok; 2014 Tokenizer *tok;
2017 2015
2018 tok = tok_init(NULL); 2016 tok = tok_init(NULL);
2019 tok_str(tok, line, &argc, &argv); 2017 tok_str(tok, line, &argc, &argv);
2020 argc = el_parse(e, argc, argv); 2018 argc = el_parse(e, argc, argv);
2021 tok_end(tok); 2019 tok_end(tok);
2022 return argc ? 1 : 0; 2020 return argc ? 1 : 0;
2023} 2021}
2024 2022
2025int 2023int
2026rl_variable_bind(const char *var, const char *value) 2024rl_variable_bind(const char *var, const char *value)
2027{ 2025{
2028 /* 2026 /*
2029 * The proper return value is undocument, but this is what the 2027 * The proper return value is undocument, but this is what the
2030 * readline source seems to do. 2028 * readline source seems to do.
2031 */ 2029 */
2032 return el_set(e, EL_BIND, "", var, value) == -1 ? 1 : 0; 2030 return el_set(e, EL_BIND, "", var, value) == -1 ? 1 : 0;
2033} 2031}
2034 2032
2035void 2033void
2036rl_stuff_char(int c) 2034rl_stuff_char(int c)
2037{ 2035{
2038 char buf[2]; 2036 char buf[2];
2039 2037
2040 buf[0] = c; 2038 buf[0] = c;
2041 buf[1] = '\0'; 2039 buf[1] = '\0';
2042 el_insertstr(e, buf); 2040 el_insertstr(e, buf);
2043} 2041}
2044 2042
2045static int 2043static int
2046_rl_event_read_char(EditLine *el, char *cp) 2044_rl_event_read_char(EditLine *el, char *cp)
2047{ 2045{
2048 int n; 2046 int n;
2049 ssize_t num_read = 0; 2047 ssize_t num_read = 0;
2050 2048
2051 *cp = '\0'; 2049 *cp = '\0';
2052 while (rl_event_hook) { 2050 while (rl_event_hook) {
2053 2051
2054 (*rl_event_hook)(); 2052 (*rl_event_hook)();
2055 2053
2056#if defined(FIONREAD) 2054#if defined(FIONREAD)
2057 if (ioctl(el->el_infd, FIONREAD, &n) < 0) 2055 if (ioctl(el->el_infd, FIONREAD, &n) < 0)
2058 return -1; 2056 return -1;
2059 if (n) 2057 if (n)
2060 num_read = read(el->el_infd, cp, 1); 2058 num_read = read(el->el_infd, cp, 1);
2061 else 2059 else
2062 num_read = 0; 2060 num_read = 0;
2063#elif defined(F_SETFL) && defined(O_NDELAY) 2061#elif defined(F_SETFL) && defined(O_NDELAY)
2064 if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0) 2062 if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0)
2065 return -1; 2063 return -1;
2066 if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0) 2064 if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0)
2067 return -1; 2065 return -1;
2068 num_read = read(el->el_infd, cp, 1); 2066 num_read = read(el->el_infd, cp, 1);
2069 if (fcntl(el->el_infd, F_SETFL, n)) 2067 if (fcntl(el->el_infd, F_SETFL, n))
2070 return -1; 2068 return -1;
2071#else 2069#else
2072 /* not non-blocking, but what you gonna do? */ 2070 /* not non-blocking, but what you gonna do? */
2073 num_read = read(el->el_infd, cp, 1); 2071 num_read = read(el->el_infd, cp, 1);
2074 return -1; 2072 return -1;
2075#endif 2073#endif
2076 2074
2077 if (num_read < 0 && errno == EAGAIN) 2075 if (num_read < 0 && errno == EAGAIN)
2078 continue; 2076 continue;
2079 if (num_read == 0) 2077 if (num_read == 0)
2080 continue; 2078 continue;
2081 break; 2079 break;
2082 } 2080 }
2083 if (!rl_event_hook) 2081 if (!rl_event_hook)
2084 el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); 2082 el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN);
2085 return (int)num_read; 2083 return (int)num_read;
2086} 2084}
2087 2085
2088static void 2086static void
2089_rl_update_pos(void) 2087_rl_update_pos(void)
2090{ 2088{
2091 const LineInfo *li = el_line(e); 2089 const LineInfo *li = el_line(e);
2092 2090
2093 rl_point = (int)(li->cursor - li->buffer); 2091 rl_point = (int)(li->cursor - li->buffer);
2094 rl_end = (int)(li->lastchar - li->buffer); 2092 rl_end = (int)(li->lastchar - li->buffer);
2095} 2093}
2096 2094
2097void 2095void
2098rl_get_screen_size(int *rows, int *cols) 2096rl_get_screen_size(int *rows, int *cols)
2099{ 2097{
2100 if (rows) 2098 if (rows)
2101 el_get(e, EL_GETTC, "li", rows); 2099 el_get(e, EL_GETTC, "li", rows);
2102 if (cols) 2100 if (cols)
2103 el_get(e, EL_GETTC, "co", cols); 2101 el_get(e, EL_GETTC, "co", cols);
2104} 2102}
2105 2103
2106void 2104void
2107rl_set_screen_size(int rows, int cols) 2105rl_set_screen_size(int rows, int cols)
2108{ 2106{
2109 char buf[64]; 2107 char buf[64];
2110 (void)snprintf(buf, sizeof(buf), "%d", rows); 2108 (void)snprintf(buf, sizeof(buf), "%d", rows);
2111 el_set(e, EL_SETTC, "li", buf); 2109 el_set(e, EL_SETTC, "li", buf);
2112 (void)snprintf(buf, sizeof(buf), "%d", cols); 2110 (void)snprintf(buf, sizeof(buf), "%d", cols);
2113 el_set(e, EL_SETTC, "co", buf); 2111 el_set(e, EL_SETTC, "co", buf);
2114} 2112}
2115 2113
2116char ** 2114char **
2117rl_completion_matches(const char *str, rl_compentry_func_t *fun) 2115rl_completion_matches(const char *str, rl_compentry_func_t *fun)
2118{ 2116{
2119 size_t len, max, i, j, min; 2117 size_t len, max, i, j, min;
2120 char **list, *match, *a, *b; 2118 char **list, *match, *a, *b;
2121 2119
2122 len = 1; 2120 len = 1;
2123 max = 10; 2121 max = 10;
2124 if ((list = el_malloc(max * sizeof(*list))) == NULL) 2122 if ((list = el_malloc(max * sizeof(*list))) == NULL)
2125 return NULL; 2123 return NULL;
2126 2124
2127 while ((match = (*fun)(str, (int)(len - 1))) != NULL) { 2125 while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
2128 list[len++] = match; 2126 list[len++] = match;
2129 if (len == max) { 2127 if (len == max) {
2130 char **nl; 2128 char **nl;
2131 max += 10; 2129 max += 10;
2132 if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL) 2130 if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL)
2133 goto out; 2131 goto out;
2134 list = nl; 2132 list = nl;
2135 } 2133 }
2136 } 2134 }
2137 if (len == 1) 2135 if (len == 1)
2138 goto out; 2136 goto out;
2139 list[len] = NULL; 2137 list[len] = NULL;
2140 if (len == 2) { 2138 if (len == 2) {
2141 if ((list[0] = strdup(list[1])) == NULL) 2139 if ((list[0] = strdup(list[1])) == NULL)
2142 goto out; 2140 goto out;
2143 return list; 2141 return list;
2144 } 2142 }
2145 qsort(&list[1], len - 1, sizeof(*list), 2143 qsort(&list[1], len - 1, sizeof(*list),
2146 (int (*)(const void *, const void *)) strcmp); 2144 (int (*)(const void *, const void *)) strcmp);
2147 min = SIZE_T_MAX; 2145 min = SIZE_T_MAX;
2148 for (i = 1, a = list[i]; i < len - 1; i++, a = b) { 2146 for (i = 1, a = list[i]; i < len - 1; i++, a = b) {
2149 b = list[i + 1]; 2147 b = list[i + 1];
2150 for (j = 0; a[j] && a[j] == b[j]; j++) 2148 for (j = 0; a[j] && a[j] == b[j]; j++)
2151 continue; 2149 continue;
2152 if (min > j) 2150 if (min > j)
2153 min = j; 2151 min = j;
2154 } 2152 }
2155 if (min == 0 && *str) { 2153 if (min == 0 && *str) {
2156 if ((list[0] = strdup(str)) == NULL) 2154 if ((list[0] = strdup(str)) == NULL)
2157 goto out; 2155 goto out;
2158 } else { 2156 } else {
2159 if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL) 2157 if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL)
2160 goto out; 2158 goto out;
2161 (void)memcpy(list[0], list[1], min); 2159 (void)memcpy(list[0], list[1], min);
2162 list[0][min] = '\0'; 2160 list[0][min] = '\0';
2163 } 2161 }
2164 return list; 2162 return list;
2165  2163
2166out: 2164out:
2167 el_free(list); 2165 el_free(list);
2168 return NULL; 2166 return NULL;
2169} 2167}
2170 2168
2171char * 2169char *
2172rl_filename_completion_function (const char *text, int state) 2170rl_filename_completion_function (const char *text, int state)
2173{ 2171{
2174 return fn_filename_completion_function(text, state); 2172 return fn_filename_completion_function(text, state);
2175} 2173}
2176 2174
2177void 2175void
2178rl_forced_update_display(void) 2176rl_forced_update_display(void)
2179{ 2177{
2180 el_set(e, EL_REFRESH); 2178 el_set(e, EL_REFRESH);
2181} 2179}
2182 2180
2183int 2181int
2184_rl_abort_internal(void) 2182_rl_abort_internal(void)
2185{ 2183{
2186 el_beep(e); 2184 el_beep(e);
2187 longjmp(topbuf, 1); 2185 longjmp(topbuf, 1);
2188 /*NOTREACHED*/ 2186 /*NOTREACHED*/
2189} 2187}
2190 2188
2191int 2189int
2192_rl_qsort_string_compare(char **s1, char **s2) 2190_rl_qsort_string_compare(char **s1, char **s2)
2193{ 2191{
2194 return strcoll(*s1, *s2); 2192 return strcoll(*s1, *s2);
2195} 2193}
2196 2194
2197HISTORY_STATE * 2195HISTORY_STATE *
2198history_get_history_state(void) 2196history_get_history_state(void)
2199{ 2197{
2200 HISTORY_STATE *hs; 2198 HISTORY_STATE *hs;
2201 2199
2202 if ((hs = el_malloc(sizeof(*hs))) == NULL) 2200 if ((hs = el_malloc(sizeof(*hs))) == NULL)
2203 return NULL; 2201 return NULL;
2204 hs->length = history_length; 2202 hs->length = history_length;
2205 return hs; 2203 return hs;
2206} 2204}
2207 2205
2208int 2206int
2209/*ARGSUSED*/ 2207/*ARGSUSED*/
2210rl_kill_text(int from, int to) 2208rl_kill_text(int from __attribute__((__unused__)),
 2209 int to __attribute__((__unused__)))
2211{ 2210{
2212 return 0; 2211 return 0;
2213} 2212}
2214 2213
2215Keymap 2214Keymap
2216rl_make_bare_keymap(void) 2215rl_make_bare_keymap(void)
2217{ 2216{
2218 return NULL; 2217 return NULL;
2219} 2218}
2220 2219
2221Keymap 2220Keymap
2222rl_get_keymap(void) 2221rl_get_keymap(void)
2223{ 2222{
2224 return NULL; 2223 return NULL;
2225} 2224}
2226 2225
2227void 2226void
2228/*ARGSUSED*/ 2227/*ARGSUSED*/
2229rl_set_keymap(Keymap k) 2228rl_set_keymap(Keymap k __attribute__((__unused__)))
2230{ 2229{
2231} 2230}
2232 2231
2233int 2232int
2234/*ARGSUSED*/ 2233/*ARGSUSED*/
2235rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k) 2234rl_generic_bind(int type __attribute__((__unused__)),
 2235 const char * keyseq __attribute__((__unused__)),
 2236 const char * data __attribute__((__unused__)),
 2237 Keymap k __attribute__((__unused__)))
2236{ 2238{
2237 return 0; 2239 return 0;
2238} 2240}
2239 2241
2240int 2242int
2241/*ARGSUSED*/ 2243/*ARGSUSED*/
2242rl_bind_key_in_map(int key, rl_command_func_t *fun, Keymap k) 2244rl_bind_key_in_map(int key __attribute__((__unused__)),
 2245 rl_command_func_t *fun __attribute__((__unused__)),
 2246 Keymap k __attribute__((__unused__)))
2243{ 2247{
2244 return 0; 2248 return 0;
2245} 2249}
2246 2250
2247/* unsupported, but needed by python */ 2251/* unsupported, but needed by python */
2248void 2252void
2249rl_cleanup_after_signal(void) 2253rl_cleanup_after_signal(void)
2250{ 2254{
2251} 2255}
2252 2256
2253int 2257int
2254rl_on_new_line(void) 2258rl_on_new_line(void)
2255{ 2259{
2256 return 0; 2260 return 0;
2257} 2261}

cvs diff -r1.37 -r1.38 src/lib/libedit/vi.c (switch to unified diff)

--- src/lib/libedit/vi.c 2011/07/29 15:16:33 1.37
+++ src/lib/libedit/vi.c 2011/07/29 20:58:07 1.38
@@ -1,1161 +1,1161 @@ @@ -1,1161 +1,1161 @@
1/* $NetBSD: vi.c,v 1.37 2011/07/29 15:16:33 christos Exp $ */ 1/* $NetBSD: vi.c,v 1.38 2011/07/29 20:58:07 christos Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1992, 1993 4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Christos Zoulas of Cornell University. 8 * Christos Zoulas of Cornell University.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 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 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include "config.h" 35#include "config.h"
36#include <stdlib.h> 36#include <stdlib.h>
37#include <unistd.h> 37#include <unistd.h>
38#include <limits.h> 38#include <limits.h>
39#include <sys/wait.h> 39#include <sys/wait.h>
40 40
41#if !defined(lint) && !defined(SCCSID) 41#if !defined(lint) && !defined(SCCSID)
42#if 0 42#if 0
43static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; 43static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
44#else 44#else
45__RCSID("$NetBSD: vi.c,v 1.37 2011/07/29 15:16:33 christos Exp $"); 45__RCSID("$NetBSD: vi.c,v 1.38 2011/07/29 20:58:07 christos Exp $");
46#endif 46#endif
47#endif /* not lint && not SCCSID */ 47#endif /* not lint && not SCCSID */
48 48
49/* 49/*
50 * vi.c: Vi mode commands. 50 * vi.c: Vi mode commands.
51 */ 51 */
52#include "el.h" 52#include "el.h"
53 53
54private el_action_t cv_action(EditLine *, Int); 54private el_action_t cv_action(EditLine *, Int);
55private el_action_t cv_paste(EditLine *, Int); 55private el_action_t cv_paste(EditLine *, Int);
56 56
57/* cv_action(): 57/* cv_action():
58 * Handle vi actions. 58 * Handle vi actions.
59 */ 59 */
60private el_action_t 60private el_action_t
61cv_action(EditLine *el, Int c) 61cv_action(EditLine *el, Int c)
62{ 62{
63 63
64 if (el->el_chared.c_vcmd.action != NOP) { 64 if (el->el_chared.c_vcmd.action != NOP) {
65 /* 'cc', 'dd' and (possibly) friends */ 65 /* 'cc', 'dd' and (possibly) friends */
66 if (c != el->el_chared.c_vcmd.action) 66 if (c != el->el_chared.c_vcmd.action)
67 return CC_ERROR; 67 return CC_ERROR;
68 68
69 if (!(c & YANK)) 69 if (!(c & YANK))
70 cv_undo(el); 70 cv_undo(el);
71 cv_yank(el, el->el_line.buffer, 71 cv_yank(el, el->el_line.buffer,
72 (int)(el->el_line.lastchar - el->el_line.buffer)); 72 (int)(el->el_line.lastchar - el->el_line.buffer));
73 el->el_chared.c_vcmd.action = NOP; 73 el->el_chared.c_vcmd.action = NOP;
74 el->el_chared.c_vcmd.pos = 0; 74 el->el_chared.c_vcmd.pos = 0;
75 if (!(c & YANK)) { 75 if (!(c & YANK)) {
76 el->el_line.lastchar = el->el_line.buffer; 76 el->el_line.lastchar = el->el_line.buffer;
77 el->el_line.cursor = el->el_line.buffer; 77 el->el_line.cursor = el->el_line.buffer;
78 } 78 }
79 if (c & INSERT) 79 if (c & INSERT)
80 el->el_map.current = el->el_map.key; 80 el->el_map.current = el->el_map.key;
81 81
82 return CC_REFRESH; 82 return CC_REFRESH;
83 } 83 }
84 el->el_chared.c_vcmd.pos = el->el_line.cursor; 84 el->el_chared.c_vcmd.pos = el->el_line.cursor;
85 el->el_chared.c_vcmd.action = c; 85 el->el_chared.c_vcmd.action = c;
86 return CC_ARGHACK; 86 return CC_ARGHACK;
87} 87}
88 88
89/* cv_paste(): 89/* cv_paste():
90 * Paste previous deletion before or after the cursor 90 * Paste previous deletion before or after the cursor
91 */ 91 */
92private el_action_t 92private el_action_t
93cv_paste(EditLine *el, Int c) 93cv_paste(EditLine *el, Int c)
94{ 94{
95 c_kill_t *k = &el->el_chared.c_kill; 95 c_kill_t *k = &el->el_chared.c_kill;
96 size_t len = (size_t)(k->last - k->buf); 96 size_t len = (size_t)(k->last - k->buf);
97 97
98 if (k->buf == NULL || len == 0) 98 if (k->buf == NULL || len == 0)
99 return CC_ERROR; 99 return CC_ERROR;
100#ifdef DEBUG_PASTE 100#ifdef DEBUG_PASTE
101 (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", (int)len, k->buf); 101 (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", (int)len, k->buf);
102#endif 102#endif
103 103
104 cv_undo(el); 104 cv_undo(el);
105 105
106 if (!c && el->el_line.cursor < el->el_line.lastchar) 106 if (!c && el->el_line.cursor < el->el_line.lastchar)
107 el->el_line.cursor++; 107 el->el_line.cursor++;
108 108
109 c_insert(el, (int)len); 109 c_insert(el, (int)len);
110 if (el->el_line.cursor + len > el->el_line.lastchar) 110 if (el->el_line.cursor + len > el->el_line.lastchar)
111 return CC_ERROR; 111 return CC_ERROR;
112 (void) memcpy(el->el_line.cursor, k->buf, len * 112 (void) memcpy(el->el_line.cursor, k->buf, len *
113 sizeof(*el->el_line.cursor)); 113 sizeof(*el->el_line.cursor));
114 114
115 return CC_REFRESH; 115 return CC_REFRESH;
116} 116}
117 117
118 118
119/* vi_paste_next(): 119/* vi_paste_next():
120 * Vi paste previous deletion to the right of the cursor 120 * Vi paste previous deletion to the right of the cursor
121 * [p] 121 * [p]
122 */ 122 */
123protected el_action_t 123protected el_action_t
124/*ARGSUSED*/ 124/*ARGSUSED*/
125vi_paste_next(EditLine *el, Int c __attribute__((__unused__))) 125vi_paste_next(EditLine *el, Int c __attribute__((__unused__)))
126{ 126{
127 127
128 return cv_paste(el, 0); 128 return cv_paste(el, 0);
129} 129}
130 130
131 131
132/* vi_paste_prev(): 132/* vi_paste_prev():
133 * Vi paste previous deletion to the left of the cursor 133 * Vi paste previous deletion to the left of the cursor
134 * [P] 134 * [P]
135 */ 135 */
136protected el_action_t 136protected el_action_t
137/*ARGSUSED*/ 137/*ARGSUSED*/
138vi_paste_prev(EditLine *el, Int c __attribute__((__unused__))) 138vi_paste_prev(EditLine *el, Int c __attribute__((__unused__)))
139{ 139{
140 140
141 return cv_paste(el, 1); 141 return cv_paste(el, 1);
142} 142}
143 143
144 144
145/* vi_prev_big_word(): 145/* vi_prev_big_word():
146 * Vi move to the previous space delimited word 146 * Vi move to the previous space delimited word
147 * [B] 147 * [B]
148 */ 148 */
149protected el_action_t 149protected el_action_t
150/*ARGSUSED*/ 150/*ARGSUSED*/
151vi_prev_big_word(EditLine *el, Int c __attribute__((__unused__))) 151vi_prev_big_word(EditLine *el, Int c __attribute__((__unused__)))
152{ 152{
153 153
154 if (el->el_line.cursor == el->el_line.buffer) 154 if (el->el_line.cursor == el->el_line.buffer)
155 return CC_ERROR; 155 return CC_ERROR;
156 156
157 el->el_line.cursor = cv_prev_word(el->el_line.cursor, 157 el->el_line.cursor = cv_prev_word(el->el_line.cursor,
158 el->el_line.buffer, 158 el->el_line.buffer,
159 el->el_state.argument, 159 el->el_state.argument,
160 cv__isWord); 160 cv__isWord);
161 161
162 if (el->el_chared.c_vcmd.action != NOP) { 162 if (el->el_chared.c_vcmd.action != NOP) {
163 cv_delfini(el); 163 cv_delfini(el);
164 return CC_REFRESH; 164 return CC_REFRESH;
165 } 165 }
166 return CC_CURSOR; 166 return CC_CURSOR;
167} 167}
168 168
169 169
170/* vi_prev_word(): 170/* vi_prev_word():
171 * Vi move to the previous word 171 * Vi move to the previous word
172 * [b] 172 * [b]
173 */ 173 */
174protected el_action_t 174protected el_action_t
175/*ARGSUSED*/ 175/*ARGSUSED*/
176vi_prev_word(EditLine *el, Int c __attribute__((__unused__))) 176vi_prev_word(EditLine *el, Int c __attribute__((__unused__)))
177{ 177{
178 178
179 if (el->el_line.cursor == el->el_line.buffer) 179 if (el->el_line.cursor == el->el_line.buffer)
180 return CC_ERROR; 180 return CC_ERROR;
181 181
182 el->el_line.cursor = cv_prev_word(el->el_line.cursor, 182 el->el_line.cursor = cv_prev_word(el->el_line.cursor,
183 el->el_line.buffer, 183 el->el_line.buffer,
184 el->el_state.argument, 184 el->el_state.argument,
185 cv__isword); 185 cv__isword);
186 186
187 if (el->el_chared.c_vcmd.action != NOP) { 187 if (el->el_chared.c_vcmd.action != NOP) {
188 cv_delfini(el); 188 cv_delfini(el);
189 return CC_REFRESH; 189 return CC_REFRESH;
190 } 190 }
191 return CC_CURSOR; 191 return CC_CURSOR;
192} 192}
193 193
194 194
195/* vi_next_big_word(): 195/* vi_next_big_word():
196 * Vi move to the next space delimited word 196 * Vi move to the next space delimited word
197 * [W] 197 * [W]
198 */ 198 */
199protected el_action_t 199protected el_action_t
200/*ARGSUSED*/ 200/*ARGSUSED*/
201vi_next_big_word(EditLine *el, Int c __attribute__((__unused__))) 201vi_next_big_word(EditLine *el, Int c __attribute__((__unused__)))
202{ 202{
203 203
204 if (el->el_line.cursor >= el->el_line.lastchar - 1) 204 if (el->el_line.cursor >= el->el_line.lastchar - 1)
205 return CC_ERROR; 205 return CC_ERROR;
206 206
207 el->el_line.cursor = cv_next_word(el, el->el_line.cursor, 207 el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
208 el->el_line.lastchar, el->el_state.argument, cv__isWord); 208 el->el_line.lastchar, el->el_state.argument, cv__isWord);
209 209
210 if (el->el_map.type == MAP_VI) 210 if (el->el_map.type == MAP_VI)
211 if (el->el_chared.c_vcmd.action != NOP) { 211 if (el->el_chared.c_vcmd.action != NOP) {
212 cv_delfini(el); 212 cv_delfini(el);
213 return CC_REFRESH; 213 return CC_REFRESH;
214 } 214 }
215 return CC_CURSOR; 215 return CC_CURSOR;
216} 216}
217 217
218 218
219/* vi_next_word(): 219/* vi_next_word():
220 * Vi move to the next word 220 * Vi move to the next word
221 * [w] 221 * [w]
222 */ 222 */
223protected el_action_t 223protected el_action_t
224/*ARGSUSED*/ 224/*ARGSUSED*/
225vi_next_word(EditLine *el, Int c __attribute__((__unused__))) 225vi_next_word(EditLine *el, Int c __attribute__((__unused__)))
226{ 226{
227 227
228 if (el->el_line.cursor >= el->el_line.lastchar - 1) 228 if (el->el_line.cursor >= el->el_line.lastchar - 1)
229 return CC_ERROR; 229 return CC_ERROR;
230 230
231 el->el_line.cursor = cv_next_word(el, el->el_line.cursor, 231 el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
232 el->el_line.lastchar, el->el_state.argument, cv__isword); 232 el->el_line.lastchar, el->el_state.argument, cv__isword);
233 233
234 if (el->el_map.type == MAP_VI) 234 if (el->el_map.type == MAP_VI)
235 if (el->el_chared.c_vcmd.action != NOP) { 235 if (el->el_chared.c_vcmd.action != NOP) {
236 cv_delfini(el); 236 cv_delfini(el);
237 return CC_REFRESH; 237 return CC_REFRESH;
238 } 238 }
239 return CC_CURSOR; 239 return CC_CURSOR;
240} 240}
241 241
242 242
243/* vi_change_case(): 243/* vi_change_case():
244 * Vi change case of character under the cursor and advance one character 244 * Vi change case of character under the cursor and advance one character
245 * [~] 245 * [~]
246 */ 246 */
247protected el_action_t 247protected el_action_t
248vi_change_case(EditLine *el, Int c) 248vi_change_case(EditLine *el, Int c)
249{ 249{
250 int i; 250 int i;
251 251
252 if (el->el_line.cursor >= el->el_line.lastchar) 252 if (el->el_line.cursor >= el->el_line.lastchar)
253 return CC_ERROR; 253 return CC_ERROR;
254 cv_undo(el); 254 cv_undo(el);
255 for (i = 0; i < el->el_state.argument; i++) { 255 for (i = 0; i < el->el_state.argument; i++) {
256 256
257 c = *el->el_line.cursor; 257 c = *el->el_line.cursor;
258 if (Isupper(c)) 258 if (Isupper(c))
259 *el->el_line.cursor = Tolower(c); 259 *el->el_line.cursor = Tolower(c);
260 else if (Islower(c)) 260 else if (Islower(c))
261 *el->el_line.cursor = Toupper(c); 261 *el->el_line.cursor = Toupper(c);
262 262
263 if (++el->el_line.cursor >= el->el_line.lastchar) { 263 if (++el->el_line.cursor >= el->el_line.lastchar) {
264 el->el_line.cursor--; 264 el->el_line.cursor--;
265 re_fastaddc(el); 265 re_fastaddc(el);
266 break; 266 break;
267 } 267 }
268 re_fastaddc(el); 268 re_fastaddc(el);
269 } 269 }
270 return CC_NORM; 270 return CC_NORM;
271} 271}
272 272
273 273
274/* vi_change_meta(): 274/* vi_change_meta():
275 * Vi change prefix command 275 * Vi change prefix command
276 * [c] 276 * [c]
277 */ 277 */
278protected el_action_t 278protected el_action_t
279/*ARGSUSED*/ 279/*ARGSUSED*/
280vi_change_meta(EditLine *el, Int c __attribute__((__unused__))) 280vi_change_meta(EditLine *el, Int c __attribute__((__unused__)))
281{ 281{
282 282
283 /* 283 /*
284 * Delete with insert == change: first we delete and then we leave in 284 * Delete with insert == change: first we delete and then we leave in
285 * insert mode. 285 * insert mode.
286 */ 286 */
287 return cv_action(el, DELETE | INSERT); 287 return cv_action(el, DELETE | INSERT);
288} 288}
289 289
290 290
291/* vi_insert_at_bol(): 291/* vi_insert_at_bol():
292 * Vi enter insert mode at the beginning of line 292 * Vi enter insert mode at the beginning of line
293 * [I] 293 * [I]
294 */ 294 */
295protected el_action_t 295protected el_action_t
296/*ARGSUSED*/ 296/*ARGSUSED*/
297vi_insert_at_bol(EditLine *el, Int c __attribute__((__unused__))) 297vi_insert_at_bol(EditLine *el, Int c __attribute__((__unused__)))
298{ 298{
299 299
300 el->el_line.cursor = el->el_line.buffer; 300 el->el_line.cursor = el->el_line.buffer;
301 cv_undo(el); 301 cv_undo(el);
302 el->el_map.current = el->el_map.key; 302 el->el_map.current = el->el_map.key;
303 return CC_CURSOR; 303 return CC_CURSOR;
304} 304}
305 305
306 306
307/* vi_replace_char(): 307/* vi_replace_char():
308 * Vi replace character under the cursor with the next character typed 308 * Vi replace character under the cursor with the next character typed
309 * [r] 309 * [r]
310 */ 310 */
311protected el_action_t 311protected el_action_t
312/*ARGSUSED*/ 312/*ARGSUSED*/
313vi_replace_char(EditLine *el, Int c __attribute__((__unused__))) 313vi_replace_char(EditLine *el, Int c __attribute__((__unused__)))
314{ 314{
315 315
316 if (el->el_line.cursor >= el->el_line.lastchar) 316 if (el->el_line.cursor >= el->el_line.lastchar)
317 return CC_ERROR; 317 return CC_ERROR;
318 318
319 el->el_map.current = el->el_map.key; 319 el->el_map.current = el->el_map.key;
320 el->el_state.inputmode = MODE_REPLACE_1; 320 el->el_state.inputmode = MODE_REPLACE_1;
321 cv_undo(el); 321 cv_undo(el);
322 return CC_ARGHACK; 322 return CC_ARGHACK;
323} 323}
324 324
325 325
326/* vi_replace_mode(): 326/* vi_replace_mode():
327 * Vi enter replace mode 327 * Vi enter replace mode
328 * [R] 328 * [R]
329 */ 329 */
330protected el_action_t 330protected el_action_t
331/*ARGSUSED*/ 331/*ARGSUSED*/
332vi_replace_mode(EditLine *el, Int c __attribute__((__unused__))) 332vi_replace_mode(EditLine *el, Int c __attribute__((__unused__)))
333{ 333{
334 334
335 el->el_map.current = el->el_map.key; 335 el->el_map.current = el->el_map.key;
336 el->el_state.inputmode = MODE_REPLACE; 336 el->el_state.inputmode = MODE_REPLACE;
337 cv_undo(el); 337 cv_undo(el);
338 return CC_NORM; 338 return CC_NORM;
339} 339}
340 340
341 341
342/* vi_substitute_char(): 342/* vi_substitute_char():
343 * Vi replace character under the cursor and enter insert mode 343 * Vi replace character under the cursor and enter insert mode
344 * [s] 344 * [s]
345 */ 345 */
346protected el_action_t 346protected el_action_t
347/*ARGSUSED*/ 347/*ARGSUSED*/
348vi_substitute_char(EditLine *el, Int c __attribute__((__unused__))) 348vi_substitute_char(EditLine *el, Int c __attribute__((__unused__)))
349{ 349{
350 350
351 c_delafter(el, el->el_state.argument); 351 c_delafter(el, el->el_state.argument);
352 el->el_map.current = el->el_map.key; 352 el->el_map.current = el->el_map.key;
353 return CC_REFRESH; 353 return CC_REFRESH;
354} 354}
355 355
356 356
357/* vi_substitute_line(): 357/* vi_substitute_line():
358 * Vi substitute entire line 358 * Vi substitute entire line
359 * [S] 359 * [S]
360 */ 360 */
361protected el_action_t 361protected el_action_t
362/*ARGSUSED*/ 362/*ARGSUSED*/
363vi_substitute_line(EditLine *el, Int c __attribute__((__unused__))) 363vi_substitute_line(EditLine *el, Int c __attribute__((__unused__)))
364{ 364{
365 365
366 cv_undo(el); 366 cv_undo(el);
367 cv_yank(el, el->el_line.buffer, 367 cv_yank(el, el->el_line.buffer,
368 (int)(el->el_line.lastchar - el->el_line.buffer)); 368 (int)(el->el_line.lastchar - el->el_line.buffer));
369 (void) em_kill_line(el, 0); 369 (void) em_kill_line(el, 0);
370 el->el_map.current = el->el_map.key; 370 el->el_map.current = el->el_map.key;
371 return CC_REFRESH; 371 return CC_REFRESH;
372} 372}
373 373
374 374
375/* vi_change_to_eol(): 375/* vi_change_to_eol():
376 * Vi change to end of line 376 * Vi change to end of line
377 * [C] 377 * [C]
378 */ 378 */
379protected el_action_t 379protected el_action_t
380/*ARGSUSED*/ 380/*ARGSUSED*/
381vi_change_to_eol(EditLine *el, Int c __attribute__((__unused__))) 381vi_change_to_eol(EditLine *el, Int c __attribute__((__unused__)))
382{ 382{
383 383
384 cv_undo(el); 384 cv_undo(el);
385 cv_yank(el, el->el_line.cursor, 385 cv_yank(el, el->el_line.cursor,
386 (int)(el->el_line.lastchar - el->el_line.cursor)); 386 (int)(el->el_line.lastchar - el->el_line.cursor));
387 (void) ed_kill_line(el, 0); 387 (void) ed_kill_line(el, 0);
388 el->el_map.current = el->el_map.key; 388 el->el_map.current = el->el_map.key;
389 return CC_REFRESH; 389 return CC_REFRESH;
390} 390}
391 391
392 392
393/* vi_insert(): 393/* vi_insert():
394 * Vi enter insert mode 394 * Vi enter insert mode
395 * [i] 395 * [i]
396 */ 396 */
397protected el_action_t 397protected el_action_t
398/*ARGSUSED*/ 398/*ARGSUSED*/
399vi_insert(EditLine *el, Int c __attribute__((__unused__))) 399vi_insert(EditLine *el, Int c __attribute__((__unused__)))
400{ 400{
401 401
402 el->el_map.current = el->el_map.key; 402 el->el_map.current = el->el_map.key;
403 cv_undo(el); 403 cv_undo(el);
404 return CC_NORM; 404 return CC_NORM;
405} 405}
406 406
407 407
408/* vi_add(): 408/* vi_add():
409 * Vi enter insert mode after the cursor 409 * Vi enter insert mode after the cursor
410 * [a] 410 * [a]
411 */ 411 */
412protected el_action_t 412protected el_action_t
413/*ARGSUSED*/ 413/*ARGSUSED*/
414vi_add(EditLine *el, Int c __attribute__((__unused__))) 414vi_add(EditLine *el, Int c __attribute__((__unused__)))
415{ 415{
416 int ret; 416 int ret;
417 417
418 el->el_map.current = el->el_map.key; 418 el->el_map.current = el->el_map.key;
419 if (el->el_line.cursor < el->el_line.lastchar) { 419 if (el->el_line.cursor < el->el_line.lastchar) {
420 el->el_line.cursor++; 420 el->el_line.cursor++;
421 if (el->el_line.cursor > el->el_line.lastchar) 421 if (el->el_line.cursor > el->el_line.lastchar)
422 el->el_line.cursor = el->el_line.lastchar; 422 el->el_line.cursor = el->el_line.lastchar;
423 ret = CC_CURSOR; 423 ret = CC_CURSOR;
424 } else 424 } else
425 ret = CC_NORM; 425 ret = CC_NORM;
426 426
427 cv_undo(el); 427 cv_undo(el);
428 428
429 return ret; 429 return ret;
430} 430}
431 431
432 432
433/* vi_add_at_eol(): 433/* vi_add_at_eol():
434 * Vi enter insert mode at end of line 434 * Vi enter insert mode at end of line
435 * [A] 435 * [A]
436 */ 436 */
437protected el_action_t 437protected el_action_t
438/*ARGSUSED*/ 438/*ARGSUSED*/
439vi_add_at_eol(EditLine *el, Int c __attribute__((__unused__))) 439vi_add_at_eol(EditLine *el, Int c __attribute__((__unused__)))
440{ 440{
441 441
442 el->el_map.current = el->el_map.key; 442 el->el_map.current = el->el_map.key;
443 el->el_line.cursor = el->el_line.lastchar; 443 el->el_line.cursor = el->el_line.lastchar;
444 cv_undo(el); 444 cv_undo(el);
445 return CC_CURSOR; 445 return CC_CURSOR;
446} 446}
447 447
448 448
449/* vi_delete_meta(): 449/* vi_delete_meta():
450 * Vi delete prefix command 450 * Vi delete prefix command
451 * [d] 451 * [d]
452 */ 452 */
453protected el_action_t 453protected el_action_t
454/*ARGSUSED*/ 454/*ARGSUSED*/
455vi_delete_meta(EditLine *el, Int c __attribute__((__unused__))) 455vi_delete_meta(EditLine *el, Int c __attribute__((__unused__)))
456{ 456{
457 457
458 return cv_action(el, DELETE); 458 return cv_action(el, DELETE);
459} 459}
460 460
461 461
462/* vi_end_big_word(): 462/* vi_end_big_word():
463 * Vi move to the end of the current space delimited word 463 * Vi move to the end of the current space delimited word
464 * [E] 464 * [E]
465 */ 465 */
466protected el_action_t 466protected el_action_t
467/*ARGSUSED*/ 467/*ARGSUSED*/
468vi_end_big_word(EditLine *el, Int c) 468vi_end_big_word(EditLine *el, Int c __attribute__((__unused__)))
469{ 469{
470 470
471 if (el->el_line.cursor == el->el_line.lastchar) 471 if (el->el_line.cursor == el->el_line.lastchar)
472 return CC_ERROR; 472 return CC_ERROR;
473 473
474 el->el_line.cursor = cv__endword(el->el_line.cursor, 474 el->el_line.cursor = cv__endword(el->el_line.cursor,
475 el->el_line.lastchar, el->el_state.argument, cv__isWord); 475 el->el_line.lastchar, el->el_state.argument, cv__isWord);
476 476
477 if (el->el_chared.c_vcmd.action != NOP) { 477 if (el->el_chared.c_vcmd.action != NOP) {
478 el->el_line.cursor++; 478 el->el_line.cursor++;
479 cv_delfini(el); 479 cv_delfini(el);
480 return CC_REFRESH; 480 return CC_REFRESH;
481 } 481 }
482 return CC_CURSOR; 482 return CC_CURSOR;
483} 483}
484 484
485 485
486/* vi_end_word(): 486/* vi_end_word():
487 * Vi move to the end of the current word 487 * Vi move to the end of the current word
488 * [e] 488 * [e]
489 */ 489 */
490protected el_action_t 490protected el_action_t
491/*ARGSUSED*/ 491/*ARGSUSED*/
492vi_end_word(EditLine *el, Int c __attribute__((__unused__))) 492vi_end_word(EditLine *el, Int c __attribute__((__unused__)))
493{ 493{
494 494
495 if (el->el_line.cursor == el->el_line.lastchar) 495 if (el->el_line.cursor == el->el_line.lastchar)
496 return CC_ERROR; 496 return CC_ERROR;
497 497
498 el->el_line.cursor = cv__endword(el->el_line.cursor, 498 el->el_line.cursor = cv__endword(el->el_line.cursor,
499 el->el_line.lastchar, el->el_state.argument, cv__isword); 499 el->el_line.lastchar, el->el_state.argument, cv__isword);
500 500
501 if (el->el_chared.c_vcmd.action != NOP) { 501 if (el->el_chared.c_vcmd.action != NOP) {
502 el->el_line.cursor++; 502 el->el_line.cursor++;
503 cv_delfini(el); 503 cv_delfini(el);
504 return CC_REFRESH; 504 return CC_REFRESH;
505 } 505 }
506 return CC_CURSOR; 506 return CC_CURSOR;
507} 507}
508 508
509 509
510/* vi_undo(): 510/* vi_undo():
511 * Vi undo last change 511 * Vi undo last change
512 * [u] 512 * [u]
513 */ 513 */
514protected el_action_t 514protected el_action_t
515/*ARGSUSED*/ 515/*ARGSUSED*/
516vi_undo(EditLine *el, Int c __attribute__((__unused__))) 516vi_undo(EditLine *el, Int c __attribute__((__unused__)))
517{ 517{
518 c_undo_t un = el->el_chared.c_undo; 518 c_undo_t un = el->el_chared.c_undo;
519 519
520 if (un.len == -1) 520 if (un.len == -1)
521 return CC_ERROR; 521 return CC_ERROR;
522 522
523 /* switch line buffer and undo buffer */ 523 /* switch line buffer and undo buffer */
524 el->el_chared.c_undo.buf = el->el_line.buffer; 524 el->el_chared.c_undo.buf = el->el_line.buffer;
525 el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer; 525 el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
526 el->el_chared.c_undo.cursor = 526 el->el_chared.c_undo.cursor =
527 (int)(el->el_line.cursor - el->el_line.buffer); 527 (int)(el->el_line.cursor - el->el_line.buffer);
528 el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer); 528 el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
529 el->el_line.buffer = un.buf; 529 el->el_line.buffer = un.buf;
530 el->el_line.cursor = un.buf + un.cursor; 530 el->el_line.cursor = un.buf + un.cursor;
531 el->el_line.lastchar = un.buf + un.len; 531 el->el_line.lastchar = un.buf + un.len;
532 532
533 return CC_REFRESH; 533 return CC_REFRESH;
534} 534}
535 535
536 536
537/* vi_command_mode(): 537/* vi_command_mode():
538 * Vi enter command mode (use alternative key bindings) 538 * Vi enter command mode (use alternative key bindings)
539 * [<ESC>] 539 * [<ESC>]
540 */ 540 */
541protected el_action_t 541protected el_action_t
542/*ARGSUSED*/ 542/*ARGSUSED*/
543vi_command_mode(EditLine *el, Int c __attribute__((__unused__))) 543vi_command_mode(EditLine *el, Int c __attribute__((__unused__)))
544{ 544{
545 545
546 /* [Esc] cancels pending action */ 546 /* [Esc] cancels pending action */
547 el->el_chared.c_vcmd.action = NOP; 547 el->el_chared.c_vcmd.action = NOP;
548 el->el_chared.c_vcmd.pos = 0; 548 el->el_chared.c_vcmd.pos = 0;
549 549
550 el->el_state.doingarg = 0; 550 el->el_state.doingarg = 0;
551 551
552 el->el_state.inputmode = MODE_INSERT; 552 el->el_state.inputmode = MODE_INSERT;
553 el->el_map.current = el->el_map.alt; 553 el->el_map.current = el->el_map.alt;
554#ifdef VI_MOVE 554#ifdef VI_MOVE
555 if (el->el_line.cursor > el->el_line.buffer) 555 if (el->el_line.cursor > el->el_line.buffer)
556 el->el_line.cursor--; 556 el->el_line.cursor--;
557#endif 557#endif
558 return CC_CURSOR; 558 return CC_CURSOR;
559} 559}
560 560
561 561
562/* vi_zero(): 562/* vi_zero():
563 * Vi move to the beginning of line 563 * Vi move to the beginning of line
564 * [0] 564 * [0]
565 */ 565 */
566protected el_action_t 566protected el_action_t
567vi_zero(EditLine *el, Int c) 567vi_zero(EditLine *el, Int c)
568{ 568{
569 569
570 if (el->el_state.doingarg) 570 if (el->el_state.doingarg)
571 return ed_argument_digit(el, c); 571 return ed_argument_digit(el, c);
572 572
573 el->el_line.cursor = el->el_line.buffer; 573 el->el_line.cursor = el->el_line.buffer;
574 if (el->el_chared.c_vcmd.action != NOP) { 574 if (el->el_chared.c_vcmd.action != NOP) {
575 cv_delfini(el); 575 cv_delfini(el);
576 return CC_REFRESH; 576 return CC_REFRESH;
577 } 577 }
578 return CC_CURSOR; 578 return CC_CURSOR;
579} 579}
580 580
581 581
582/* vi_delete_prev_char(): 582/* vi_delete_prev_char():
583 * Vi move to previous character (backspace) 583 * Vi move to previous character (backspace)
584 * [^H] in insert mode only 584 * [^H] in insert mode only
585 */ 585 */
586protected el_action_t 586protected el_action_t
587/*ARGSUSED*/ 587/*ARGSUSED*/
588vi_delete_prev_char(EditLine *el, Int c __attribute__((__unused__))) 588vi_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
589{ 589{
590 590
591 if (el->el_line.cursor <= el->el_line.buffer) 591 if (el->el_line.cursor <= el->el_line.buffer)
592 return CC_ERROR; 592 return CC_ERROR;
593 593
594 c_delbefore1(el); 594 c_delbefore1(el);
595 el->el_line.cursor--; 595 el->el_line.cursor--;
596 return CC_REFRESH; 596 return CC_REFRESH;
597} 597}
598 598
599 599
600/* vi_list_or_eof(): 600/* vi_list_or_eof():
601 * Vi list choices for completion or indicate end of file if empty line 601 * Vi list choices for completion or indicate end of file if empty line
602 * [^D] 602 * [^D]
603 */ 603 */
604protected el_action_t 604protected el_action_t
605/*ARGSUSED*/ 605/*ARGSUSED*/
606vi_list_or_eof(EditLine *el, Int c) 606vi_list_or_eof(EditLine *el, Int c)
607{ 607{
608 608
609 if (el->el_line.cursor == el->el_line.lastchar) { 609 if (el->el_line.cursor == el->el_line.lastchar) {
610 if (el->el_line.cursor == el->el_line.buffer) { 610 if (el->el_line.cursor == el->el_line.buffer) {
611 terminal_writec(el, c); /* then do a EOF */ 611 terminal_writec(el, c); /* then do a EOF */
612 return CC_EOF; 612 return CC_EOF;
613 } else { 613 } else {
614 /* 614 /*
615 * Here we could list completions, but it is an 615 * Here we could list completions, but it is an
616 * error right now 616 * error right now
617 */ 617 */
618 terminal_beep(el); 618 terminal_beep(el);
619 return CC_ERROR; 619 return CC_ERROR;
620 } 620 }
621 } else { 621 } else {
622#ifdef notyet 622#ifdef notyet
623 re_goto_bottom(el); 623 re_goto_bottom(el);
624 *el->el_line.lastchar = '\0'; /* just in case */ 624 *el->el_line.lastchar = '\0'; /* just in case */
625 return CC_LIST_CHOICES; 625 return CC_LIST_CHOICES;
626#else 626#else
627 /* 627 /*
628 * Just complain for now. 628 * Just complain for now.
629 */ 629 */
630 terminal_beep(el); 630 terminal_beep(el);
631 return CC_ERROR; 631 return CC_ERROR;
632#endif 632#endif
633 } 633 }
634} 634}
635 635
636 636
637/* vi_kill_line_prev(): 637/* vi_kill_line_prev():
638 * Vi cut from beginning of line to cursor 638 * Vi cut from beginning of line to cursor
639 * [^U] 639 * [^U]
640 */ 640 */
641protected el_action_t 641protected el_action_t
642/*ARGSUSED*/ 642/*ARGSUSED*/
643vi_kill_line_prev(EditLine *el, Int c __attribute__((__unused__))) 643vi_kill_line_prev(EditLine *el, Int c __attribute__((__unused__)))
644{ 644{
645 Char *kp, *cp; 645 Char *kp, *cp;
646 646
647 cp = el->el_line.buffer; 647 cp = el->el_line.buffer;
648 kp = el->el_chared.c_kill.buf; 648 kp = el->el_chared.c_kill.buf;
649 while (cp < el->el_line.cursor) 649 while (cp < el->el_line.cursor)
650 *kp++ = *cp++; /* copy it */ 650 *kp++ = *cp++; /* copy it */
651 el->el_chared.c_kill.last = kp; 651 el->el_chared.c_kill.last = kp;
652 c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer)); 652 c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer));
653 el->el_line.cursor = el->el_line.buffer; /* zap! */ 653 el->el_line.cursor = el->el_line.buffer; /* zap! */
654 return CC_REFRESH; 654 return CC_REFRESH;
655} 655}
656 656
657 657
658/* vi_search_prev(): 658/* vi_search_prev():
659 * Vi search history previous 659 * Vi search history previous
660 * [?] 660 * [?]
661 */ 661 */
662protected el_action_t 662protected el_action_t
663/*ARGSUSED*/ 663/*ARGSUSED*/
664vi_search_prev(EditLine *el, Int c __attribute__((__unused__))) 664vi_search_prev(EditLine *el, Int c __attribute__((__unused__)))
665{ 665{
666 666
667 return cv_search(el, ED_SEARCH_PREV_HISTORY); 667 return cv_search(el, ED_SEARCH_PREV_HISTORY);
668} 668}
669 669
670 670
671/* vi_search_next(): 671/* vi_search_next():
672 * Vi search history next 672 * Vi search history next
673 * [/] 673 * [/]
674 */ 674 */
675protected el_action_t 675protected el_action_t
676/*ARGSUSED*/ 676/*ARGSUSED*/
677vi_search_next(EditLine *el, Int c __attribute__((__unused__))) 677vi_search_next(EditLine *el, Int c __attribute__((__unused__)))
678{ 678{
679 679
680 return cv_search(el, ED_SEARCH_NEXT_HISTORY); 680 return cv_search(el, ED_SEARCH_NEXT_HISTORY);
681} 681}
682 682
683 683
684/* vi_repeat_search_next(): 684/* vi_repeat_search_next():
685 * Vi repeat current search in the same search direction 685 * Vi repeat current search in the same search direction
686 * [n] 686 * [n]
687 */ 687 */
688protected el_action_t 688protected el_action_t
689/*ARGSUSED*/ 689/*ARGSUSED*/
690vi_repeat_search_next(EditLine *el, Int c __attribute__((__unused__))) 690vi_repeat_search_next(EditLine *el, Int c __attribute__((__unused__)))
691{ 691{
692 692
693 if (el->el_search.patlen == 0) 693 if (el->el_search.patlen == 0)
694 return CC_ERROR; 694 return CC_ERROR;
695 else 695 else
696 return cv_repeat_srch(el, el->el_search.patdir); 696 return cv_repeat_srch(el, el->el_search.patdir);
697} 697}
698 698
699 699
700/* vi_repeat_search_prev(): 700/* vi_repeat_search_prev():
701 * Vi repeat current search in the opposite search direction 701 * Vi repeat current search in the opposite search direction
702 * [N] 702 * [N]
703 */ 703 */
704/*ARGSUSED*/ 704/*ARGSUSED*/
705protected el_action_t 705protected el_action_t
706vi_repeat_search_prev(EditLine *el, Int c __attribute__((__unused__))) 706vi_repeat_search_prev(EditLine *el, Int c __attribute__((__unused__)))
707{ 707{
708 708
709 if (el->el_search.patlen == 0) 709 if (el->el_search.patlen == 0)
710 return CC_ERROR; 710 return CC_ERROR;
711 else 711 else
712 return (cv_repeat_srch(el, 712 return (cv_repeat_srch(el,
713 el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? 713 el->el_search.patdir == ED_SEARCH_PREV_HISTORY ?
714 ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY)); 714 ED_SEARCH_NEXT_HISTORY : ED_SEARCH_PREV_HISTORY));
715} 715}
716 716
717 717
718/* vi_next_char(): 718/* vi_next_char():
719 * Vi move to the character specified next 719 * Vi move to the character specified next
720 * [f] 720 * [f]
721 */ 721 */
722protected el_action_t 722protected el_action_t
723/*ARGSUSED*/ 723/*ARGSUSED*/
724vi_next_char(EditLine *el, Int c __attribute__((__unused__))) 724vi_next_char(EditLine *el, Int c __attribute__((__unused__)))
725{ 725{
726 return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); 726 return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);
727} 727}
728 728
729 729
730/* vi_prev_char(): 730/* vi_prev_char():
731 * Vi move to the character specified previous 731 * Vi move to the character specified previous
732 * [F] 732 * [F]
733 */ 733 */
734protected el_action_t 734protected el_action_t
735/*ARGSUSED*/ 735/*ARGSUSED*/
736vi_prev_char(EditLine *el, Int c __attribute__((__unused__))) 736vi_prev_char(EditLine *el, Int c __attribute__((__unused__)))
737{ 737{
738 return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); 738 return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);
739} 739}
740 740
741 741
742/* vi_to_next_char(): 742/* vi_to_next_char():
743 * Vi move up to the character specified next 743 * Vi move up to the character specified next
744 * [t] 744 * [t]
745 */ 745 */
746protected el_action_t 746protected el_action_t
747/*ARGSUSED*/ 747/*ARGSUSED*/
748vi_to_next_char(EditLine *el, Int c __attribute__((__unused__))) 748vi_to_next_char(EditLine *el, Int c __attribute__((__unused__)))
749{ 749{
750 return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); 750 return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);
751} 751}
752 752
753 753
754/* vi_to_prev_char(): 754/* vi_to_prev_char():
755 * Vi move up to the character specified previous 755 * Vi move up to the character specified previous
756 * [T] 756 * [T]
757 */ 757 */
758protected el_action_t 758protected el_action_t
759/*ARGSUSED*/ 759/*ARGSUSED*/
760vi_to_prev_char(EditLine *el, Int c __attribute__((__unused__))) 760vi_to_prev_char(EditLine *el, Int c __attribute__((__unused__)))
761{ 761{
762 return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); 762 return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);
763} 763}
764 764
765 765
766/* vi_repeat_next_char(): 766/* vi_repeat_next_char():
767 * Vi repeat current character search in the same search direction 767 * Vi repeat current character search in the same search direction
768 * [;] 768 * [;]
769 */ 769 */
770protected el_action_t 770protected el_action_t
771/*ARGSUSED*/ 771/*ARGSUSED*/
772vi_repeat_next_char(EditLine *el, Int c __attribute__((__unused__))) 772vi_repeat_next_char(EditLine *el, Int c __attribute__((__unused__)))
773{ 773{
774 774
775 return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, 775 return cv_csearch(el, el->el_search.chadir, el->el_search.chacha,
776 el->el_state.argument, el->el_search.chatflg); 776 el->el_state.argument, el->el_search.chatflg);
777} 777}
778 778
779 779
780/* vi_repeat_prev_char(): 780/* vi_repeat_prev_char():
781 * Vi repeat current character search in the opposite search direction 781 * Vi repeat current character search in the opposite search direction
782 * [,] 782 * [,]
783 */ 783 */
784protected el_action_t 784protected el_action_t
785/*ARGSUSED*/ 785/*ARGSUSED*/
786vi_repeat_prev_char(EditLine *el, Int c __attribute__((__unused__))) 786vi_repeat_prev_char(EditLine *el, Int c __attribute__((__unused__)))
787{ 787{
788 el_action_t r; 788 el_action_t r;
789 int dir = el->el_search.chadir; 789 int dir = el->el_search.chadir;
790 790
791 r = cv_csearch(el, -dir, el->el_search.chacha, 791 r = cv_csearch(el, -dir, el->el_search.chacha,
792 el->el_state.argument, el->el_search.chatflg); 792 el->el_state.argument, el->el_search.chatflg);
793 el->el_search.chadir = dir; 793 el->el_search.chadir = dir;
794 return r; 794 return r;
795} 795}
796 796
797 797
798/* vi_match(): 798/* vi_match():
799 * Vi go to matching () {} or [] 799 * Vi go to matching () {} or []
800 * [%] 800 * [%]
801 */ 801 */
802protected el_action_t 802protected el_action_t
803/*ARGSUSED*/ 803/*ARGSUSED*/
804vi_match(EditLine *el, Int c) 804vi_match(EditLine *el, Int c __attribute__((__unused__)))
805{ 805{
806 const Char match_chars[] = STR("()[]{}"); 806 const Char match_chars[] = STR("()[]{}");
807 Char *cp; 807 Char *cp;
808 size_t delta, i, count; 808 size_t delta, i, count;
809 Char o_ch, c_ch; 809 Char o_ch, c_ch;
810 810
811 *el->el_line.lastchar = '\0'; /* just in case */ 811 *el->el_line.lastchar = '\0'; /* just in case */
812 812
813 i = Strcspn(el->el_line.cursor, match_chars); 813 i = Strcspn(el->el_line.cursor, match_chars);
814 o_ch = el->el_line.cursor[i]; 814 o_ch = el->el_line.cursor[i];
815 if (o_ch == 0) 815 if (o_ch == 0)
816 return CC_ERROR; 816 return CC_ERROR;
817 delta = Strchr(match_chars, o_ch) - match_chars; 817 delta = Strchr(match_chars, o_ch) - match_chars;
818 c_ch = match_chars[delta ^ 1]; 818 c_ch = match_chars[delta ^ 1];
819 count = 1; 819 count = 1;
820 delta = 1 - (delta & 1) * 2; 820 delta = 1 - (delta & 1) * 2;
821 821
822 for (cp = &el->el_line.cursor[i]; count; ) { 822 for (cp = &el->el_line.cursor[i]; count; ) {
823 cp += delta; 823 cp += delta;
824 if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) 824 if (cp < el->el_line.buffer || cp >= el->el_line.lastchar)
825 return CC_ERROR; 825 return CC_ERROR;
826 if (*cp == o_ch) 826 if (*cp == o_ch)
827 count++; 827 count++;
828 else if (*cp == c_ch) 828 else if (*cp == c_ch)
829 count--; 829 count--;
830 } 830 }
831 831
832 el->el_line.cursor = cp; 832 el->el_line.cursor = cp;
833 833
834 if (el->el_chared.c_vcmd.action != NOP) { 834 if (el->el_chared.c_vcmd.action != NOP) {
835 /* NB posix says char under cursor should NOT be deleted 835 /* NB posix says char under cursor should NOT be deleted
836 for -ve delta - this is different to netbsd vi. */ 836 for -ve delta - this is different to netbsd vi. */
837 if (delta > 0) 837 if (delta > 0)
838 el->el_line.cursor++; 838 el->el_line.cursor++;
839 cv_delfini(el); 839 cv_delfini(el);
840 return CC_REFRESH; 840 return CC_REFRESH;
841 } 841 }
842 return CC_CURSOR; 842 return CC_CURSOR;
843} 843}
844 844
845/* vi_undo_line(): 845/* vi_undo_line():
846 * Vi undo all changes to line 846 * Vi undo all changes to line
847 * [U] 847 * [U]
848 */ 848 */
849protected el_action_t 849protected el_action_t
850/*ARGSUSED*/ 850/*ARGSUSED*/
851vi_undo_line(EditLine *el, Int c) 851vi_undo_line(EditLine *el, Int c __attribute__((__unused__)))
852{ 852{
853 853
854 cv_undo(el); 854 cv_undo(el);
855 return hist_get(el); 855 return hist_get(el);
856} 856}
857 857
858/* vi_to_column(): 858/* vi_to_column():
859 * Vi go to specified column 859 * Vi go to specified column
860 * [|] 860 * [|]
861 * NB netbsd vi goes to screen column 'n', posix says nth character 861 * NB netbsd vi goes to screen column 'n', posix says nth character
862 */ 862 */
863protected el_action_t 863protected el_action_t
864/*ARGSUSED*/ 864/*ARGSUSED*/
865vi_to_column(EditLine *el, Int c) 865vi_to_column(EditLine *el, Int c __attribute__((__unused__)))
866{ 866{
867 867
868 el->el_line.cursor = el->el_line.buffer; 868 el->el_line.cursor = el->el_line.buffer;
869 el->el_state.argument--; 869 el->el_state.argument--;
870 return ed_next_char(el, 0); 870 return ed_next_char(el, 0);
871} 871}
872 872
873/* vi_yank_end(): 873/* vi_yank_end():
874 * Vi yank to end of line 874 * Vi yank to end of line
875 * [Y] 875 * [Y]
876 */ 876 */
877protected el_action_t 877protected el_action_t
878/*ARGSUSED*/ 878/*ARGSUSED*/
879vi_yank_end(EditLine *el, Int c) 879vi_yank_end(EditLine *el, Int c __attribute__((__unused__)))
880{ 880{
881 881
882 cv_yank(el, el->el_line.cursor, 882 cv_yank(el, el->el_line.cursor,
883 (int)(el->el_line.lastchar - el->el_line.cursor)); 883 (int)(el->el_line.lastchar - el->el_line.cursor));
884 return CC_REFRESH; 884 return CC_REFRESH;
885} 885}
886 886
887/* vi_yank(): 887/* vi_yank():
888 * Vi yank 888 * Vi yank
889 * [y] 889 * [y]
890 */ 890 */
891protected el_action_t 891protected el_action_t
892/*ARGSUSED*/ 892/*ARGSUSED*/
893vi_yank(EditLine *el, Int c) 893vi_yank(EditLine *el, Int c __attribute__((__unused__)))
894{ 894{
895 895
896 return cv_action(el, YANK); 896 return cv_action(el, YANK);
897} 897}
898 898
899/* vi_comment_out(): 899/* vi_comment_out():
900 * Vi comment out current command 900 * Vi comment out current command
901 * [#] 901 * [#]
902 */ 902 */
903protected el_action_t 903protected el_action_t
904/*ARGSUSED*/ 904/*ARGSUSED*/
905vi_comment_out(EditLine *el, Int c) 905vi_comment_out(EditLine *el, Int c __attribute__((__unused__)))
906{ 906{
907 907
908 el->el_line.cursor = el->el_line.buffer; 908 el->el_line.cursor = el->el_line.buffer;
909 c_insert(el, 1); 909 c_insert(el, 1);
910 *el->el_line.cursor = '#'; 910 *el->el_line.cursor = '#';
911 re_refresh(el); 911 re_refresh(el);
912 return ed_newline(el, 0); 912 return ed_newline(el, 0);
913} 913}
914 914
915/* vi_alias(): 915/* vi_alias():
916 * Vi include shell alias 916 * Vi include shell alias
917 * [@] 917 * [@]
918 * NB: posix implies that we should enter insert mode, however 918 * NB: posix implies that we should enter insert mode, however
919 * this is against historical precedent... 919 * this is against historical precedent...
920 */ 920 */
921#ifdef __weak_reference 921#ifdef __weak_reference
922__weakref_visible char *my_get_alias_text(const char *) 922__weakref_visible char *my_get_alias_text(const char *)
923 __weak_reference(get_alias_text); 923 __weak_reference(get_alias_text);
924#endif 924#endif
925protected el_action_t 925protected el_action_t
926/*ARGSUSED*/ 926/*ARGSUSED*/
927vi_alias(EditLine *el, Int c) 927vi_alias(EditLine *el, Int c __attribute__((__unused__)))
928{ 928{
929#ifdef __weak_reference 929#ifdef __weak_reference
930 char alias_name[3]; 930 char alias_name[3];
931 char *alias_text; 931 char *alias_text;
932 932
933 if (my_get_alias_text == 0) { 933 if (my_get_alias_text == 0) {
934 return CC_ERROR; 934 return CC_ERROR;
935 } 935 }
936 936
937 alias_name[0] = '_'; 937 alias_name[0] = '_';
938 alias_name[2] = 0; 938 alias_name[2] = 0;
939 if (el_getc(el, &alias_name[1]) != 1) 939 if (el_getc(el, &alias_name[1]) != 1)
940 return CC_ERROR; 940 return CC_ERROR;
941 941
942 alias_text = my_get_alias_text(alias_name); 942 alias_text = my_get_alias_text(alias_name);
943 if (alias_text != NULL) 943 if (alias_text != NULL)
944 FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch)); 944 FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch));
945 return CC_NORM; 945 return CC_NORM;
946#else 946#else
947 return CC_ERROR; 947 return CC_ERROR;
948#endif 948#endif
949} 949}
950 950
951/* vi_to_history_line(): 951/* vi_to_history_line():
952 * Vi go to specified history file line. 952 * Vi go to specified history file line.
953 * [G] 953 * [G]
954 */ 954 */
955protected el_action_t 955protected el_action_t
956/*ARGSUSED*/ 956/*ARGSUSED*/
957vi_to_history_line(EditLine *el, Int c) 957vi_to_history_line(EditLine *el, Int c __attribute__((__unused__)))
958{ 958{
959 int sv_event_no = el->el_history.eventno; 959 int sv_event_no = el->el_history.eventno;
960 el_action_t rval; 960 el_action_t rval;
961 961
962 962
963 if (el->el_history.eventno == 0) { 963 if (el->el_history.eventno == 0) {
964 (void) Strncpy(el->el_history.buf, el->el_line.buffer, 964 (void) Strncpy(el->el_history.buf, el->el_line.buffer,
965 EL_BUFSIZ); 965 EL_BUFSIZ);
966 el->el_history.last = el->el_history.buf + 966 el->el_history.last = el->el_history.buf +
967 (el->el_line.lastchar - el->el_line.buffer); 967 (el->el_line.lastchar - el->el_line.buffer);
968 } 968 }
969 969
970 /* Lack of a 'count' means oldest, not 1 */ 970 /* Lack of a 'count' means oldest, not 1 */
971 if (!el->el_state.doingarg) { 971 if (!el->el_state.doingarg) {
972 el->el_history.eventno = 0x7fffffff; 972 el->el_history.eventno = 0x7fffffff;
973 hist_get(el); 973 hist_get(el);
974 } else { 974 } else {
975 /* This is brain dead, all the rest of this code counts 975 /* This is brain dead, all the rest of this code counts
976 * upwards going into the past. Here we need count in the 976 * upwards going into the past. Here we need count in the
977 * other direction (to match the output of fc -l). 977 * other direction (to match the output of fc -l).
978 * I could change the world, but this seems to suffice. 978 * I could change the world, but this seems to suffice.
979 */ 979 */
980 el->el_history.eventno = 1; 980 el->el_history.eventno = 1;
981 if (hist_get(el) == CC_ERROR) 981 if (hist_get(el) == CC_ERROR)
982 return CC_ERROR; 982 return CC_ERROR;
983 el->el_history.eventno = 1 + el->el_history.ev.num  983 el->el_history.eventno = 1 + el->el_history.ev.num
984 - el->el_state.argument; 984 - el->el_state.argument;
985 if (el->el_history.eventno < 0) { 985 if (el->el_history.eventno < 0) {
986 el->el_history.eventno = sv_event_no; 986 el->el_history.eventno = sv_event_no;
987 return CC_ERROR; 987 return CC_ERROR;
988 } 988 }
989 } 989 }
990 rval = hist_get(el); 990 rval = hist_get(el);
991 if (rval == CC_ERROR) 991 if (rval == CC_ERROR)
992 el->el_history.eventno = sv_event_no; 992 el->el_history.eventno = sv_event_no;
993 return rval; 993 return rval;
994} 994}
995 995
996/* vi_histedit(): 996/* vi_histedit():
997 * Vi edit history line with vi 997 * Vi edit history line with vi
998 * [v] 998 * [v]
999 */ 999 */
1000protected el_action_t 1000protected el_action_t
1001/*ARGSUSED*/ 1001/*ARGSUSED*/
1002vi_histedit(EditLine *el, Int c) 1002vi_histedit(EditLine *el, Int c __attribute__((__unused__)))
1003{ 1003{
1004 int fd; 1004 int fd;
1005 pid_t pid; 1005 pid_t pid;
1006 ssize_t st; 1006 ssize_t st;
1007 int status; 1007 int status;
1008 char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; 1008 char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
1009 char *cp; 1009 char *cp;
1010 size_t len; 1010 size_t len;
1011 Char *line; 1011 Char *line;
1012 1012
1013 if (el->el_state.doingarg) { 1013 if (el->el_state.doingarg) {
1014 if (vi_to_history_line(el, 0) == CC_ERROR) 1014 if (vi_to_history_line(el, 0) == CC_ERROR)
1015 return CC_ERROR; 1015 return CC_ERROR;
1016 } 1016 }
1017 1017
1018 fd = mkstemp(tempfile); 1018 fd = mkstemp(tempfile);
1019 if (fd < 0) 1019 if (fd < 0)
1020 return CC_ERROR; 1020 return CC_ERROR;
1021 len = (size_t)(el->el_line.lastchar - el->el_line.buffer); 1021 len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
1022#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX) 1022#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
1023 cp = el_malloc(TMP_BUFSIZ * sizeof(*cp)); 1023 cp = el_malloc(TMP_BUFSIZ * sizeof(*cp));
1024 if (cp == NULL) { 1024 if (cp == NULL) {
1025 unlink(tempfile); 1025 unlink(tempfile);
1026 close(fd); 1026 close(fd);
1027 return CC_ERROR; 1027 return CC_ERROR;
1028 } 1028 }
1029 line = el_malloc(len * sizeof(*line)); 1029 line = el_malloc(len * sizeof(*line));
1030 if (line == NULL) { 1030 if (line == NULL) {
1031 el_free(cp); 1031 el_free(cp);
1032 return CC_ERROR; 1032 return CC_ERROR;
1033 } 1033 }
1034 Strncpy(line, el->el_line.buffer, len); 1034 Strncpy(line, el->el_line.buffer, len);
1035 line[len] = '\0'; 1035 line[len] = '\0';
1036 ct_wcstombs(cp, line, TMP_BUFSIZ - 1); 1036 ct_wcstombs(cp, line, TMP_BUFSIZ - 1);
1037 cp[TMP_BUFSIZ - 1] = '\0'; 1037 cp[TMP_BUFSIZ - 1] = '\0';
1038 len = strlen(cp); 1038 len = strlen(cp);
1039 write(fd, cp, len); 1039 write(fd, cp, len);
1040 write(fd, "\n", 1); 1040 write(fd, "\n", 1);
1041 pid = fork(); 1041 pid = fork();
1042 switch (pid) { 1042 switch (pid) {
1043 case -1: 1043 case -1:
1044 close(fd); 1044 close(fd);
1045 unlink(tempfile); 1045 unlink(tempfile);
1046 el_free(cp); 1046 el_free(cp);
1047 el_free(line); 1047 el_free(line);
1048 return CC_ERROR; 1048 return CC_ERROR;
1049 case 0: 1049 case 0:
1050 close(fd); 1050 close(fd);
1051 execlp("vi", "vi", tempfile, (char *)NULL); 1051 execlp("vi", "vi", tempfile, (char *)NULL);
1052 exit(0); 1052 exit(0);
1053 /*NOTREACHED*/ 1053 /*NOTREACHED*/
1054 default: 1054 default:
1055 while (waitpid(pid, &status, 0) != pid) 1055 while (waitpid(pid, &status, 0) != pid)
1056 continue; 1056 continue;
1057 lseek(fd, (off_t)0, SEEK_SET); 1057 lseek(fd, (off_t)0, SEEK_SET);
1058 st = read(fd, cp, TMP_BUFSIZ); 1058 st = read(fd, cp, TMP_BUFSIZ);
1059 if (st > 0) { 1059 if (st > 0) {
1060 len = (size_t)(el->el_line.lastchar - 1060 len = (size_t)(el->el_line.lastchar -
1061 el->el_line.buffer); 1061 el->el_line.buffer);
1062 len = ct_mbstowcs(el->el_line.buffer, cp, len); 1062 len = ct_mbstowcs(el->el_line.buffer, cp, len);
1063 if (len > 0 && el->el_line.buffer[len -1] == '\n') 1063 if (len > 0 && el->el_line.buffer[len -1] == '\n')
1064 --len; 1064 --len;
1065 } 1065 }
1066 else 1066 else
1067 len = 0; 1067 len = 0;
1068 el->el_line.cursor = el->el_line.buffer; 1068 el->el_line.cursor = el->el_line.buffer;
1069 el->el_line.lastchar = el->el_line.buffer + len; 1069 el->el_line.lastchar = el->el_line.buffer + len;
1070 el_free(cp); 1070 el_free(cp);
1071 el_free(line); 1071 el_free(line);
1072 break; 1072 break;
1073 } 1073 }
1074 1074
1075 close(fd); 1075 close(fd);
1076 unlink(tempfile); 1076 unlink(tempfile);
1077 /* return CC_REFRESH; */ 1077 /* return CC_REFRESH; */
1078 return ed_newline(el, 0); 1078 return ed_newline(el, 0);
1079} 1079}
1080 1080
1081/* vi_history_word(): 1081/* vi_history_word():
1082 * Vi append word from previous input line 1082 * Vi append word from previous input line
1083 * [_] 1083 * [_]
1084 * Who knows where this one came from! 1084 * Who knows where this one came from!
1085 * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' 1085 * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
1086 */ 1086 */
1087protected el_action_t 1087protected el_action_t
1088/*ARGSUSED*/ 1088/*ARGSUSED*/
1089vi_history_word(EditLine *el, Int c) 1089vi_history_word(EditLine *el, Int c __attribute__((__unused__)))
1090{ 1090{
1091 const Char *wp = HIST_FIRST(el); 1091 const Char *wp = HIST_FIRST(el);
1092 const Char *wep, *wsp; 1092 const Char *wep, *wsp;
1093 int len; 1093 int len;
1094 Char *cp; 1094 Char *cp;
1095 const Char *lim; 1095 const Char *lim;
1096 1096
1097 if (wp == NULL) 1097 if (wp == NULL)
1098 return CC_ERROR; 1098 return CC_ERROR;
1099 1099
1100 wep = wsp = 0; 1100 wep = wsp = 0;
1101 do { 1101 do {
1102 while (Isspace(*wp)) 1102 while (Isspace(*wp))
1103 wp++; 1103 wp++;
1104 if (*wp == 0) 1104 if (*wp == 0)
1105 break; 1105 break;
1106 wsp = wp; 1106 wsp = wp;
1107 while (*wp && !Isspace(*wp)) 1107 while (*wp && !Isspace(*wp))
1108 wp++; 1108 wp++;
1109 wep = wp; 1109 wep = wp;
1110 } while ((!el->el_state.doingarg || --el->el_state.argument > 0) 1110 } while ((!el->el_state.doingarg || --el->el_state.argument > 0)
1111 && *wp != 0); 1111 && *wp != 0);
1112 1112
1113 if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0)) 1113 if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0))
1114 return CC_ERROR; 1114 return CC_ERROR;
1115 1115
1116 cv_undo(el); 1116 cv_undo(el);
1117 len = (int)(wep - wsp); 1117 len = (int)(wep - wsp);
1118 if (el->el_line.cursor < el->el_line.lastchar) 1118 if (el->el_line.cursor < el->el_line.lastchar)
1119 el->el_line.cursor++; 1119 el->el_line.cursor++;
1120 c_insert(el, len + 1); 1120 c_insert(el, len + 1);
1121 cp = el->el_line.cursor; 1121 cp = el->el_line.cursor;
1122 lim = el->el_line.limit; 1122 lim = el->el_line.limit;
1123 if (cp < lim) 1123 if (cp < lim)
1124 *cp++ = ' '; 1124 *cp++ = ' ';
1125 while (wsp < wep && cp < lim) 1125 while (wsp < wep && cp < lim)
1126 *cp++ = *wsp++; 1126 *cp++ = *wsp++;
1127 el->el_line.cursor = cp; 1127 el->el_line.cursor = cp;
1128 1128
1129 el->el_map.current = el->el_map.key; 1129 el->el_map.current = el->el_map.key;
1130 return CC_REFRESH; 1130 return CC_REFRESH;
1131} 1131}
1132 1132
1133/* vi_redo(): 1133/* vi_redo():
1134 * Vi redo last non-motion command 1134 * Vi redo last non-motion command
1135 * [.] 1135 * [.]
1136 */ 1136 */
1137protected el_action_t 1137protected el_action_t
1138/*ARGSUSED*/ 1138/*ARGSUSED*/
1139vi_redo(EditLine *el, Int c) 1139vi_redo(EditLine *el, Int c __attribute__((__unused__)))
1140{ 1140{
1141 c_redo_t *r = &el->el_chared.c_redo; 1141 c_redo_t *r = &el->el_chared.c_redo;
1142 1142
1143 if (!el->el_state.doingarg && r->count) { 1143 if (!el->el_state.doingarg && r->count) {
1144 el->el_state.doingarg = 1; 1144 el->el_state.doingarg = 1;
1145 el->el_state.argument = r->count; 1145 el->el_state.argument = r->count;
1146 } 1146 }
1147 1147
1148 el->el_chared.c_vcmd.pos = el->el_line.cursor; 1148 el->el_chared.c_vcmd.pos = el->el_line.cursor;
1149 el->el_chared.c_vcmd.action = r->action; 1149 el->el_chared.c_vcmd.action = r->action;
1150 if (r->pos != r->buf) { 1150 if (r->pos != r->buf) {
1151 if (r->pos + 1 > r->lim) 1151 if (r->pos + 1 > r->lim)
1152 /* sanity */ 1152 /* sanity */
1153 r->pos = r->lim - 1; 1153 r->pos = r->lim - 1;
1154 r->pos[0] = 0; 1154 r->pos[0] = 0;
1155 FUN(el,push)(el, r->buf); 1155 FUN(el,push)(el, r->buf);
1156 } 1156 }
1157 1157
1158 el->el_state.thiscmd = r->cmd; 1158 el->el_state.thiscmd = r->cmd;
1159 el->el_state.thisch = r->ch; 1159 el->el_state.thisch = r->ch;
1160 return (*el->el_map.func[r->cmd])(el, r->ch); 1160 return (*el->el_map.func[r->cmd])(el, r->ch);
1161} 1161}