echo-area.c revision 1.1 1 1.1 christos /* $NetBSD: echo-area.c,v 1.1 2016/01/14 00:11:29 christos Exp $ */
2 1.1 christos
3 1.1 christos /* echo-area.c -- how to read a line in the echo area.
4 1.1 christos Id: echo-area.c,v 1.7 2004/12/14 00:15:36 karl Exp
5 1.1 christos
6 1.1 christos Copyright (C) 1993, 1997, 1998, 1999, 2001, 2004 Free Software
7 1.1 christos Foundation, Inc.
8 1.1 christos
9 1.1 christos This program is free software; you can redistribute it and/or modify
10 1.1 christos it under the terms of the GNU General Public License as published by
11 1.1 christos the Free Software Foundation; either version 2, or (at your option)
12 1.1 christos any later version.
13 1.1 christos
14 1.1 christos This program is distributed in the hope that it will be useful,
15 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
16 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 1.1 christos GNU General Public License for more details.
18 1.1 christos
19 1.1 christos You should have received a copy of the GNU General Public License
20 1.1 christos along with this program; if not, write to the Free Software
21 1.1 christos Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 1.1 christos
23 1.1 christos Written by Brian Fox (bfox (at) ai.mit.edu). */
24 1.1 christos
25 1.1 christos #include "info.h"
26 1.1 christos
27 1.1 christos #if defined (FD_SET)
28 1.1 christos # if defined (hpux)
29 1.1 christos # define fd_set_cast(x) (int *)(x)
30 1.1 christos # else
31 1.1 christos # define fd_set_cast(x) (fd_set *)(x)
32 1.1 christos # endif /* !hpux */
33 1.1 christos #endif /* FD_SET */
34 1.1 christos
35 1.1 christos /* Non-zero means that C-g was used to quit reading input. */
36 1.1 christos int info_aborted_echo_area = 0;
37 1.1 christos
38 1.1 christos /* Non-zero means that the echo area is being used to read input. */
39 1.1 christos int echo_area_is_active = 0;
40 1.1 christos
41 1.1 christos /* The address of the last command executed in the echo area. */
42 1.1 christos VFunction *ea_last_executed_command = (VFunction *)NULL;
43 1.1 christos
44 1.1 christos /* Non-zero means that the last command executed while reading input
45 1.1 christos killed some text. */
46 1.1 christos int echo_area_last_command_was_kill = 0;
47 1.1 christos
48 1.1 christos /* Variables which hold on to the current state of the input line. */
49 1.1 christos static char input_line[1 + EA_MAX_INPUT];
50 1.1 christos static char *input_line_prompt;
51 1.1 christos static int input_line_point;
52 1.1 christos static int input_line_beg;
53 1.1 christos static int input_line_end;
54 1.1 christos static NODE input_line_node = {
55 1.1 christos (char *)NULL, (char *)NULL, (char *)NULL, input_line,
56 1.1 christos EA_MAX_INPUT, 0, N_IsInternal
57 1.1 christos };
58 1.1 christos
59 1.1 christos static void echo_area_initialize_node (void);
60 1.1 christos static void push_echo_area (void), pop_echo_area (void);
61 1.1 christos static int echo_area_stack_contains_completions_p (void);
62 1.1 christos
63 1.1 christos static void ea_kill_text (int from, int to);
64 1.1 christos
65 1.1 christos /* Non-zero means we force the user to complete. */
66 1.1 christos static int echo_area_must_complete_p = 0;
67 1.1 christos static int completions_window_p (WINDOW *window);
68 1.1 christos
69 1.1 christos /* If non-null, this is a window which was specifically created to display
70 1.1 christos possible completions output. We remember it so we can delete it when
71 1.1 christos appropriate. */
72 1.1 christos static WINDOW *echo_area_completions_window = (WINDOW *)NULL;
73 1.1 christos
74 1.1 christos /* Variables which keep track of the window which was active prior to
75 1.1 christos entering the echo area. */
76 1.1 christos static WINDOW *calling_window = (WINDOW *)NULL;
77 1.1 christos static NODE *calling_window_node = (NODE *)NULL;
78 1.1 christos static long calling_window_point = 0;
79 1.1 christos static long calling_window_pagetop = 0;
80 1.1 christos
81 1.1 christos /* Remember the node and pertinent variables of the calling window. */
82 1.1 christos static void
83 1.1 christos remember_calling_window (WINDOW *window)
84 1.1 christos {
85 1.1 christos /* Only do this if the calling window is not the completions window, or,
86 1.1 christos if it is the completions window and there is no other window. */
87 1.1 christos if (!completions_window_p (window) ||
88 1.1 christos ((window == windows) && !(window->next)))
89 1.1 christos {
90 1.1 christos calling_window = window;
91 1.1 christos calling_window_node = window->node;
92 1.1 christos calling_window_point = window->point;
93 1.1 christos calling_window_pagetop = window->pagetop;
94 1.1 christos }
95 1.1 christos }
96 1.1 christos
97 1.1 christos /* Restore the caller's window so that it shows the node that it was showing
98 1.1 christos on entry to info_read_xxx_echo_area (). */
99 1.1 christos static void
100 1.1 christos restore_calling_window (void)
101 1.1 christos {
102 1.1 christos register WINDOW *win, *compwin = (WINDOW *)NULL;
103 1.1 christos
104 1.1 christos /* If the calling window is still visible, and it is the window that
105 1.1 christos we used for completions output, then restore the calling window. */
106 1.1 christos for (win = windows; win; win = win->next)
107 1.1 christos {
108 1.1 christos if (completions_window_p (win))
109 1.1 christos compwin = win;
110 1.1 christos
111 1.1 christos if (win == calling_window && win == compwin)
112 1.1 christos {
113 1.1 christos window_set_node_of_window (calling_window, calling_window_node);
114 1.1 christos calling_window->point = calling_window_point;
115 1.1 christos calling_window->pagetop = calling_window_pagetop;
116 1.1 christos compwin = (WINDOW *)NULL;
117 1.1 christos break;
118 1.1 christos }
119 1.1 christos }
120 1.1 christos
121 1.1 christos /* Delete the completions window if it is still present, it isn't the
122 1.1 christos last window on the screen, and there aren't any prior echo area reads
123 1.1 christos pending which created a completions window. */
124 1.1 christos if (compwin)
125 1.1 christos {
126 1.1 christos if ((compwin != windows || windows->next) &&
127 1.1 christos !echo_area_stack_contains_completions_p ())
128 1.1 christos {
129 1.1 christos WINDOW *next;
130 1.1 christos int pagetop = 0;
131 1.1 christos int start = 0;
132 1.1 christos int end = 0;
133 1.1 christos int amount = 0;
134 1.1 christos
135 1.1 christos next = compwin->next;
136 1.1 christos if (next)
137 1.1 christos {
138 1.1 christos start = next->first_row;
139 1.1 christos end = start + next->height;
140 1.1 christos amount = - (compwin->height + 1);
141 1.1 christos pagetop = next->pagetop;
142 1.1 christos }
143 1.1 christos
144 1.1 christos info_delete_window_internal (compwin);
145 1.1 christos
146 1.1 christos /* This is not necessary because info_delete_window_internal ()
147 1.1 christos calls echo_area_inform_of_deleted_window (), which does the
148 1.1 christos right thing. */
149 1.1 christos #if defined (UNNECESSARY)
150 1.1 christos echo_area_completions_window = (WINDOW *)NULL;
151 1.1 christos #endif /* UNNECESSARY */
152 1.1 christos
153 1.1 christos if (next)
154 1.1 christos {
155 1.1 christos display_scroll_display (start, end, amount);
156 1.1 christos next->pagetop = pagetop;
157 1.1 christos display_update_display (windows);
158 1.1 christos }
159 1.1 christos }
160 1.1 christos }
161 1.1 christos }
162 1.1 christos
163 1.1 christos /* Set up a new input line with PROMPT. */
164 1.1 christos static void
165 1.1 christos initialize_input_line (char *prompt)
166 1.1 christos {
167 1.1 christos input_line_prompt = prompt;
168 1.1 christos if (prompt)
169 1.1 christos strcpy (input_line, prompt);
170 1.1 christos else
171 1.1 christos input_line[0] = '\0';
172 1.1 christos
173 1.1 christos input_line_beg = input_line_end = input_line_point = strlen (prompt);
174 1.1 christos }
175 1.1 christos
176 1.1 christos static char *
177 1.1 christos echo_area_after_read (void)
178 1.1 christos {
179 1.1 christos char *return_value;
180 1.1 christos
181 1.1 christos if (info_aborted_echo_area)
182 1.1 christos {
183 1.1 christos info_aborted_echo_area = 0;
184 1.1 christos return_value = (char *)NULL;
185 1.1 christos }
186 1.1 christos else
187 1.1 christos {
188 1.1 christos if (input_line_beg == input_line_end)
189 1.1 christos return_value = xstrdup ("");
190 1.1 christos else
191 1.1 christos {
192 1.1 christos int line_len = input_line_end - input_line_beg;
193 1.1 christos return_value = (char *) xmalloc (1 + line_len);
194 1.1 christos strncpy (return_value, &input_line[input_line_beg], line_len);
195 1.1 christos return_value[line_len] = '\0';
196 1.1 christos }
197 1.1 christos }
198 1.1 christos return (return_value);
199 1.1 christos }
200 1.1 christos
201 1.1 christos /* Read a line of text in the echo area. Return a malloc ()'ed string,
202 1.1 christos or NULL if the user aborted out of this read. WINDOW is the currently
203 1.1 christos active window, so that we can restore it when we need to. PROMPT, if
204 1.1 christos non-null, is a prompt to print before reading the line. */
205 1.1 christos char *
206 1.1 christos info_read_in_echo_area (WINDOW *window, char *prompt)
207 1.1 christos {
208 1.1 christos char *line;
209 1.1 christos
210 1.1 christos /* If the echo area is already active, remember the current state. */
211 1.1 christos if (echo_area_is_active)
212 1.1 christos push_echo_area ();
213 1.1 christos
214 1.1 christos /* Initialize our local variables. */
215 1.1 christos initialize_input_line (prompt);
216 1.1 christos
217 1.1 christos /* Initialize the echo area for the first (but maybe not the last) time. */
218 1.1 christos echo_area_initialize_node ();
219 1.1 christos
220 1.1 christos /* Save away the original node of this window, and the window itself,
221 1.1 christos so echo area commands can temporarily use this window. */
222 1.1 christos remember_calling_window (window);
223 1.1 christos
224 1.1 christos /* Let the rest of Info know that the echo area is active. */
225 1.1 christos echo_area_is_active++;
226 1.1 christos active_window = the_echo_area;
227 1.1 christos
228 1.1 christos /* Read characters in the echo area. */
229 1.1 christos info_read_and_dispatch ();
230 1.1 christos
231 1.1 christos echo_area_is_active--;
232 1.1 christos
233 1.1 christos /* Restore the original active window and show point in it. */
234 1.1 christos active_window = calling_window;
235 1.1 christos restore_calling_window ();
236 1.1 christos display_cursor_at_point (active_window);
237 1.1 christos fflush (stdout);
238 1.1 christos
239 1.1 christos /* Get the value of the line. */
240 1.1 christos line = echo_area_after_read ();
241 1.1 christos
242 1.1 christos /* If there is a previous loop waiting for us, restore it now. */
243 1.1 christos if (echo_area_is_active)
244 1.1 christos pop_echo_area ();
245 1.1 christos
246 1.1 christos /* Return the results to the caller. */
247 1.1 christos return (line);
248 1.1 christos }
249 1.1 christos
250 1.1 christos /* (re) Initialize the echo area node. */
251 1.1 christos static void
252 1.1 christos echo_area_initialize_node (void)
253 1.1 christos {
254 1.1 christos register int i;
255 1.1 christos
256 1.1 christos for (i = input_line_end; (unsigned int) i < sizeof (input_line); i++)
257 1.1 christos input_line[i] = ' ';
258 1.1 christos
259 1.1 christos input_line[i - 1] = '\n';
260 1.1 christos window_set_node_of_window (the_echo_area, &input_line_node);
261 1.1 christos input_line[input_line_end] = '\n';
262 1.1 christos }
263 1.1 christos
264 1.1 christos /* Prepare to read characters in the echo area. This can initialize the
265 1.1 christos echo area node, but its primary purpose is to side effect the input
266 1.1 christos line buffer contents. */
267 1.1 christos void
268 1.1 christos echo_area_prep_read (void)
269 1.1 christos {
270 1.1 christos if (the_echo_area->node != &input_line_node)
271 1.1 christos echo_area_initialize_node ();
272 1.1 christos
273 1.1 christos the_echo_area->point = input_line_point;
274 1.1 christos input_line[input_line_end] = '\n';
275 1.1 christos display_update_one_window (the_echo_area);
276 1.1 christos display_cursor_at_point (active_window);
277 1.1 christos }
278 1.1 christos
279 1.1 christos
280 1.1 christos /* **************************************************************** */
282 1.1 christos /* */
283 1.1 christos /* Echo Area Movement Commands */
284 1.1 christos /* */
285 1.1 christos /* **************************************************************** */
286 1.1 christos
287 1.1 christos DECLARE_INFO_COMMAND (ea_forward, _("Move forward a character"))
288 1.1 christos {
289 1.1 christos if (count < 0)
290 1.1 christos ea_backward (window, -count, key);
291 1.1 christos else
292 1.1 christos {
293 1.1 christos input_line_point += count;
294 1.1 christos if (input_line_point > input_line_end)
295 1.1 christos input_line_point = input_line_end;
296 1.1 christos }
297 1.1 christos }
298 1.1 christos
299 1.1 christos DECLARE_INFO_COMMAND (ea_backward, _("Move backward a character"))
300 1.1 christos {
301 1.1 christos if (count < 0)
302 1.1 christos ea_forward (window, -count, key);
303 1.1 christos else
304 1.1 christos {
305 1.1 christos input_line_point -= count;
306 1.1 christos if (input_line_point < input_line_beg)
307 1.1 christos input_line_point = input_line_beg;
308 1.1 christos }
309 1.1 christos }
310 1.1 christos
311 1.1 christos DECLARE_INFO_COMMAND (ea_beg_of_line, _("Move to the start of this line"))
312 1.1 christos {
313 1.1 christos input_line_point = input_line_beg;
314 1.1 christos }
315 1.1 christos
316 1.1 christos DECLARE_INFO_COMMAND (ea_end_of_line, _("Move to the end of this line"))
317 1.1 christos {
318 1.1 christos input_line_point = input_line_end;
319 1.1 christos }
320 1.1 christos
321 1.1 christos #define alphabetic(c) (islower (c) || isupper (c) || isdigit (c))
322 1.1 christos
323 1.1 christos /* Move forward a word in the input line. */
324 1.1 christos DECLARE_INFO_COMMAND (ea_forward_word, _("Move forward a word"))
325 1.1 christos {
326 1.1 christos int c;
327 1.1 christos
328 1.1 christos if (count < 0)
329 1.1 christos ea_backward_word (window, -count, key);
330 1.1 christos else
331 1.1 christos {
332 1.1 christos while (count--)
333 1.1 christos {
334 1.1 christos if (input_line_point == input_line_end)
335 1.1 christos return;
336 1.1 christos
337 1.1 christos /* If we are not in a word, move forward until we are in one.
338 1.1 christos Then, move forward until we hit a non-alphabetic character. */
339 1.1 christos c = input_line[input_line_point];
340 1.1 christos
341 1.1 christos if (!alphabetic (c))
342 1.1 christos {
343 1.1 christos while (++input_line_point < input_line_end)
344 1.1 christos {
345 1.1 christos c = input_line[input_line_point];
346 1.1 christos if (alphabetic (c))
347 1.1 christos break;
348 1.1 christos }
349 1.1 christos }
350 1.1 christos
351 1.1 christos if (input_line_point == input_line_end)
352 1.1 christos return;
353 1.1 christos
354 1.1 christos while (++input_line_point < input_line_end)
355 1.1 christos {
356 1.1 christos c = input_line[input_line_point];
357 1.1 christos if (!alphabetic (c))
358 1.1 christos break;
359 1.1 christos }
360 1.1 christos }
361 1.1 christos }
362 1.1 christos }
363 1.1 christos
364 1.1 christos DECLARE_INFO_COMMAND (ea_backward_word, _("Move backward a word"))
365 1.1 christos {
366 1.1 christos int c;
367 1.1 christos
368 1.1 christos if (count < 0)
369 1.1 christos ea_forward_word (window, -count, key);
370 1.1 christos else
371 1.1 christos {
372 1.1 christos while (count--)
373 1.1 christos {
374 1.1 christos if (input_line_point == input_line_beg)
375 1.1 christos return;
376 1.1 christos
377 1.1 christos /* Like ea_forward_word (), except that we look at the
378 1.1 christos characters just before point. */
379 1.1 christos
380 1.1 christos c = input_line[input_line_point - 1];
381 1.1 christos
382 1.1 christos if (!alphabetic (c))
383 1.1 christos {
384 1.1 christos while ((--input_line_point) != input_line_beg)
385 1.1 christos {
386 1.1 christos c = input_line[input_line_point - 1];
387 1.1 christos if (alphabetic (c))
388 1.1 christos break;
389 1.1 christos }
390 1.1 christos }
391 1.1 christos
392 1.1 christos while (input_line_point != input_line_beg)
393 1.1 christos {
394 1.1 christos c = input_line[input_line_point - 1];
395 1.1 christos if (!alphabetic (c))
396 1.1 christos break;
397 1.1 christos else
398 1.1 christos --input_line_point;
399 1.1 christos }
400 1.1 christos }
401 1.1 christos }
402 1.1 christos }
403 1.1 christos
404 1.1 christos DECLARE_INFO_COMMAND (ea_delete, _("Delete the character under the cursor"))
405 1.1 christos {
406 1.1 christos register int i;
407 1.1 christos
408 1.1 christos if (count < 0)
409 1.1 christos ea_rubout (window, -count, key);
410 1.1 christos else
411 1.1 christos {
412 1.1 christos if (input_line_point == input_line_end)
413 1.1 christos return;
414 1.1 christos
415 1.1 christos if (info_explicit_arg || count > 1)
416 1.1 christos {
417 1.1 christos int orig_point;
418 1.1 christos
419 1.1 christos orig_point = input_line_point;
420 1.1 christos ea_forward (window, count, key);
421 1.1 christos ea_kill_text (orig_point, input_line_point);
422 1.1 christos input_line_point = orig_point;
423 1.1 christos }
424 1.1 christos else
425 1.1 christos {
426 1.1 christos for (i = input_line_point; i < input_line_end; i++)
427 1.1 christos input_line[i] = input_line[i + 1];
428 1.1 christos
429 1.1 christos input_line_end--;
430 1.1 christos }
431 1.1 christos }
432 1.1 christos }
433 1.1 christos
434 1.1 christos DECLARE_INFO_COMMAND (ea_rubout, _("Delete the character behind the cursor"))
435 1.1 christos {
436 1.1 christos if (count < 0)
437 1.1 christos ea_delete (window, -count, key);
438 1.1 christos else
439 1.1 christos {
440 1.1 christos int start;
441 1.1 christos
442 1.1 christos if (input_line_point == input_line_beg)
443 1.1 christos return;
444 1.1 christos
445 1.1 christos start = input_line_point;
446 1.1 christos ea_backward (window, count, key);
447 1.1 christos
448 1.1 christos if (info_explicit_arg || count > 1)
449 1.1 christos ea_kill_text (start, input_line_point);
450 1.1 christos else
451 1.1 christos ea_delete (window, count, key);
452 1.1 christos }
453 1.1 christos }
454 1.1 christos
455 1.1 christos DECLARE_INFO_COMMAND (ea_abort, _("Cancel or quit operation"))
456 1.1 christos {
457 1.1 christos /* If any text, just discard it, and restore the calling window's node.
458 1.1 christos If no text, quit. */
459 1.1 christos if (input_line_end != input_line_beg)
460 1.1 christos {
461 1.1 christos terminal_ring_bell ();
462 1.1 christos input_line_end = input_line_point = input_line_beg;
463 1.1 christos if (calling_window->node != calling_window_node)
464 1.1 christos restore_calling_window ();
465 1.1 christos }
466 1.1 christos else
467 1.1 christos info_aborted_echo_area = 1;
468 1.1 christos }
469 1.1 christos
470 1.1 christos DECLARE_INFO_COMMAND (ea_newline, _("Accept (or force completion of) this line"))
471 1.1 christos {
472 1.1 christos /* Stub does nothing. Simply here to see if it has been executed. */
473 1.1 christos }
474 1.1 christos
475 1.1 christos DECLARE_INFO_COMMAND (ea_quoted_insert, _("Insert next character verbatim"))
476 1.1 christos {
477 1.1 christos unsigned char character;
478 1.1 christos
479 1.1 christos character = info_get_another_input_char ();
480 1.1 christos ea_insert (window, count, character);
481 1.1 christos }
482 1.1 christos
483 1.1 christos DECLARE_INFO_COMMAND (ea_insert, _("Insert this character"))
484 1.1 christos {
485 1.1 christos register int i;
486 1.1 christos
487 1.1 christos if ((input_line_end + 1) == EA_MAX_INPUT)
488 1.1 christos {
489 1.1 christos terminal_ring_bell ();
490 1.1 christos return;
491 1.1 christos }
492 1.1 christos
493 1.1 christos for (i = input_line_end + 1; i != input_line_point; i--)
494 1.1 christos input_line[i] = input_line[i - 1];
495 1.1 christos
496 1.1 christos input_line[input_line_point] = key;
497 1.1 christos input_line_point++;
498 1.1 christos input_line_end++;
499 1.1 christos }
500 1.1 christos
501 1.1 christos DECLARE_INFO_COMMAND (ea_tab_insert, _("Insert a TAB character"))
502 1.1 christos {
503 1.1 christos ea_insert (window, count, '\t');
504 1.1 christos }
505 1.1 christos
506 1.1 christos /* Transpose the characters at point. If point is at the end of the line,
507 1.1 christos then transpose the characters before point. */
508 1.1 christos DECLARE_INFO_COMMAND (ea_transpose_chars, _("Transpose characters at point"))
509 1.1 christos {
510 1.1 christos /* Handle conditions that would make it impossible to transpose
511 1.1 christos characters. */
512 1.1 christos if (!count || !input_line_point || (input_line_end - input_line_beg) < 2)
513 1.1 christos return;
514 1.1 christos
515 1.1 christos while (count)
516 1.1 christos {
517 1.1 christos int t;
518 1.1 christos if (input_line_point == input_line_end)
519 1.1 christos {
520 1.1 christos t = input_line[input_line_point - 1];
521 1.1 christos
522 1.1 christos input_line[input_line_point - 1] = input_line[input_line_point - 2];
523 1.1 christos input_line[input_line_point - 2] = t;
524 1.1 christos }
525 1.1 christos else
526 1.1 christos {
527 1.1 christos t = input_line[input_line_point];
528 1.1 christos
529 1.1 christos input_line[input_line_point] = input_line[input_line_point - 1];
530 1.1 christos input_line[input_line_point - 1] = t;
531 1.1 christos
532 1.1 christos if (count < 0 && input_line_point != input_line_beg)
533 1.1 christos input_line_point--;
534 1.1 christos else
535 1.1 christos input_line_point++;
536 1.1 christos }
537 1.1 christos
538 1.1 christos if (count < 0)
539 1.1 christos count++;
540 1.1 christos else
541 1.1 christos count--;
542 1.1 christos }
543 1.1 christos }
544 1.1 christos
545 1.1 christos /* **************************************************************** */
547 1.1 christos /* */
548 1.1 christos /* Echo Area Killing and Yanking */
549 1.1 christos /* */
550 1.1 christos /* **************************************************************** */
551 1.1 christos
552 1.1 christos static char **kill_ring = (char **)NULL;
553 1.1 christos static int kill_ring_index = 0; /* Number of kills appearing in KILL_RING. */
554 1.1 christos static int kill_ring_slots = 0; /* Number of slots allocated to KILL_RING. */
555 1.1 christos static int kill_ring_loc = 0; /* Location of current yank pointer. */
556 1.1 christos
557 1.1 christos /* The largest number of kills that we remember at one time. */
558 1.1 christos static int max_retained_kills = 15;
559 1.1 christos
560 1.1 christos DECLARE_INFO_COMMAND (ea_yank, _("Yank back the contents of the last kill"))
561 1.1 christos {
562 1.1 christos register int i;
563 1.1 christos register char *text;
564 1.1 christos
565 1.1 christos if (!kill_ring_index)
566 1.1 christos {
567 1.1 christos inform_in_echo_area ((char *) _("Kill ring is empty"));
568 1.1 christos return;
569 1.1 christos }
570 1.1 christos
571 1.1 christos text = kill_ring[kill_ring_loc];
572 1.1 christos
573 1.1 christos for (i = 0; text[i]; i++)
574 1.1 christos ea_insert (window, 1, text[i]);
575 1.1 christos }
576 1.1 christos
577 1.1 christos /* If the last command was yank, or yank_pop, and the text just before
578 1.1 christos point is identical to the current kill item, then delete that text
579 1.1 christos from the line, rotate the index down, and yank back some other text. */
580 1.1 christos DECLARE_INFO_COMMAND (ea_yank_pop, _("Yank back a previous kill"))
581 1.1 christos {
582 1.1 christos register int len;
583 1.1 christos
584 1.1 christos if (((ea_last_executed_command != (VFunction *) ea_yank) &&
585 1.1 christos (ea_last_executed_command != (VFunction *) ea_yank_pop)) ||
586 1.1 christos (kill_ring_index == 0))
587 1.1 christos return;
588 1.1 christos
589 1.1 christos len = strlen (kill_ring[kill_ring_loc]);
590 1.1 christos
591 1.1 christos /* Delete the last yanked item from the line. */
592 1.1 christos {
593 1.1 christos register int i, counter;
594 1.1 christos
595 1.1 christos counter = input_line_end - input_line_point;
596 1.1 christos
597 1.1 christos for (i = input_line_point - len; counter; i++, counter--)
598 1.1 christos input_line[i] = input_line[i + len];
599 1.1 christos
600 1.1 christos input_line_end -= len;
601 1.1 christos input_line_point -= len;
602 1.1 christos }
603 1.1 christos
604 1.1 christos /* Get a previous kill, and yank that. */
605 1.1 christos kill_ring_loc--;
606 1.1 christos if (kill_ring_loc < 0)
607 1.1 christos kill_ring_loc = kill_ring_index - 1;
608 1.1 christos
609 1.1 christos ea_yank (window, count, key);
610 1.1 christos }
611 1.1 christos
612 1.1 christos /* Delete the text from point to end of line. */
613 1.1 christos DECLARE_INFO_COMMAND (ea_kill_line, _("Kill to the end of the line"))
614 1.1 christos {
615 1.1 christos if (count < 0)
616 1.1 christos {
617 1.1 christos ea_kill_text (input_line_point, input_line_beg);
618 1.1 christos input_line_point = input_line_beg;
619 1.1 christos }
620 1.1 christos else
621 1.1 christos ea_kill_text (input_line_point, input_line_end);
622 1.1 christos }
623 1.1 christos
624 1.1 christos /* Delete the text from point to beg of line. */
625 1.1 christos DECLARE_INFO_COMMAND (ea_backward_kill_line,
626 1.1 christos _("Kill to the beginning of the line"))
627 1.1 christos {
628 1.1 christos if (count < 0)
629 1.1 christos ea_kill_text (input_line_point, input_line_end);
630 1.1 christos else
631 1.1 christos {
632 1.1 christos ea_kill_text (input_line_point, input_line_beg);
633 1.1 christos input_line_point = input_line_beg;
634 1.1 christos }
635 1.1 christos }
636 1.1 christos
637 1.1 christos /* Delete from point to the end of the current word. */
638 1.1 christos DECLARE_INFO_COMMAND (ea_kill_word, _("Kill the word following the cursor"))
639 1.1 christos {
640 1.1 christos int orig_point = input_line_point;
641 1.1 christos
642 1.1 christos if (count < 0)
643 1.1 christos ea_backward_kill_word (window, -count, key);
644 1.1 christos else
645 1.1 christos {
646 1.1 christos ea_forward_word (window, count, key);
647 1.1 christos
648 1.1 christos if (input_line_point != orig_point)
649 1.1 christos ea_kill_text (orig_point, input_line_point);
650 1.1 christos
651 1.1 christos input_line_point = orig_point;
652 1.1 christos }
653 1.1 christos }
654 1.1 christos
655 1.1 christos /* Delete from point to the start of the current word. */
656 1.1 christos DECLARE_INFO_COMMAND (ea_backward_kill_word,
657 1.1 christos _("Kill the word preceding the cursor"))
658 1.1 christos {
659 1.1 christos int orig_point = input_line_point;
660 1.1 christos
661 1.1 christos if (count < 0)
662 1.1 christos ea_kill_word (window, -count, key);
663 1.1 christos else
664 1.1 christos {
665 1.1 christos ea_backward_word (window, count, key);
666 1.1 christos
667 1.1 christos if (input_line_point != orig_point)
668 1.1 christos ea_kill_text (orig_point, input_line_point);
669 1.1 christos }
670 1.1 christos }
671 1.1 christos
672 1.1 christos /* The way to kill something. This appends or prepends to the last
673 1.1 christos kill, if the last command was a kill command. If FROM is less
674 1.1 christos than TO, then the killed text is appended to the most recent kill,
675 1.1 christos otherwise it is prepended. If the last command was not a kill command,
676 1.1 christos then a new slot is made for this kill. */
677 1.1 christos static void
678 1.1 christos ea_kill_text (int from, int to)
679 1.1 christos {
680 1.1 christos register int i, counter, distance;
681 1.1 christos int killing_backwards, slot;
682 1.1 christos char *killed_text;
683 1.1 christos
684 1.1 christos killing_backwards = (from > to);
685 1.1 christos
686 1.1 christos /* If killing backwards, reverse the values of FROM and TO. */
687 1.1 christos if (killing_backwards)
688 1.1 christos {
689 1.1 christos int temp = from;
690 1.1 christos from = to;
691 1.1 christos to = temp;
692 1.1 christos }
693 1.1 christos
694 1.1 christos /* Remember the text that we are about to delete. */
695 1.1 christos distance = to - from;
696 1.1 christos killed_text = (char *)xmalloc (1 + distance);
697 1.1 christos strncpy (killed_text, &input_line[from], distance);
698 1.1 christos killed_text[distance] = '\0';
699 1.1 christos
700 1.1 christos /* Actually delete the text from the line. */
701 1.1 christos counter = input_line_end - to;
702 1.1 christos
703 1.1 christos for (i = from; counter; i++, counter--)
704 1.1 christos input_line[i] = input_line[i + distance];
705 1.1 christos
706 1.1 christos input_line_end -= distance;
707 1.1 christos
708 1.1 christos /* If the last command was a kill, append or prepend the killed text to
709 1.1 christos the last command's killed text. */
710 1.1 christos if (echo_area_last_command_was_kill)
711 1.1 christos {
712 1.1 christos char *old, *new;
713 1.1 christos
714 1.1 christos slot = kill_ring_loc;
715 1.1 christos old = kill_ring[slot];
716 1.1 christos new = (char *)xmalloc (1 + strlen (old) + strlen (killed_text));
717 1.1 christos
718 1.1 christos if (killing_backwards)
719 1.1 christos {
720 1.1 christos /* Prepend TEXT to current kill. */
721 1.1 christos strcpy (new, killed_text);
722 1.1 christos strcat (new, old);
723 1.1 christos }
724 1.1 christos else
725 1.1 christos {
726 1.1 christos /* Append TEXT to current kill. */
727 1.1 christos strcpy (new, old);
728 1.1 christos strcat (new, killed_text);
729 1.1 christos }
730 1.1 christos
731 1.1 christos free (old);
732 1.1 christos free (killed_text);
733 1.1 christos kill_ring[slot] = new;
734 1.1 christos }
735 1.1 christos else
736 1.1 christos {
737 1.1 christos /* Try to store the kill in a new slot, unless that would cause there
738 1.1 christos to be too many remembered kills. */
739 1.1 christos slot = kill_ring_index;
740 1.1 christos
741 1.1 christos if (slot == max_retained_kills)
742 1.1 christos slot = 0;
743 1.1 christos
744 1.1 christos if (slot + 1 > kill_ring_slots)
745 1.1 christos kill_ring = (char **) xrealloc
746 1.1 christos (kill_ring,
747 1.1 christos (kill_ring_slots += max_retained_kills) * sizeof (char *));
748 1.1 christos
749 1.1 christos if (slot != kill_ring_index)
750 1.1 christos free (kill_ring[slot]);
751 1.1 christos else
752 1.1 christos kill_ring_index++;
753 1.1 christos
754 1.1 christos kill_ring[slot] = killed_text;
755 1.1 christos
756 1.1 christos kill_ring_loc = slot;
757 1.1 christos }
758 1.1 christos
759 1.1 christos /* Notice that the last command was a kill. */
760 1.1 christos echo_area_last_command_was_kill++;
761 1.1 christos }
762 1.1 christos
763 1.1 christos /* **************************************************************** */
765 1.1 christos /* */
766 1.1 christos /* Echo Area Completion */
767 1.1 christos /* */
768 1.1 christos /* **************************************************************** */
769 1.1 christos
770 1.1 christos /* Pointer to an array of REFERENCE to complete over. */
771 1.1 christos static REFERENCE **echo_area_completion_items = (REFERENCE **)NULL;
772 1.1 christos
773 1.1 christos /* Sorted array of REFERENCE * which is the possible completions found in
774 1.1 christos the variable echo_area_completion_items. If there is only one element,
775 1.1 christos it is the only possible completion. */
776 1.1 christos static REFERENCE **completions_found = (REFERENCE **)NULL;
777 1.1 christos static int completions_found_index = 0;
778 1.1 christos static int completions_found_slots = 0;
779 1.1 christos
780 1.1 christos /* The lowest common denominator found while completing. */
781 1.1 christos static REFERENCE *LCD_completion;
782 1.1 christos
783 1.1 christos /* Internal functions used by the user calls. */
784 1.1 christos static void build_completions (void), completions_must_be_rebuilt (void);
785 1.1 christos
786 1.1 christos /* Variable which holds the output of completions. */
787 1.1 christos static NODE *possible_completions_output_node = (NODE *)NULL;
788 1.1 christos
789 1.1 christos static char *compwin_name = "*Completions*";
790 1.1 christos
791 1.1 christos /* Return non-zero if WINDOW is a window used for completions output. */
792 1.1 christos static int
793 1.1 christos completions_window_p (WINDOW *window)
794 1.1 christos {
795 1.1 christos int result = 0;
796 1.1 christos
797 1.1 christos if (internal_info_node_p (window->node) &&
798 1.1 christos (strcmp (window->node->nodename, compwin_name) == 0))
799 1.1 christos result = 1;
800 1.1 christos
801 1.1 christos return (result);
802 1.1 christos }
803 1.1 christos
804 1.1 christos /* Workhorse for completion readers. If FORCE is non-zero, the user cannot
805 1.1 christos exit unless the line read completes, or is empty. */
806 1.1 christos char *
807 1.1 christos info_read_completing_internal (WINDOW *window, char *prompt,
808 1.1 christos REFERENCE **completions, int force)
809 1.1 christos {
810 1.1 christos char *line;
811 1.1 christos
812 1.1 christos /* If the echo area is already active, remember the current state. */
813 1.1 christos if (echo_area_is_active)
814 1.1 christos push_echo_area ();
815 1.1 christos
816 1.1 christos echo_area_must_complete_p = force;
817 1.1 christos
818 1.1 christos /* Initialize our local variables. */
819 1.1 christos initialize_input_line (prompt);
820 1.1 christos
821 1.1 christos /* Initialize the echo area for the first (but maybe not the last) time. */
822 1.1 christos echo_area_initialize_node ();
823 1.1 christos
824 1.1 christos /* Save away the original node of this window, and the window itself,
825 1.1 christos so echo area commands can temporarily use this window. */
826 1.1 christos remember_calling_window (window);
827 1.1 christos
828 1.1 christos /* Save away the list of items to complete over. */
829 1.1 christos echo_area_completion_items = completions;
830 1.1 christos completions_must_be_rebuilt ();
831 1.1 christos
832 1.1 christos active_window = the_echo_area;
833 1.1 christos echo_area_is_active++;
834 1.1 christos
835 1.1 christos /* Read characters in the echo area. */
836 1.1 christos while (1)
837 1.1 christos {
838 1.1 christos info_read_and_dispatch ();
839 1.1 christos
840 1.1 christos line = echo_area_after_read ();
841 1.1 christos
842 1.1 christos /* Force the completion to take place if the user hasn't accepted
843 1.1 christos a default or aborted, and if FORCE is active. */
844 1.1 christos if (force && line && *line && completions)
845 1.1 christos {
846 1.1 christos register int i;
847 1.1 christos
848 1.1 christos build_completions ();
849 1.1 christos
850 1.1 christos /* If there is only one completion, then make the line be that
851 1.1 christos completion. */
852 1.1 christos if (completions_found_index == 1)
853 1.1 christos {
854 1.1 christos free (line);
855 1.1 christos line = xstrdup (completions_found[0]->label);
856 1.1 christos break;
857 1.1 christos }
858 1.1 christos
859 1.1 christos /* If one of the completions matches exactly, then that is okay, so
860 1.1 christos return the current line. */
861 1.1 christos for (i = 0; i < completions_found_index; i++)
862 1.1 christos if (strcasecmp (completions_found[i]->label, line) == 0)
863 1.1 christos {
864 1.1 christos free (line);
865 1.1 christos line = xstrdup (completions_found[i]->label);
866 1.1 christos break;
867 1.1 christos }
868 1.1 christos
869 1.1 christos /* If no match, go back and try again. */
870 1.1 christos if (i == completions_found_index)
871 1.1 christos {
872 1.1 christos if (!completions_found_index)
873 1.1 christos inform_in_echo_area ((char *) _("No completions"));
874 1.1 christos else
875 1.1 christos inform_in_echo_area ((char *) _("Not complete"));
876 1.1 christos continue;
877 1.1 christos }
878 1.1 christos }
879 1.1 christos break;
880 1.1 christos }
881 1.1 christos echo_area_is_active--;
882 1.1 christos
883 1.1 christos /* Restore the original active window and show point in it. */
884 1.1 christos active_window = calling_window;
885 1.1 christos restore_calling_window ();
886 1.1 christos display_cursor_at_point (active_window);
887 1.1 christos fflush (stdout);
888 1.1 christos
889 1.1 christos echo_area_completion_items = (REFERENCE **)NULL;
890 1.1 christos completions_must_be_rebuilt ();
891 1.1 christos
892 1.1 christos /* If there is a previous loop waiting for us, restore it now. */
893 1.1 christos if (echo_area_is_active)
894 1.1 christos pop_echo_area ();
895 1.1 christos
896 1.1 christos return (line);
897 1.1 christos }
898 1.1 christos
899 1.1 christos /* Read a line in the echo area with completion over COMPLETIONS. */
900 1.1 christos char *
901 1.1 christos info_read_completing_in_echo_area (WINDOW *window,
902 1.1 christos char *prompt, REFERENCE **completions)
903 1.1 christos {
904 1.1 christos return (info_read_completing_internal (window, prompt, completions, 1));
905 1.1 christos }
906 1.1 christos
907 1.1 christos /* Read a line in the echo area allowing completion over COMPLETIONS, but
908 1.1 christos not requiring it. */
909 1.1 christos char *
910 1.1 christos info_read_maybe_completing (WINDOW *window,
911 1.1 christos char *prompt, REFERENCE **completions)
912 1.1 christos {
913 1.1 christos return (info_read_completing_internal (window, prompt, completions, 0));
914 1.1 christos }
915 1.1 christos
916 1.1 christos DECLARE_INFO_COMMAND (ea_possible_completions, _("List possible completions"))
917 1.1 christos {
918 1.1 christos if (!echo_area_completion_items)
919 1.1 christos {
920 1.1 christos ea_insert (window, count, key);
921 1.1 christos return;
922 1.1 christos }
923 1.1 christos
924 1.1 christos build_completions ();
925 1.1 christos
926 1.1 christos if (!completions_found_index)
927 1.1 christos {
928 1.1 christos terminal_ring_bell ();
929 1.1 christos inform_in_echo_area ((char *) _("No completions"));
930 1.1 christos }
931 1.1 christos else if ((completions_found_index == 1) && (key != '?'))
932 1.1 christos {
933 1.1 christos inform_in_echo_area ((char *) _("Sole completion"));
934 1.1 christos }
935 1.1 christos else
936 1.1 christos {
937 1.1 christos register int i, l;
938 1.1 christos int limit, iterations, max_label = 0;
939 1.1 christos
940 1.1 christos initialize_message_buffer ();
941 1.1 christos printf_to_message_buffer (completions_found_index == 1
942 1.1 christos ? (char *) _("One completion:\n")
943 1.1 christos : (char *) _("%d completions:\n"),
944 1.1 christos (void *) (long) completions_found_index,
945 1.1 christos NULL, NULL);
946 1.1 christos
947 1.1 christos /* Find the maximum length of a label. */
948 1.1 christos for (i = 0; i < completions_found_index; i++)
949 1.1 christos {
950 1.1 christos int len = strlen (completions_found[i]->label);
951 1.1 christos if (len > max_label)
952 1.1 christos max_label = len;
953 1.1 christos }
954 1.1 christos
955 1.1 christos max_label += 4;
956 1.1 christos
957 1.1 christos /* Find out how many columns we should print in. */
958 1.1 christos limit = calling_window->width / max_label;
959 1.1 christos if (limit != 1 && (limit * max_label == calling_window->width))
960 1.1 christos limit--;
961 1.1 christos
962 1.1 christos /* Avoid a possible floating exception. If max_label > width then
963 1.1 christos the limit will be 0 and a divide-by-zero fault will result. */
964 1.1 christos if (limit == 0)
965 1.1 christos limit = 1;
966 1.1 christos
967 1.1 christos /* How many iterations of the printing loop? */
968 1.1 christos iterations = (completions_found_index + (limit - 1)) / limit;
969 1.1 christos
970 1.1 christos /* Watch out for special case. If the number of completions is less
971 1.1 christos than LIMIT, then just do the inner printing loop. */
972 1.1 christos if (completions_found_index < limit)
973 1.1 christos iterations = 1;
974 1.1 christos
975 1.1 christos /* Print the sorted items, up-and-down alphabetically. */
976 1.1 christos for (i = 0; i < iterations; i++)
977 1.1 christos {
978 1.1 christos register int j;
979 1.1 christos
980 1.1 christos for (j = 0, l = i; j < limit; j++)
981 1.1 christos {
982 1.1 christos if (l >= completions_found_index)
983 1.1 christos break;
984 1.1 christos else
985 1.1 christos {
986 1.1 christos char *label;
987 1.1 christos int printed_length, k;
988 1.1 christos
989 1.1 christos label = completions_found[l]->label;
990 1.1 christos printed_length = strlen (label);
991 1.1 christos printf_to_message_buffer ("%s", label, NULL, NULL);
992 1.1 christos
993 1.1 christos if (j + 1 < limit)
994 1.1 christos {
995 1.1 christos for (k = 0; k < max_label - printed_length; k++)
996 1.1 christos printf_to_message_buffer (" ", NULL, NULL, NULL);
997 1.1 christos }
998 1.1 christos }
999 1.1 christos l += iterations;
1000 1.1 christos }
1001 1.1 christos printf_to_message_buffer ("\n", NULL, NULL, NULL);
1002 1.1 christos }
1003 1.1 christos
1004 1.1 christos /* Make a new node to hold onto possible completions. Don't destroy
1005 1.1 christos dangling pointers. */
1006 1.1 christos {
1007 1.1 christos NODE *temp;
1008 1.1 christos
1009 1.1 christos temp = message_buffer_to_node ();
1010 1.1 christos add_gcable_pointer (temp->contents);
1011 1.1 christos name_internal_node (temp, compwin_name);
1012 1.1 christos possible_completions_output_node = temp;
1013 1.1 christos }
1014 1.1 christos
1015 1.1 christos /* Find a suitable window for displaying the completions output.
1016 1.1 christos First choice is an existing window showing completions output.
1017 1.1 christos If there is only one window, and it is large, make another
1018 1.1 christos (smaller) window, and use that one. Otherwise, use the caller's
1019 1.1 christos window. */
1020 1.1 christos {
1021 1.1 christos WINDOW *compwin;
1022 1.1 christos
1023 1.1 christos compwin = get_internal_info_window (compwin_name);
1024 1.1 christos
1025 1.1 christos if (!compwin)
1026 1.1 christos {
1027 1.1 christos /* If we can split the window to display most of the completion
1028 1.1 christos items, then do so. */
1029 1.1 christos if (calling_window->height > (iterations * 2)
1030 1.1 christos && calling_window->height / 2 >= WINDOW_MIN_SIZE)
1031 1.1 christos {
1032 1.1 christos int start, pagetop;
1033 1.1 christos #ifdef SPLIT_BEFORE_ACTIVE
1034 1.1 christos int end;
1035 1.1 christos #endif
1036 1.1 christos
1037 1.1 christos active_window = calling_window;
1038 1.1 christos
1039 1.1 christos /* Perhaps we can scroll this window on redisplay. */
1040 1.1 christos start = calling_window->first_row;
1041 1.1 christos pagetop = calling_window->pagetop;
1042 1.1 christos
1043 1.1 christos compwin =
1044 1.1 christos window_make_window (possible_completions_output_node);
1045 1.1 christos active_window = the_echo_area;
1046 1.1 christos window_change_window_height
1047 1.1 christos (compwin, -(compwin->height - (iterations + 2)));
1048 1.1 christos
1049 1.1 christos window_adjust_pagetop (calling_window);
1050 1.1 christos remember_calling_window (calling_window);
1051 1.1 christos
1052 1.1 christos #if defined (SPLIT_BEFORE_ACTIVE)
1053 1.1 christos /* If the pagetop hasn't changed, scrolling the calling
1054 1.1 christos window is a reasonable thing to do. */
1055 1.1 christos if (pagetop == calling_window->pagetop)
1056 1.1 christos {
1057 1.1 christos end = start + calling_window->height;
1058 1.1 christos display_scroll_display
1059 1.1 christos (start, end, calling_window->prev->height + 1);
1060 1.1 christos }
1061 1.1 christos #else /* !SPLIT_BEFORE_ACTIVE */
1062 1.1 christos /* If the pagetop has changed, set the new pagetop here. */
1063 1.1 christos if (pagetop != calling_window->pagetop)
1064 1.1 christos {
1065 1.1 christos int newtop = calling_window->pagetop;
1066 1.1 christos calling_window->pagetop = pagetop;
1067 1.1 christos set_window_pagetop (calling_window, newtop);
1068 1.1 christos }
1069 1.1 christos #endif /* !SPLIT_BEFORE_ACTIVE */
1070 1.1 christos
1071 1.1 christos echo_area_completions_window = compwin;
1072 1.1 christos remember_window_and_node (compwin, compwin->node);
1073 1.1 christos }
1074 1.1 christos else
1075 1.1 christos compwin = calling_window;
1076 1.1 christos }
1077 1.1 christos
1078 1.1 christos if (compwin->node != possible_completions_output_node)
1079 1.1 christos {
1080 1.1 christos window_set_node_of_window
1081 1.1 christos (compwin, possible_completions_output_node);
1082 1.1 christos remember_window_and_node (compwin, compwin->node);
1083 1.1 christos }
1084 1.1 christos
1085 1.1 christos display_update_display (windows);
1086 1.1 christos }
1087 1.1 christos }
1088 1.1 christos }
1089 1.1 christos
1090 1.1 christos DECLARE_INFO_COMMAND (ea_complete, _("Insert completion"))
1091 1.1 christos {
1092 1.1 christos if (!echo_area_completion_items)
1093 1.1 christos {
1094 1.1 christos ea_insert (window, count, key);
1095 1.1 christos return;
1096 1.1 christos }
1097 1.1 christos
1098 1.1 christos /* If KEY is SPC, and we are not forcing completion to take place, simply
1099 1.1 christos insert the key. */
1100 1.1 christos if (!echo_area_must_complete_p && key == SPC)
1101 1.1 christos {
1102 1.1 christos ea_insert (window, count, key);
1103 1.1 christos return;
1104 1.1 christos }
1105 1.1 christos
1106 1.1 christos if (ea_last_executed_command == (VFunction *) ea_complete)
1107 1.1 christos {
1108 1.1 christos /* If the keypress is a SPC character, and we have already tried
1109 1.1 christos completing once, and there are several completions, then check
1110 1.1 christos the batch of completions to see if any continue with a space.
1111 1.1 christos If there are some, insert the space character and continue. */
1112 1.1 christos if (key == SPC && completions_found_index > 1)
1113 1.1 christos {
1114 1.1 christos register int i, offset;
1115 1.1 christos
1116 1.1 christos offset = input_line_end - input_line_beg;
1117 1.1 christos
1118 1.1 christos for (i = 0; i < completions_found_index; i++)
1119 1.1 christos if (completions_found[i]->label[offset] == ' ')
1120 1.1 christos break;
1121 1.1 christos
1122 1.1 christos if (completions_found[i])
1123 1.1 christos ea_insert (window, 1, ' ');
1124 1.1 christos else
1125 1.1 christos {
1126 1.1 christos ea_possible_completions (window, count, key);
1127 1.1 christos return;
1128 1.1 christos }
1129 1.1 christos }
1130 1.1 christos else
1131 1.1 christos {
1132 1.1 christos ea_possible_completions (window, count, key);
1133 1.1 christos return;
1134 1.1 christos }
1135 1.1 christos }
1136 1.1 christos
1137 1.1 christos input_line_point = input_line_end;
1138 1.1 christos build_completions ();
1139 1.1 christos
1140 1.1 christos if (!completions_found_index)
1141 1.1 christos terminal_ring_bell ();
1142 1.1 christos else if (LCD_completion->label[0] == '\0')
1143 1.1 christos ea_possible_completions (window, count, key);
1144 1.1 christos else
1145 1.1 christos {
1146 1.1 christos register int i;
1147 1.1 christos input_line_point = input_line_end = input_line_beg;
1148 1.1 christos for (i = 0; LCD_completion->label[i]; i++)
1149 1.1 christos ea_insert (window, 1, LCD_completion->label[i]);
1150 1.1 christos }
1151 1.1 christos }
1152 1.1 christos
1153 1.1 christos /* Utility REFERENCE used to store possible LCD. */
1154 1.1 christos static REFERENCE LCD_reference = {
1155 1.1 christos (char *)NULL, (char *)NULL, (char *)NULL, 0, 0, 0
1156 1.1 christos };
1157 1.1 christos
1158 1.1 christos static void remove_completion_duplicates (void);
1159 1.1 christos
1160 1.1 christos /* Variables which remember the state of the most recent call
1161 1.1 christos to build_completions (). */
1162 1.1 christos static char *last_completion_request = (char *)NULL;
1163 1.1 christos static REFERENCE **last_completion_items = (REFERENCE **)NULL;
1164 1.1 christos
1165 1.1 christos /* How to tell the completion builder to reset internal state. */
1166 1.1 christos static void
1167 1.1 christos completions_must_be_rebuilt (void)
1168 1.1 christos {
1169 1.1 christos maybe_free (last_completion_request);
1170 1.1 christos last_completion_request = (char *)NULL;
1171 1.1 christos last_completion_items = (REFERENCE **)NULL;
1172 1.1 christos }
1173 1.1 christos
1174 1.1 christos /* Build a list of possible completions from echo_area_completion_items,
1175 1.1 christos and the contents of input_line. */
1176 1.1 christos static void
1177 1.1 christos build_completions (void)
1178 1.1 christos {
1179 1.1 christos register int i, len;
1180 1.1 christos register REFERENCE *entry;
1181 1.1 christos char *request;
1182 1.1 christos int informed_of_lengthy_job = 0;
1183 1.1 christos
1184 1.1 christos /* If there are no items to complete over, exit immediately. */
1185 1.1 christos if (!echo_area_completion_items)
1186 1.1 christos {
1187 1.1 christos completions_found_index = 0;
1188 1.1 christos LCD_completion = (REFERENCE *)NULL;
1189 1.1 christos return;
1190 1.1 christos }
1191 1.1 christos
1192 1.1 christos /* Check to see if this call to build completions is the same as the last
1193 1.1 christos call to build completions. */
1194 1.1 christos len = input_line_end - input_line_beg;
1195 1.1 christos request = (char *)xmalloc (1 + len);
1196 1.1 christos strncpy (request, &input_line[input_line_beg], len);
1197 1.1 christos request[len] = '\0';
1198 1.1 christos
1199 1.1 christos if (last_completion_request && last_completion_items &&
1200 1.1 christos last_completion_items == echo_area_completion_items &&
1201 1.1 christos (strcmp (last_completion_request, request) == 0))
1202 1.1 christos {
1203 1.1 christos free (request);
1204 1.1 christos return;
1205 1.1 christos }
1206 1.1 christos
1207 1.1 christos maybe_free (last_completion_request);
1208 1.1 christos last_completion_request = request;
1209 1.1 christos last_completion_items = echo_area_completion_items;
1210 1.1 christos
1211 1.1 christos /* Always start at the beginning of the list. */
1212 1.1 christos completions_found_index = 0;
1213 1.1 christos LCD_completion = (REFERENCE *)NULL;
1214 1.1 christos
1215 1.1 christos for (i = 0; (entry = echo_area_completion_items[i]); i++)
1216 1.1 christos {
1217 1.1 christos if (strncasecmp (request, entry->label, len) == 0)
1218 1.1 christos add_pointer_to_array (entry, completions_found_index,
1219 1.1 christos completions_found, completions_found_slots,
1220 1.1 christos 20, REFERENCE *);
1221 1.1 christos
1222 1.1 christos if (!informed_of_lengthy_job && completions_found_index > 100)
1223 1.1 christos {
1224 1.1 christos informed_of_lengthy_job = 1;
1225 1.1 christos window_message_in_echo_area ((char *) _("Building completions..."),
1226 1.1 christos NULL, NULL);
1227 1.1 christos }
1228 1.1 christos }
1229 1.1 christos
1230 1.1 christos if (!completions_found_index)
1231 1.1 christos return;
1232 1.1 christos
1233 1.1 christos /* Sort and prune duplicate entries from the completions array. */
1234 1.1 christos remove_completion_duplicates ();
1235 1.1 christos
1236 1.1 christos /* If there is only one completion, just return that. */
1237 1.1 christos if (completions_found_index == 1)
1238 1.1 christos {
1239 1.1 christos LCD_completion = completions_found[0];
1240 1.1 christos return;
1241 1.1 christos }
1242 1.1 christos
1243 1.1 christos /* Find the least common denominator. */
1244 1.1 christos {
1245 1.1 christos long shortest = 100000;
1246 1.1 christos
1247 1.1 christos for (i = 1; i < completions_found_index; i++)
1248 1.1 christos {
1249 1.1 christos register int j;
1250 1.1 christos int c1, c2;
1251 1.1 christos
1252 1.1 christos for (j = 0;
1253 1.1 christos (c1 = info_tolower (completions_found[i - 1]->label[j])) &&
1254 1.1 christos (c2 = info_tolower (completions_found[i]->label[j]));
1255 1.1 christos j++)
1256 1.1 christos if (c1 != c2)
1257 1.1 christos break;
1258 1.1 christos
1259 1.1 christos if (shortest > j)
1260 1.1 christos shortest = j;
1261 1.1 christos }
1262 1.1 christos
1263 1.1 christos maybe_free (LCD_reference.label);
1264 1.1 christos LCD_reference.label = (char *)xmalloc (1 + shortest);
1265 1.1 christos /* Since both the sorting done inside remove_completion_duplicates
1266 1.1 christos and all the comparisons above are case-insensitive, it's
1267 1.1 christos possible that the completion we are going to return is
1268 1.1 christos identical to what the user typed but for the letter-case. This
1269 1.1 christos is confusing, since the user could type FOOBAR<TAB> and get her
1270 1.1 christos string change letter-case for no good reason. So try to find a
1271 1.1 christos possible completion whose letter-case is identical, and if so,
1272 1.1 christos use that. */
1273 1.1 christos if (completions_found_index > 1)
1274 1.1 christos {
1275 1.1 christos int req_len = strlen (request);
1276 1.1 christos
1277 1.1 christos for (i = 0; i < completions_found_index; i++)
1278 1.1 christos if (strncmp (request, completions_found[i]->label, req_len) == 0)
1279 1.1 christos break;
1280 1.1 christos /* If none of the candidates match exactly, use the first one. */
1281 1.1 christos if (i >= completions_found_index)
1282 1.1 christos i = 0;
1283 1.1 christos }
1284 1.1 christos strncpy (LCD_reference.label, completions_found[i]->label, shortest);
1285 1.1 christos LCD_reference.label[shortest] = '\0';
1286 1.1 christos LCD_completion = &LCD_reference;
1287 1.1 christos }
1288 1.1 christos
1289 1.1 christos if (informed_of_lengthy_job)
1290 1.1 christos echo_area_initialize_node ();
1291 1.1 christos }
1292 1.1 christos
1293 1.1 christos /* Function called by qsort. */
1294 1.1 christos static int
1295 1.1 christos compare_references (const void *entry1, const void *entry2)
1296 1.1 christos {
1297 1.1 christos REFERENCE **e1 = (REFERENCE **) entry1;
1298 1.1 christos REFERENCE **e2 = (REFERENCE **) entry2;
1299 1.1 christos
1300 1.1 christos return (strcasecmp ((*e1)->label, (*e2)->label));
1301 1.1 christos }
1302 1.1 christos
1303 1.1 christos /* Prune duplicate entries from COMPLETIONS_FOUND. */
1304 1.1 christos static void
1305 1.1 christos remove_completion_duplicates (void)
1306 1.1 christos {
1307 1.1 christos register int i, j;
1308 1.1 christos REFERENCE **temp;
1309 1.1 christos int newlen;
1310 1.1 christos
1311 1.1 christos if (!completions_found_index)
1312 1.1 christos return;
1313 1.1 christos
1314 1.1 christos /* Sort the items. */
1315 1.1 christos qsort (completions_found, completions_found_index, sizeof (REFERENCE *),
1316 1.1 christos compare_references);
1317 1.1 christos
1318 1.1 christos for (i = 0, newlen = 1; i < completions_found_index - 1; i++)
1319 1.1 christos {
1320 1.1 christos if (strcmp (completions_found[i]->label,
1321 1.1 christos completions_found[i + 1]->label) == 0)
1322 1.1 christos completions_found[i] = (REFERENCE *)NULL;
1323 1.1 christos else
1324 1.1 christos newlen++;
1325 1.1 christos }
1326 1.1 christos
1327 1.1 christos /* We have marked all the dead slots. It is faster to copy the live slots
1328 1.1 christos twice than to prune the dead slots one by one. */
1329 1.1 christos temp = (REFERENCE **)xmalloc ((1 + newlen) * sizeof (REFERENCE *));
1330 1.1 christos for (i = 0, j = 0; i < completions_found_index; i++)
1331 1.1 christos if (completions_found[i])
1332 1.1 christos temp[j++] = completions_found[i];
1333 1.1 christos
1334 1.1 christos for (i = 0; i < newlen; i++)
1335 1.1 christos completions_found[i] = temp[i];
1336 1.1 christos
1337 1.1 christos completions_found[i] = (REFERENCE *)NULL;
1338 1.1 christos completions_found_index = newlen;
1339 1.1 christos free (temp);
1340 1.1 christos }
1341 1.1 christos
1342 1.1 christos /* Scroll the "other" window. If there is a window showing completions, scroll
1343 1.1 christos that one, otherwise scroll the window which was active on entering the read
1344 1.1 christos function. */
1345 1.1 christos DECLARE_INFO_COMMAND (ea_scroll_completions_window, _("Scroll the completions window"))
1346 1.1 christos {
1347 1.1 christos WINDOW *compwin;
1348 1.1 christos int old_pagetop;
1349 1.1 christos
1350 1.1 christos compwin = get_internal_info_window (compwin_name);
1351 1.1 christos
1352 1.1 christos if (!compwin)
1353 1.1 christos compwin = calling_window;
1354 1.1 christos
1355 1.1 christos old_pagetop = compwin->pagetop;
1356 1.1 christos
1357 1.1 christos /* Let info_scroll_forward () do the work, and print any messages that
1358 1.1 christos need to be displayed. */
1359 1.1 christos info_scroll_forward (compwin, count, key);
1360 1.1 christos }
1361 1.1 christos
1362 1.1 christos /* Function which gets called when an Info window is deleted while the
1363 1.1 christos echo area is active. WINDOW is the window which has just been deleted. */
1364 1.1 christos void
1365 1.1 christos echo_area_inform_of_deleted_window (WINDOW *window)
1366 1.1 christos {
1367 1.1 christos /* If this is the calling_window, forget what we remembered about it. */
1368 1.1 christos if (window == calling_window)
1369 1.1 christos {
1370 1.1 christos if (active_window != the_echo_area)
1371 1.1 christos remember_calling_window (active_window);
1372 1.1 christos else
1373 1.1 christos remember_calling_window (windows);
1374 1.1 christos }
1375 1.1 christos
1376 1.1 christos /* If this window was the echo_area_completions_window, then notice that
1377 1.1 christos the window has been deleted. */
1378 1.1 christos if (window == echo_area_completions_window)
1379 1.1 christos echo_area_completions_window = (WINDOW *)NULL;
1380 1.1 christos }
1381 1.1 christos
1382 1.1 christos /* **************************************************************** */
1384 1.1 christos /* */
1385 1.1 christos /* Pushing and Popping the Echo Area */
1386 1.1 christos /* */
1387 1.1 christos /* **************************************************************** */
1388 1.1 christos
1389 1.1 christos /* Push and Pop the echo area. */
1390 1.1 christos typedef struct {
1391 1.1 christos char *line;
1392 1.1 christos char *prompt;
1393 1.1 christos REFERENCE **comp_items;
1394 1.1 christos int point, beg, end;
1395 1.1 christos int must_complete;
1396 1.1 christos NODE node;
1397 1.1 christos WINDOW *compwin;
1398 1.1 christos } PUSHED_EA;
1399 1.1 christos
1400 1.1 christos static PUSHED_EA **pushed_echo_areas = (PUSHED_EA **)NULL;
1401 1.1 christos static int pushed_echo_areas_index = 0;
1402 1.1 christos static int pushed_echo_areas_slots = 0;
1403 1.1 christos
1404 1.1 christos /* Pushing the echo_area has a side effect of zeroing the completion_items. */
1405 1.1 christos static void
1406 1.1 christos push_echo_area (void)
1407 1.1 christos {
1408 1.1 christos PUSHED_EA *pushed;
1409 1.1 christos
1410 1.1 christos pushed = (PUSHED_EA *)xmalloc (sizeof (PUSHED_EA));
1411 1.1 christos pushed->line = xstrdup (input_line);
1412 1.1 christos pushed->prompt = input_line_prompt;
1413 1.1 christos pushed->point = input_line_point;
1414 1.1 christos pushed->beg = input_line_beg;
1415 1.1 christos pushed->end = input_line_end;
1416 1.1 christos pushed->node = input_line_node;
1417 1.1 christos pushed->comp_items = echo_area_completion_items;
1418 1.1 christos pushed->must_complete = echo_area_must_complete_p;
1419 1.1 christos pushed->compwin = echo_area_completions_window;
1420 1.1 christos
1421 1.1 christos add_pointer_to_array (pushed, pushed_echo_areas_index, pushed_echo_areas,
1422 1.1 christos pushed_echo_areas_slots, 4, PUSHED_EA *);
1423 1.1 christos
1424 1.1 christos echo_area_completion_items = (REFERENCE **)NULL;
1425 1.1 christos }
1426 1.1 christos
1427 1.1 christos static void
1428 1.1 christos pop_echo_area (void)
1429 1.1 christos {
1430 1.1 christos PUSHED_EA *popped;
1431 1.1 christos
1432 1.1 christos popped = pushed_echo_areas[--pushed_echo_areas_index];
1433 1.1 christos
1434 1.1 christos strcpy (input_line, popped->line);
1435 1.1 christos free (popped->line);
1436 1.1 christos input_line_prompt = popped->prompt;
1437 1.1 christos input_line_point = popped->point;
1438 1.1 christos input_line_beg = popped->beg;
1439 1.1 christos input_line_end = popped->end;
1440 1.1 christos input_line_node = popped->node;
1441 1.1 christos echo_area_completion_items = popped->comp_items;
1442 1.1 christos echo_area_must_complete_p = popped->must_complete;
1443 1.1 christos echo_area_completions_window = popped->compwin;
1444 1.1 christos completions_must_be_rebuilt ();
1445 1.1 christos
1446 1.1 christos /* If the completion window no longer exists, forget about it. */
1447 1.1 christos if (echo_area_completions_window)
1448 1.1 christos {
1449 1.1 christos register WINDOW *win;
1450 1.1 christos
1451 1.1 christos for (win = windows; win; win = win->next)
1452 1.1 christos if (echo_area_completions_window == win)
1453 1.1 christos break;
1454 1.1 christos
1455 1.1 christos /* If the window wasn't found, then it has already been deleted. */
1456 1.1 christos if (!win)
1457 1.1 christos echo_area_completions_window = (WINDOW *)NULL;
1458 1.1 christos }
1459 1.1 christos
1460 1.1 christos free (popped);
1461 1.1 christos }
1462 1.1 christos
1463 1.1 christos /* Returns non-zero if any of the prior stacked calls to read in the echo
1464 1.1 christos area produced a completions window. */
1465 1.1 christos static int
1466 1.1 christos echo_area_stack_contains_completions_p (void)
1467 1.1 christos {
1468 1.1 christos register int i;
1469 1.1 christos
1470 1.1 christos for (i = 0; i < pushed_echo_areas_index; i++)
1471 1.1 christos if (pushed_echo_areas[i]->compwin)
1472 1.1 christos return (1);
1473 1.1 christos
1474 1.1 christos return (0);
1475 1.1 christos }
1476 1.1 christos
1477 1.1 christos /* **************************************************************** */
1479 1.1 christos /* */
1480 1.1 christos /* Error Messages While Reading in Echo Area */
1481 1.1 christos /* */
1482 1.1 christos /* **************************************************************** */
1483 1.1 christos
1484 1.1 christos #if defined (HAVE_SYS_TIME_H)
1485 1.1 christos # include <sys/time.h>
1486 1.1 christos # define HAVE_STRUCT_TIMEVAL
1487 1.1 christos #endif /* HAVE_SYS_TIME_H */
1488 1.1 christos
1489 1.1 christos static void
1490 1.1 christos pause_or_input (void)
1491 1.1 christos {
1492 1.1 christos #ifdef FD_SET
1493 1.1 christos struct timeval timer;
1494 1.1 christos fd_set readfds;
1495 1.1 christos int ready;
1496 1.1 christos
1497 1.1 christos FD_ZERO (&readfds);
1498 1.1 christos FD_SET (fileno (stdin), &readfds);
1499 1.1 christos timer.tv_sec = 2;
1500 1.1 christos timer.tv_usec = 0;
1501 1.1 christos ready = select (fileno (stdin) + 1, &readfds, (fd_set *) NULL,
1502 1.1 christos (fd_set *) NULL, &timer);
1503 1.1 christos #endif /* FD_SET */
1504 1.1 christos }
1505 1.1 christos
1506 1.1 christos /* Print MESSAGE right after the end of the current line, and wait
1507 1.1 christos for input or a couple of seconds, whichever comes first. Then flush the
1508 1.1 christos informational message that was printed. */
1509 1.1 christos void
1510 1.1 christos inform_in_echo_area (const char *message)
1511 1.1 christos {
1512 1.1 christos int i;
1513 1.1 christos char *text;
1514 1.1 christos int avail = EA_MAX_INPUT + 1 - input_line_end;
1515 1.1 christos
1516 1.1 christos text = xstrdup (message);
1517 1.1 christos for (i = 0; text[i] && text[i] != '\n' && i < avail; i++)
1518 1.1 christos ;
1519 1.1 christos text[i] = 0;
1520 1.1 christos
1521 1.1 christos echo_area_initialize_node ();
1522 1.1 christos sprintf (&input_line[input_line_end], "%s[%s]\n",
1523 1.1 christos echo_area_is_active ? " ": "", text);
1524 1.1 christos free (text);
1525 1.1 christos the_echo_area->point = input_line_point;
1526 1.1 christos display_update_one_window (the_echo_area);
1527 display_cursor_at_point (active_window);
1528 fflush (stdout);
1529 pause_or_input ();
1530 echo_area_initialize_node ();
1531 }
1532