#include "config.h"
#ifdef HAVE_NCURSES_H
#include <ncurses.h>
#else
#ifdef HAVE_CURSES_H
#include <curses.h>
#endif
#endif
#include <stdio.h>
#include "defs.h"
#include "terminal.h"
#include "target.h"
#include "event-loop.h"
#include "command.h"
#include "top.h"
#include "readline/readline.h"
#include "tui.h"
#include "tuiData.h"
#include "tuiIO.h"
#include "tuiCommand.h"
#include "tuiWin.h"
#include "tuiGeneralWin.h"
#include "tui-file.h"
#include "ui-out.h"
#include "cli-out.h"
#include <fcntl.h>
#include <signal.h>
static struct ui_file *tui_stdout;
static struct ui_file *tui_stderr;
static struct ui_out *tui_out;
static struct ui_file *tui_old_stdout;
static struct ui_file *tui_old_stderr;
static struct ui_out *tui_old_uiout;
static Function *tui_old_rl_getc_function;
static VFunction *tui_old_rl_redisplay_function;
static VFunction *tui_old_rl_prep_terminal;
static VFunction *tui_old_rl_deprep_terminal;
static int tui_old_readline_echoing_p;
static FILE *tui_rl_outstream;
static FILE *tui_old_rl_outstream;
static int tui_readline_pipe[2];
static unsigned int _tuiHandleResizeDuringIO (unsigned int);
void
tui_puts (const char *string)
{
static int tui_skip_line = -1;
char c;
WINDOW *w;
w = cmdWin->generic.handle;
while ((c = *string++) != 0)
{
if (c == '\032')
{
tui_skip_line++;
}
else if (tui_skip_line != 1)
{
tui_skip_line = -1;
waddch (w, c);
}
else if (c == '\n')
tui_skip_line = -1;
}
getyx (w, cmdWin->detail.commandInfo.curLine,
cmdWin->detail.commandInfo.curch);
cmdWin->detail.commandInfo.start_line = cmdWin->detail.commandInfo.curLine;
wrefresh (w);
fflush (stdout);
}
static void
tui_redisplay_readline (void)
{
int prev_col;
int height;
int col, line;
int c_pos;
int c_line;
int in;
WINDOW *w;
char *prompt;
int start_line;
prompt = get_prompt ();
c_pos = -1;
c_line = -1;
w = cmdWin->generic.handle;
start_line = cmdWin->detail.commandInfo.start_line;
wmove (w, start_line, 0);
prev_col = 0;
height = 1;
for (in = 0; prompt && prompt[in]; in++)
{
waddch (w, prompt[in]);
getyx (w, line, col);
if (col < prev_col)
height++;
prev_col = col;
}
for (in = 0; in < rl_end; in++)
{
unsigned char c;
c = (unsigned char) rl_line_buffer[in];
if (in == rl_point)
{
getyx (w, c_line, c_pos);
}
if (CTRL_CHAR (c) || c == RUBOUT)
{
waddch (w, '^');
waddch (w, CTRL_CHAR (c) ? UNCTRL (c) : '?');
}
else
{
waddch (w, c);
}
if (c == '\n')
{
getyx (w, cmdWin->detail.commandInfo.start_line,
cmdWin->detail.commandInfo.curch);
}
getyx (w, line, col);
if (col < prev_col)
height++;
prev_col = col;
}
wclrtobot (w);
getyx (w, cmdWin->detail.commandInfo.start_line,
cmdWin->detail.commandInfo.curch);
if (c_line >= 0)
{
wmove (w, c_line, c_pos);
cmdWin->detail.commandInfo.curLine = c_line;
cmdWin->detail.commandInfo.curch = c_pos;
}
cmdWin->detail.commandInfo.start_line -= height - 1;
wrefresh (w);
fflush(stdout);
}
static void
tui_prep_terminal (void)
{
}
static void
tui_deprep_terminal (void)
{
}
static void
tui_readline_output (int code, gdb_client_data data)
{
int size;
char buf[256];
size = read (tui_readline_pipe[0], buf, sizeof (buf) - 1);
if (size > 0 && tui_active)
{
buf[size] = 0;
tui_puts (buf);
}
}
void
tui_setup_io (int mode)
{
extern int readline_echoing_p;
if (mode)
{
tui_old_rl_redisplay_function = rl_redisplay_function;
tui_old_rl_deprep_terminal = rl_deprep_term_function;
tui_old_rl_prep_terminal = rl_prep_term_function;
tui_old_rl_getc_function = rl_getc_function;
tui_old_rl_outstream = rl_outstream;
tui_old_readline_echoing_p = readline_echoing_p;
rl_redisplay_function = tui_redisplay_readline;
rl_deprep_term_function = tui_deprep_terminal;
rl_prep_term_function = tui_prep_terminal;
rl_getc_function = tui_getc;
readline_echoing_p = 0;
rl_outstream = tui_rl_outstream;
rl_prompt = 0;
tui_old_stdout = gdb_stdout;
tui_old_stderr = gdb_stderr;
tui_old_uiout = uiout;
gdb_stdout = tui_stdout;
gdb_stderr = tui_stderr;
gdb_stdlog = gdb_stdout;
gdb_stdtarg = gdb_stderr;
uiout = tui_out;
savetty ();
}
else
{
gdb_stdout = tui_old_stdout;
gdb_stderr = tui_old_stderr;
gdb_stdlog = gdb_stdout;
gdb_stdtarg = gdb_stderr;
uiout = tui_old_uiout;
rl_redisplay_function = tui_old_rl_redisplay_function;
rl_deprep_term_function = tui_old_rl_deprep_terminal;
rl_prep_term_function = tui_old_rl_prep_terminal;
rl_getc_function = tui_old_rl_getc_function;
rl_outstream = tui_old_rl_outstream;
readline_echoing_p = tui_old_readline_echoing_p;
savetty ();
}
}
#ifdef SIGCONT
static void
tui_cont_sig (int sig)
{
if (tui_active)
{
resetty ();
tuiRefreshAll ();
wmove (cmdWin->generic.handle,
cmdWin->detail.commandInfo.start_line,
cmdWin->detail.commandInfo.curch);
wrefresh (cmdWin->generic.handle);
}
signal (sig, tui_cont_sig);
}
#endif
void
tui_initialize_io ()
{
#ifdef SIGCONT
signal (SIGCONT, tui_cont_sig);
#endif
tui_stdout = tui_fileopen (stdout);
tui_stderr = tui_fileopen (stderr);
tui_out = tui_out_new (tui_stdout);
uiout = cli_out_new (gdb_stdout);
if (pipe (tui_readline_pipe) != 0)
{
fprintf_unfiltered (gdb_stderr, "Cannot create pipe for readline");
exit (1);
}
tui_rl_outstream = fdopen (tui_readline_pipe[1], "w");
if (tui_rl_outstream == 0)
{
fprintf_unfiltered (gdb_stderr, "Cannot redirect readline output");
exit (1);
}
setlinebuf (tui_rl_outstream);
#ifdef O_NONBLOCK
(void) fcntl (tui_readline_pipe[0], F_SETFL, O_NONBLOCK);
#else
#ifdef O_NDELAY
(void) fcntl (tui_readline_pipe[0], F_SETFL, O_NDELAY);
#endif
#endif
add_file_handler (tui_readline_pipe[0], tui_readline_output, 0);
}
int
tui_getc (FILE *fp)
{
int ch;
WINDOW *w;
w = cmdWin->generic.handle;
tui_readline_output (GDB_READABLE, 0);
ch = wgetch (w);
ch = _tuiHandleResizeDuringIO (ch);
if (ch == '\n')
{
if (rl_end == 0)
{
wmove (w, cmdWin->detail.commandInfo.curLine, 0);
wclrtoeol (w);
wrefresh (w);
napms (20);
}
else
{
wmove (w, cmdWin->detail.commandInfo.curLine,
cmdWin->detail.commandInfo.curch);
waddch (w, ch);
}
}
if (m_isCommandChar (ch))
{
ch = tuiDispatchCtrlChar (ch);
}
if (ch == '\n' || ch == '\r' || ch == '\f')
cmdWin->detail.commandInfo.curch = 0;
#if 0
else
tuiIncrCommandCharCountBy (1);
#endif
if (ch == KEY_BACKSPACE)
return '\b';
return ch;
}
static unsigned int
_tuiHandleResizeDuringIO (unsigned int originalCh)
{
if (tuiWinResized ())
{
tuiRefreshAll ();
dont_repeat ();
tuiSetWinResizedTo (FALSE);
return '\n';
}
else
return originalCh;
}