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