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