diff options
Diffstat (limited to 'gdb/tui/tuiIO.c')
-rw-r--r-- | gdb/tui/tuiIO.c | 734 |
1 files changed, 734 insertions, 0 deletions
diff --git a/gdb/tui/tuiIO.c b/gdb/tui/tuiIO.c new file mode 100644 index 00000000000..29a3613f968 --- /dev/null +++ b/gdb/tui/tuiIO.c @@ -0,0 +1,734 @@ + +/* +** This module contains functions to support i/o in the TUI +*/ + + +#include <stdio.h> +#include "defs.h" +#include "terminal.h" +#include "tui.h" +#include "tuiData.h" +#include "tuiIO.h" +#include "tuiCommand.h" +#include "tuiWin.h" + +#ifdef ANSI_PROTOTYPES +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +/* The Solaris header files seem to provide no declaration for this at + all when __STDC__ is defined. This shouldn't conflict with + anything. */ +extern char *tgoto (); + +int insert_mode = 0; + +/******************************************** +** LOCAL STATIC FORWARD DECLS ** +********************************************/ +static void _updateCommandInfo PARAMS ((int)); +static unsigned int _tuiHandleResizeDuringIO PARAMS ((unsigned int)); + + +/********************************************************************************* +** PUBLIC FUNCTIONS ** +*********************************************************************************/ + +/* +** tuiPuts_unfiltered(). +** Function to put a string to the command window +** When running in TUI mode, this is the "hook" +** for fputs_unfiltered(). That is, all debugger +** output eventually makes it's way to the bottom-level +** routine fputs_unfiltered (main.c), which (in TUI +** mode), calls tuiPuts_unfiltered(). +*/ +void +#ifdef __STDC__ +tuiPuts_unfiltered ( + const char *string, + GDB_FILE * stream) +#else +tuiPuts_unfiltered (string, stream) + char *string; + GDB_FILE *stream; +#endif +{ + int len = strlen (string); + int i, linech; + + for (i = 0; i < len; i++) + { + if (string[i] == '\n' || string[i] == '\r') + m_tuiStartNewLine; + else + { + if ((cmdWin->detail.commandInfo.curch + 1) > cmdWin->generic.width) + m_tuiStartNewLine; + + if (insert_mode) + { + mvwinsch (cmdWin->generic.handle, + cmdWin->detail.commandInfo.curLine, + cmdWin->detail.commandInfo.curch++, + string[i]); + wmove (cmdWin->generic.handle, + cmdWin->detail.commandInfo.curLine, + cmdWin->detail.commandInfo.curch); + } + else + mvwaddch (cmdWin->generic.handle, + cmdWin->detail.commandInfo.curLine, + cmdWin->detail.commandInfo.curch++, + string[i]); + } + } + tuiRefreshWin (&cmdWin->generic); + + return; +} /* tuiPuts_unfiltered */ + +/* A cover routine for tputs(). + * tputs() is called from the readline package to put + * out strings representing cursor positioning. + * In TUI mode (non-XDB-style), tui_tputs() is called instead. + * + * The reason we need to hook tputs() is: + * Since the output is going to curses and not to + * a raw terminal, we need to intercept these special + * sequences, and handle them them here. + * + * This function seems to be correctly handling all sequences + * aimed at hpterm's, but there is additional work to do + * for xterm's and dtterm's. I abandoned further work on this + * in favor of "XDB style". In "XDB style", the command region + * looks like terminal, not a curses window, and this routine + * is not called. - RT + */ +void +tui_tputs (str, affcnt, putfunc) + char *str; + int affcnt; + int (*putfunc) PARAMS ((int)); +{ + extern char *rl_prompt; /* the prompt string */ + + /* This set of globals are defined and initialized + * by the readline package. + * + * Note we're assuming tui_tputs() is being called + * by the readline package. That's because we're recognizing + * that a given string is being passed by + * matching the string address against readline's + * term_<whatever> global. To make this more general, + * we'd have to actually recognize the termcap sequence + * inside the string (more work than I want to do). - RT + * + * We don't see or need to handle every one of these here; + * this is just the full list defined in readline/readline.c + */ + extern char *term_backspace; + extern char *term_clreol; + extern char *term_clrpag; + extern char *term_cr; + extern char *term_dc; + extern char *term_ei; + extern char *term_goto; + extern char *term_ic; + extern char *term_im; + extern char *term_mm; + extern char *term_mo; + extern char *term_up; + extern char *term_scroll_region; + extern char *term_memory_lock; + extern char *term_memory_unlock; + extern char *term_cursor_move; + extern char *visible_bell; + + /* Sanity check - if not TUI, just call tputs() */ + if (!tui_version) + tputs (str, affcnt, putfunc); + + /* The strings we special-case are handled first */ + + if (str == term_backspace) + { + /* Backspace. */ + + /* We see this on an emacs control-B. + * I.e., it's like the left-arrow key (not like the backspace key). + * The effect that readline wants when it transmits this + * character to us is simply to back up one character + * (but not to write a space over the old character). + */ + + _updateCommandInfo (-1); + wmove (cmdWin->generic.handle, + cmdWin->detail.commandInfo.curLine, + cmdWin->detail.commandInfo.curch); + wrefresh (cmdWin->generic.handle); + + } + else if (str == term_clreol) + { + + /* Clear to end of line. */ + wclrtoeol (cmdWin->generic.handle); + wrefresh (cmdWin->generic.handle); + + } + else if (str == term_cr) + { + + /* Carriage return */ + _updateCommandInfo (-cmdWin->detail.commandInfo.curch); + wmove (cmdWin->generic.handle, + cmdWin->detail.commandInfo.curLine, + 0 /* readline will rewrite the prompt from 0 */ ); + wrefresh (cmdWin->generic.handle); + + } + else if (str == term_goto) + { + + /* This is actually a tgoto() specifying a character position, + * followed by either a term_IC/term_DC which [I think] means + * insert/delete one character at that position. + * There are complications with this one - need to either + * extract the position from the string, or have a backdoor + * means of communicating it from ../readline/display.c. + * So this one is not yet implemented. + * Not doing it seems to have no ill effects on command-line-editing + * that I've noticed so far. - RT + */ + + } + else if (str == term_dc) + { + + /* Delete character at current cursor position */ + wdelch (cmdWin->generic.handle); + wrefresh (cmdWin->generic.handle); + + } + else if (str == term_im) + { + + /* Turn on insert mode. */ + insert_mode = 1; + + } + else if (str == term_ei) + { + + /* Turn off insert mode. */ + insert_mode = 0; + + /* Strings we know about but don't handle + * specially here are just passed along to tputs(). + * + * These are not handled because (as far as I can tell) + * they are not actually emitted by the readline package + * in the course of doing command-line editing. Some of them + * theoretically could be used in the future, in which case we'd + * need to handle them. + */ + } + else if (str == term_ic || /* insert character */ + str == term_cursor_move || /* cursor move */ + str == term_clrpag ||/* clear page */ + str == term_mm || /* turn on meta key */ + str == term_mo || /* turn off meta key */ + str == term_up || /* up one line (not expected) */ + str == term_scroll_region || /* set scroll region */ + str == term_memory_lock || /* lock screen above cursor */ + str == term_memory_unlock || /* unlock screen above cursor */ + str == visible_bell) + { /* flash screen */ + tputs (str, affcnt, putfunc); + } + else + { /* something else */ + tputs (str, affcnt, putfunc); + } +} /* tui_tputs */ + + +/* +** tui_vwgetch() +** Wrapper around wgetch with the window in a va_list +*/ +unsigned int +#ifdef __STDC__ +tui_vwgetch (va_list args) +#else +tui_vwgetch (args) + va_list args; +#endif +{ + unsigned int ch; + WINDOW *window; + + window = va_arg (args, WINDOW *); + + return ((unsigned int) wgetch (window)); +} /* tui_vwgetch */ + + +/* +** tui_vread() +** Wrapper around read() with paramets in a va_list +*/ +unsigned int +#ifdef __STDC__ +tui_vread (va_list args) +#else +tui_vread (args) + va_list args; +#endif +{ + int result = 0; + int filedes = va_arg (args, int); + char *buf = va_arg (args, char *); + int nbytes = va_arg (args, int); + + result = read (filedes, buf, nbytes); + + return result; +} /* tui_vread() */ + +/* +** tuiRead() +** Function to perform a read() catching resize events +*/ +int +#ifdef __STDC__ +tuiRead ( + int filedes, + char *buf, + int nbytes) +#else +tuiRead (filedes, buf, nbytes) + int filedes; + char *buf; + int nbytes; +#endif +{ + int result = 0; + + result = (int) vcatch_errors ((OpaqueFuncPtr) tui_vread, filedes, buf, nbytes); + *buf = _tuiHandleResizeDuringIO (*buf); + + return result; +} /* tuiRead */ + + +/* +** tuiGetc(). +** Get a character from the command window. +** This is called from the readline package, +** that is, we have: +** tuiGetc() [here], called from +** readline code [in ../readline/], called from +** command_line_input() in top.c +*/ +unsigned int +#ifdef __STDC__ +tuiGetc (void) +#else +tuiGetc () +#endif +{ + unsigned int ch; + extern char *rl_prompt; + extern char *rl_line_buffer; + extern int rl_point; + + /* Call the curses routine that reads one character */ +#ifndef COMMENT + ch = (unsigned int) vcatch_errors ((OpaqueFuncPtr) tui_vwgetch, + cmdWin->generic.handle); +#else + ch = wgetch (cmdWin->generic.handle); +#endif + ch = _tuiHandleResizeDuringIO (ch); + + if (m_isCommandChar (ch)) + { /* Handle prev/next/up/down here */ + tuiTermSetup (0); + ch = tuiDispatchCtrlChar (ch); + cmdWin->detail.commandInfo.curch = strlen (rl_prompt) + rl_point; + tuiTermUnsetup (0, cmdWin->detail.commandInfo.curch); + } + if (ch == '\n' || ch == '\r' || ch == '\f') + cmdWin->detail.commandInfo.curch = 0; + else + tuiIncrCommandCharCountBy (1); + + return ch; +} /* tuiGetc */ + + +/* +** tuiBufferGetc(). +*/ +/*elz: this function reads a line of input from the user and +puts it in a static buffer. Subsequent calls to this same function +obtain one char at the time, providing the caller with a behavior +similar to fgetc. When the input is buffered, the backspaces have +the needed effect, i.e. ignore the last char active in the buffer*/ +/* so far this function is called only from the query function in +utils.c*/ + +unsigned int +#ifdef __STDC__ +tuiBufferGetc (void) +#else +tuiBufferGetc () +#endif +{ + unsigned int ch; + static unsigned char _ibuffer[512]; + static int index_read = -1; + static int length_of_answer = -1; + int pos = 0; + + if (length_of_answer == -1) + { + /* this is the first time through, need to read the answer*/ + do + { + /* Call the curses routine that reads one character */ + ch = (unsigned int) wgetch (cmdWin->generic.handle); + if (ch != '\b') + { + _ibuffer[pos] = ch; + pos++; + } + else + pos--; + } + while (ch != '\r' && ch != '\n'); + + length_of_answer = pos; + index_read = 0; + } + + ch = _ibuffer[index_read]; + index_read++; + + if (index_read == length_of_answer) + { + /*this is the last time through, reset for next query*/ + index_read = -1; + length_of_answer = -1; + } + + wrefresh (cmdWin->generic.handle); + + return (ch); +} /* tuiBufferGetc */ + + +/* +** tuiStartNewLines(). +*/ +void +#ifdef __STDC__ +tuiStartNewLines ( + int numLines) +#else +tuiStartNewLines (numLines) + int numLines; +#endif +{ + if (numLines > 0) + { + if (cmdWin->generic.viewportHeight > 1 && + cmdWin->detail.commandInfo.curLine < cmdWin->generic.viewportHeight) + cmdWin->detail.commandInfo.curLine += numLines; + else + scroll (cmdWin->generic.handle); + cmdWin->detail.commandInfo.curch = 0; + wmove (cmdWin->generic.handle, + cmdWin->detail.commandInfo.curLine, + cmdWin->detail.commandInfo.curch); + tuiRefreshWin (&cmdWin->generic); + } + + return; +} /* tuiStartNewLines */ + + +/* +** tui_vStartNewLines(). +** With numLines in a va_list +*/ +void +#ifdef __STDC__ +tui_vStartNewLines ( + va_list args) +#else +tui_vStartNewLines (args) + va_list args; +#endif +{ + int numLines = va_arg (args, int); + + tuiStartNewLines (numLines); + + return; +} /* tui_vStartNewLines */ + + +/**************************************************************************** +** LOCAL STATIC FUNCTIONS ** +*****************************************************************************/ + + +/* +** _tuiHandleResizeDuringIO +** This function manages the cleanup when a resize has occured +** From within a call to getch() or read. Returns the character +** to return from getc or read. +*/ +static unsigned int +#ifdef __STDC__ +_tuiHandleResizeDuringIO ( + unsigned int originalCh) /* the char just read */ +#else +_tuiHandleResizeDuringIO (originalCh) + unsigned int originalCh; +#endif +{ + if (tuiWinResized ()) + { + tuiDo ((TuiOpaqueFuncPtr) tuiRefreshAll); + dont_repeat (); + tuiSetWinResizedTo (FALSE); + rl_reset (); + return '\n'; + } + else + return originalCh; +} /* _tuiHandleResizeDuringIO */ + + +/* +** _updateCommandInfo(). +** Function to update the command window information. +*/ +static void +#ifdef __STDC__ +_updateCommandInfo ( + int sizeOfString) +#else +_updateCommandInfo (sizeOfString) + int sizeOfString; +#endif +{ + + if ((sizeOfString + + cmdWin->detail.commandInfo.curch) > cmdWin->generic.width) + { + int newCurch = sizeOfString + cmdWin->detail.commandInfo.curch; + + tuiStartNewLines (1); + cmdWin->detail.commandInfo.curch = newCurch - cmdWin->generic.width; + } + else + cmdWin->detail.commandInfo.curch += sizeOfString; + + return; +} /* _updateCommandInfo */ + + +/* Looked at in main.c, fputs_unfiltered(), to decide + * if it's safe to do standard output to the command window. + */ +int tui_owns_terminal = 0; + +/* Called to set up the terminal for TUI (curses) I/O. + * We do this either on our way "in" to GDB after target + * program execution, or else within tuiDo just before + * going off to TUI routines. + */ + +void +#ifdef __STDC__ +tuiTermSetup ( + int turn_off_echo) +#else +tuiTermSetup (turn_off_echo) + int turn_off_echo; +#endif +{ + char *buffer; + int start; + int end; + int endcol; + extern char *term_scroll_region; + extern char *term_cursor_move; + extern char *term_memory_lock; + extern char *term_memory_unlock; + + /* Turn off echoing, since the TUI does not + * expect echoing. Below I only put in the TERMIOS + * case, since that is what applies on HP-UX. turn_off_echo + * is 1 except for the case where we're being called + * on a "quit", in which case we want to leave echo on. + */ + if (turn_off_echo) + { +#ifdef HAVE_TERMIOS + struct termios tio; + tcgetattr (0, &tio); + tio.c_lflag &= ~(ECHO); + tcsetattr (0, TCSANOW, &tio); +#endif + } + + /* Compute the start and end lines of the command + * region. (Actually we only use end here) + */ + start = winList[CMD_WIN]->generic.origin.y; + end = start + winList[CMD_WIN]->generic.height - 1; + endcol = winList[CMD_WIN]->generic.width - 1; + + if (term_memory_unlock) + { + + /* Un-do the effect of the memory lock in terminal_inferior() */ + tputs (term_memory_unlock, 1, (int (*)PARAMS ((int))) putchar); + fflush (stdout); + + } + else if (term_scroll_region) + { + + /* Un-do the effect of setting scroll region in terminal_inferior() */ + /* I'm actually not sure how to do this (we don't know for + * sure what the scroll region was *before* we changed it), + * but I'll guess that setting it to the whole screen is + * the right thing. So, ... + */ + + /* Set scroll region to be 0..end */ + buffer = (char *) tgoto (term_scroll_region, end, 0); + tputs (buffer, 1, (int (*)PARAMS ((int))) putchar); + + } /* else we're out of luck */ + + /* This is an attempt to keep the logical & physical + * cursor in synch, going into curses. Without this, + * curses seems to be confused by the fact that + * GDB has physically moved the curser on it. One + * visible effect of removing this code is that the + * locator window fails to get updated and the line + * of text that *should* go into the locator window + * often goes to the wrong place. + */ + /* What's done here is to tell curses to write a ' ' + * at the bottom right corner of the screen. + * The idea is to wind up with the cursor in a known + * place. + * Note I'm relying on refresh() + * only writing what changed (the space), + * not the whole screen. + */ + standend (); + move (end, endcol - 1); + addch (' '); + refresh (); + + tui_owns_terminal = 1; +} /* tuiTermSetup */ + + +/* Called to set up the terminal for target program I/O, meaning I/O + * is confined to the command-window area. We also call this on our + * way out of tuiDo, thus setting up the terminal this way for + * debugger command I/O. */ +void +#ifdef __STDC__ +tuiTermUnsetup ( + int turn_on_echo, + int to_column) +#else +tuiTermUnsetup (turn_on_echo, to_column) + int turn_on_echo; + int to_column; +#endif +{ + int start; + int end; + int curline; + char *buffer; + /* The next bunch of things are from readline */ + extern char *term_scroll_region; + extern char *term_cursor_move; + extern char *term_memory_lock; + extern char *term_memory_unlock; + extern char *term_se; + + /* We need to turn on echoing, since the TUI turns it off */ + /* Below I only put in the TERMIOS case, since that + * is what applies on HP-UX. + */ + if (turn_on_echo) + { +#ifdef HAVE_TERMIOS + struct termios tio; + tcgetattr (0, &tio); + tio.c_lflag |= (ECHO); + tcsetattr (0, TCSANOW, &tio); +#endif + } + + /* Compute the start and end lines of the command + * region, as well as the last "real" line of + * the region (normally same as end, except when + * we're first populating the region) + */ + start = winList[CMD_WIN]->generic.origin.y; + end = start + winList[CMD_WIN]->generic.height - 1; + curline = start + winList[CMD_WIN]->detail.commandInfo.curLine; + + /* We want to confine target I/O to the command region. + * In order to do so, we must either have "memory lock" + * (hpterm's) or "scroll regions" (xterm's). + */ + if (term_cursor_move && term_memory_lock) + { + + /* Memory lock means lock region above cursor. + * So first position the cursor, then call memory lock. + */ + buffer = tgoto (term_cursor_move, 0, start); + tputs (buffer, 1, (int (*)PARAMS ((int))) putchar); + tputs (term_memory_lock, 1, (int (*)PARAMS ((int))) putchar); + + } + else if (term_scroll_region) + { + + /* Set the scroll region to the command window */ + buffer = tgoto (term_scroll_region, end, start); + tputs (buffer, 1, (int (*)PARAMS ((int))) putchar); + + } /* else we can't do anything about target I/O */ + + /* Also turn off standout mode, in case it is on */ + if (term_se != NULL) + tputs (term_se, 1, (int (*)PARAMS ((int))) putchar); + + /* Now go to the appropriate spot on the end line */ + buffer = tgoto (term_cursor_move, to_column, end); + tputs (buffer, 1, (int (*)PARAMS ((int))) putchar); + fflush (stdout); + + tui_owns_terminal = 0; +} /* tuiTermUnsetup */ |