]> Git Repo - binutils.git/blob - gdb/tui/tui.c
* tui.c (tui_rl_switch_mode): Renames tui_switch_mode.
[binutils.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   tui_update_gdb_sizes ();
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.  */
276 void
277 tui_disable (void)
278 {
279   if (!tui_active)
280     return;
281
282   /* Remove TUI hooks.  */
283   tui_remove_hooks ();
284
285   /* Leave curses and restore previous gdb terminal setting.  */
286   endwin ();
287
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);
291
292   tui_version = 0;
293   tui_active = 0;
294   tui_update_gdb_sizes ();
295 }
296
297 /* Wrapper on top of free() to ensure that input address
298    is greater than 0x0.  */
299 void
300 tuiFree (char *ptr)
301 {
302   if (ptr != (char *) NULL)
303     {
304       xfree (ptr);
305     }
306 }
307
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.  */
311 CORE_ADDR
312 tuiGetLowDisassemblyAddress (CORE_ADDR low, CORE_ADDR pc)
313 {
314   int line;
315   CORE_ADDR newLow;
316
317   /* Determine where to start the disassembly so that the pc is about in the
318      middle of the viewport.  */
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;
331 }
332
333 void
334 strcat_to_buf (char *buf, int buflen, const char *itemToAdd)
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     }
343 }
344
345 #if 0
346 /* Solaris <sys/termios.h> defines CTRL. */
347 #ifndef CTRL
348 #define CTRL(x)         (x & ~0140)
349 #endif
350
351 #define FILEDES         2
352 #define CHK(val, dft)   (val<=0 ? dft : val)
353
354 static void
355 _tuiReset (void)
356 {
357   struct termio mode;
358
359   /*
360      ** reset the teletype mode bits to a sensible state.
361      ** Copied tset.c
362    */
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;
398 #else /*USG */
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);
412 #else /*hp9000s800 */
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 */
422 #endif
423
424 void
425 tui_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 }
433
434 void
435 tui_show_assembly (CORE_ADDR addr)
436 {
437   tuiAddWinToLayout (DISASSEM_WIN);
438   tuiUpdateSourceWindowsWithAddr (addr);
439 }
440
441 int
442 tui_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
453 int
454 tui_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.052798 seconds and 4 git commands to generate.