GDB (API)
|
00001 /* TUI support I/O functions. 00002 00003 Copyright (C) 1998-2013 Free Software Foundation, Inc. 00004 00005 Contributed by Hewlett-Packard Company. 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "target.h" 00024 #include "event-loop.h" 00025 #include "event-top.h" 00026 #include "command.h" 00027 #include "top.h" 00028 #include "tui/tui.h" 00029 #include "tui/tui-data.h" 00030 #include "tui/tui-io.h" 00031 #include "tui/tui-command.h" 00032 #include "tui/tui-win.h" 00033 #include "tui/tui-wingeneral.h" 00034 #include "tui/tui-file.h" 00035 #include "ui-out.h" 00036 #include "cli-out.h" 00037 #include <fcntl.h> 00038 #include <signal.h> 00039 #include <stdio.h> 00040 #include "filestuff.h" 00041 00042 #include "gdb_curses.h" 00043 00044 /* This redefines CTRL if it is not already defined, so it must come 00045 after terminal state releated include files like <term.h> and 00046 "gdb_curses.h". */ 00047 #include "readline/readline.h" 00048 00049 int 00050 key_is_start_sequence (int ch) 00051 { 00052 return (ch == 27); 00053 } 00054 00055 int 00056 key_is_end_sequence (int ch) 00057 { 00058 return (ch == 126); 00059 } 00060 00061 int 00062 key_is_backspace (int ch) 00063 { 00064 return (ch == 8); 00065 } 00066 00067 int 00068 key_is_command_char (int ch) 00069 { 00070 return ((ch == KEY_NPAGE) || (ch == KEY_PPAGE) 00071 || (ch == KEY_LEFT) || (ch == KEY_RIGHT) 00072 || (ch == KEY_UP) || (ch == KEY_DOWN) 00073 || (ch == KEY_SF) || (ch == KEY_SR) 00074 || (ch == (int)'\f') 00075 || key_is_start_sequence (ch)); 00076 } 00077 00078 /* Use definition from readline 4.3. */ 00079 #undef CTRL_CHAR 00080 #define CTRL_CHAR(c) \ 00081 ((c) < control_character_threshold && (((c) & 0x80) == 0)) 00082 00083 /* This file controls the IO interactions between gdb and curses. 00084 When the TUI is enabled, gdb has two modes a curses and a standard 00085 mode. 00086 00087 In curses mode, the gdb outputs are made in a curses command 00088 window. For this, the gdb_stdout and gdb_stderr are redirected to 00089 the specific ui_file implemented by TUI. The output is handled by 00090 tui_puts(). The input is also controlled by curses with 00091 tui_getc(). The readline library uses this function to get its 00092 input. Several readline hooks are installed to redirect readline 00093 output to the TUI (see also the note below). 00094 00095 In normal mode, the gdb outputs are restored to their origin, that 00096 is as if TUI is not used. Readline also uses its original getc() 00097 function with stdin. 00098 00099 Note SCz/2001-07-21: the current readline is not clean in its 00100 management of the output. Even if we install a redisplay handler, 00101 it sometimes writes on a stdout file. It is important to redirect 00102 every output produced by readline, otherwise the curses window will 00103 be garbled. This is implemented with a pipe that TUI reads and 00104 readline writes to. A gdb input handler is created so that reading 00105 the pipe is handled automatically. This will probably not work on 00106 non-Unix platforms. The best fix is to make readline clean enougth 00107 so that is never write on stdout. 00108 00109 Note SCz/2002-09-01: we now use more readline hooks and it seems 00110 that with them we don't need the pipe anymore (verified by creating 00111 the pipe and closing its end so that write causes a SIGPIPE). The 00112 old pipe code is still there and can be conditionally removed by 00113 #undef TUI_USE_PIPE_FOR_READLINE. */ 00114 00115 /* For gdb 5.3, prefer to continue the pipe hack as a backup wheel. */ 00116 #ifdef HAVE_PIPE 00117 #define TUI_USE_PIPE_FOR_READLINE 00118 #endif 00119 /* #undef TUI_USE_PIPE_FOR_READLINE */ 00120 00121 /* TUI output files. */ 00122 static struct ui_file *tui_stdout; 00123 static struct ui_file *tui_stderr; 00124 struct ui_out *tui_out; 00125 00126 /* GDB output files in non-curses mode. */ 00127 static struct ui_file *tui_old_stdout; 00128 static struct ui_file *tui_old_stderr; 00129 struct ui_out *tui_old_uiout; 00130 00131 /* Readline previous hooks. */ 00132 static Function *tui_old_rl_getc_function; 00133 static VFunction *tui_old_rl_redisplay_function; 00134 static VFunction *tui_old_rl_prep_terminal; 00135 static VFunction *tui_old_rl_deprep_terminal; 00136 static int tui_old_rl_echoing_p; 00137 00138 /* Readline output stream. 00139 Should be removed when readline is clean. */ 00140 static FILE *tui_rl_outstream; 00141 static FILE *tui_old_rl_outstream; 00142 #ifdef TUI_USE_PIPE_FOR_READLINE 00143 static int tui_readline_pipe[2]; 00144 #endif 00145 00146 /* The last gdb prompt that was registered in readline. 00147 This may be the main gdb prompt or a secondary prompt. */ 00148 static char *tui_rl_saved_prompt; 00149 00150 static unsigned int tui_handle_resize_during_io (unsigned int); 00151 00152 static void 00153 tui_putc (char c) 00154 { 00155 char buf[2]; 00156 00157 buf[0] = c; 00158 buf[1] = 0; 00159 tui_puts (buf); 00160 } 00161 00162 /* Print the string in the curses command window. */ 00163 void 00164 tui_puts (const char *string) 00165 { 00166 static int tui_skip_line = -1; 00167 char c; 00168 WINDOW *w; 00169 00170 w = TUI_CMD_WIN->generic.handle; 00171 while ((c = *string++) != 0) 00172 { 00173 /* Catch annotation and discard them. We need two \032 and 00174 discard until a \n is seen. */ 00175 if (c == '\032') 00176 { 00177 tui_skip_line++; 00178 } 00179 else if (tui_skip_line != 1) 00180 { 00181 tui_skip_line = -1; 00182 waddch (w, c); 00183 } 00184 else if (c == '\n') 00185 tui_skip_line = -1; 00186 } 00187 getyx (w, TUI_CMD_WIN->detail.command_info.cur_line, 00188 TUI_CMD_WIN->detail.command_info.curch); 00189 TUI_CMD_WIN->detail.command_info.start_line 00190 = TUI_CMD_WIN->detail.command_info.cur_line; 00191 00192 /* We could defer the following. */ 00193 wrefresh (w); 00194 fflush (stdout); 00195 } 00196 00197 /* Readline callback. 00198 Redisplay the command line with its prompt after readline has 00199 changed the edited text. */ 00200 void 00201 tui_redisplay_readline (void) 00202 { 00203 int prev_col; 00204 int height; 00205 int col, line; 00206 int c_pos; 00207 int c_line; 00208 int in; 00209 WINDOW *w; 00210 char *prompt; 00211 int start_line; 00212 00213 /* Detect when we temporarily left SingleKey and now the readline 00214 edit buffer is empty, automatically restore the SingleKey 00215 mode. The restore must only be done if the command has finished. 00216 The command could call prompt_for_continue and we must not 00217 restore SingleKey so that the prompt and normal keymap are used. */ 00218 if (tui_current_key_mode == TUI_ONE_COMMAND_MODE && rl_end == 0 00219 && immediate_quit == 0) 00220 tui_set_key_mode (TUI_SINGLE_KEY_MODE); 00221 00222 if (tui_current_key_mode == TUI_SINGLE_KEY_MODE) 00223 prompt = ""; 00224 else 00225 prompt = tui_rl_saved_prompt; 00226 00227 c_pos = -1; 00228 c_line = -1; 00229 w = TUI_CMD_WIN->generic.handle; 00230 start_line = TUI_CMD_WIN->detail.command_info.start_line; 00231 wmove (w, start_line, 0); 00232 prev_col = 0; 00233 height = 1; 00234 for (in = 0; prompt && prompt[in]; in++) 00235 { 00236 waddch (w, prompt[in]); 00237 getyx (w, line, col); 00238 if (col < prev_col) 00239 height++; 00240 prev_col = col; 00241 } 00242 for (in = 0; in < rl_end; in++) 00243 { 00244 unsigned char c; 00245 00246 c = (unsigned char) rl_line_buffer[in]; 00247 if (in == rl_point) 00248 { 00249 getyx (w, c_line, c_pos); 00250 } 00251 00252 if (CTRL_CHAR (c) || c == RUBOUT) 00253 { 00254 waddch (w, '^'); 00255 waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?'); 00256 } 00257 else 00258 { 00259 waddch (w, c); 00260 } 00261 if (c == '\n') 00262 { 00263 getyx (w, TUI_CMD_WIN->detail.command_info.start_line, 00264 TUI_CMD_WIN->detail.command_info.curch); 00265 } 00266 getyx (w, line, col); 00267 if (col < prev_col) 00268 height++; 00269 prev_col = col; 00270 } 00271 wclrtobot (w); 00272 getyx (w, TUI_CMD_WIN->detail.command_info.start_line, 00273 TUI_CMD_WIN->detail.command_info.curch); 00274 if (c_line >= 0) 00275 { 00276 wmove (w, c_line, c_pos); 00277 TUI_CMD_WIN->detail.command_info.cur_line = c_line; 00278 TUI_CMD_WIN->detail.command_info.curch = c_pos; 00279 } 00280 TUI_CMD_WIN->detail.command_info.start_line -= height - 1; 00281 00282 wrefresh (w); 00283 fflush(stdout); 00284 } 00285 00286 /* Readline callback to prepare the terminal. It is called once each 00287 time we enter readline. Terminal is already setup in curses 00288 mode. */ 00289 static void 00290 tui_prep_terminal (int notused1) 00291 { 00292 /* Save the prompt registered in readline to correctly display it. 00293 (we can't use gdb_prompt() due to secondary prompts and can't use 00294 rl_prompt because it points to an alloca buffer). */ 00295 xfree (tui_rl_saved_prompt); 00296 tui_rl_saved_prompt = xstrdup (rl_prompt); 00297 } 00298 00299 /* Readline callback to restore the terminal. It is called once each 00300 time we leave readline. There is nothing to do in curses mode. */ 00301 static void 00302 tui_deprep_terminal (void) 00303 { 00304 } 00305 00306 #ifdef TUI_USE_PIPE_FOR_READLINE 00307 /* Read readline output pipe and feed the command window with it. 00308 Should be removed when readline is clean. */ 00309 static void 00310 tui_readline_output (int error, gdb_client_data data) 00311 { 00312 int size; 00313 char buf[256]; 00314 00315 size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1); 00316 if (size > 0 && tui_active) 00317 { 00318 buf[size] = 0; 00319 tui_puts (buf); 00320 } 00321 } 00322 #endif 00323 00324 /* Return the portion of PATHNAME that should be output when listing 00325 possible completions. If we are hacking filename completion, we 00326 are only interested in the basename, the portion following the 00327 final slash. Otherwise, we return what we were passed. 00328 00329 Comes from readline/complete.c. */ 00330 static const char * 00331 printable_part (const char *pathname) 00332 { 00333 return rl_filename_completion_desired ? lbasename (pathname) : pathname; 00334 } 00335 00336 /* Output TO_PRINT to rl_outstream. If VISIBLE_STATS is defined and 00337 we are using it, check for and output a single character for 00338 `special' filenames. Return the number of characters we 00339 output. */ 00340 00341 #define PUTX(c) \ 00342 do { \ 00343 if (CTRL_CHAR (c)) \ 00344 { \ 00345 tui_puts ("^"); \ 00346 tui_putc (UNCTRL (c)); \ 00347 printed_len += 2; \ 00348 } \ 00349 else if (c == RUBOUT) \ 00350 { \ 00351 tui_puts ("^?"); \ 00352 printed_len += 2; \ 00353 } \ 00354 else \ 00355 { \ 00356 tui_putc (c); \ 00357 printed_len++; \ 00358 } \ 00359 } while (0) 00360 00361 static int 00362 print_filename (const char *to_print, const char *full_pathname) 00363 { 00364 int printed_len = 0; 00365 const char *s; 00366 00367 for (s = to_print; *s; s++) 00368 { 00369 PUTX (*s); 00370 } 00371 return printed_len; 00372 } 00373 00374 /* The user must press "y" or "n". Non-zero return means "y" pressed. 00375 Comes from readline/complete.c. */ 00376 static int 00377 get_y_or_n (void) 00378 { 00379 extern int _rl_abort_internal (); 00380 int c; 00381 00382 for (;;) 00383 { 00384 c = rl_read_key (); 00385 if (c == 'y' || c == 'Y' || c == ' ') 00386 return (1); 00387 if (c == 'n' || c == 'N' || c == RUBOUT) 00388 return (0); 00389 if (c == ABORT_CHAR) 00390 _rl_abort_internal (); 00391 beep (); 00392 } 00393 } 00394 00395 /* A convenience function for displaying a list of strings in 00396 columnar format on readline's output stream. MATCHES is the list 00397 of strings, in argv format, LEN is the number of strings in MATCHES, 00398 and MAX is the length of the longest string in MATCHES. 00399 00400 Comes from readline/complete.c and modified to write in 00401 the TUI command window using tui_putc/tui_puts. */ 00402 static void 00403 tui_rl_display_match_list (char **matches, int len, int max) 00404 { 00405 typedef int QSFUNC (const void *, const void *); 00406 extern int _rl_qsort_string_compare (const void *, 00407 const void *); 00408 extern int _rl_print_completions_horizontally; 00409 00410 int count, limit, printed_len; 00411 int i, j, k, l; 00412 const char *temp; 00413 00414 /* Screen dimension correspond to the TUI command window. */ 00415 int screenwidth = TUI_CMD_WIN->generic.width; 00416 00417 /* If there are many items, then ask the user if she really wants to 00418 see them all. */ 00419 if (len >= rl_completion_query_items) 00420 { 00421 char msg[256]; 00422 00423 xsnprintf (msg, sizeof (msg), 00424 "\nDisplay all %d possibilities? (y or n)", len); 00425 tui_puts (msg); 00426 if (get_y_or_n () == 0) 00427 { 00428 tui_puts ("\n"); 00429 return; 00430 } 00431 } 00432 00433 /* How many items of MAX length can we fit in the screen window? */ 00434 max += 2; 00435 limit = screenwidth / max; 00436 if (limit != 1 && (limit * max == screenwidth)) 00437 limit--; 00438 00439 /* Avoid a possible floating exception. If max > screenwidth, limit 00440 will be 0 and a divide-by-zero fault will result. */ 00441 if (limit == 0) 00442 limit = 1; 00443 00444 /* How many iterations of the printing loop? */ 00445 count = (len + (limit - 1)) / limit; 00446 00447 /* Watch out for special case. If LEN is less than LIMIT, then 00448 just do the inner printing loop. 00449 0 < len <= limit implies count = 1. */ 00450 00451 /* Sort the items if they are not already sorted. */ 00452 if (rl_ignore_completion_duplicates == 0) 00453 qsort (matches + 1, len, sizeof (char *), 00454 (QSFUNC *)_rl_qsort_string_compare); 00455 00456 tui_putc ('\n'); 00457 00458 if (_rl_print_completions_horizontally == 0) 00459 { 00460 /* Print the sorted items, up-and-down alphabetically, like ls. */ 00461 for (i = 1; i <= count; i++) 00462 { 00463 for (j = 0, l = i; j < limit; j++) 00464 { 00465 if (l > len || matches[l] == 0) 00466 break; 00467 else 00468 { 00469 temp = printable_part (matches[l]); 00470 printed_len = print_filename (temp, matches[l]); 00471 00472 if (j + 1 < limit) 00473 for (k = 0; k < max - printed_len; k++) 00474 tui_putc (' '); 00475 } 00476 l += count; 00477 } 00478 tui_putc ('\n'); 00479 } 00480 } 00481 else 00482 { 00483 /* Print the sorted items, across alphabetically, like ls -x. */ 00484 for (i = 1; matches[i]; i++) 00485 { 00486 temp = printable_part (matches[i]); 00487 printed_len = print_filename (temp, matches[i]); 00488 /* Have we reached the end of this line? */ 00489 if (matches[i+1]) 00490 { 00491 if (i && (limit > 1) && (i % limit) == 0) 00492 tui_putc ('\n'); 00493 else 00494 for (k = 0; k < max - printed_len; k++) 00495 tui_putc (' '); 00496 } 00497 } 00498 tui_putc ('\n'); 00499 } 00500 } 00501 00502 /* Setup the IO for curses or non-curses mode. 00503 - In non-curses mode, readline and gdb use the standard input and 00504 standard output/error directly. 00505 - In curses mode, the standard output/error is controlled by TUI 00506 with the tui_stdout and tui_stderr. The output is redirected in 00507 the curses command window. Several readline callbacks are installed 00508 so that readline asks for its input to the curses command window 00509 with wgetch(). */ 00510 void 00511 tui_setup_io (int mode) 00512 { 00513 extern int _rl_echoing_p; 00514 00515 if (mode) 00516 { 00517 /* Redirect readline to TUI. */ 00518 tui_old_rl_redisplay_function = rl_redisplay_function; 00519 tui_old_rl_deprep_terminal = rl_deprep_term_function; 00520 tui_old_rl_prep_terminal = rl_prep_term_function; 00521 tui_old_rl_getc_function = rl_getc_function; 00522 tui_old_rl_outstream = rl_outstream; 00523 tui_old_rl_echoing_p = _rl_echoing_p; 00524 rl_redisplay_function = tui_redisplay_readline; 00525 rl_deprep_term_function = tui_deprep_terminal; 00526 rl_prep_term_function = tui_prep_terminal; 00527 rl_getc_function = tui_getc; 00528 _rl_echoing_p = 0; 00529 rl_outstream = tui_rl_outstream; 00530 rl_prompt = 0; 00531 rl_completion_display_matches_hook = tui_rl_display_match_list; 00532 rl_already_prompted = 0; 00533 00534 /* Keep track of previous gdb output. */ 00535 tui_old_stdout = gdb_stdout; 00536 tui_old_stderr = gdb_stderr; 00537 tui_old_uiout = current_uiout; 00538 00539 /* Reconfigure gdb output. */ 00540 gdb_stdout = tui_stdout; 00541 gdb_stderr = tui_stderr; 00542 gdb_stdlog = gdb_stdout; /* for moment */ 00543 gdb_stdtarg = gdb_stderr; /* for moment */ 00544 gdb_stdtargerr = gdb_stderr; /* for moment */ 00545 current_uiout = tui_out; 00546 00547 /* Save tty for SIGCONT. */ 00548 savetty (); 00549 } 00550 else 00551 { 00552 /* Restore gdb output. */ 00553 gdb_stdout = tui_old_stdout; 00554 gdb_stderr = tui_old_stderr; 00555 gdb_stdlog = gdb_stdout; /* for moment */ 00556 gdb_stdtarg = gdb_stderr; /* for moment */ 00557 gdb_stdtargerr = gdb_stderr; /* for moment */ 00558 current_uiout = tui_old_uiout; 00559 00560 /* Restore readline. */ 00561 rl_redisplay_function = tui_old_rl_redisplay_function; 00562 rl_deprep_term_function = tui_old_rl_deprep_terminal; 00563 rl_prep_term_function = tui_old_rl_prep_terminal; 00564 rl_getc_function = tui_old_rl_getc_function; 00565 rl_outstream = tui_old_rl_outstream; 00566 rl_completion_display_matches_hook = 0; 00567 _rl_echoing_p = tui_old_rl_echoing_p; 00568 rl_already_prompted = 0; 00569 00570 /* Save tty for SIGCONT. */ 00571 savetty (); 00572 } 00573 } 00574 00575 #ifdef SIGCONT 00576 /* Catch SIGCONT to restore the terminal and refresh the screen. */ 00577 static void 00578 tui_cont_sig (int sig) 00579 { 00580 if (tui_active) 00581 { 00582 /* Restore the terminal setting because another process (shell) 00583 might have changed it. */ 00584 resetty (); 00585 00586 /* Force a refresh of the screen. */ 00587 tui_refresh_all_win (); 00588 00589 /* Update cursor position on the screen. */ 00590 wmove (TUI_CMD_WIN->generic.handle, 00591 TUI_CMD_WIN->detail.command_info.start_line, 00592 TUI_CMD_WIN->detail.command_info.curch); 00593 wrefresh (TUI_CMD_WIN->generic.handle); 00594 } 00595 signal (sig, tui_cont_sig); 00596 } 00597 #endif 00598 00599 /* Initialize the IO for gdb in curses mode. */ 00600 void 00601 tui_initialize_io (void) 00602 { 00603 #ifdef SIGCONT 00604 signal (SIGCONT, tui_cont_sig); 00605 #endif 00606 00607 /* Create tui output streams. */ 00608 tui_stdout = tui_fileopen (stdout); 00609 tui_stderr = tui_fileopen (stderr); 00610 tui_out = tui_out_new (tui_stdout); 00611 00612 /* Create the default UI. */ 00613 tui_old_uiout = cli_out_new (gdb_stdout); 00614 00615 #ifdef TUI_USE_PIPE_FOR_READLINE 00616 /* Temporary solution for readline writing to stdout: redirect 00617 readline output in a pipe, read that pipe and output the content 00618 in the curses command window. */ 00619 if (gdb_pipe_cloexec (tui_readline_pipe) != 0) 00620 { 00621 fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline"); 00622 exit (1); 00623 } 00624 tui_rl_outstream = fdopen (tui_readline_pipe[1], "w"); 00625 if (tui_rl_outstream == 0) 00626 { 00627 fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output"); 00628 exit (1); 00629 } 00630 setvbuf (tui_rl_outstream, (char*) NULL, _IOLBF, 0); 00631 00632 #ifdef O_NONBLOCK 00633 (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK); 00634 #else 00635 #ifdef O_NDELAY 00636 (void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY); 00637 #endif 00638 #endif 00639 add_file_handler (tui_readline_pipe[0], tui_readline_output, 0); 00640 #else 00641 tui_rl_outstream = stdout; 00642 #endif 00643 } 00644 00645 /* Get a character from the command window. This is called from the 00646 readline package. */ 00647 int 00648 tui_getc (FILE *fp) 00649 { 00650 int ch; 00651 WINDOW *w; 00652 00653 w = TUI_CMD_WIN->generic.handle; 00654 00655 #ifdef TUI_USE_PIPE_FOR_READLINE 00656 /* Flush readline output. */ 00657 tui_readline_output (0, 0); 00658 #endif 00659 00660 ch = wgetch (w); 00661 ch = tui_handle_resize_during_io (ch); 00662 00663 /* The \n must be echoed because it will not be printed by 00664 readline. */ 00665 if (ch == '\n') 00666 { 00667 /* When hitting return with an empty input, gdb executes the last 00668 command. If we emit a newline, this fills up the command window 00669 with empty lines with gdb prompt at beginning. Instead of that, 00670 stay on the same line but provide a visual effect to show the 00671 user we recognized the command. */ 00672 if (rl_end == 0) 00673 { 00674 wmove (w, TUI_CMD_WIN->detail.command_info.cur_line, 0); 00675 00676 /* Clear the line. This will blink the gdb prompt since 00677 it will be redrawn at the same line. */ 00678 wclrtoeol (w); 00679 wrefresh (w); 00680 napms (20); 00681 } 00682 else 00683 { 00684 wmove (w, TUI_CMD_WIN->detail.command_info.cur_line, 00685 TUI_CMD_WIN->detail.command_info.curch); 00686 waddch (w, ch); 00687 } 00688 } 00689 00690 if (key_is_command_char (ch)) 00691 { /* Handle prev/next/up/down here. */ 00692 ch = tui_dispatch_ctrl_char (ch); 00693 } 00694 00695 if (ch == '\n' || ch == '\r' || ch == '\f') 00696 TUI_CMD_WIN->detail.command_info.curch = 0; 00697 if (ch == KEY_BACKSPACE) 00698 return '\b'; 00699 00700 return ch; 00701 } 00702 00703 00704 /* Cleanup when a resize has occured. 00705 Returns the character that must be processed. */ 00706 static unsigned int 00707 tui_handle_resize_during_io (unsigned int original_ch) 00708 { 00709 if (tui_win_resized ()) 00710 { 00711 tui_resize_all (); 00712 tui_refresh_all_win (); 00713 dont_repeat (); 00714 tui_set_win_resized_to (FALSE); 00715 return '\n'; 00716 } 00717 else 00718 return original_ch; 00719 }