Fix PR gdb/393:
[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>
6d7fbb5a 51#if 0
c906108c 52#include <termio.h>
6d7fbb5a 53#endif
c906108c
SS
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"
377c38ea 62#include "tuiStack.h"
c906108c 63#include "tuiWin.h"
c6f60bcd 64#include "tuiSourceWin.h"
39db33d6
SC
65#include "readline/readline.h"
66#include "target.h"
67#include "frame.h"
68#include "breakpoint.h"
c6f60bcd 69#include "inferior.h"
39db33d6
SC
70
71/* Tells whether the TUI is active or not. */
72int tui_active = 0;
73static int tui_finish_init = 1;
74
75/* Switch the output mode between TUI/standard gdb. */
76static int
6ba6ffa2 77tui_rl_switch_mode (void)
c906108c 78{
39db33d6 79 if (tui_active)
c906108c 80 {
39db33d6 81 tui_disable ();
c6f60bcd
SC
82 rl_prep_terminal (0);
83
39db33d6
SC
84 printf_filtered ("Left the TUI mode\n");
85 }
86 else
87 {
c6f60bcd 88 rl_deprep_terminal ();
39db33d6
SC
89 tui_enable ();
90 printf_filtered ("Entered the TUI mode\n");
c906108c 91 }
c906108c 92
39db33d6
SC
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');
c6f60bcd
SC
104
105 /* Make sure the \n we are returning does not repeat the last command. */
106 dont_repeat ();
39db33d6
SC
107 return 0;
108}
c906108c 109
6ba6ffa2
SC
110/* TUI readline command.
111 Change the TUI layout to show a next layout.
377c38ea
SC
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). */
115static int
6ba6ffa2 116tui_rl_change_windows (void)
377c38ea
SC
117{
118 if (!tui_active)
6ba6ffa2 119 tui_rl_switch_mode ();
377c38ea
SC
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
6ba6ffa2
SC
161/* TUI readline command.
162 Delete the second TUI window to only show one. */
377c38ea 163static int
6ba6ffa2 164tui_rl_delete_other_windows (void)
377c38ea
SC
165{
166 if (!tui_active)
6ba6ffa2 167 tui_rl_switch_mode ();
377c38ea
SC
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
39db33d6
SC
196/* Initialize readline and configure the keymap for the switching
197 key shortcut. */
c906108c 198void
39db33d6 199tui_initialize_readline ()
c906108c 200{
39db33d6 201 rl_initialize ();
c906108c 202
6ba6ffa2
SC
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);
39db33d6 209}
c906108c 210
39db33d6
SC
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. */
c906108c 215void
39db33d6 216tui_enable (void)
c906108c 217{
39db33d6
SC
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)
c906108c 225 {
39db33d6
SC
226 WINDOW *w;
227
228 w = initscr ();
229
377c38ea
SC
230 cbreak ();
231 noecho ();
39db33d6
SC
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
c7037be1
SC
241 tuiShowFrameInfo (0);
242 tuiSetLayout (SRC_COMMAND, TUI_UNDEFINED_REGS);
39db33d6 243 tuiSetWinFocusTo (srcWin);
377c38ea 244 keypad (cmdWin->generic.handle, TRUE);
39db33d6
SC
245 wrefresh (cmdWin->generic.handle);
246 tui_finish_init = 0;
c906108c 247 }
39db33d6
SC
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 }
c906108c 255
39db33d6
SC
256 /* Install the TUI specific hooks. */
257 tui_install_hooks ();
c906108c 258
377c38ea
SC
259 tui_update_variables ();
260
39db33d6 261 tui_setup_io (1);
c906108c 262
39db33d6
SC
263 tui_version = 1;
264 tui_active = 1;
297d1607
SC
265 if (selected_frame)
266 tuiShowFrameInfo (selected_frame);
267
39db33d6 268 refresh ();
3e752b04 269 tui_update_gdb_sizes ();
39db33d6
SC
270}
271
272/* Leave the tui mode.
273 Remove the tui hooks and configure the gdb output and readline
274 back to their original state. The curses mode is left so that
275 the terminal setting is restored to the point when we entered. */
c906108c 276void
39db33d6 277tui_disable (void)
c906108c 278{
39db33d6
SC
279 if (!tui_active)
280 return;
c906108c 281
39db33d6
SC
282 /* Remove TUI hooks. */
283 tui_remove_hooks ();
c906108c 284
39db33d6
SC
285 /* Leave curses and restore previous gdb terminal setting. */
286 endwin ();
c906108c 287
39db33d6
SC
288 /* gdb terminal has changed, update gdb internal copy of it
289 so that terminal management with the inferior works. */
290 tui_setup_io (0);
c906108c 291
39db33d6
SC
292 tui_version = 0;
293 tui_active = 0;
3e752b04 294 tui_update_gdb_sizes ();
39db33d6 295}
c906108c 296
39db33d6
SC
297/* Wrapper on top of free() to ensure that input address
298 is greater than 0x0. */
c906108c 299void
eca6576c 300tuiFree (char *ptr)
c906108c
SS
301{
302 if (ptr != (char *) NULL)
303 {
b8c9b27d 304 xfree (ptr);
c906108c 305 }
39db33d6 306}
c906108c 307
39db33d6
SC
308/* Determine what the low address will be to display in the TUI's
309 disassembly window. This may or may not be the same as the
310 low address input. */
311CORE_ADDR
312tuiGetLowDisassemblyAddress (CORE_ADDR low, CORE_ADDR pc)
c906108c
SS
313{
314 int line;
c6f60bcd 315 CORE_ADDR newLow;
c906108c 316
39db33d6
SC
317 /* Determine where to start the disassembly so that the pc is about in the
318 middle of the viewport. */
c906108c
SS
319 for (line = 0, newLow = pc;
320 (newLow > low &&
321 line < (tuiDefaultWinViewportHeight (DISASSEM_WIN,
322 DISASSEM_COMMAND) / 2));)
323 {
324 bfd_byte buffer[4];
325
326 newLow -= sizeof (bfd_getb32 (buffer));
327 line++;
328 }
329
330 return newLow;
39db33d6 331}
c906108c 332
c906108c 333void
297d1607 334strcat_to_buf (char *buf, int buflen, const char *itemToAdd)
c906108c
SS
335{
336 if (itemToAdd != (char *) NULL && buf != (char *) NULL)
337 {
338 if ((strlen (buf) + strlen (itemToAdd)) <= buflen)
339 strcat (buf, itemToAdd);
340 else
341 strncat (buf, itemToAdd, (buflen - strlen (buf)));
342 }
c906108c
SS
343}
344
39db33d6
SC
345#if 0
346/* Solaris <sys/termios.h> defines CTRL. */
347#ifndef CTRL
348#define CTRL(x) (x & ~0140)
349#endif
c906108c 350
39db33d6
SC
351#define FILEDES 2
352#define CHK(val, dft) (val<=0 ? dft : val)
c906108c
SS
353
354static void
c906108c 355_tuiReset (void)
c906108c
SS
356{
357 struct termio mode;
358
359 /*
c5aa993b
JM
360 ** reset the teletype mode bits to a sensible state.
361 ** Copied tset.c
362 */
c906108c
SS
363#if ! defined (USG) && defined (TIOCGETC)
364 struct tchars tbuf;
365#endif /* !USG && TIOCGETC */
366#ifdef UCB_NTTY
367 struct ltchars ltc;
368
369 if (ldisc == NTTYDISC)
370 {
371 ioctl (FILEDES, TIOCGLTC, &ltc);
372 ltc.t_suspc = CHK (ltc.t_suspc, CTRL ('Z'));
373 ltc.t_dsuspc = CHK (ltc.t_dsuspc, CTRL ('Y'));
374 ltc.t_rprntc = CHK (ltc.t_rprntc, CTRL ('R'));
375 ltc.t_flushc = CHK (ltc.t_flushc, CTRL ('O'));
376 ltc.t_werasc = CHK (ltc.t_werasc, CTRL ('W'));
377 ltc.t_lnextc = CHK (ltc.t_lnextc, CTRL ('V'));
378 ioctl (FILEDES, TIOCSLTC, &ltc);
379 }
380#endif /* UCB_NTTY */
381#ifndef USG
382#ifdef TIOCGETC
383 ioctl (FILEDES, TIOCGETC, &tbuf);
384 tbuf.t_intrc = CHK (tbuf.t_intrc, CTRL ('?'));
385 tbuf.t_quitc = CHK (tbuf.t_quitc, CTRL ('\\'));
386 tbuf.t_startc = CHK (tbuf.t_startc, CTRL ('Q'));
387 tbuf.t_stopc = CHK (tbuf.t_stopc, CTRL ('S'));
388 tbuf.t_eofc = CHK (tbuf.t_eofc, CTRL ('D'));
389 /* brkc is left alone */
390 ioctl (FILEDES, TIOCSETC, &tbuf);
391#endif /* TIOCGETC */
392 mode.sg_flags &= ~(RAW
393#ifdef CBREAK
394 | CBREAK
395#endif /* CBREAK */
396 | VTDELAY | ALLDELAY);
397 mode.sg_flags |= XTABS | ECHO | CRMOD | ANYP;
c5aa993b 398#else /*USG */
c906108c
SS
399 ioctl (FILEDES, TCGETA, &mode);
400 mode.c_cc[VINTR] = CHK (mode.c_cc[VINTR], CTRL ('?'));
401 mode.c_cc[VQUIT] = CHK (mode.c_cc[VQUIT], CTRL ('\\'));
402 mode.c_cc[VEOF] = CHK (mode.c_cc[VEOF], CTRL ('D'));
403
404 mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | INLCR | IGNCR | IUCLC | IXOFF);
405 mode.c_iflag |= (BRKINT | ISTRIP | ICRNL | IXON);
406 mode.c_oflag &= ~(OLCUC | OCRNL | ONOCR | ONLRET | OFILL | OFDEL |
407 NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY);
408 mode.c_oflag |= (OPOST | ONLCR);
409 mode.c_cflag &= ~(CSIZE | PARODD | CLOCAL);
410#ifndef hp9000s800
411 mode.c_cflag |= (CS8 | CREAD);
c5aa993b 412#else /*hp9000s800 */
c906108c
SS
413 mode.c_cflag |= (CS8 | CSTOPB | CREAD);
414#endif /* hp9000s800 */
415 mode.c_lflag &= ~(XCASE | ECHONL | NOFLSH);
416 mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOK);
417 ioctl (FILEDES, TCSETAW, &mode);
418#endif /* USG */
419
420 return;
421} /* _tuiReset */
39db33d6
SC
422#endif
423
c6f60bcd
SC
424void
425tui_show_source (const char *file, int line)
426{
427 /* make sure that the source window is displayed */
428 tuiAddWinToLayout (SRC_WIN);
429
430 tuiUpdateSourceWindowsWithLine (current_source_symtab, line);
431 tuiUpdateLocatorFilename (file);
432}
1403b519
SC
433
434void
435tui_show_assembly (CORE_ADDR addr)
436{
437 tuiAddWinToLayout (DISASSEM_WIN);
438 tuiUpdateSourceWindowsWithAddr (addr);
439}
440
441int
442tui_is_window_visible (TuiWinType type)
443{
444 if (tui_version == 0)
445 return 0;
446
447 if (winList[type] == 0)
448 return 0;
449
450 return winList[type]->generic.isVisible;
451}
452
453int
454tui_get_command_dimension (int *width, int *height)
455{
456 if (!tui_version || !m_winPtrNotNull (cmdWin))
457 {
458 return 0;
459 }
460
461 *width = cmdWin->generic.width;
462 *height = cmdWin->generic.height;
463 return 1;
464}
This page took 0.265866 seconds and 4 git commands to generate.