2b9ccae8c980fd3572bfd44891bfb6fc1caa094c
[deliverable/binutils-gdb.git] / gdb / tui / tui.c
1 /* General functions for the WDB TUI.
2
3 Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation,
4 Inc.
5
6 Contributed by Hewlett-Packard Company.
7
8 This file is part of GDB.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330,
23 Boston, MA 02111-1307, USA. */
24
25 /* FIXME: cagney/2002-02-28: The GDB coding standard indicates that
26 "defs.h" should be included first. Unfortunatly some systems
27 (currently Debian GNU/Linux) include the <stdbool.h> via <curses.h>
28 and they clash with "bfd.h"'s definiton of true/false. The correct
29 fix is to remove true/false from "bfd.h", however, until that
30 happens, hack around it by including "config.h" and <curses.h>
31 first. */
32
33 #include "config.h"
34 #ifdef HAVE_NCURSES_H
35 #include <ncurses.h>
36 #else
37 #ifdef HAVE_CURSES_H
38 #include <curses.h>
39 #endif
40 #endif
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <ctype.h>
45 #include <malloc.h>
46 #ifdef HAVE_TERM_H
47 #include <term.h>
48 #endif
49 #include <signal.h>
50 #include <fcntl.h>
51 #if 0
52 #include <termio.h>
53 #endif
54 #include <setjmp.h>
55 #include "defs.h"
56 #include "gdbcmd.h"
57 #include "tui.h"
58 #include "tuiData.h"
59 #include "tuiLayout.h"
60 #include "tuiIO.h"
61 #include "tuiRegs.h"
62 #include "tuiStack.h"
63 #include "tuiWin.h"
64 #include "tuiSourceWin.h"
65 #include "readline/readline.h"
66 #include "target.h"
67 #include "frame.h"
68 #include "breakpoint.h"
69 #include "inferior.h"
70
71 /* Tells whether the TUI is active or not. */
72 int tui_active = 0;
73 static int tui_finish_init = 1;
74
75 /* Switch the output mode between TUI/standard gdb. */
76 static int
77 tui_rl_switch_mode (void)
78 {
79 if (tui_active)
80 {
81 tui_disable ();
82 rl_prep_terminal (0);
83
84 printf_filtered ("Left the TUI mode\n");
85 }
86 else
87 {
88 rl_deprep_terminal ();
89 tui_enable ();
90 printf_filtered ("Entered the TUI mode\n");
91 }
92
93 /* Clear the readline in case switching occurred in middle of something. */
94 if (rl_end)
95 rl_kill_text (0, rl_end);
96
97 /* Since we left the curses mode, the terminal mode is restored to
98 some previous state. That state may not be suitable for readline
99 to work correctly (it may be restored in line mode). We force an
100 exit of the current readline so that readline is re-entered and it
101 will be able to setup the terminal for its needs. By re-entering
102 in readline, we also redisplay its prompt in the non-curses mode. */
103 rl_newline (1, '\n');
104
105 /* Make sure the \n we are returning does not repeat the last command. */
106 dont_repeat ();
107 return 0;
108 }
109
110 /* TUI readline command.
111 Change the TUI layout to show a next layout.
112 This function is bound to CTRL-X 2. It is intended to provide
113 a functionality close to the Emacs split-window command. We always
114 show two windows (src+asm), (src+regs) or (asm+regs). */
115 static int
116 tui_rl_change_windows (void)
117 {
118 if (!tui_active)
119 tui_rl_switch_mode ();
120
121 if (tui_active)
122 {
123 TuiLayoutType new_layout;
124 TuiRegisterDisplayType regs_type = TUI_UNDEFINED_REGS;
125
126 new_layout = currentLayout ();
127
128 /* Select a new layout to have a rolling layout behavior
129 with always two windows (except when undefined). */
130 switch (new_layout)
131 {
132 case SRC_COMMAND:
133 new_layout = SRC_DISASSEM_COMMAND;
134 break;
135
136 case DISASSEM_COMMAND:
137 new_layout = SRC_DISASSEM_COMMAND;
138 break;
139
140 case SRC_DATA_COMMAND:
141 new_layout = SRC_DISASSEM_COMMAND;
142 break;
143
144 case SRC_DISASSEM_COMMAND:
145 new_layout = DISASSEM_DATA_COMMAND;
146 break;
147
148 case DISASSEM_DATA_COMMAND:
149 new_layout = SRC_DATA_COMMAND;
150 break;
151
152 default:
153 new_layout = SRC_COMMAND;
154 break;
155 }
156 tuiSetLayout (new_layout, regs_type);
157 }
158 return 0;
159 }
160
161 /* TUI readline command.
162 Delete the second TUI window to only show one. */
163 static int
164 tui_rl_delete_other_windows (void)
165 {
166 if (!tui_active)
167 tui_rl_switch_mode ();
168
169 if (tui_active)
170 {
171 TuiLayoutType new_layout;
172 TuiRegisterDisplayType regs_type = TUI_UNDEFINED_REGS;
173
174 new_layout = currentLayout ();
175
176 /* Kill one window. */
177 switch (new_layout)
178 {
179 case SRC_COMMAND:
180 case SRC_DATA_COMMAND:
181 case SRC_DISASSEM_COMMAND:
182 default:
183 new_layout = SRC_COMMAND;
184 break;
185
186 case DISASSEM_COMMAND:
187 case DISASSEM_DATA_COMMAND:
188 new_layout = DISASSEM_COMMAND;
189 break;
190 }
191 tuiSetLayout (new_layout, regs_type);
192 }
193 return 0;
194 }
195
196 /* Initialize readline and configure the keymap for the switching
197 key shortcut. */
198 void
199 tui_initialize_readline ()
200 {
201 rl_initialize ();
202
203 rl_add_defun ("tui-switch-mode", tui_rl_switch_mode, -1);
204 rl_bind_key_in_map ('a', tui_rl_switch_mode, emacs_ctlx_keymap);
205 rl_bind_key_in_map ('A', tui_rl_switch_mode, emacs_ctlx_keymap);
206 rl_bind_key_in_map (CTRL ('A'), tui_rl_switch_mode, emacs_ctlx_keymap);
207 rl_bind_key_in_map ('1', tui_rl_delete_other_windows, emacs_ctlx_keymap);
208 rl_bind_key_in_map ('2', tui_rl_change_windows, emacs_ctlx_keymap);
209 }
210
211 /* Enter in the tui mode (curses).
212 When in normal mode, it installs the tui hooks in gdb, redirects
213 the gdb output, configures the readline to work in tui mode.
214 When in curses mode, it does nothing. */
215 void
216 tui_enable (void)
217 {
218 if (tui_active)
219 return;
220
221 /* To avoid to initialize curses when gdb starts, there is a defered
222 curses initialization. This initialization is made only once
223 and the first time the curses mode is entered. */
224 if (tui_finish_init)
225 {
226 WINDOW *w;
227
228 w = initscr ();
229
230 cbreak ();
231 noecho ();
232 /*timeout (1);*/
233 nodelay(w, FALSE);
234 nl();
235 keypad (w, TRUE);
236 rl_initialize ();
237 setTermHeightTo (LINES);
238 setTermWidthTo (COLS);
239 def_prog_mode ();
240
241 tuiShowFrameInfo (0);
242 tuiSetLayout (SRC_COMMAND, TUI_UNDEFINED_REGS);
243 tuiSetWinFocusTo (srcWin);
244 keypad (cmdWin->generic.handle, TRUE);
245 wrefresh (cmdWin->generic.handle);
246 tui_finish_init = 0;
247 }
248 else
249 {
250 /* Save the current gdb setting of the terminal.
251 Curses will restore this state when endwin() is called. */
252 def_shell_mode ();
253 clearok (stdscr, TRUE);
254 }
255
256 /* Install the TUI specific hooks. */
257 tui_install_hooks ();
258
259 tui_update_variables ();
260
261 tui_setup_io (1);
262
263 tui_version = 1;
264 tui_active = 1;
265 if (selected_frame)
266 tuiShowFrameInfo (selected_frame);
267
268 refresh ();
269
270 /* Update gdb's knowledge of its terminal. */
271 target_terminal_save_ours ();
272 tui_update_gdb_sizes ();
273 }
274
275 /* Leave the tui mode.
276 Remove the tui hooks and configure the gdb output and readline
277 back to their original state. The curses mode is left so that
278 the terminal setting is restored to the point when we entered. */
279 void
280 tui_disable (void)
281 {
282 if (!tui_active)
283 return;
284
285 /* Remove TUI hooks. */
286 tui_remove_hooks ();
287
288 /* Leave curses and restore previous gdb terminal setting. */
289 endwin ();
290
291 /* gdb terminal has changed, update gdb internal copy of it
292 so that terminal management with the inferior works. */
293 tui_setup_io (0);
294
295 /* Update gdb's knowledge of its terminal. */
296 target_terminal_save_ours ();
297
298 tui_version = 0;
299 tui_active = 0;
300 tui_update_gdb_sizes ();
301 }
302
303 /* Wrapper on top of free() to ensure that input address
304 is greater than 0x0. */
305 void
306 tuiFree (char *ptr)
307 {
308 if (ptr != (char *) NULL)
309 {
310 xfree (ptr);
311 }
312 }
313
314 /* Determine what the low address will be to display in the TUI's
315 disassembly window. This may or may not be the same as the
316 low address input. */
317 CORE_ADDR
318 tuiGetLowDisassemblyAddress (CORE_ADDR low, CORE_ADDR pc)
319 {
320 int line;
321 CORE_ADDR newLow;
322
323 /* Determine where to start the disassembly so that the pc is about in the
324 middle of the viewport. */
325 for (line = 0, newLow = pc;
326 (newLow > low &&
327 line < (tuiDefaultWinViewportHeight (DISASSEM_WIN,
328 DISASSEM_COMMAND) / 2));)
329 {
330 bfd_byte buffer[4];
331
332 newLow -= sizeof (bfd_getb32 (buffer));
333 line++;
334 }
335
336 return newLow;
337 }
338
339 void
340 strcat_to_buf (char *buf, int buflen, const char *itemToAdd)
341 {
342 if (itemToAdd != (char *) NULL && buf != (char *) NULL)
343 {
344 if ((strlen (buf) + strlen (itemToAdd)) <= buflen)
345 strcat (buf, itemToAdd);
346 else
347 strncat (buf, itemToAdd, (buflen - strlen (buf)));
348 }
349 }
350
351 #if 0
352 /* Solaris <sys/termios.h> defines CTRL. */
353 #ifndef CTRL
354 #define CTRL(x) (x & ~0140)
355 #endif
356
357 #define FILEDES 2
358 #define CHK(val, dft) (val<=0 ? dft : val)
359
360 static void
361 _tuiReset (void)
362 {
363 struct termio mode;
364
365 /*
366 ** reset the teletype mode bits to a sensible state.
367 ** Copied tset.c
368 */
369 #if ! defined (USG) && defined (TIOCGETC)
370 struct tchars tbuf;
371 #endif /* !USG && TIOCGETC */
372 #ifdef UCB_NTTY
373 struct ltchars ltc;
374
375 if (ldisc == NTTYDISC)
376 {
377 ioctl (FILEDES, TIOCGLTC, &ltc);
378 ltc.t_suspc = CHK (ltc.t_suspc, CTRL ('Z'));
379 ltc.t_dsuspc = CHK (ltc.t_dsuspc, CTRL ('Y'));
380 ltc.t_rprntc = CHK (ltc.t_rprntc, CTRL ('R'));
381 ltc.t_flushc = CHK (ltc.t_flushc, CTRL ('O'));
382 ltc.t_werasc = CHK (ltc.t_werasc, CTRL ('W'));
383 ltc.t_lnextc = CHK (ltc.t_lnextc, CTRL ('V'));
384 ioctl (FILEDES, TIOCSLTC, &ltc);
385 }
386 #endif /* UCB_NTTY */
387 #ifndef USG
388 #ifdef TIOCGETC
389 ioctl (FILEDES, TIOCGETC, &tbuf);
390 tbuf.t_intrc = CHK (tbuf.t_intrc, CTRL ('?'));
391 tbuf.t_quitc = CHK (tbuf.t_quitc, CTRL ('\\'));
392 tbuf.t_startc = CHK (tbuf.t_startc, CTRL ('Q'));
393 tbuf.t_stopc = CHK (tbuf.t_stopc, CTRL ('S'));
394 tbuf.t_eofc = CHK (tbuf.t_eofc, CTRL ('D'));
395 /* brkc is left alone */
396 ioctl (FILEDES, TIOCSETC, &tbuf);
397 #endif /* TIOCGETC */
398 mode.sg_flags &= ~(RAW
399 #ifdef CBREAK
400 | CBREAK
401 #endif /* CBREAK */
402 | VTDELAY | ALLDELAY);
403 mode.sg_flags |= XTABS | ECHO | CRMOD | ANYP;
404 #else /*USG */
405 ioctl (FILEDES, TCGETA, &mode);
406 mode.c_cc[VINTR] = CHK (mode.c_cc[VINTR], CTRL ('?'));
407 mode.c_cc[VQUIT] = CHK (mode.c_cc[VQUIT], CTRL ('\\'));
408 mode.c_cc[VEOF] = CHK (mode.c_cc[VEOF], CTRL ('D'));
409
410 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | INLCR | IGNCR | IUCLC | IXOFF);
411 mode.c_iflag |= (BRKINT | ISTRIP | ICRNL | IXON);
412 mode.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |
413 NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
414 mode.c_oflag |= (OPOST | ONLCR);
415 mode.c_cflag &= ~(CSIZE | PARODD | CLOCAL);
416 #ifndef hp9000s800
417 mode.c_cflag |= (CS8 | CREAD);
418 #else /*hp9000s800 */
419 mode.c_cflag |= (CS8 | CSTOPB | CREAD);
420 #endif /* hp9000s800 */
421 mode.c_lflag &= ~(XCASE | ECHONL | NOFLSH);
422 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOK);
423 ioctl (FILEDES, TCSETAW, &mode);
424 #endif /* USG */
425
426 return;
427 } /* _tuiReset */
428 #endif
429
430 void
431 tui_show_source (const char *file, int line)
432 {
433 /* make sure that the source window is displayed */
434 tuiAddWinToLayout (SRC_WIN);
435
436 tuiUpdateSourceWindowsWithLine (current_source_symtab, line);
437 tuiUpdateLocatorFilename (file);
438 }
439
440 void
441 tui_show_assembly (CORE_ADDR addr)
442 {
443 tuiAddWinToLayout (DISASSEM_WIN);
444 tuiUpdateSourceWindowsWithAddr (addr);
445 }
446
447 int
448 tui_is_window_visible (TuiWinType type)
449 {
450 if (tui_version == 0)
451 return 0;
452
453 if (winList[type] == 0)
454 return 0;
455
456 return winList[type]->generic.isVisible;
457 }
458
459 int
460 tui_get_command_dimension (int *width, int *height)
461 {
462 if (!tui_version || !m_winPtrNotNull (cmdWin))
463 {
464 return 0;
465 }
466
467 *width = cmdWin->generic.width;
468 *height = cmdWin->generic.height;
469 return 1;
470 }
This page took 0.042508 seconds and 3 git commands to generate.