1 1.2 christos /* $NetBSD: echo-area.c,v 1.2 2016/01/14 00:34:52 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.2 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*)((intptr_t)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