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