mirror of
https://github.com/irssi/irssi.git
synced 2025-02-02 15:08:01 -05:00
Added support for using terminfo/termcap instead of curses. By default,
configure chooses to use ncurses if found, of terminfo if only curses was found. --with-terminfo parameter can be used to specify if you want it or not. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1924 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
8567481fd0
commit
2ba339a26b
@ -23,12 +23,13 @@
|
||||
#undef SCO_FLAVOR
|
||||
|
||||
/* our own curses checks */
|
||||
#undef USE_CURSES_WINDOWS
|
||||
#undef HAVE_NCURSES_USE_DEFAULT_COLORS
|
||||
#undef HAVE_CURSES_IDCOK
|
||||
#undef HAVE_CURSES_RESIZETERM
|
||||
#undef HAVE_CURSES_WRESIZE
|
||||
#undef USE_CURSES_WINDOWS
|
||||
|
||||
/* terminfo/termcap */
|
||||
#undef HAVE_TERMINFO
|
||||
|
||||
/* nls */
|
||||
#undef ENABLE_NLS
|
||||
|
99
configure.in
99
configure.in
@ -90,6 +90,18 @@ AC_ARG_WITH(proxy,
|
||||
fi,
|
||||
want_irssiproxy=no)
|
||||
|
||||
AC_ARG_WITH(terminfo,
|
||||
[ --with-terminfo Use terminfo directly instead of curses],
|
||||
if test x$withval = xyes; then
|
||||
want_terminfo=yes
|
||||
else
|
||||
if test "x$withval" = xno; then
|
||||
want_terminfo=no
|
||||
else
|
||||
want_terminfo=yes
|
||||
fi
|
||||
fi,
|
||||
want_terminfo=auto)
|
||||
|
||||
AC_ARG_WITH(modules,
|
||||
[ --with-modules Specify what modules to build in binary],
|
||||
@ -173,13 +185,6 @@ AC_ARG_WITH(tests,
|
||||
TEST_DIR=)
|
||||
AC_SUBST(TEST_DIR)
|
||||
|
||||
AC_ARG_ENABLE(curses-windows,
|
||||
[ --enable-curses-windows Use curses windows],
|
||||
if test x$enableval != xno; then
|
||||
AC_DEFINE(USE_CURSES_WINDOWS)
|
||||
fi,
|
||||
AC_DEFINE(USE_CURSES_WINDOWS))
|
||||
|
||||
AC_ARG_ENABLE(memdebug,
|
||||
[ --enable-memdebug Enable memory debugging],
|
||||
if test x$enableval = xyes; then
|
||||
@ -213,11 +218,11 @@ dnl **
|
||||
AC_CHECK_FUNCS(mkfifo fcntl)
|
||||
|
||||
AC_CHECK_LIB(socket, socket, [
|
||||
PROG_LIBS="$PROG_LIBS -lsocket"
|
||||
LIBS="$LIBS -lsocket"
|
||||
])
|
||||
|
||||
AC_CHECK_LIB(nsl, inet_addr, [
|
||||
PROG_LIBS="$PROG_LIBS -lnsl"
|
||||
LIBS="$LIBS -lnsl"
|
||||
], -lsocket)
|
||||
|
||||
dnl * gcc specific options
|
||||
@ -256,7 +261,7 @@ dnl **
|
||||
|
||||
if test "x$want_socks" = "xyes"; then
|
||||
AC_CHECK_LIB(socks, connect, [
|
||||
PROG_LIBS="$PROG_LIBS -lsocks"
|
||||
LIBS="$LIBS -lsocks"
|
||||
AC_CHECK_HEADER(socks.h, [
|
||||
AC_DEFINE(HAVE_SOCKS_H)
|
||||
CFLAGS="$CFLAGS -DSOCKS"
|
||||
@ -369,7 +374,7 @@ if test -z "$GLIB_DIR"; then
|
||||
fi
|
||||
fi
|
||||
|
||||
PROG_LIBS="$PROG_LIBS $GLIB_LIBS"
|
||||
LIBS="$LIBS $GLIB_LIBS"
|
||||
|
||||
dnl **
|
||||
dnl ** check if we can link dynamic libraries to modules
|
||||
@ -434,35 +439,38 @@ dnl **
|
||||
if test "x$want_textui" = "xyes"; then
|
||||
AC_CHECK_CURSES
|
||||
|
||||
if test -n "$has_ncurses"; then
|
||||
AC_CHECK_LIB(ncurses, use_default_colors, [
|
||||
AC_DEFINE(HAVE_NCURSES_USE_DEFAULT_COLORS)
|
||||
],, $CURSES_LIBS)
|
||||
AC_CHECK_LIB(ncurses, idcok, [
|
||||
AC_DEFINE(HAVE_CURSES_IDCOK)
|
||||
],, $CURSES_LIBS)
|
||||
AC_CHECK_LIB(ncurses, resizeterm, [
|
||||
AC_DEFINE(HAVE_CURSES_RESIZETERM)
|
||||
],, $CURSES_LIBS)
|
||||
AC_CHECK_LIB(ncurses, wresize, [
|
||||
AC_DEFINE(HAVE_CURSES_WRESIZE)
|
||||
],, $CURSES_LIBS)
|
||||
elif test "x$has_curses" = "xtrue"; then
|
||||
AC_CHECK_LIB(curses, idcok, [
|
||||
AC_DEFINE(HAVE_CURSES_IDCOK)
|
||||
],, $CURSES_LIBS)
|
||||
AC_CHECK_LIB(curses, resizeterm, [
|
||||
AC_DEFINE(HAVE_CURSES_RESIZETERM)
|
||||
],, $CURSES_LIBS)
|
||||
AC_CHECK_LIB(curses, wresize, [
|
||||
AC_DEFINE(HAVE_CURSES_WRESIZE)
|
||||
],, $CURSES_LIBS)
|
||||
LIBS="$LIBS $CURSES_LIBS"
|
||||
if test "x$has_curses" = "xtrue"; then
|
||||
AC_CHECK_FUNC(use_default_colors, AC_DEFINE(HAVE_NCURSES_USE_DEFAULT_COLORS))
|
||||
AC_CHECK_FUNC(idcok, AC_DEFINE(HAVE_CURSES_IDCOK))
|
||||
AC_CHECK_FUNC(resizeterm, AC_DEFINE(HAVE_CURSES_RESIZETERM))
|
||||
AC_CHECK_FUNC(wresize, AC_DEFINE(HAVE_CURSES_WRESIZE))
|
||||
if test "x$want_terminfo" = "xauto" -a "x$has_ncurses" != "xtrue"; then
|
||||
dnl * we'd rather use terminfo/termcap than plain curses
|
||||
want_terminfo=yes
|
||||
AC_CHECK_FUNC(setupterm,, want_termcap=yes)
|
||||
fi
|
||||
else
|
||||
want_textui=no
|
||||
curses_error=yes
|
||||
AC_CHECK_LIB(tinfo, setupterm, [
|
||||
LIBS="$LIBS -ltinfo"
|
||||
want_terminfo=yes
|
||||
], AC_CHECK_LIB(termlib, tgetent, [
|
||||
LIBS="$LIBS -ltermlib"
|
||||
want_termcap=yes
|
||||
], AC_CHECK_LIB(termcap, tgetent, [
|
||||
LIBS="$LIBS -ltermcap"
|
||||
want_termcap=yes
|
||||
], [
|
||||
AC_MSG_WARN(Terminfo/termcap not found)
|
||||
want_textui=no
|
||||
curses_error=yes
|
||||
])))
|
||||
fi
|
||||
else
|
||||
has_curses=false
|
||||
if test "x$want_termcap" = "xyes"; then
|
||||
AC_CHECK_FUNC(tparm,, need_tparm=yes)
|
||||
else
|
||||
AC_DEFINE(HAVE_TERMINFO)
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl **
|
||||
@ -642,8 +650,8 @@ AM_CONDITIONAL(BUILD_PLUGINS, test "$want_plugins" = "yes")
|
||||
AM_CONDITIONAL(BUILD_SERVERTEST, test -n "$TEST_DIR")
|
||||
AM_CONDITIONAL(HAVE_PERL, test "$want_perl" != "no")
|
||||
AM_CONDITIONAL(HAVE_STATIC_PERL, test "$want_perl" = "static")
|
||||
|
||||
AC_SUBST(PROG_LIBS)
|
||||
AM_CONDITIONAL(NEED_TPARM, test "$need_tparm" = "yes")
|
||||
AM_CONDITIONAL(USE_CURSES, test "$want_terminfo" != "yes" -a "$want_termcap" != "yes")
|
||||
|
||||
dnl **
|
||||
dnl ** Keep all the libraries here so each frontend doesn't need to
|
||||
@ -811,7 +819,16 @@ fi
|
||||
echo
|
||||
|
||||
if test "x$curses_error" != "xyes"; then
|
||||
echo "Building text frontend ..... : $want_textui"
|
||||
if test "x$want_textui" = "xno"; then
|
||||
text=no
|
||||
elif test "x$want_termcap" = "xyes"; then
|
||||
text="yes, using termcap"
|
||||
elif test "x$want_terminfo" = "xyes"; then
|
||||
text="yes, using terminfo"
|
||||
else
|
||||
text="yes, using curses"
|
||||
fi
|
||||
echo "Building text frontend ..... : $text"
|
||||
else
|
||||
echo "Building text frontend ..... : NO!!"
|
||||
echo " - Because curses was not found, specify the path to it with"
|
||||
|
@ -47,9 +47,9 @@
|
||||
|
||||
#############################################################################
|
||||
|
||||
# default foreground color (%N) - 0 is the "default terminal color"
|
||||
default_color = 0;
|
||||
# default foreground color when "0" can't be used,
|
||||
# default foreground color (%N) - -1 is the "default terminal color"
|
||||
default_color = -1;
|
||||
# default foreground color when -1 can't be used,
|
||||
# such as with bolds and reverses. white is default.
|
||||
default_real_color = 7;
|
||||
|
||||
|
@ -990,8 +990,16 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
if (*ptr != FORMAT_COLOR_NOCHANGE)
|
||||
if (*ptr != FORMAT_COLOR_NOCHANGE) {
|
||||
bgcolor = *ptr-'0';
|
||||
if (bgcolor <= 7)
|
||||
flags &= ~GUI_PRINT_FLAG_BLINK;
|
||||
else {
|
||||
/* blink */
|
||||
bgcolor -= 8;
|
||||
flags |= GUI_PRINT_FLAG_BLINK;
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr++;
|
||||
break;
|
||||
|
@ -799,9 +799,11 @@ static int theme_read(THEME_REC *theme, const char *path, const char *data)
|
||||
}
|
||||
|
||||
theme->default_color =
|
||||
config_get_int(config, NULL, "default_color", 0);
|
||||
theme->default_real_color =
|
||||
config_get_int(config, NULL, "default_real_color", 7);
|
||||
config_get_int(config, NULL, "default_color", -1);
|
||||
/* FIXME: remove after 0.7.99 */
|
||||
if (theme->default_color == 0 &&
|
||||
config_get_int(config, NULL, "default_real_color", -1) != -1)
|
||||
theme->default_color = -1;
|
||||
theme_read_replaces(config, theme);
|
||||
|
||||
if (data == NULL) {
|
||||
@ -1141,8 +1143,7 @@ static void themes_read(void)
|
||||
if (current_theme == NULL) {
|
||||
fname = g_strdup_printf("%s/default.theme", get_irssi_dir());
|
||||
current_theme = theme_create(fname, "default");
|
||||
current_theme->default_color = 0;
|
||||
current_theme->default_real_color = 7;
|
||||
current_theme->default_color = -1;
|
||||
theme_read(current_theme, NULL, default_theme);
|
||||
g_free(fname);
|
||||
}
|
||||
|
@ -16,11 +16,8 @@ typedef struct {
|
||||
time_t last_modify;
|
||||
|
||||
int default_color; /* default color to use with text with default
|
||||
background. default is 0 which means the default
|
||||
color set by terminal */
|
||||
int default_real_color; /* default color to use with background set.
|
||||
this shouldn't be 0, unless black is really
|
||||
wanted. default is 7 (white). */
|
||||
background. default is -1 which means the
|
||||
default color set by terminal */
|
||||
GHashTable *modules;
|
||||
|
||||
int replace_keys[256]; /* index to replace_values for each char */
|
||||
|
@ -19,9 +19,27 @@ irssi_LDADD = \
|
||||
@COMMON_LIBS@ \
|
||||
@PERL_LINK_LIBS@ \
|
||||
@PERL_FE_LINK_LIBS@ \
|
||||
@PERL_LINK_FLAGS@ \
|
||||
$(PROG_LIBS) \
|
||||
$(CURSES_LIBS)
|
||||
@PERL_LINK_FLAGS@
|
||||
|
||||
tparm_sources = \
|
||||
tparm.c
|
||||
|
||||
terminfo_sources = \
|
||||
term-terminfo.c \
|
||||
terminfo-core.c
|
||||
|
||||
curses_sources = \
|
||||
term-curses.c
|
||||
|
||||
if NEED_TPARM
|
||||
use_tparm_sources = $(tparm_sources)
|
||||
endif
|
||||
|
||||
if USE_CURSES
|
||||
use_term_sources = $(curses_sources)
|
||||
else
|
||||
use_term_sources = $(terminfo_sources)
|
||||
endif
|
||||
|
||||
irssi_SOURCES = \
|
||||
gui-entry.c \
|
||||
@ -33,10 +51,12 @@ irssi_SOURCES = \
|
||||
mainwindows.c \
|
||||
mainwindow-activity.c \
|
||||
mainwindows-layout.c \
|
||||
screen.c \
|
||||
statusbar.c \
|
||||
statusbar-config.c \
|
||||
statusbar-items.c \
|
||||
term.c \
|
||||
$(use_tparm_sources) \
|
||||
$(use_term_sources) \
|
||||
textbuffer.c \
|
||||
textbuffer-commands.c \
|
||||
textbuffer-reformat.c \
|
||||
@ -50,12 +70,18 @@ noinst_HEADERS = \
|
||||
gui-readline.h \
|
||||
gui-windows.h \
|
||||
mainwindows.h \
|
||||
screen.h \
|
||||
statusbar.h \
|
||||
statusbar-config.h \
|
||||
statusbar-items.h \
|
||||
term.h \
|
||||
terminfo-core.h \
|
||||
textbuffer.h \
|
||||
textbuffer-view.h \
|
||||
textbuffer-reformat.h \
|
||||
module.h \
|
||||
module-formats.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(tparm_sources) \
|
||||
$(terminfo_sources) \
|
||||
$(curses_sources)
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include "gui-entry.h"
|
||||
#include "gui-printtext.h"
|
||||
#include "screen.h"
|
||||
#include "term.h"
|
||||
|
||||
GUI_ENTRY_REC *active_entry;
|
||||
|
||||
@ -76,36 +76,36 @@ static void gui_entry_draw_from(GUI_ENTRY_REC *entry, int pos)
|
||||
if (xpos > end_xpos)
|
||||
return;
|
||||
|
||||
screen_set_color(screen_root, 0);
|
||||
screen_move(screen_root, xpos, entry->ypos);
|
||||
term_set_color(root_window, ATTR_RESET);
|
||||
term_move(root_window, xpos, entry->ypos);
|
||||
|
||||
p = entry->scrstart + pos >= entry->text->len ? "" :
|
||||
entry->text->str + entry->scrstart + pos;
|
||||
for (; *p != '\0' && xpos < end_xpos; p++, xpos++) {
|
||||
if (entry->hidden)
|
||||
screen_addch(screen_root, ' ');
|
||||
term_addch(root_window, ' ');
|
||||
else if ((unsigned char) *p >= 32)
|
||||
screen_addch(screen_root, (unsigned char) *p);
|
||||
term_addch(root_window, (unsigned char) *p);
|
||||
else {
|
||||
screen_set_color(screen_root, ATTR_REVERSE);
|
||||
screen_addch(screen_root, *p+'A'-1);
|
||||
screen_set_color(screen_root, 0);
|
||||
term_set_color(root_window, ATTR_RESET|ATTR_REVERSE);
|
||||
term_addch(root_window, *p+'A'-1);
|
||||
term_set_color(root_window, ATTR_RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/* clear the rest of the input line */
|
||||
if (end_xpos == screen_width)
|
||||
screen_clrtoeol(screen_root);
|
||||
if (end_xpos == term_width)
|
||||
term_clrtoeol(root_window);
|
||||
else {
|
||||
while (xpos < end_xpos) {
|
||||
screen_addch(screen_root, ' ');
|
||||
term_addch(root_window, ' ');
|
||||
xpos++;
|
||||
}
|
||||
}
|
||||
|
||||
screen_move_cursor(entry->xpos + entry->scrpos + entry->promptlen,
|
||||
entry->ypos);
|
||||
screen_refresh(NULL);
|
||||
term_move_cursor(entry->xpos + entry->scrpos + entry->promptlen,
|
||||
entry->ypos);
|
||||
term_refresh(NULL);
|
||||
}
|
||||
|
||||
static void gui_entry_draw(GUI_ENTRY_REC *entry)
|
||||
@ -153,9 +153,9 @@ void gui_entry_set_active(GUI_ENTRY_REC *entry)
|
||||
active_entry = entry;
|
||||
|
||||
if (entry != NULL) {
|
||||
screen_move_cursor(entry->xpos + entry->scrpos +
|
||||
entry->promptlen, entry->ypos);
|
||||
screen_refresh(NULL);
|
||||
term_move_cursor(entry->xpos + entry->scrpos +
|
||||
entry->promptlen, entry->ypos);
|
||||
term_refresh(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,14 +25,14 @@
|
||||
#include "formats.h"
|
||||
#include "printtext.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "term.h"
|
||||
#include "gui-printtext.h"
|
||||
#include "gui-windows.h"
|
||||
|
||||
int mirc_colors[] = { 15, 0, 1, 2, 12, 6, 5, 4, 14, 10, 3, 11, 9, 13, 8, 7 };
|
||||
static int scrollback_lines, scrollback_hours, scrollback_burst_remove;
|
||||
|
||||
static int last_color, last_flags;
|
||||
static int last_fg, last_bg, last_flags;
|
||||
static int next_xpos, next_ypos;
|
||||
|
||||
static GHashTable *indent_functions;
|
||||
@ -137,51 +137,51 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
|
||||
}
|
||||
}
|
||||
|
||||
static void get_colors(int flags, int *fg, int *bg)
|
||||
static void get_colors(int flags, int *fg, int *bg, int *attr)
|
||||
{
|
||||
if (flags & GUI_PRINT_FLAG_MIRC_COLOR) {
|
||||
/* mirc colors - real range is 0..15, but after 16
|
||||
colors wrap to 0, 1, ... */
|
||||
*bg = *bg < 0 ? 0 : mirc_colors[*bg % 16];
|
||||
if (*fg > 0) *fg = mirc_colors[*fg % 16];
|
||||
} else {
|
||||
/* default colors */
|
||||
*bg = *bg < 0 || *bg > 15 ? 0 : *bg;
|
||||
if (*fg > 8) *fg &= ~8;
|
||||
if (*bg >= 0) *bg = mirc_colors[*bg % 16];
|
||||
if (*fg >= 0) *fg = mirc_colors[*fg % 16];
|
||||
}
|
||||
|
||||
if (*fg < 0 || *fg > 15) {
|
||||
*fg = *bg == 0 ? current_theme->default_color :
|
||||
current_theme->default_real_color;
|
||||
}
|
||||
if (*fg < 0 || *fg > 15)
|
||||
*fg = current_theme->default_color;
|
||||
if (*bg < 0 || *bg > 15)
|
||||
*bg = -1;
|
||||
|
||||
if (flags & GUI_PRINT_FLAG_REVERSE)
|
||||
*fg |= ATTR_REVERSE;
|
||||
|
||||
if (*fg == 8) *fg |= ATTR_COLOR8;
|
||||
if (flags & GUI_PRINT_FLAG_BOLD) {
|
||||
if (*fg == 0) *fg = current_theme->default_real_color;
|
||||
*fg |= 8;
|
||||
}
|
||||
if (flags & GUI_PRINT_FLAG_UNDERLINE) *fg |= ATTR_UNDERLINE;
|
||||
if (flags & GUI_PRINT_FLAG_BLINK) *bg |= 0x08;
|
||||
*attr = 0;
|
||||
if (flags & GUI_PRINT_FLAG_REVERSE) *attr |= ATTR_REVERSE;
|
||||
if (flags & GUI_PRINT_FLAG_BOLD) *attr |= ATTR_BOLD;
|
||||
if (flags & GUI_PRINT_FLAG_UNDERLINE) *attr |= ATTR_UNDERLINE;
|
||||
if (flags & GUI_PRINT_FLAG_BLINK) *attr |= ATTR_BLINK;
|
||||
}
|
||||
|
||||
static void line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line,
|
||||
int fg, int bg, int flags)
|
||||
{
|
||||
unsigned char data[20];
|
||||
int color, pos;
|
||||
int pos;
|
||||
|
||||
/* get the fg & bg command chars */
|
||||
fg = fg < 0 ? LINE_COLOR_DEFAULT : fg & 0x0f;
|
||||
bg = LINE_COLOR_BG | (bg < 0 ? LINE_COLOR_DEFAULT : bg & 0x0f);
|
||||
if (flags & GUI_PRINT_FLAG_BOLD)
|
||||
fg |= LINE_COLOR_BOLD;
|
||||
if (flags & GUI_PRINT_FLAG_BLINK)
|
||||
bg |= LINE_COLOR_BLINK;
|
||||
|
||||
/* color should never have last bit on or it would be treated as a
|
||||
command! */
|
||||
color = (fg & 0x0f) | ((bg & 0x07) << 4);
|
||||
pos = 0;
|
||||
|
||||
if (((fg & ATTR_COLOR8) == 0 && (fg|(bg << 4)) != last_color) ||
|
||||
((fg & ATTR_COLOR8) && (fg & 0xf0) != (last_color & 0xf0))) {
|
||||
if (fg != last_fg) {
|
||||
last_fg = fg;
|
||||
data[pos++] = 0;
|
||||
data[pos++] = color == 0 ? LINE_CMD_COLOR0 : color;
|
||||
data[pos++] = fg == 0 ? LINE_CMD_COLOR0 : fg;
|
||||
}
|
||||
if (bg != last_bg) {
|
||||
last_bg = bg;
|
||||
data[pos++] = 0;
|
||||
data[pos++] = bg;
|
||||
}
|
||||
|
||||
if ((flags & GUI_PRINT_FLAG_UNDERLINE) != (last_flags & GUI_PRINT_FLAG_UNDERLINE)) {
|
||||
@ -192,14 +192,6 @@ static void line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line,
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_REVERSE;
|
||||
}
|
||||
if (fg & ATTR_COLOR8) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_COLOR8;
|
||||
}
|
||||
if (bg & 0x08) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_BLINK;
|
||||
}
|
||||
if (flags & GUI_PRINT_FLAG_INDENT) {
|
||||
data[pos++] = 0;
|
||||
data[pos++] = LINE_CMD_INDENT;
|
||||
@ -209,7 +201,6 @@ static void line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line,
|
||||
*line = textbuffer_insert(buffer, *line, data, pos, NULL);
|
||||
|
||||
last_flags = flags;
|
||||
last_color = fg | (bg << 4);
|
||||
}
|
||||
|
||||
static void line_add_indent_func(TEXT_BUFFER_REC *buffer, LINE_REC **line,
|
||||
@ -243,24 +234,24 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
|
||||
TEXT_BUFFER_VIEW_REC *view;
|
||||
LINE_REC *insert_after;
|
||||
LINE_INFO_REC lineinfo;
|
||||
int fg, bg, flags;
|
||||
int fg, bg, flags, attr;
|
||||
|
||||
flags = GPOINTER_TO_INT(pflags);
|
||||
fg = GPOINTER_TO_INT(fgcolor);
|
||||
bg = GPOINTER_TO_INT(bgcolor);
|
||||
get_colors(flags, &fg, &bg);
|
||||
get_colors(flags, &fg, &bg, &attr);
|
||||
|
||||
if (window == NULL) {
|
||||
g_return_if_fail(next_xpos != -1);
|
||||
|
||||
screen_move(screen_root, next_xpos, next_ypos);
|
||||
if (flags & GUI_PRINT_FLAG_CLRTOEOL) {
|
||||
screen_set_bg(screen_root, fg | (bg << 4));
|
||||
screen_clrtoeol(screen_root);
|
||||
screen_set_bg(screen_root, 0);
|
||||
}
|
||||
screen_set_color(screen_root, fg | (bg << 4));
|
||||
screen_addstr(screen_root, str);
|
||||
attr |= fg > 0 ? fg : ATTR_RESETFG;
|
||||
attr |= bg > 0 ? (bg << 4) : ATTR_RESETBG;
|
||||
term_set_color(root_window, attr);
|
||||
|
||||
term_move(root_window, next_xpos, next_ypos);
|
||||
if (flags & GUI_PRINT_FLAG_CLRTOEOL)
|
||||
term_clrtoeol(root_window);
|
||||
term_addstr(root_window, str);
|
||||
next_xpos += strlen(str);
|
||||
return;
|
||||
}
|
||||
@ -293,7 +284,7 @@ static void sig_gui_printtext_finished(WINDOW_REC *window)
|
||||
TEXT_BUFFER_VIEW_REC *view;
|
||||
LINE_REC *insert_after;
|
||||
|
||||
last_color = 0;
|
||||
last_fg = last_bg = -1;
|
||||
last_flags = 0;
|
||||
|
||||
view = WINDOW_GUI(window)->view;
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "keyboard.h"
|
||||
#include "translation.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "term.h"
|
||||
#include "gui-entry.h"
|
||||
#include "gui-windows.h"
|
||||
|
||||
@ -330,7 +330,7 @@ void readline(void)
|
||||
int key;
|
||||
|
||||
for (;;) {
|
||||
key = screen_getch();
|
||||
key = term_getch();
|
||||
if (key == -1)
|
||||
break;
|
||||
|
||||
@ -485,6 +485,11 @@ static void key_insert_text(const char *data)
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
static void key_sig_stop(void)
|
||||
{
|
||||
term_stop();
|
||||
}
|
||||
|
||||
static void sig_window_auto_changed(void)
|
||||
{
|
||||
command_history_next(active_win, gui_entry_get_text(active_entry));
|
||||
@ -615,9 +620,11 @@ void gui_readline_init(void)
|
||||
/* inserting special input characters to line.. */
|
||||
key_bind("insert_text", "Append text to line", NULL, NULL, (SIGNAL_FUNC) key_insert_text);
|
||||
|
||||
/* autoreplaces */
|
||||
key_bind("multi", NULL, "return", "check_replaces;send_line", NULL);
|
||||
key_bind("multi", NULL, "space", "check_replaces;insert_text ", NULL);
|
||||
|
||||
/* moving between windows */
|
||||
for (n = 0; changekeys[n] != '\0'; n++) {
|
||||
key = g_strdup_printf("meta-%c", changekeys[n]);
|
||||
ltoa(data, n+1);
|
||||
@ -625,6 +632,9 @@ void gui_readline_init(void)
|
||||
g_free(key);
|
||||
}
|
||||
|
||||
/* misc */
|
||||
key_bind("stop_irc", "Send SIGSTOP to client", "^Z", NULL, (SIGNAL_FUNC) key_sig_stop);
|
||||
|
||||
key_configure_thaw();
|
||||
|
||||
signal_add("window changed automatic", (SIGNAL_FUNC) sig_window_auto_changed);
|
||||
@ -681,6 +691,7 @@ void gui_readline_deinit(void)
|
||||
|
||||
key_unbind("insert_text", (SIGNAL_FUNC) key_insert_text);
|
||||
key_unbind("change_window", (SIGNAL_FUNC) key_change_window);
|
||||
key_unbind("stop_irc", (SIGNAL_FUNC) key_sig_stop);
|
||||
keyboard_destroy(keyboard);
|
||||
|
||||
key_configure_thaw();
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "settings.h"
|
||||
#include "special-vars.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "term.h"
|
||||
#include "gui-entry.h"
|
||||
#include "gui-windows.h"
|
||||
#include "gui-printtext.h"
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "fe-common-irc.h"
|
||||
#include "themes.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "term.h"
|
||||
#include "gui-entry.h"
|
||||
#include "mainwindows.h"
|
||||
#include "gui-printtext.h"
|
||||
@ -91,8 +91,8 @@ static void sig_exit(void)
|
||||
/* redraw irssi's screen.. */
|
||||
void irssi_redraw(void)
|
||||
{
|
||||
screen_clear();
|
||||
screen_refresh(NULL);
|
||||
term_clear();
|
||||
term_refresh(NULL);
|
||||
|
||||
/* windows */
|
||||
mainwindows_redraw();
|
||||
@ -116,7 +116,7 @@ static void textui_finish_init(void)
|
||||
{
|
||||
quitting = FALSE;
|
||||
|
||||
screen_refresh_freeze();
|
||||
term_refresh_freeze();
|
||||
textbuffer_init();
|
||||
textbuffer_view_init();
|
||||
textbuffer_commands_init();
|
||||
@ -130,7 +130,7 @@ static void textui_finish_init(void)
|
||||
mainwindows_layout_init();
|
||||
gui_windows_init();
|
||||
statusbar_init();
|
||||
screen_refresh_thaw();
|
||||
term_refresh_thaw();
|
||||
|
||||
settings_check();
|
||||
module_register("core", "fe-text");
|
||||
@ -155,7 +155,7 @@ static void textui_deinit(void)
|
||||
quitting = TRUE;
|
||||
signal(SIGINT, SIG_DFL);
|
||||
|
||||
screen_refresh_freeze();
|
||||
term_refresh_freeze();
|
||||
while (modules != NULL)
|
||||
module_unload(modules->data);
|
||||
|
||||
@ -180,8 +180,8 @@ static void textui_deinit(void)
|
||||
textbuffer_view_deinit();
|
||||
textbuffer_deinit();
|
||||
|
||||
screen_refresh_thaw();
|
||||
deinit_screen();
|
||||
term_refresh_thaw();
|
||||
term_deinit();
|
||||
|
||||
theme_unregister();
|
||||
|
||||
@ -274,7 +274,7 @@ int main(int argc, char **argv)
|
||||
textui_init();
|
||||
args_execute(argc, argv);
|
||||
|
||||
if (!init_screen())
|
||||
if (!term_init())
|
||||
g_error("Can't initialize screen handling, quitting.\n");
|
||||
|
||||
textui_finish_init();
|
||||
|
@ -38,7 +38,7 @@ static void window_lastlog_clear(WINDOW_REC *window)
|
||||
TEXT_BUFFER_VIEW_REC *view;
|
||||
LINE_REC *line, *next;
|
||||
|
||||
screen_refresh_freeze();
|
||||
term_refresh_freeze();
|
||||
view = WINDOW_GUI(window)->view;
|
||||
line = textbuffer_view_get_lines(view);
|
||||
|
||||
@ -50,7 +50,7 @@ static void window_lastlog_clear(WINDOW_REC *window)
|
||||
line = next;
|
||||
}
|
||||
textbuffer_view_redraw(view);
|
||||
screen_refresh_thaw();
|
||||
term_refresh_thaw();
|
||||
}
|
||||
|
||||
/* Only unknown keys in `optlist' should be levels.
|
||||
|
@ -123,7 +123,7 @@ static void sig_layout_restore(void)
|
||||
windows_count = g_slist_length(sorted_config);
|
||||
|
||||
/* calculate the saved terminal height */
|
||||
avail_height = screen_height -
|
||||
avail_height = term_height -
|
||||
screen_reserved_top - screen_reserved_bottom;
|
||||
height = 0;
|
||||
heights = g_new0(int, windows_count);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "settings.h"
|
||||
#include "printtext.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "term.h"
|
||||
#include "gui-windows.h"
|
||||
|
||||
#define NEW_WINDOW_SIZE (WINDOW_MIN_SIZE + 1)
|
||||
@ -39,16 +39,16 @@ int screen_reserved_top, screen_reserved_bottom;
|
||||
static int old_screen_width, old_screen_height;
|
||||
|
||||
#define mainwindow_create_screen(window) \
|
||||
screen_window_create(0, \
|
||||
(window)->first_line + (window)->statusbar_lines_top, \
|
||||
(window)->width, \
|
||||
(window)->height + (window)->statusbar_lines)
|
||||
|
||||
#define mainwindow_set_screen_size(window) \
|
||||
screen_window_move((window)->screen_win, 0, \
|
||||
term_window_create(0, \
|
||||
(window)->first_line + (window)->statusbar_lines_top, \
|
||||
(window)->width, \
|
||||
(window)->height - (window)->statusbar_lines);
|
||||
(window)->height + (window)->statusbar_lines)
|
||||
|
||||
#define mainwindow_set_screen_size(window) \
|
||||
term_window_move((window)->screen_win, 0, \
|
||||
(window)->first_line + (window)->statusbar_lines_top, \
|
||||
(window)->width, \
|
||||
(window)->height - (window)->statusbar_lines);
|
||||
|
||||
|
||||
static MAIN_WINDOW_REC *find_window_with_room(void)
|
||||
@ -176,13 +176,13 @@ MAIN_WINDOW_REC *mainwindow_create(void)
|
||||
int space;
|
||||
|
||||
rec = g_new0(MAIN_WINDOW_REC, 1);
|
||||
rec->width = screen_width;
|
||||
rec->width = term_width;
|
||||
|
||||
if (mainwindows == NULL) {
|
||||
active_mainwin = rec;
|
||||
|
||||
rec->first_line = screen_reserved_top;
|
||||
rec->last_line = screen_height-1 - screen_reserved_bottom;
|
||||
rec->last_line = term_height-1 - screen_reserved_bottom;
|
||||
rec->height = rec->last_line-rec->first_line+1;
|
||||
} else {
|
||||
parent = WINDOW_MAIN(active_win);
|
||||
@ -204,7 +204,7 @@ MAIN_WINDOW_REC *mainwindow_create(void)
|
||||
}
|
||||
|
||||
rec->screen_win = mainwindow_create_screen(rec);
|
||||
screen_refresh(NULL);
|
||||
term_refresh(NULL);
|
||||
|
||||
mainwindows = g_slist_append(mainwindows, rec);
|
||||
signal_emit("mainwindow created", 1, rec);
|
||||
@ -290,7 +290,7 @@ void mainwindow_destroy(MAIN_WINDOW_REC *window)
|
||||
mainwindows = g_slist_remove(mainwindows, window);
|
||||
signal_emit("mainwindow destroyed", 1, window);
|
||||
|
||||
screen_window_destroy(window->screen_win);
|
||||
term_window_destroy(window->screen_win);
|
||||
|
||||
if (!quitting && mainwindows != NULL) {
|
||||
gui_windows_remove_parent(window);
|
||||
@ -308,13 +308,13 @@ void mainwindows_redraw(void)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
screen_refresh_freeze();
|
||||
term_refresh_freeze();
|
||||
for (tmp = mainwindows; tmp != NULL; tmp = tmp->next) {
|
||||
MAIN_WINDOW_REC *rec = tmp->data;
|
||||
|
||||
gui_window_redraw(rec->active);
|
||||
}
|
||||
screen_refresh_thaw();
|
||||
term_refresh_thaw();
|
||||
}
|
||||
|
||||
static int mainwindows_compare(MAIN_WINDOW_REC *w1, MAIN_WINDOW_REC *w2)
|
||||
@ -453,7 +453,7 @@ void mainwindows_resize(int width, int height)
|
||||
old_screen_width = width;
|
||||
old_screen_height = height;
|
||||
|
||||
screen_refresh_freeze();
|
||||
term_refresh_freeze();
|
||||
if (ydiff < 0)
|
||||
mainwindows_resize_smaller(xdiff, ydiff);
|
||||
else if (ydiff > 0)
|
||||
@ -462,7 +462,7 @@ void mainwindows_resize(int width, int height)
|
||||
mainwindows_resize_horiz(xdiff);
|
||||
|
||||
signal_emit("terminal resized", 0);
|
||||
screen_refresh_thaw();
|
||||
term_refresh_thaw();
|
||||
|
||||
irssi_redraw();
|
||||
}
|
||||
@ -492,7 +492,7 @@ int mainwindows_reserve_lines(int top, int bottom)
|
||||
ret = screen_reserved_bottom;
|
||||
screen_reserved_bottom += bottom;
|
||||
|
||||
window = mainwindows_find_upper(screen_height);
|
||||
window = mainwindows_find_upper(term_height);
|
||||
if (window != NULL) {
|
||||
window->last_line -= bottom;
|
||||
mainwindow_resize(window, 0, -bottom);
|
||||
@ -706,7 +706,7 @@ static void cmd_window_balance(void)
|
||||
windows = g_slist_length(mainwindows);
|
||||
if (windows == 1) return;
|
||||
|
||||
avail_size = screen_height - screen_reserved_top-screen_reserved_bottom;
|
||||
avail_size = term_height - screen_reserved_top-screen_reserved_bottom;
|
||||
unit_size = avail_size/windows;
|
||||
bigger_units = avail_size%windows;
|
||||
|
||||
@ -1033,8 +1033,8 @@ static void sig_window_print_info(WINDOW_REC *win)
|
||||
|
||||
void mainwindows_init(void)
|
||||
{
|
||||
old_screen_width = screen_width;
|
||||
old_screen_height = screen_height;
|
||||
old_screen_width = term_width;
|
||||
old_screen_height = term_height;
|
||||
|
||||
mainwindows = NULL;
|
||||
active_mainwin = NULL;
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define __MAINWINDOWS_H
|
||||
|
||||
#include "fe-windows.h"
|
||||
#include "screen.h"
|
||||
#include "term.h"
|
||||
|
||||
#define WINDOW_MIN_SIZE 2
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
typedef struct {
|
||||
WINDOW_REC *active;
|
||||
|
||||
SCREEN_WINDOW *screen_win;
|
||||
TERM_WINDOW *screen_win;
|
||||
int sticky_windows; /* number of sticky windows */
|
||||
|
||||
int first_line, last_line; /* first/last line used by this window (0..x) (includes statusbars) */
|
||||
|
@ -277,8 +277,8 @@ static void item_input(SBAR_ITEM_REC *item, int get_size_only)
|
||||
GUI_ENTRY_REC *rec;
|
||||
|
||||
if (get_size_only) {
|
||||
item->min_size = 2+screen_width/10;
|
||||
item->max_size = screen_width;
|
||||
item->min_size = 2+term_width/10;
|
||||
item->max_size = term_width;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -235,7 +235,7 @@ static void statusbar_redraw_items(STATUSBAR_REC *bar)
|
||||
if (bar->parent_window != NULL)
|
||||
active_win = bar->parent_window->active;
|
||||
|
||||
statusbar_resize_items(bar, screen_width);
|
||||
statusbar_resize_items(bar, term_width);
|
||||
|
||||
xpos = 0;
|
||||
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
|
||||
@ -248,7 +248,7 @@ static void statusbar_redraw_items(STATUSBAR_REC *bar)
|
||||
}
|
||||
}
|
||||
|
||||
rxpos = screen_width;
|
||||
rxpos = term_width;
|
||||
for (tmp = bar->items; tmp != NULL; tmp = tmp->next) {
|
||||
SBAR_ITEM_REC *rec = tmp->data;
|
||||
|
||||
@ -282,10 +282,10 @@ void statusbar_redraw(STATUSBAR_REC *bar)
|
||||
|
||||
if (bar == NULL) {
|
||||
if (active_statusbar_group != NULL) {
|
||||
screen_refresh_freeze();
|
||||
term_refresh_freeze();
|
||||
g_slist_foreach(active_statusbar_group->bars,
|
||||
(GFunc) statusbar_redraw, NULL);
|
||||
screen_refresh_thaw();
|
||||
term_refresh_thaw();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -295,7 +295,7 @@ void statusbar_redraw(STATUSBAR_REC *bar)
|
||||
g_free(str);
|
||||
|
||||
statusbar_redraw_items(bar);
|
||||
screen_refresh(NULL);
|
||||
term_refresh(NULL);
|
||||
}
|
||||
|
||||
void statusbar_item_redraw(SBAR_ITEM_REC *item)
|
||||
@ -317,7 +317,7 @@ void statusbar_item_redraw(SBAR_ITEM_REC *item)
|
||||
} else {
|
||||
/*FIXME:fprintf(stderr, "%s redrawing", item->config->name);*/
|
||||
item->func(item, FALSE);
|
||||
screen_refresh(NULL);
|
||||
term_refresh(NULL);
|
||||
}
|
||||
|
||||
active_win = old_active_win;
|
||||
@ -360,7 +360,7 @@ static void statusbars_recalc_ypos(STATUSBAR_REC *bar)
|
||||
/* get the Y-position for the first statusbar */
|
||||
if (bar->config->type == STATUSBAR_TYPE_ROOT) {
|
||||
ypos = bar->config->placement == STATUSBAR_TOP ? 0 :
|
||||
screen_height - g_slist_length(bar_group);
|
||||
term_height - g_slist_length(bar_group);
|
||||
} else {
|
||||
ypos = bar->config->placement == STATUSBAR_TOP ?
|
||||
bar->parent_window->first_line :
|
||||
|
368
src/fe-text/term-curses.c
Normal file
368
src/fe-text/term-curses.c
Normal file
@ -0,0 +1,368 @@
|
||||
/*
|
||||
term-curses.c : irssi
|
||||
|
||||
Copyright (C) 1999-2001 Timo Sirainen
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "term.h"
|
||||
#include "mainwindows.h"
|
||||
|
||||
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
|
||||
# include <ncurses.h>
|
||||
#else
|
||||
# include <curses.h>
|
||||
#endif
|
||||
#include <termios.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef COLOR_PAIRS
|
||||
# define COLOR_PAIRS 64
|
||||
#endif
|
||||
|
||||
#if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM)
|
||||
# define USE_RESIZE_TERM
|
||||
#endif
|
||||
|
||||
#ifndef _POSIX_VDISABLE
|
||||
# define _POSIX_VDISABLE 0
|
||||
#endif
|
||||
|
||||
struct _TERM_WINDOW {
|
||||
int x, y;
|
||||
int width, height;
|
||||
WINDOW *win;
|
||||
};
|
||||
|
||||
TERM_WINDOW *root_window;
|
||||
int term_width, term_height;
|
||||
|
||||
static int curs_x, curs_y;
|
||||
static int freeze_refresh;
|
||||
static struct termios old_tio;
|
||||
|
||||
static int init_curses(void)
|
||||
{
|
||||
char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
||||
int num;
|
||||
struct termios tio;
|
||||
|
||||
if (!initscr())
|
||||
return FALSE;
|
||||
|
||||
cbreak(); noecho(); idlok(stdscr, 1);
|
||||
#ifdef HAVE_CURSES_IDCOK
|
||||
/*idcok(stdscr, 1); - disabled currently, causes redrawing problems with NetBSD */
|
||||
#endif
|
||||
intrflush(stdscr, FALSE); nodelay(stdscr, TRUE);
|
||||
|
||||
/* Disable INTR, QUIT, VDSUSP and SUSP keys */
|
||||
if (tcgetattr(0, &old_tio) == 0) {
|
||||
memcpy(&tio, &old_tio, sizeof(tio));
|
||||
tio.c_cc[VINTR] = _POSIX_VDISABLE;
|
||||
tio.c_cc[VQUIT] = _POSIX_VDISABLE;
|
||||
#ifdef VDSUSP
|
||||
tio.c_cc[VDSUSP] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
#ifdef VSUSP
|
||||
tio.c_cc[VSUSP] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
tcsetattr(0, 0, &tio);
|
||||
}
|
||||
|
||||
if (has_colors())
|
||||
start_color();
|
||||
else if (term_use_colors)
|
||||
term_use_colors = FALSE;
|
||||
|
||||
#ifdef HAVE_NCURSES_USE_DEFAULT_COLORS
|
||||
/* this lets us to use the "default" background color for colors <= 7 so
|
||||
background pixmaps etc. show up right */
|
||||
use_default_colors();
|
||||
|
||||
for (num = 1; num < COLOR_PAIRS; num++)
|
||||
init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]);
|
||||
|
||||
init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more
|
||||
people want dark grey than white on white.. */
|
||||
#else
|
||||
for (num = 1; num < COLOR_PAIRS; num++)
|
||||
init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]);
|
||||
init_pair(63, 0, 0);
|
||||
#endif
|
||||
|
||||
clear();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int term_init_int(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = init_curses();
|
||||
if (!ret) return 0;
|
||||
|
||||
curs_x = curs_y = 0;
|
||||
freeze_refresh = 0;
|
||||
|
||||
root_window = g_new0(TERM_WINDOW, 1);
|
||||
root_window->win = stdscr;
|
||||
|
||||
term_width = COLS;
|
||||
term_height = LINES;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void term_deinit_int(void)
|
||||
{
|
||||
tcsetattr(0, 0, &old_tio);
|
||||
|
||||
endwin();
|
||||
g_free_and_null(root_window);
|
||||
}
|
||||
|
||||
int term_init(void)
|
||||
{
|
||||
if (!term_init_int())
|
||||
return FALSE;
|
||||
|
||||
settings_add_int("lookandfeel", "default_color", 7);
|
||||
term_common_init();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void term_deinit(void)
|
||||
{
|
||||
term_common_deinit();
|
||||
term_deinit_int();
|
||||
}
|
||||
|
||||
/* Resize terminal - if width or height is negative,
|
||||
the new size is unknown and should be figured out somehow */
|
||||
void term_resize(int width, int height)
|
||||
{
|
||||
#ifdef HAVE_CURSES_RESIZETERM
|
||||
if (width < 0 || height < 0) {
|
||||
#endif
|
||||
term_deinit_int();
|
||||
term_init_int();
|
||||
mainwindows_recreate();
|
||||
#ifdef HAVE_CURSES_RESIZETERM
|
||||
} else if (term_width != width || term_height != height) {
|
||||
term_width = width;
|
||||
term_height = height;
|
||||
resizeterm(term_height, term_width);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Returns TRUE if terminal has colors */
|
||||
int term_has_colors(void)
|
||||
{
|
||||
return has_colors();
|
||||
}
|
||||
|
||||
/* Force the colors on any way you can */
|
||||
void term_force_colors(int set)
|
||||
{
|
||||
/* don't do anything with curses */
|
||||
}
|
||||
|
||||
/* Clear screen */
|
||||
void term_clear(void)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
/* Beep */
|
||||
void term_beep(void)
|
||||
{
|
||||
beep();
|
||||
}
|
||||
|
||||
/* Create a new window in terminal */
|
||||
TERM_WINDOW *term_window_create(int x, int y, int width, int height)
|
||||
{
|
||||
TERM_WINDOW *window;
|
||||
|
||||
window = g_new0(TERM_WINDOW, 1);
|
||||
window->x = x; window->y = y;
|
||||
window->width = width; window->height = height;
|
||||
window->win = newwin(height, width, y, x);
|
||||
idlok(window->win, 1);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/* Destroy a terminal window */
|
||||
void term_window_destroy(TERM_WINDOW *window)
|
||||
{
|
||||
delwin(window->win);
|
||||
g_free(window);
|
||||
}
|
||||
|
||||
/* Move/resize a window */
|
||||
void term_window_move(TERM_WINDOW *window, int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
/* some checks to make sure the window is visible in screen,
|
||||
otherwise curses could get nasty and not show our window anymore. */
|
||||
if (width < 1) width = 1;
|
||||
if (height < 1) height = 1;
|
||||
if (x+width > term_width) x = term_width-width;
|
||||
if (y+height > term_height) y = term_height-height;
|
||||
|
||||
#ifdef HAVE_CURSES_WRESIZE
|
||||
if (window->width != width || window->height != height)
|
||||
wresize(window->win, height, width);
|
||||
if (window->x != x || window->y != y)
|
||||
mvwin(window->win, y, x);
|
||||
#else
|
||||
if (window->width != width || window->height != height ||
|
||||
window->x != x || window->y != y) {
|
||||
delwin(window->win);
|
||||
window->win = newwin(height, width, y, x);
|
||||
idlok(window->win, 1);
|
||||
}
|
||||
#endif
|
||||
window->x = x; window->y = y;
|
||||
window->width = width; window->height = height;
|
||||
}
|
||||
|
||||
/* Clear window */
|
||||
void term_window_clear(TERM_WINDOW *window)
|
||||
{
|
||||
werase(window->win);
|
||||
}
|
||||
|
||||
/* Scroll window up/down */
|
||||
void term_window_scroll(TERM_WINDOW *window, int count)
|
||||
{
|
||||
scrollok(window->win, TRUE);
|
||||
wscrl(window->win, count);
|
||||
scrollok(window->win, FALSE);
|
||||
}
|
||||
|
||||
static int get_attr(int color)
|
||||
{
|
||||
int attr;
|
||||
|
||||
if (!term_use_colors)
|
||||
attr = (color & 0x70) ? A_REVERSE : 0;
|
||||
else if (((color & 0x0f) == 8) && (color & ATTR_BOLD) == 0)
|
||||
attr = (A_DIM | COLOR_PAIR(63));
|
||||
else if ((color & 0x77) == 0)
|
||||
attr = A_NORMAL;
|
||||
else {
|
||||
if (color & ATTR_RESETFG) {
|
||||
color &= ~0x0f;
|
||||
color |= settings_get_int("default_color");
|
||||
}
|
||||
attr = (COLOR_PAIR((color&7) + (color&0x70)/2));
|
||||
}
|
||||
|
||||
if ((color & 0x08) || (color & ATTR_BOLD)) attr |= A_BOLD;
|
||||
if (color & ATTR_BLINK) attr |= A_BLINK;
|
||||
|
||||
if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE;
|
||||
if (color & ATTR_REVERSE) attr |= A_REVERSE;
|
||||
return attr;
|
||||
}
|
||||
|
||||
/* Change active color */
|
||||
void term_set_color(TERM_WINDOW *window, int col)
|
||||
{
|
||||
wattrset(window->win, get_attr(col));
|
||||
wbkgdset(window->win, ' ' | get_attr(col));
|
||||
}
|
||||
|
||||
void term_move(TERM_WINDOW *window, int x, int y)
|
||||
{
|
||||
wmove(window->win, y, x);
|
||||
}
|
||||
|
||||
void term_addch(TERM_WINDOW *window, int chr)
|
||||
{
|
||||
waddch(window->win, chr);
|
||||
}
|
||||
|
||||
void term_addstr(TERM_WINDOW *window, char *str)
|
||||
{
|
||||
waddstr(window->win, str);
|
||||
}
|
||||
|
||||
void term_clrtoeol(TERM_WINDOW *window)
|
||||
{
|
||||
wclrtoeol(window->win);
|
||||
}
|
||||
|
||||
void term_move_cursor(int x, int y)
|
||||
{
|
||||
curs_x = x;
|
||||
curs_y = y;
|
||||
}
|
||||
|
||||
void term_refresh_freeze(void)
|
||||
{
|
||||
freeze_refresh++;
|
||||
}
|
||||
|
||||
void term_refresh_thaw(void)
|
||||
{
|
||||
if (freeze_refresh > 0) {
|
||||
freeze_refresh--;
|
||||
if (freeze_refresh == 0) term_refresh(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void term_refresh(TERM_WINDOW *window)
|
||||
{
|
||||
if (window != NULL)
|
||||
wnoutrefresh(window->win);
|
||||
|
||||
if (freeze_refresh == 0) {
|
||||
move(curs_y, curs_x);
|
||||
wnoutrefresh(stdscr);
|
||||
doupdate();
|
||||
}
|
||||
}
|
||||
|
||||
void term_stop(void)
|
||||
{
|
||||
term_deinit_int();
|
||||
kill(getpid(), SIGSTOP);
|
||||
term_init_int();
|
||||
irssi_redraw();
|
||||
}
|
||||
|
||||
int term_getch(void)
|
||||
{
|
||||
int key;
|
||||
|
||||
key = getch();
|
||||
if (key == ERR)
|
||||
return -1;
|
||||
|
||||
#ifdef KEY_RESIZE
|
||||
if (key == KEY_RESIZE)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return key;
|
||||
}
|
296
src/fe-text/term-terminfo.c
Normal file
296
src/fe-text/term-terminfo.c
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
term-terminfo.c : irssi
|
||||
|
||||
Copyright (C) 2001 Timo Sirainen
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "term.h"
|
||||
#include "terminfo-core.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
struct _TERM_WINDOW {
|
||||
/* Terminal to use for window */
|
||||
TERM_REC *term;
|
||||
|
||||
/* Area for window in terminal */
|
||||
int x, y;
|
||||
int width, height;
|
||||
};
|
||||
|
||||
TERM_WINDOW *root_window;
|
||||
int term_width, term_height;
|
||||
|
||||
static int curs_x, curs_y;
|
||||
static int last_fg, last_bg, last_attrs;
|
||||
static int redraw_needed, redraw_tag;
|
||||
|
||||
/* SIGCONT handler */
|
||||
static void sig_cont(int p)
|
||||
{
|
||||
redraw_needed = TRUE;
|
||||
terminfo_cont(current_term);
|
||||
}
|
||||
|
||||
static int redraw_timeout(void)
|
||||
{
|
||||
if (redraw_needed) {
|
||||
irssi_redraw();
|
||||
redraw_needed = FALSE;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int term_init(void)
|
||||
{
|
||||
struct sigaction act;
|
||||
|
||||
last_fg = last_bg = -1;
|
||||
last_attrs = 0;
|
||||
|
||||
current_term = terminfo_core_init(stdin, stdout);
|
||||
if (current_term == NULL)
|
||||
return FALSE;
|
||||
|
||||
/* grab CONT signal */
|
||||
sigemptyset(&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = sig_cont;
|
||||
sigaction(SIGCONT, &act, NULL);
|
||||
redraw_tag = g_timeout_add(500, (GSourceFunc) redraw_timeout, NULL);
|
||||
|
||||
curs_x = curs_y = 0;
|
||||
term_width = current_term->width;
|
||||
term_height = current_term->height;
|
||||
root_window = term_window_create(0, 0, term_width, term_height);
|
||||
|
||||
term_common_init();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void term_deinit(void)
|
||||
{
|
||||
g_source_remove(redraw_tag);
|
||||
|
||||
term_common_deinit();
|
||||
terminfo_core_deinit(current_term);
|
||||
}
|
||||
|
||||
/* Resize terminal - if width or height is negative,
|
||||
the new size is unknown and should be figured out somehow */
|
||||
void term_resize(int width, int height)
|
||||
{
|
||||
if (width < 0 || height < 0) {
|
||||
terminfo_resize(current_term);
|
||||
width = current_term->width;
|
||||
height = current_term->height;
|
||||
}
|
||||
|
||||
if (term_width != width || term_height != height) {
|
||||
term_width = current_term->width = width;
|
||||
term_height = current_term->height = height;
|
||||
term_window_move(root_window, 0, 0, term_width, term_height);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns TRUE if terminal has colors */
|
||||
int term_has_colors(void)
|
||||
{
|
||||
return terminfo_has_colors(current_term);
|
||||
}
|
||||
|
||||
/* Force the colors on any way you can */
|
||||
void term_force_colors(int set)
|
||||
{
|
||||
terminfo_setup_colors(current_term, set);
|
||||
}
|
||||
|
||||
/* Clear screen */
|
||||
void term_clear(void)
|
||||
{
|
||||
terminfo_clear();
|
||||
}
|
||||
|
||||
/* Beep */
|
||||
void term_beep(void)
|
||||
{
|
||||
/* FIXME */
|
||||
}
|
||||
|
||||
/* Create a new window in terminal */
|
||||
TERM_WINDOW *term_window_create(int x, int y, int width, int height)
|
||||
{
|
||||
TERM_WINDOW *window;
|
||||
|
||||
window = g_new0(TERM_WINDOW, 1);
|
||||
window->term = current_term;
|
||||
window->x = x; window->y = y;
|
||||
window->width = width; window->height = height;
|
||||
return window;
|
||||
}
|
||||
|
||||
/* Destroy a terminal window */
|
||||
void term_window_destroy(TERM_WINDOW *window)
|
||||
{
|
||||
g_free(window);
|
||||
}
|
||||
|
||||
/* Move/resize a window */
|
||||
void term_window_move(TERM_WINDOW *window, int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
window->x = x;
|
||||
window->y = y;
|
||||
window->width = width;
|
||||
window->height = height;
|
||||
}
|
||||
|
||||
/* Clear window */
|
||||
void term_window_clear(TERM_WINDOW *window)
|
||||
{
|
||||
int y;
|
||||
|
||||
terminfo_set_normal();
|
||||
for (y = 0; y < window->height; y++) {
|
||||
terminfo_move(0, window->y+y);
|
||||
terminfo_clrtoeol();
|
||||
}
|
||||
}
|
||||
|
||||
/* Scroll window up/down */
|
||||
void term_window_scroll(TERM_WINDOW *window, int count)
|
||||
{
|
||||
terminfo_scroll(window->y, window->y+window->height-1, count);
|
||||
}
|
||||
|
||||
/* Change active color */
|
||||
void term_set_color(TERM_WINDOW *window, int col)
|
||||
{
|
||||
int set_normal;
|
||||
|
||||
set_normal = ((col & ATTR_RESETFG) && last_fg != -1) ||
|
||||
((col & ATTR_RESETBG) && last_bg != -1);
|
||||
if (((last_attrs & ATTR_BOLD) && (col & ATTR_BOLD) == 0) ||
|
||||
((last_attrs & ATTR_BLINK) && (col & ATTR_BLINK) == 0)) {
|
||||
/* we'll need to get rid of bold/blink - this can only be
|
||||
done with setting the default color */
|
||||
set_normal = TRUE;
|
||||
}
|
||||
|
||||
if (set_normal) {
|
||||
last_fg = last_bg = -1;
|
||||
last_attrs = 0;
|
||||
terminfo_set_normal();
|
||||
}
|
||||
|
||||
/* reversed text (use standout) */
|
||||
if (col & ATTR_REVERSE) {
|
||||
if ((last_attrs & ATTR_REVERSE) == 0)
|
||||
terminfo_set_standout(TRUE);
|
||||
} else if (last_attrs & ATTR_REVERSE)
|
||||
terminfo_set_standout(FALSE);
|
||||
|
||||
/* set foreground color */
|
||||
if ((col & 0x0f) != last_fg &&
|
||||
((col & 0x0f) != 0 || (col & ATTR_RESETFG) == 0)) {
|
||||
last_fg = col & 0x0f;
|
||||
terminfo_set_fg(last_fg);
|
||||
}
|
||||
|
||||
/* set background color */
|
||||
if (col & ATTR_BLINK)
|
||||
col |= 0x80;
|
||||
else if (col & 0x80)
|
||||
col |= ATTR_BLINK;
|
||||
|
||||
if ((col & 0xf0) >> 4 != last_bg &&
|
||||
((col & 0xf0) != 0 || (col & ATTR_RESETBG) == 0)) {
|
||||
last_bg = (col & 0xf0) >> 4;
|
||||
terminfo_set_bg(last_bg);
|
||||
}
|
||||
|
||||
/* bold */
|
||||
if (col & 0x08)
|
||||
col |= ATTR_BOLD;
|
||||
else if (col & ATTR_BOLD)
|
||||
terminfo_set_bold();
|
||||
|
||||
/* underline */
|
||||
if (col & ATTR_UNDERLINE) {
|
||||
if ((last_attrs & ATTR_UNDERLINE) == 0)
|
||||
terminfo_set_uline(TRUE);
|
||||
} else if (last_attrs & ATTR_UNDERLINE)
|
||||
terminfo_set_uline(FALSE);
|
||||
|
||||
last_attrs = col & ~0xff;
|
||||
}
|
||||
|
||||
void term_move(TERM_WINDOW *window, int x, int y)
|
||||
{
|
||||
terminfo_move(x+window->x, y+window->y);
|
||||
}
|
||||
|
||||
void term_addch(TERM_WINDOW *window, int chr)
|
||||
{
|
||||
putc(chr, window->term->out);
|
||||
}
|
||||
|
||||
void term_addstr(TERM_WINDOW *window, char *str)
|
||||
{
|
||||
fputs(str, window->term->out);
|
||||
}
|
||||
|
||||
void term_clrtoeol(TERM_WINDOW *window)
|
||||
{
|
||||
terminfo_clrtoeol();
|
||||
}
|
||||
|
||||
void term_move_cursor(int x, int y)
|
||||
{
|
||||
curs_x = x;
|
||||
curs_y = y;
|
||||
}
|
||||
|
||||
void term_refresh(TERM_WINDOW *window)
|
||||
{
|
||||
terminfo_move(curs_x, curs_y);
|
||||
fflush(window != NULL ? window->term->out : current_term->out);
|
||||
}
|
||||
|
||||
void term_refresh_freeze(void)
|
||||
{
|
||||
}
|
||||
|
||||
void term_refresh_thaw(void)
|
||||
{
|
||||
}
|
||||
|
||||
void term_stop(void)
|
||||
{
|
||||
terminfo_stop(current_term);
|
||||
kill(getpid(), SIGSTOP);
|
||||
terminfo_cont(current_term);
|
||||
irssi_redraw();
|
||||
}
|
||||
|
||||
int term_getch(void)
|
||||
{
|
||||
return fgetc(current_term->in);
|
||||
}
|
140
src/fe-text/term.c
Normal file
140
src/fe-text/term.c
Normal file
@ -0,0 +1,140 @@
|
||||
/*
|
||||
term.c : irssi
|
||||
|
||||
Copyright (C) 2001 Timo Sirainen
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "commands.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "term.h"
|
||||
#include "mainwindows.h"
|
||||
|
||||
#ifdef HAVE_SYS_IOCTL_H
|
||||
# include <sys/ioctl.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#include <termios.h>
|
||||
|
||||
#define RESIZE_TIMEOUT 500 /* how often to check if the terminal has been resized */
|
||||
#define MIN_SCREEN_WIDTH 20
|
||||
|
||||
int term_use_colors;
|
||||
|
||||
#ifdef SIGWINCH
|
||||
static int resize_timeout_tag;
|
||||
#endif
|
||||
static int resize_needed;
|
||||
|
||||
static int resize_timeout(void)
|
||||
{
|
||||
#ifdef TIOCGWINSZ
|
||||
struct winsize ws;
|
||||
#endif
|
||||
|
||||
if (!resize_needed)
|
||||
return TRUE;
|
||||
|
||||
resize_needed = FALSE;
|
||||
|
||||
#ifdef TIOCGWINSZ
|
||||
/* Get new window size */
|
||||
if (ioctl(0, TIOCGWINSZ, &ws) < 0)
|
||||
return TRUE;
|
||||
|
||||
if (ws.ws_row == term_height && ws.ws_col == term_width) {
|
||||
/* Same size, abort. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (ws.ws_col < MIN_SCREEN_WIDTH)
|
||||
ws.ws_col = MIN_SCREEN_WIDTH;
|
||||
|
||||
term_resize(ws.ws_col, ws.ws_row);
|
||||
#else
|
||||
term_resize(-1, -1);
|
||||
#endif
|
||||
mainwindows_resize(term_width, term_height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef SIGWINCH
|
||||
static void sig_winch(int p)
|
||||
{
|
||||
resize_needed = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void cmd_resize(void)
|
||||
{
|
||||
resize_needed = TRUE;
|
||||
resize_timeout();
|
||||
}
|
||||
|
||||
static void read_settings(void)
|
||||
{
|
||||
int old_colors = term_use_colors;
|
||||
|
||||
if (settings_get_bool("force_colors"))
|
||||
term_use_colors = TRUE;
|
||||
else {
|
||||
term_use_colors = settings_get_bool("colors");
|
||||
if (term_use_colors && !term_has_colors())
|
||||
term_use_colors = FALSE;
|
||||
}
|
||||
|
||||
if (term_use_colors != old_colors)
|
||||
irssi_redraw();
|
||||
}
|
||||
|
||||
void term_common_init(void)
|
||||
{
|
||||
#ifdef SIGWINCH
|
||||
struct sigaction act;
|
||||
#endif
|
||||
settings_add_bool("lookandfeel", "colors", TRUE);
|
||||
settings_add_bool("lookandfeel", "force_colors", FALSE);
|
||||
term_use_colors = settings_get_bool("colors");
|
||||
|
||||
signal_add("beep", (SIGNAL_FUNC) term_beep);
|
||||
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
command_bind("resize", NULL, (SIGNAL_FUNC) cmd_resize);
|
||||
|
||||
#ifdef SIGWINCH
|
||||
sigemptyset (&act.sa_mask);
|
||||
act.sa_flags = 0;
|
||||
act.sa_handler = sig_winch;
|
||||
sigaction(SIGWINCH, &act, NULL);
|
||||
|
||||
resize_timeout_tag = g_timeout_add(RESIZE_TIMEOUT,
|
||||
(GSourceFunc) resize_timeout, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void term_common_deinit(void)
|
||||
{
|
||||
#ifdef SIGWINCH
|
||||
g_source_remove(resize_timeout_tag);
|
||||
#endif
|
||||
|
||||
command_unbind("resize", (SIGNAL_FUNC) cmd_resize);
|
||||
signal_remove("beep", (SIGNAL_FUNC) term_beep);
|
||||
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
||||
}
|
81
src/fe-text/term.h
Normal file
81
src/fe-text/term.h
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef __TERM_H
|
||||
#define __TERM_H
|
||||
|
||||
typedef struct _TERM_WINDOW TERM_WINDOW;
|
||||
|
||||
#define ATTR_RESETFG 0x0100
|
||||
#define ATTR_RESETBG 0x0200
|
||||
#define ATTR_BOLD 0x0400
|
||||
#define ATTR_BLINK 0x0800
|
||||
#define ATTR_UNDERLINE 0x1000
|
||||
#define ATTR_REVERSE 0x2000
|
||||
|
||||
#define ATTR_RESET (ATTR_RESETFG|ATTR_RESETBG)
|
||||
|
||||
#define ATTR_NOCOLORS (ATTR_UNDERLINE|ATTR_REVERSE)
|
||||
|
||||
#ifdef WANT_BIG5
|
||||
/* XXX I didn't check the encoding range of big5+. This is standard big5. */
|
||||
# define is_big5_los(lo) (((char)0x40<=lo)&&(lo<=(char)0x7E)) /* standard */
|
||||
# define is_big5_lox(lo) (((char)0x80<=lo)&&(lo<=(char)0xFE)) /* extended */
|
||||
# define is_big5_hi(hi) (((char)0x81<=hi)&&(hi<=(char)0xFE))
|
||||
# define is_big5(hi,lo) is_big5_hi(hi) && (is_big5_los(lo) || is_big5_lox(lo))
|
||||
#endif
|
||||
|
||||
extern TERM_WINDOW *root_window;
|
||||
extern int term_width, term_height, term_use_colors;
|
||||
|
||||
/* Initialize / deinitialize terminal */
|
||||
int term_init(void);
|
||||
void term_deinit(void);
|
||||
|
||||
/* Resize terminal - if width or height is negative,
|
||||
the new size is unknown and should be figured out somehow */
|
||||
void term_resize(int width, int height);
|
||||
|
||||
/* Returns TRUE if terminal has colors */
|
||||
int term_has_colors(void);
|
||||
/* Force the colors on any way you can */
|
||||
void term_force_colors(int set);
|
||||
|
||||
/* Clear screen */
|
||||
void term_clear(void);
|
||||
/* Beep */
|
||||
void term_beep(void);
|
||||
|
||||
/* Create a new window in terminal */
|
||||
TERM_WINDOW *term_window_create(int x, int y, int width, int height);
|
||||
/* Destroy a terminal window */
|
||||
void term_window_destroy(TERM_WINDOW *window);
|
||||
|
||||
/* Move/resize window */
|
||||
void term_window_move(TERM_WINDOW *window, int x, int y,
|
||||
int width, int height);
|
||||
/* Clear window */
|
||||
void term_window_clear(TERM_WINDOW *window);
|
||||
/* Scroll window up/down */
|
||||
void term_window_scroll(TERM_WINDOW *window, int count);
|
||||
|
||||
void term_set_color(TERM_WINDOW *window, int col);
|
||||
|
||||
void term_move(TERM_WINDOW *window, int x, int y);
|
||||
void term_addch(TERM_WINDOW *window, int chr);
|
||||
void term_addstr(TERM_WINDOW *window, char *str);
|
||||
void term_clrtoeol(TERM_WINDOW *window);
|
||||
|
||||
void term_move_cursor(int x, int y);
|
||||
|
||||
void term_refresh_freeze(void);
|
||||
void term_refresh_thaw(void);
|
||||
void term_refresh(TERM_WINDOW *window);
|
||||
|
||||
void term_stop(void);
|
||||
int term_getch(void);
|
||||
|
||||
/* internal */
|
||||
void term_common_init(void);
|
||||
void term_common_deinit(void);
|
||||
|
||||
void term_force_resize(void);
|
||||
|
||||
#endif
|
584
src/fe-text/terminfo-core.c
Normal file
584
src/fe-text/terminfo-core.c
Normal file
@ -0,0 +1,584 @@
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "terminfo-core.h"
|
||||
|
||||
#ifndef _POSIX_VDISABLE
|
||||
# define _POSIX_VDISABLE 0
|
||||
#endif
|
||||
|
||||
#define tput(s) tputs(s, 0, term_putchar)
|
||||
inline static int term_putchar(int c)
|
||||
{
|
||||
return fputc(c, current_term->out);
|
||||
}
|
||||
|
||||
/* Don't bother including curses.h because of these -
|
||||
they might not even be defined there */
|
||||
char *tparm();
|
||||
int tputs();
|
||||
|
||||
#ifdef HAVE_TERMINFO
|
||||
int setupterm();
|
||||
char *tigetstr();
|
||||
int tigetnum();
|
||||
int tigetflag();
|
||||
#define term_getstr(x, buffer) tigetstr(x.ti_name)
|
||||
#define term_getnum(x) tigetnum(x.ti_name);
|
||||
#define term_getflag(x) tigetflag(x.ti_name);
|
||||
#else
|
||||
int tgetent();
|
||||
char *tgetstr();
|
||||
int tgetnum();
|
||||
int tgetflag();
|
||||
#define term_getstr(x, buffer) tgetstr(x.tc_name, &buffer)
|
||||
#define term_getnum(x) tgetnum(x.tc_name)
|
||||
#define term_getflag(x) tgetflag(x.tc_name)
|
||||
#endif
|
||||
|
||||
#define CAP_TYPE_FLAG 0
|
||||
#define CAP_TYPE_INT 1
|
||||
#define CAP_TYPE_STR 2
|
||||
|
||||
typedef struct {
|
||||
const char *ti_name; /* terminfo name */
|
||||
const char *tc_name; /* termcap name */
|
||||
int type;
|
||||
void *ptr;
|
||||
} TERMINFO_REC;
|
||||
|
||||
TERM_REC *current_term;
|
||||
static TERM_REC temp_term; /* not really used for anything */
|
||||
|
||||
/* Define only what we might need */
|
||||
static TERMINFO_REC tcaps[] = {
|
||||
/* Terminal size */
|
||||
{ "cols", "co", CAP_TYPE_INT, &temp_term.width },
|
||||
{ "lines", "li", CAP_TYPE_INT, &temp_term.height },
|
||||
|
||||
/* Cursor movement */
|
||||
{ "smcup", "ti", CAP_TYPE_STR, &temp_term.TI_smcup },
|
||||
{ "rmcup", "te", CAP_TYPE_STR, &temp_term.TI_rmcup },
|
||||
{ "cup", "cm", CAP_TYPE_STR, &temp_term.TI_cup },
|
||||
{ "hpa", "ch", CAP_TYPE_STR, &temp_term.TI_hpa },
|
||||
{ "vpa", "vh", CAP_TYPE_STR, &temp_term.TI_vpa },
|
||||
{ "xvpa", "YD", CAP_TYPE_FLAG, &temp_term.TI_xvpa },
|
||||
{ "hvpa", "YA", CAP_TYPE_FLAG, &temp_term.TI_xhpa },
|
||||
|
||||
/* Scrolling */
|
||||
{ "csr", "cs", CAP_TYPE_STR, &temp_term.TI_csr },
|
||||
{ "wind", "wi", CAP_TYPE_STR, &temp_term.TI_wind },
|
||||
{ "ri", "sr", CAP_TYPE_STR, &temp_term.TI_ri },
|
||||
{ "rin", "SR", CAP_TYPE_STR, &temp_term.TI_rin },
|
||||
{ "ind", "sf", CAP_TYPE_STR, &temp_term.TI_ind },
|
||||
{ "indn", "SF", CAP_TYPE_STR, &temp_term.TI_indn },
|
||||
{ "il", "AL", CAP_TYPE_STR, &temp_term.TI_il },
|
||||
{ "il1", "al", CAP_TYPE_STR, &temp_term.TI_il1 },
|
||||
{ "dl", "DL", CAP_TYPE_STR, &temp_term.TI_dl },
|
||||
{ "dl1", "dl", CAP_TYPE_STR, &temp_term.TI_dl1 },
|
||||
|
||||
/* Clearing screen */
|
||||
{ "clear", "cl", CAP_TYPE_STR, &temp_term.TI_clear },
|
||||
{ "ed", "cd", CAP_TYPE_STR, &temp_term.TI_ed },
|
||||
|
||||
/* Clearing to end of line */
|
||||
{ "el", "ce", CAP_TYPE_STR, &temp_term.TI_el },
|
||||
|
||||
/* Colors */
|
||||
{ "sgr0", "me", CAP_TYPE_STR, &temp_term.TI_sgr0 },
|
||||
{ "smul", "us", CAP_TYPE_STR, &temp_term.TI_smul },
|
||||
{ "rmul", "ue", CAP_TYPE_STR, &temp_term.TI_rmul },
|
||||
{ "smso", "so", CAP_TYPE_STR, &temp_term.TI_smso },
|
||||
{ "rmso", "se", CAP_TYPE_STR, &temp_term.TI_rmso },
|
||||
{ "bold", "md", CAP_TYPE_STR, &temp_term.TI_bold },
|
||||
{ "blink", "mb", CAP_TYPE_STR, &temp_term.TI_blink },
|
||||
{ "setaf", "AF", CAP_TYPE_STR, &temp_term.TI_setaf },
|
||||
{ "setab", "AB", CAP_TYPE_STR, &temp_term.TI_setab },
|
||||
{ "setf", "Sf", CAP_TYPE_STR, &temp_term.TI_setf },
|
||||
{ "setb", "Sb", CAP_TYPE_STR, &temp_term.TI_setb },
|
||||
|
||||
/* Beep */
|
||||
{ "bel", "bl", CAP_TYPE_STR, &temp_term.TI_bel },
|
||||
};
|
||||
|
||||
/* Move cursor (cursor_address / cup) */
|
||||
static void _move_cup(TERM_REC *term, int x, int y)
|
||||
{
|
||||
tput(tparm(term->TI_cup, y, x));
|
||||
}
|
||||
|
||||
/* Move cursor (column_address+row_address / hpa+vpa) */
|
||||
static void _move_pa(TERM_REC *term, int x, int y)
|
||||
{
|
||||
tput(tparm(term->TI_hpa, x));
|
||||
tput(tparm(term->TI_vpa, y));
|
||||
}
|
||||
|
||||
#define scroll_region_setup(term, y1, y2) \
|
||||
if ((term)->TI_csr != NULL) \
|
||||
tput(tparm((term)->TI_csr, y1, y2)); \
|
||||
else \
|
||||
tput(tparm((term)->TI_wind, y1, y2, 0, (term)->width-1));
|
||||
|
||||
/* Scroll (change_scroll_region+parm_rindex+parm_index / csr+rin+indn) */
|
||||
static void _scroll_region(TERM_REC *term, int y1, int y2, int count)
|
||||
{
|
||||
/* setup the scrolling region to wanted area */
|
||||
scroll_region_setup(term, y1, y2);
|
||||
|
||||
term->move(term, 0, y1);
|
||||
if (count > 0) {
|
||||
term->move(term, 0, y2);
|
||||
tput(tparm(term->TI_indn, count, count));
|
||||
} else if (count < 0) {
|
||||
term->move(term, 0, y1);
|
||||
tput(tparm(term->TI_rin, -count, -count));
|
||||
}
|
||||
|
||||
/* reset the scrolling region to full screen */
|
||||
scroll_region_setup(term, 0, term->height-1);
|
||||
}
|
||||
|
||||
/* Scroll (change_scroll_region+scroll_reverse+scroll_forward / csr+ri+ind) */
|
||||
static void _scroll_region_1(TERM_REC *term, int y1, int y2, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* setup the scrolling region to wanted area */
|
||||
scroll_region_setup(term, y1, y2);
|
||||
|
||||
if (count > 0) {
|
||||
term->move(term, 0, y2);
|
||||
for (i = 0; i < count; i++)
|
||||
tput(tparm(term->TI_ind));
|
||||
} else if (count < 0) {
|
||||
term->move(term, 0, y1);
|
||||
for (i = count; i < 0; i++)
|
||||
tput(tparm(term->TI_ri));
|
||||
tput(tparm(term->TI_rin, -count, -count));
|
||||
}
|
||||
|
||||
/* reset the scrolling region to full screen */
|
||||
scroll_region_setup(term, 0, term->height-1);
|
||||
}
|
||||
|
||||
/* Scroll (parm_insert_line+parm_delete_line / il+dl) */
|
||||
static void _scroll_line(TERM_REC *term, int y1, int y2, int count)
|
||||
{
|
||||
if (count > 0) {
|
||||
term->move(term, 0, y1);
|
||||
tput(tparm(term->TI_dl, count, count));
|
||||
term->move(term, 0, y2-count+1);
|
||||
tput(tparm(term->TI_il, count, count));
|
||||
} else if (count < 0) {
|
||||
term->move(term, 0, y2+count+1);
|
||||
tput(tparm(term->TI_dl, -count, -count));
|
||||
term->move(term, 0, y1);
|
||||
tput(tparm(term->TI_il, -count, -count));
|
||||
}
|
||||
}
|
||||
|
||||
/* Scroll (insert_line+delete_line / il1+dl1) */
|
||||
static void _scroll_line_1(TERM_REC *term, int y1, int y2, int count)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (count > 0) {
|
||||
term->move(term, 0, y1);
|
||||
for (i = 0; i < count; i++)
|
||||
tput(tparm(term->TI_dl1));
|
||||
term->move(term, 0, y2-count+1);
|
||||
for (i = 0; i < count; i++)
|
||||
tput(tparm(term->TI_il1));
|
||||
} else if (count < 0) {
|
||||
term->move(term, 0, y2+count+1);
|
||||
for (i = count; i < 0; i++)
|
||||
tput(tparm(term->TI_dl1));
|
||||
term->move(term, 0, y1);
|
||||
for (i = count; i < 0; i++)
|
||||
tput(tparm(term->TI_il1));
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear screen (clear_screen / clear) */
|
||||
static void _clear_screen(TERM_REC *term)
|
||||
{
|
||||
tput(tparm(term->TI_clear));
|
||||
}
|
||||
|
||||
/* Clear screen (clr_eos / ed) */
|
||||
static void _clear_eos(TERM_REC *term)
|
||||
{
|
||||
term->move(term, 0, 0);
|
||||
tput(tparm(term->TI_ed));
|
||||
}
|
||||
|
||||
/* Clear screen (parm_delete_line / dl) */
|
||||
static void _clear_del(TERM_REC *term)
|
||||
{
|
||||
term->move(term, 0, 0);
|
||||
tput(tparm(term->TI_dl, term->height, term->height));
|
||||
}
|
||||
|
||||
/* Clear screen (delete_line / dl1) */
|
||||
static void _clear_del_1(TERM_REC *term)
|
||||
{
|
||||
int i;
|
||||
|
||||
term->move(term, 0, 0);
|
||||
for (i = 0; i < term->height; i++)
|
||||
tput(tparm(term->TI_dl1));
|
||||
}
|
||||
|
||||
/* Clear to end of line (clr_eol / el) */
|
||||
static void _clrtoeol(TERM_REC *term)
|
||||
{
|
||||
tput(tparm(term->TI_el));
|
||||
}
|
||||
|
||||
/* Reset all terminal attributes */
|
||||
static void _set_normal(TERM_REC *term)
|
||||
{
|
||||
tput(tparm(term->TI_normal));
|
||||
}
|
||||
|
||||
/* Bold on */
|
||||
static void _set_bold(TERM_REC *term)
|
||||
{
|
||||
tput(tparm(term->TI_bold));
|
||||
}
|
||||
|
||||
/* Underline on/off */
|
||||
static void _set_uline(TERM_REC *term, int set)
|
||||
{
|
||||
tput(tparm(set ? term->TI_smul : term->TI_rmul));
|
||||
}
|
||||
|
||||
/* Standout on/off */
|
||||
static void _set_standout(TERM_REC *term, int set)
|
||||
{
|
||||
tput(tparm(set ? term->TI_smso : term->TI_rmso));
|
||||
}
|
||||
|
||||
/* Change foreground color */
|
||||
static void _set_fg(TERM_REC *term, int color)
|
||||
{
|
||||
tput(tparm(term->TI_fg[color & 0x0f]));
|
||||
}
|
||||
|
||||
/* Change background color */
|
||||
static void _set_bg(TERM_REC *term, int color)
|
||||
{
|
||||
tput(tparm(term->TI_bg[color & 0x0f]));
|
||||
}
|
||||
|
||||
/* Beep */
|
||||
static void _beep(TERM_REC *term)
|
||||
{
|
||||
tput(tparm(term->TI_bel));
|
||||
}
|
||||
|
||||
static void _ignore(TERM_REC *term)
|
||||
{
|
||||
}
|
||||
|
||||
static void _ignore_parm(TERM_REC *term, int param)
|
||||
{
|
||||
}
|
||||
|
||||
static void term_fill_capabilities(TERM_REC *term)
|
||||
{
|
||||
int i, ival;
|
||||
char *sval;
|
||||
void *ptr;
|
||||
|
||||
#ifndef HAVE_TERMINFO
|
||||
char *tptr = term->buffer2;
|
||||
#endif
|
||||
for (i = 0; i < sizeof(tcaps)/sizeof(tcaps[0]); i++) {
|
||||
ptr = (char *) term + (int) ((char *) tcaps[i].ptr - (char *) &temp_term);
|
||||
|
||||
switch (tcaps[i].type) {
|
||||
case CAP_TYPE_FLAG:
|
||||
ival = term_getflag(tcaps[i]);
|
||||
*(int *)ptr = ival;
|
||||
break;
|
||||
case CAP_TYPE_INT:
|
||||
ival = term_getnum(tcaps[i]);
|
||||
*(int *)ptr = ival;
|
||||
break;
|
||||
case CAP_TYPE_STR:
|
||||
sval = term_getstr(tcaps[i], tptr);
|
||||
if (sval == (char *) -1)
|
||||
*(char **)ptr = NULL;
|
||||
else
|
||||
*(char **)ptr = sval;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminal was resized - ask the width/height from terminfo again */
|
||||
void terminfo_resize(TERM_REC *term)
|
||||
{
|
||||
/* easiest way to do this is just to refill everything, and since
|
||||
termcap needs that buffer this is probably also the safest way */
|
||||
/* FIXME: leaks memory? does this even work? */
|
||||
term_fill_capabilities(term);
|
||||
}
|
||||
|
||||
static void terminfo_colors_deinit(TERM_REC *term)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (terminfo_has_colors(term)) {
|
||||
for (i = 0; i < 16; i++) {
|
||||
g_free(term->TI_fg[i]);
|
||||
g_free(term->TI_bg[i]);
|
||||
}
|
||||
|
||||
memset(term->TI_fg, 0, sizeof(term->TI_fg));
|
||||
memset(term->TI_bg, 0, sizeof(term->TI_fg));
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup colors - if force is set, use ANSI-style colors if
|
||||
terminal capabilities don't contain color codes */
|
||||
void terminfo_setup_colors(TERM_REC *term, int force)
|
||||
{
|
||||
static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
||||
const char *bold, *blink;
|
||||
int i;
|
||||
|
||||
terminfo_colors_deinit(term);
|
||||
|
||||
if (term->TI_setf) {
|
||||
for (i = 0; i < 8; i++)
|
||||
term->TI_fg[i] = g_strdup(tparm(term->TI_setf, i, 0));
|
||||
} else if (term->TI_setaf) {
|
||||
for (i = 0; i < 8; i++)
|
||||
term->TI_fg[i] = g_strdup(tparm(term->TI_setaf, ansitab[i], 0));
|
||||
} else if (force) {
|
||||
for (i = 0; i < 8; i++)
|
||||
term->TI_fg[i] = g_strdup_printf("\033[%dm", 30+ansitab[i]);
|
||||
}
|
||||
|
||||
if (term->TI_setb) {
|
||||
for (i = 0; i < 8; i++)
|
||||
term->TI_bg[i] = g_strdup(tparm(term->TI_setb, i, 0));
|
||||
} else if (term->TI_setab) {
|
||||
for (i = 0; i < 8; i++)
|
||||
term->TI_bg[i] = g_strdup(tparm(term->TI_setab, ansitab[i], 0));
|
||||
} else if (force) {
|
||||
for (i = 0; i < 8; i++)
|
||||
term->TI_bg[i] = g_strdup_printf("\033[%dm", 40+ansitab[i]);
|
||||
}
|
||||
|
||||
if (term->TI_setf || term->TI_setaf || force) {
|
||||
term->set_fg = _set_fg;
|
||||
term->set_bg = _set_bg;
|
||||
|
||||
/* bold fg, blink bg */
|
||||
bold = term->TI_bold ? term->TI_bold : "";
|
||||
for (i = 0; i < 8; i++)
|
||||
term->TI_fg[i+8] = g_strconcat(bold, term->TI_fg[i], NULL);
|
||||
|
||||
blink = term->TI_blink ? term->TI_blink : "";
|
||||
for (i = 0; i < 8; i++)
|
||||
term->TI_bg[i+8] = g_strconcat(blink, term->TI_bg[i], NULL);
|
||||
} else {
|
||||
/* no colors */
|
||||
term->set_fg = term->set_bg = _ignore_parm;
|
||||
}
|
||||
}
|
||||
|
||||
static void terminfo_input_init(TERM_REC *term)
|
||||
{
|
||||
tcgetattr(fileno(term->in), &term->old_tio);
|
||||
memcpy(&term->tio, &term->old_tio, sizeof(term->tio));
|
||||
|
||||
term->tio.c_lflag &= ~(ICANON | ECHO); /* CBREAK, no ECHO */
|
||||
term->tio.c_cc[VMIN] = 0; /* non-blocking read */
|
||||
term->tio.c_cc[VTIME] = 0; /* No timer */
|
||||
|
||||
/* Disable INTR, QUIT, VDSUSP and SUSP keys */
|
||||
term->tio.c_cc[VINTR] = _POSIX_VDISABLE;
|
||||
term->tio.c_cc[VQUIT] = _POSIX_VDISABLE;
|
||||
#ifdef VDSUSP
|
||||
term->tio.c_cc[VDSUSP] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
#ifdef VSUSP
|
||||
term->tio.c_cc[VSUSP] = _POSIX_VDISABLE;
|
||||
#endif
|
||||
|
||||
tcsetattr(fileno(term->in), 0, &term->tio);
|
||||
|
||||
}
|
||||
|
||||
static void terminfo_input_deinit(TERM_REC *term)
|
||||
{
|
||||
tcsetattr(fileno(term->in), 0, &term->old_tio);
|
||||
}
|
||||
|
||||
void terminfo_cont(TERM_REC *term)
|
||||
{
|
||||
if (term->TI_smcup)
|
||||
tput(tparm(term->TI_smcup));
|
||||
terminfo_input_init(term);
|
||||
}
|
||||
|
||||
void terminfo_stop(TERM_REC *term)
|
||||
{
|
||||
/* reset colors */
|
||||
terminfo_set_normal();
|
||||
/* move cursor to bottom of the screen */
|
||||
terminfo_move(0, term->height-1);
|
||||
|
||||
/* stop cup-mode */
|
||||
if (term->TI_rmcup)
|
||||
tput(tparm(term->TI_rmcup));
|
||||
|
||||
/* reset input settings */
|
||||
terminfo_input_deinit(term);
|
||||
fflush(term->out);
|
||||
}
|
||||
|
||||
static int term_setup(TERM_REC *term)
|
||||
{
|
||||
GString *str;
|
||||
#ifdef HAVE_TERMINFO
|
||||
int err;
|
||||
#endif
|
||||
char *term_env;
|
||||
|
||||
term_env = getenv("TERM");
|
||||
if (term_env == NULL) {
|
||||
fprintf(term->out, "TERM environment not set\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TERMINFO
|
||||
if (setupterm(term_env, 1, &err) != 0) {
|
||||
fprintf(term->out, "setupterm() failed for TERM=%s: %d\n", term_env, err);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
if (tgetent(term->buffer1, term_env) < 1)
|
||||
{
|
||||
fprintf(term->out, "Termcap not found for TERM=%s\n", term_env);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
term_fill_capabilities(term);
|
||||
|
||||
/* Cursor movement */
|
||||
if (term->TI_cup)
|
||||
term->move = _move_cup;
|
||||
else if (term->TI_hpa && term->TI_vpa &&
|
||||
!term->TI_xhpa && !term->TI_xvpa)
|
||||
term->move = _move_pa;
|
||||
else {
|
||||
fprintf(term->out, "Terminal doesn't support cursor movement\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Scrolling */
|
||||
if ((term->TI_csr || term->TI_wind) && term->TI_rin && term->TI_indn)
|
||||
term->scroll = _scroll_region;
|
||||
else if ((term->TI_csr || term->TI_wind) && term->TI_ri && term->TI_ind)
|
||||
term->scroll = _scroll_region_1;
|
||||
else if (term->TI_il && term->TI_dl)
|
||||
term->scroll = _scroll_line;
|
||||
else if (term->TI_il1 && term->TI_dl1)
|
||||
term->scroll = _scroll_line_1;
|
||||
else {
|
||||
fprintf(term->out, "Terminal doesn't support scrolling\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clearing screen */
|
||||
if (term->TI_clear)
|
||||
term->clear = _clear_screen;
|
||||
else if (term->TI_ed)
|
||||
term->clear = _clear_eos;
|
||||
else if (term->TI_dl)
|
||||
term->clear = _clear_del;
|
||||
else if (term->TI_dl1)
|
||||
term->clear = _clear_del_1;
|
||||
else {
|
||||
/* we could do this by line inserts as well, but don't
|
||||
bother - if some terminal has insert line it most probably
|
||||
has delete line as well, if not a regular clear screen */
|
||||
fprintf(term->out, "Terminal doesn't support clearing screen\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Clearing to end of line */
|
||||
if (term->TI_el)
|
||||
term->clrtoeol = _clrtoeol;
|
||||
else {
|
||||
fprintf(term->out, "Terminal doesn't support clearing to end of line\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Bold, underline, standout */
|
||||
term->set_bold = term->TI_bold ? _set_bold : _ignore;
|
||||
term->set_uline = term->TI_smul && term->TI_rmul ?
|
||||
_set_uline : _ignore_parm;
|
||||
term->set_standout = term->TI_smso && term->TI_rmso ?
|
||||
_set_standout : _ignore_parm;
|
||||
|
||||
/* Create a string to set all attributes off */
|
||||
str = g_string_new(NULL);
|
||||
if (term->TI_sgr0)
|
||||
g_string_append(str, term->TI_sgr0);
|
||||
if (term->TI_rmul && (term->TI_sgr0 == NULL || strcmp(term->TI_rmul, term->TI_sgr0) != 0))
|
||||
g_string_append(str, term->TI_rmul);
|
||||
if (term->TI_rmso && (term->TI_sgr0 == NULL || strcmp(term->TI_rmso, term->TI_sgr0) != 0))
|
||||
g_string_append(str, term->TI_rmso);
|
||||
term->TI_normal = str->str;
|
||||
g_string_free(str, FALSE);
|
||||
term->set_normal = _set_normal;
|
||||
|
||||
term->beep = term->TI_bel ? _beep : _ignore;
|
||||
|
||||
terminfo_setup_colors(term, FALSE);
|
||||
terminfo_cont(term);
|
||||
return 1;
|
||||
}
|
||||
|
||||
TERM_REC *terminfo_core_init(FILE *in, FILE *out)
|
||||
{
|
||||
TERM_REC *old_term, *term;
|
||||
|
||||
old_term = current_term;
|
||||
current_term = term = g_new0(TERM_REC, 1);
|
||||
|
||||
term->in = in;
|
||||
term->out = out;
|
||||
|
||||
if (!term_setup(term)) {
|
||||
g_free(term);
|
||||
term = NULL;
|
||||
}
|
||||
|
||||
current_term = old_term;
|
||||
return term;
|
||||
}
|
||||
|
||||
void terminfo_core_deinit(TERM_REC *term)
|
||||
{
|
||||
TERM_REC *old_term;
|
||||
|
||||
old_term = current_term;
|
||||
current_term = term;
|
||||
term->set_normal(term);
|
||||
current_term = old_term;
|
||||
|
||||
terminfo_stop(term);
|
||||
|
||||
g_free(term->TI_normal);
|
||||
terminfo_colors_deinit(term);
|
||||
|
||||
g_free(term);
|
||||
}
|
91
src/fe-text/terminfo-core.h
Normal file
91
src/fe-text/terminfo-core.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef __TERMINFO_CORE_H
|
||||
#define __TERMINFO_CORE_H
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#define terminfo_move(x, y) current_term->move(current_term, x, y)
|
||||
#define terminfo_scroll(y1, y2, count) current_term->scroll(current_term, y1, y2, count)
|
||||
#define terminfo_clear() current_term->clear(current_term)
|
||||
#define terminfo_clrtoeol() current_term->clrtoeol(current_term)
|
||||
#define terminfo_set_fg(color) current_term->set_fg(current_term, color)
|
||||
#define terminfo_set_bg(color) current_term->set_bg(current_term, color)
|
||||
#define terminfo_set_normal() current_term->set_normal(current_term)
|
||||
#define terminfo_set_bold() current_term->set_bold(current_term)
|
||||
#define terminfo_set_uline(set) current_term->set_uline(current_term, set)
|
||||
#define terminfo_set_standout(set) current_term->set_standout(current_term, set)
|
||||
#define terminfo_has_colors(term) (term->TI_fg[0] != NULL)
|
||||
|
||||
typedef struct _TERM_REC TERM_REC;
|
||||
|
||||
struct _TERM_REC {
|
||||
/* Functions */
|
||||
void (*move)(TERM_REC *term, int x, int y);
|
||||
void (*scroll)(TERM_REC *term, int y1, int y2, int count);
|
||||
|
||||
void (*clear)(TERM_REC *term);
|
||||
void (*clrtoeol)(TERM_REC *term);
|
||||
|
||||
void (*set_fg)(TERM_REC *term, int color);
|
||||
void (*set_bg)(TERM_REC *term, int color);
|
||||
void (*set_normal)(TERM_REC *term);
|
||||
void (*set_bold)(TERM_REC *term);
|
||||
void (*set_uline)(TERM_REC *term, int set);
|
||||
void (*set_standout)(TERM_REC *term, int set);
|
||||
|
||||
void (*beep)(TERM_REC *term);
|
||||
|
||||
#ifndef HAVE_TERMINFO
|
||||
char buffer1[1024], buffer2[1024];
|
||||
#endif
|
||||
FILE *in, *out;
|
||||
struct termios tio, old_tio;
|
||||
|
||||
/* Terminal size */
|
||||
int width, height;
|
||||
|
||||
/* Cursor movement */
|
||||
const char *TI_smcup, *TI_rmcup, *TI_cup;
|
||||
const char *TI_hpa, *TI_vpa;
|
||||
int TI_xhpa, TI_xvpa;
|
||||
|
||||
/* Scrolling */
|
||||
const char *TI_csr, *TI_wind;
|
||||
const char *TI_ri, *TI_rin, *TI_ind, *TI_indn;
|
||||
const char *TI_il, *TI_il1, *TI_dl, *TI_dl1;
|
||||
|
||||
/* Clearing screen */
|
||||
const char *TI_clear, *TI_ed; /* + *TI_dl, *TI_dl1; */
|
||||
|
||||
/* Clearing to end of line */
|
||||
const char *TI_el;
|
||||
|
||||
/* Colors */
|
||||
const char *TI_sgr0; /* turn off all attributes */
|
||||
const char *TI_smul, *TI_rmul; /* underline on/off */
|
||||
const char *TI_smso, *TI_rmso; /* standout on/off */
|
||||
const char *TI_bold, *TI_blink;
|
||||
const char *TI_setaf, *TI_setab, *TI_setf, *TI_setb;
|
||||
|
||||
/* Colors - generated and dynamically allocated */
|
||||
char *TI_fg[16], *TI_bg[16], *TI_normal;
|
||||
|
||||
/* Beep */
|
||||
char *TI_bel;
|
||||
};
|
||||
|
||||
extern TERM_REC *current_term;
|
||||
|
||||
TERM_REC *terminfo_core_init(FILE *in, FILE *out);
|
||||
void terminfo_core_deinit(TERM_REC *term);
|
||||
|
||||
/* Setup colors - if force is set, use ANSI-style colors if
|
||||
terminal capabilities don't contain color codes */
|
||||
void terminfo_setup_colors(TERM_REC *term, int force);
|
||||
|
||||
/* Terminal was resized - ask the width/height from terminfo again */
|
||||
void terminfo_resize(TERM_REC *term);
|
||||
|
||||
void terminfo_cont(TERM_REC *term);
|
||||
void terminfo_stop(TERM_REC *term);
|
||||
|
||||
#endif
|
@ -239,7 +239,7 @@ static void cmd_scrollback_redraw(void)
|
||||
|
||||
gui = WINDOW_GUI(active_win);
|
||||
|
||||
screen_refresh_freeze();
|
||||
term_refresh_freeze();
|
||||
line = textbuffer_view_get_lines(gui->view);
|
||||
while (line != NULL) {
|
||||
next = line->next;
|
||||
@ -248,7 +248,7 @@ static void cmd_scrollback_redraw(void)
|
||||
}
|
||||
|
||||
gui_window_redraw(active_win);
|
||||
screen_refresh_thaw();
|
||||
term_refresh_thaw();
|
||||
}
|
||||
|
||||
static void cmd_scrollback_status(void)
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
#include "module.h"
|
||||
#include "textbuffer-view.h"
|
||||
#include "screen.h"
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
@ -102,6 +101,46 @@ static void textbuffer_cache_unref(TEXT_BUFFER_CACHE_REC *cache)
|
||||
textbuffer_cache_destroy(cache);
|
||||
}
|
||||
|
||||
#define FGATTR (ATTR_NOCOLORS | ATTR_RESETBG | ATTR_BLINK | 0xf0)
|
||||
#define BGATTR (ATTR_NOCOLORS | ATTR_RESETFG | ATTR_BOLD | 0x0f)
|
||||
|
||||
static void update_cmd_color(unsigned char cmd, int *color)
|
||||
{
|
||||
if ((cmd & 0x80) == 0) {
|
||||
if (cmd & LINE_COLOR_BG) {
|
||||
/* set background color */
|
||||
*color &= BGATTR;
|
||||
if ((cmd & LINE_COLOR_DEFAULT) == 0)
|
||||
*color |= (cmd & 0x0f) << 4;
|
||||
else {
|
||||
*color |= ATTR_RESETBG;
|
||||
if (cmd & LINE_COLOR_BLINK)
|
||||
*color |= ATTR_BLINK;
|
||||
}
|
||||
} else {
|
||||
/* set foreground color */
|
||||
*color &= FGATTR;
|
||||
if ((cmd & LINE_COLOR_DEFAULT) == 0)
|
||||
*color |= cmd & 0x0f;
|
||||
else {
|
||||
*color |= ATTR_RESETFG;
|
||||
if (cmd & LINE_COLOR_BOLD)
|
||||
*color |= ATTR_BOLD;
|
||||
}
|
||||
}
|
||||
} else switch (cmd) {
|
||||
case LINE_CMD_UNDERLINE:
|
||||
*color ^= ATTR_UNDERLINE;
|
||||
break;
|
||||
case LINE_CMD_REVERSE:
|
||||
*color ^= ATTR_REVERSE;
|
||||
break;
|
||||
case LINE_CMD_COLOR0:
|
||||
*color &= BGATTR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static LINE_CACHE_REC *
|
||||
view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
|
||||
{
|
||||
@ -115,7 +154,8 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
|
||||
|
||||
g_return_val_if_fail(line->text != NULL, NULL);
|
||||
|
||||
xpos = 0; color = 0; indent_pos = view->default_indent;
|
||||
color = ATTR_RESETFG | ATTR_RESETBG;
|
||||
xpos = 0; indent_pos = view->default_indent;
|
||||
last_space = last_color = 0; last_space_ptr = NULL; sub = NULL;
|
||||
|
||||
indent_func = view->default_indent_func;
|
||||
@ -139,38 +179,17 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((cmd & 0x80) == 0) {
|
||||
/* set color */
|
||||
color = (color & ATTR_NOCOLORS) | cmd;
|
||||
} else switch (cmd) {
|
||||
case LINE_CMD_UNDERLINE:
|
||||
color ^= ATTR_UNDERLINE;
|
||||
break;
|
||||
case LINE_CMD_REVERSE:
|
||||
color ^= ATTR_REVERSE;
|
||||
break;
|
||||
case LINE_CMD_COLOR0:
|
||||
color = color & ATTR_NOCOLORS;
|
||||
break;
|
||||
case LINE_CMD_COLOR8:
|
||||
color &= 0xfff0;
|
||||
color |= 8|ATTR_COLOR8;
|
||||
break;
|
||||
case LINE_CMD_BLINK:
|
||||
color |= 0x80;
|
||||
break;
|
||||
case LINE_CMD_INDENT:
|
||||
if (cmd == LINE_CMD_INDENT) {
|
||||
/* set indentation position here - don't do
|
||||
it if we're too close to right border */
|
||||
if (xpos < view->width-5) indent_pos = xpos;
|
||||
break;
|
||||
case LINE_CMD_INDENT_FUNC:
|
||||
} else if (cmd == LINE_CMD_INDENT_FUNC) {
|
||||
memcpy(&indent_func, ptr, sizeof(INDENT_FUNC));
|
||||
ptr += sizeof(INDENT_FUNC);
|
||||
if (indent_func == NULL)
|
||||
indent_func = view->default_indent_func;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
update_cmd_color(cmd, &color);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -306,9 +325,9 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
}
|
||||
|
||||
/* first clear the line */
|
||||
screen_set_color(view->window, 0);
|
||||
screen_move(view->window, 0, ypos);
|
||||
screen_clrtoeol(view->window);
|
||||
term_set_color(view->window, ATTR_RESET);
|
||||
term_move(view->window, 0, ypos);
|
||||
term_clrtoeol(view->window);
|
||||
|
||||
if (subline > 0) {
|
||||
indent_func = cache->lines[subline-1].indent_func;
|
||||
@ -318,8 +337,8 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
color = cache->lines[subline-1].color;
|
||||
}
|
||||
|
||||
screen_move(view->window, xpos, ypos);
|
||||
screen_set_color(view->window, color);
|
||||
term_move(view->window, xpos, ypos);
|
||||
term_set_color(view->window, color);
|
||||
|
||||
/* get the beginning of the next subline */
|
||||
text_newline = subline == cache->count-1 ? NULL :
|
||||
@ -335,47 +354,28 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
if (*text == LINE_CMD_EOL || *text == LINE_CMD_FORMAT)
|
||||
break;
|
||||
|
||||
if ((*text & 0x80) == 0) {
|
||||
/* set color */
|
||||
color = (color & ATTR_NOCOLORS) | *text;
|
||||
} else if (*text == LINE_CMD_CONTINUE) {
|
||||
if (*text == LINE_CMD_CONTINUE) {
|
||||
/* jump to next block */
|
||||
memcpy(&tmp, text+1, sizeof(unsigned char *));
|
||||
text = tmp;
|
||||
continue;
|
||||
} else switch (*text) {
|
||||
case LINE_CMD_UNDERLINE:
|
||||
color ^= ATTR_UNDERLINE;
|
||||
break;
|
||||
case LINE_CMD_REVERSE:
|
||||
color ^= ATTR_REVERSE;
|
||||
break;
|
||||
case LINE_CMD_COLOR0:
|
||||
color = color & ATTR_NOCOLORS;
|
||||
break;
|
||||
case LINE_CMD_COLOR8:
|
||||
color &= 0xfff0;
|
||||
color |= 8|ATTR_COLOR8;
|
||||
break;
|
||||
case LINE_CMD_BLINK:
|
||||
color |= 0x80;
|
||||
break;
|
||||
case LINE_CMD_INDENT_FUNC:
|
||||
text += sizeof(INDENT_FUNC);
|
||||
break;
|
||||
} else if (*text == LINE_CMD_INDENT_FUNC) {
|
||||
text += sizeof(INDENT_FUNC);
|
||||
} else {
|
||||
update_cmd_color(*text, &color);
|
||||
term_set_color(view->window, color);
|
||||
}
|
||||
screen_set_color(view->window, color);
|
||||
text++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((*text & 127) >= 32)
|
||||
screen_addch(view->window, *text);
|
||||
term_addch(view->window, *text);
|
||||
else {
|
||||
/* low-ascii */
|
||||
screen_set_color(view->window, ATTR_REVERSE);
|
||||
screen_addch(view->window, (*text & 127)+'A'-1);
|
||||
screen_set_color(view->window, color);
|
||||
term_set_color(view->window, ATTR_RESET|ATTR_REVERSE);
|
||||
term_addch(view->window, (*text & 127)+'A'-1);
|
||||
term_set_color(view->window, color);
|
||||
}
|
||||
text++;
|
||||
}
|
||||
@ -594,9 +594,10 @@ static void view_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
}
|
||||
|
||||
/* clear the rest of the view */
|
||||
term_set_color(view->window, ATTR_RESET);
|
||||
while (lines > 0) {
|
||||
screen_move(view->window, 0, ypos);
|
||||
screen_clrtoeol(view->window);
|
||||
term_move(view->window, 0, ypos);
|
||||
term_clrtoeol(view->window);
|
||||
ypos++; lines--;
|
||||
}
|
||||
}
|
||||
@ -682,7 +683,7 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
|
||||
whole view */
|
||||
textbuffer_view_redraw(view);
|
||||
} else {
|
||||
screen_window_scroll(view->window, realcount);
|
||||
term_window_scroll(view->window, realcount);
|
||||
|
||||
if (draw_nonclean) {
|
||||
if (realcount < 0)
|
||||
@ -691,7 +692,7 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
|
||||
view_draw_bottom(view, realcount);
|
||||
}
|
||||
|
||||
screen_refresh(view->window);
|
||||
term_refresh(view->window);
|
||||
}
|
||||
}
|
||||
|
||||
@ -792,7 +793,7 @@ void textbuffer_view_scroll(TEXT_BUFFER_VIEW_REC *view, int lines)
|
||||
view->bottom = view_is_bottom(view);
|
||||
|
||||
if (view->window != NULL)
|
||||
screen_refresh(view->window);
|
||||
term_refresh(view->window);
|
||||
}
|
||||
|
||||
/* Scroll to specified line */
|
||||
@ -888,7 +889,7 @@ static void view_insert_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
|
||||
}
|
||||
|
||||
if (view->window != NULL)
|
||||
screen_refresh(view->window);
|
||||
term_refresh(view->window);
|
||||
}
|
||||
|
||||
/* Update some line in the buffer which has been modified using
|
||||
@ -1051,7 +1052,7 @@ static void view_remove_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
|
||||
|
||||
view->bottom = view_is_bottom(view);
|
||||
if (view->window != NULL)
|
||||
screen_refresh(view->window);
|
||||
term_refresh(view->window);
|
||||
}
|
||||
|
||||
/* Remove one line from buffer. */
|
||||
@ -1147,7 +1148,7 @@ LINE_REC *textbuffer_view_get_bookmark(TEXT_BUFFER_VIEW_REC *view,
|
||||
/* Specify window where the changes in view should be drawn,
|
||||
NULL disables it. */
|
||||
void textbuffer_view_set_window(TEXT_BUFFER_VIEW_REC *view,
|
||||
SCREEN_WINDOW *window)
|
||||
TERM_WINDOW *window)
|
||||
{
|
||||
g_return_if_fail(view != NULL);
|
||||
|
||||
@ -1164,9 +1165,9 @@ void textbuffer_view_redraw(TEXT_BUFFER_VIEW_REC *view)
|
||||
g_return_if_fail(view != NULL);
|
||||
|
||||
if (view->window != NULL) {
|
||||
screen_window_clear(view->window);
|
||||
term_window_clear(view->window);
|
||||
view_draw_top(view, view->height);
|
||||
screen_refresh(view->window);
|
||||
term_refresh(view->window);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define __TEXTBUFFER_VIEW_H
|
||||
|
||||
#include "textbuffer.h"
|
||||
#include "screen.h"
|
||||
#include "term.h"
|
||||
|
||||
typedef struct _TEXT_BUFFER_VIEW_REC TEXT_BUFFER_VIEW_REC;
|
||||
|
||||
@ -48,7 +48,7 @@ struct _TEXT_BUFFER_VIEW_REC {
|
||||
TEXT_BUFFER_REC *buffer;
|
||||
GSList *siblings; /* other views that use the same buffer */
|
||||
|
||||
SCREEN_WINDOW *window;
|
||||
TERM_WINDOW *window;
|
||||
int width, height;
|
||||
|
||||
int default_indent;
|
||||
@ -134,7 +134,7 @@ LINE_REC *textbuffer_view_get_bookmark(TEXT_BUFFER_VIEW_REC *view,
|
||||
/* Specify window where the changes in view should be drawn,
|
||||
NULL disables it. */
|
||||
void textbuffer_view_set_window(TEXT_BUFFER_VIEW_REC *view,
|
||||
SCREEN_WINDOW *window);
|
||||
TERM_WINDOW *window);
|
||||
/* Redraw the view */
|
||||
void textbuffer_view_redraw(TEXT_BUFFER_VIEW_REC *view);
|
||||
|
||||
|
@ -340,16 +340,55 @@ void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer)
|
||||
buffer->last_eol = TRUE;
|
||||
}
|
||||
|
||||
static void set_color(GString *str, int cmd, int *last_fg, int *last_bg)
|
||||
{
|
||||
if (cmd & LINE_COLOR_DEFAULT) {
|
||||
g_string_sprintfa(str, "\004%c", FORMAT_STYLE_DEFAULTS);
|
||||
|
||||
/* need to reset the fg/bg color */
|
||||
if (cmd & LINE_COLOR_BG) {
|
||||
*last_bg = -1;
|
||||
if (*last_fg != -1) {
|
||||
g_string_sprintfa(str, "\004%c%c",
|
||||
*last_fg,
|
||||
FORMAT_COLOR_NOCHANGE);
|
||||
}
|
||||
} else {
|
||||
*last_fg = -1;
|
||||
if (*last_bg != -1) {
|
||||
g_string_sprintfa(str, "\004%c%c",
|
||||
FORMAT_COLOR_NOCHANGE,
|
||||
*last_bg);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((cmd & LINE_COLOR_BG) == 0) {
|
||||
/* change foreground color */
|
||||
*last_fg = (cmd & 0x0f)+'0';
|
||||
g_string_sprintfa(str, "\004%c%c", *last_fg,
|
||||
FORMAT_COLOR_NOCHANGE);
|
||||
} else {
|
||||
/* change background color */
|
||||
*last_bg = (cmd & 0x0f)+'0';
|
||||
g_string_sprintfa(str, "\004%c%c",
|
||||
FORMAT_COLOR_NOCHANGE, *last_bg);
|
||||
}
|
||||
}
|
||||
|
||||
void textbuffer_line2text(LINE_REC *line, int coloring, GString *str)
|
||||
{
|
||||
unsigned char cmd;
|
||||
char *ptr, *tmp;
|
||||
int last_fg, last_bg;
|
||||
|
||||
g_return_if_fail(line != NULL);
|
||||
g_return_if_fail(str != NULL);
|
||||
|
||||
g_string_truncate(str, 0);
|
||||
|
||||
last_fg = last_bg = -1;
|
||||
for (ptr = line->text;;) {
|
||||
if (*ptr != 0) {
|
||||
g_string_append_c(str, *ptr);
|
||||
@ -380,9 +419,7 @@ void textbuffer_line2text(LINE_REC *line, int coloring, GString *str)
|
||||
|
||||
if ((cmd & 0x80) == 0) {
|
||||
/* set color */
|
||||
g_string_sprintfa(str, "\004%c%c",
|
||||
(cmd & 0x0f)+'0',
|
||||
((cmd & 0xf0) >> 4)+'0');
|
||||
set_color(str, cmd, &last_fg, &last_bg);
|
||||
} else switch (cmd) {
|
||||
case LINE_CMD_UNDERLINE:
|
||||
g_string_append_c(str, 31);
|
||||
@ -394,13 +431,6 @@ void textbuffer_line2text(LINE_REC *line, int coloring, GString *str)
|
||||
g_string_sprintfa(str, "\004%c%c",
|
||||
'0', FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
case LINE_CMD_COLOR8:
|
||||
g_string_sprintfa(str, "\004%c%c",
|
||||
'8', FORMAT_COLOR_NOCHANGE);
|
||||
break;
|
||||
case LINE_CMD_BLINK:
|
||||
g_string_sprintfa(str, "\004%c", FORMAT_STYLE_BLINK);
|
||||
break;
|
||||
case LINE_CMD_INDENT:
|
||||
break;
|
||||
case LINE_CMD_INDENT_FUNC:
|
||||
|
@ -3,16 +3,19 @@
|
||||
|
||||
#define LINE_TEXT_CHUNK_SIZE 16384
|
||||
|
||||
#define LINE_COLOR_BG 0x20
|
||||
#define LINE_COLOR_DEFAULT 0x10
|
||||
#define LINE_COLOR_BOLD 0x08
|
||||
#define LINE_COLOR_BLINK 0x08
|
||||
|
||||
enum {
|
||||
LINE_CMD_EOL=0x80, /* line ends here */
|
||||
LINE_CMD_CONTINUE, /* line continues in next block */
|
||||
LINE_CMD_COLOR0, /* change to black, would be same as \0\0 but it breaks things.. */
|
||||
LINE_CMD_COLOR8, /* change to dark grey, normally 8 = bold black */
|
||||
LINE_CMD_UNDERLINE, /* enable/disable underlining */
|
||||
LINE_CMD_REVERSE, /* enable/disable reversed text */
|
||||
LINE_CMD_INDENT, /* if line is split, indent it at this position */
|
||||
LINE_CMD_INDENT_FUNC, /* if line is split, use the specified indentation function */
|
||||
LINE_CMD_BLINK, /* blinking background */
|
||||
LINE_CMD_FORMAT, /* end of line, but next will come the format that was used to create the
|
||||
text in format <module><format_name><arg><arg2...> - fields are separated
|
||||
with \0<format> and last argument ends with \0<eol>. \0<continue> is allowed
|
||||
@ -26,9 +29,17 @@ typedef struct {
|
||||
} LINE_INFO_REC;
|
||||
|
||||
typedef struct _LINE_REC {
|
||||
/* text in the line. \0 means that the next char will be a
|
||||
color or command. <= 127 = color or if 8. bit is set, the
|
||||
first 7 bits are the command. See LINE_CMD_xxxx.
|
||||
/* Text in the line. \0 means that the next char will be a
|
||||
color or command.
|
||||
|
||||
If the 8th bit is set, the first 7 bits are the command
|
||||
(see LINE_CMD_xxxx). Otherwise they specify a color change:
|
||||
|
||||
Bit:
|
||||
5 - Setting a background color
|
||||
4 - Use "default terminal color"
|
||||
3 - Bold (fg) / blink (bg) - can be used with 4th bit
|
||||
0-2 - Color
|
||||
|
||||
DO NOT ADD BLACK WITH \0\0 - this will break things. Use
|
||||
LINE_CMD_COLOR0 instead. */
|
||||
|
740
src/fe-text/tparm.c
Normal file
740
src/fe-text/tparm.c
Normal file
@ -0,0 +1,740 @@
|
||||
/*
|
||||
* tparm.c
|
||||
*
|
||||
* By Ross Ridge
|
||||
* Public Domain
|
||||
* 92/02/01 07:30:36
|
||||
*
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef MAX_PUSHED
|
||||
#define MAX_PUSHED 32
|
||||
#endif
|
||||
|
||||
#define ARG 1
|
||||
#define NUM 2
|
||||
|
||||
#define INTEGER 1
|
||||
#define STRING 2
|
||||
|
||||
#define MAX_LINE 640
|
||||
|
||||
typedef void* anyptr;
|
||||
|
||||
typedef struct stack_str {
|
||||
int type;
|
||||
int argnum;
|
||||
int value;
|
||||
} stack;
|
||||
|
||||
static stack S[MAX_PUSHED];
|
||||
static stack vars['z'-'a'+1];
|
||||
static int pos = 0;
|
||||
|
||||
static struct arg_str {
|
||||
int type;
|
||||
int integer;
|
||||
char *string;
|
||||
} arg_list[10];
|
||||
|
||||
static int argcnt;
|
||||
|
||||
static va_list tparm_args;
|
||||
|
||||
static int pusharg(int arg)
|
||||
{
|
||||
if (pos == MAX_PUSHED)
|
||||
return 1;
|
||||
S[pos].type = ARG;
|
||||
S[pos++].argnum = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pushnum(int num)
|
||||
{
|
||||
if (pos == MAX_PUSHED)
|
||||
return 1;
|
||||
S[pos].type = NUM;
|
||||
S[pos++].value = num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* VARARGS2 */
|
||||
static int getarg(int argnum, int type, anyptr p)
|
||||
{
|
||||
while (argcnt < argnum) {
|
||||
arg_list[argcnt].type = INTEGER;
|
||||
arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
|
||||
}
|
||||
if (argcnt > argnum) {
|
||||
if (arg_list[argnum].type != type)
|
||||
return 1;
|
||||
else if (type == STRING)
|
||||
*(char **)p = arg_list[argnum].string;
|
||||
else
|
||||
*(int *)p = arg_list[argnum].integer;
|
||||
} else {
|
||||
arg_list[argcnt].type = type;
|
||||
if (type == STRING)
|
||||
*(char **)p = arg_list[argcnt++].string
|
||||
= (char *) va_arg(tparm_args, char *);
|
||||
else
|
||||
*(int *)p = arg_list[argcnt++].integer = (int) va_arg(tparm_args, int);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int popstring(char **str)
|
||||
{
|
||||
if (pos-- == 0)
|
||||
return 1;
|
||||
if (S[pos].type != ARG)
|
||||
return 1;
|
||||
return(getarg(S[pos].argnum, STRING, (anyptr) str));
|
||||
}
|
||||
|
||||
static int popnum(int *num)
|
||||
{
|
||||
if (pos-- == 0)
|
||||
return 1;
|
||||
switch (S[pos].type) {
|
||||
case ARG:
|
||||
return (getarg(S[pos].argnum, INTEGER, (anyptr) num));
|
||||
case NUM:
|
||||
*num = S[pos].value;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cvtchar(char *sp, char *c)
|
||||
{
|
||||
switch(*sp) {
|
||||
case '\\':
|
||||
switch(*++sp) {
|
||||
case '\'':
|
||||
case '$':
|
||||
case '\\':
|
||||
case '%':
|
||||
*c = *sp;
|
||||
return 2;
|
||||
case '\0':
|
||||
*c = '\\';
|
||||
return 1;
|
||||
case '0':
|
||||
if (sp[1] == '0' && sp[2] == '0') {
|
||||
*c = '\0';
|
||||
return 4;
|
||||
}
|
||||
*c = '\200'; /* '\0' ???? */
|
||||
return 2;
|
||||
default:
|
||||
*c = *sp;
|
||||
return 2;
|
||||
}
|
||||
default:
|
||||
*c = *sp;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static int termcap;
|
||||
|
||||
/* sigh... this has got to be the ugliest code I've ever written.
|
||||
Trying to handle everything has its cost, I guess.
|
||||
|
||||
It actually isn't to hard to figure out if a given % code is supposed
|
||||
to be interpeted with its termcap or terminfo meaning since almost
|
||||
all terminfo codes are invalid unless something has been pushed on
|
||||
the stack and termcap strings will never push things on the stack
|
||||
(%p isn't used by termcap). So where we have a choice we make the
|
||||
decision by wether or not somthing has been pushed on the stack.
|
||||
The static variable termcap keeps track of this; it starts out set
|
||||
to 1 and is incremented as each argument processed by a termcap % code,
|
||||
however if something is pushed on the stack it's set to 0 and the
|
||||
rest of the % codes are interpeted as terminfo % codes. Another way
|
||||
of putting it is that if termcap equals one we haven't decided either
|
||||
way yet, if it equals zero we're looking for terminfo codes, and if
|
||||
its greater than 1 we're looking for termcap codes.
|
||||
|
||||
Terminfo % codes:
|
||||
|
||||
%% output a '%'
|
||||
%[[:][-+# ][width][.precision]][doxXs]
|
||||
output pop according to the printf format
|
||||
%c output pop as a char
|
||||
%'c' push character constant c.
|
||||
%{n} push decimal constant n.
|
||||
%p[1-9] push paramter [1-9]
|
||||
%g[a-z] push variable [a-z]
|
||||
%P[a-z] put pop in variable [a-z]
|
||||
%l push the length of pop (a string)
|
||||
%+ add pop to pop and push the result
|
||||
%- subtract pop from pop and push the result
|
||||
%* multiply pop and pop and push the result
|
||||
%& bitwise and pop and pop and push the result
|
||||
%| bitwise or pop and pop and push the result
|
||||
%^ bitwise xor pop and pop and push the result
|
||||
%~ push the bitwise not of pop
|
||||
%= compare if pop and pop are equal and push the result
|
||||
%> compare if pop is less than pop and push the result
|
||||
%< compare if pop is greater than pop and push the result
|
||||
%A logical and pop and pop and push the result
|
||||
%O logical or pop and pop and push the result
|
||||
%! push the logical not of pop
|
||||
%? condition %t if_true [%e if_false] %;
|
||||
if condtion evaulates as true then evaluate if_true,
|
||||
else evaluate if_false. elseif's can be done:
|
||||
%? cond %t true [%e cond2 %t true2] ... [%e condN %t trueN] [%e false] %;
|
||||
%i add one to parameters 1 and 2. (ANSI)
|
||||
|
||||
Termcap Codes:
|
||||
|
||||
%% output a %
|
||||
%. output parameter as a character
|
||||
%d output parameter as a decimal number
|
||||
%2 output parameter in printf format %02d
|
||||
%3 output parameter in printf format %03d
|
||||
%+x add the character x to parameter and output it as a character
|
||||
(UW) %-x subtract parameter FROM the character x and output it as a char
|
||||
(UW) %ax add the character x to parameter
|
||||
(GNU) %a[+*-/=][cp]x
|
||||
GNU arithmetic.
|
||||
(UW) %sx subtract parameter FROM the character x
|
||||
%>xy if parameter > character x then add character y to parameter
|
||||
%B convert to BCD (parameter = (parameter/10)*16 + parameter%16)
|
||||
%D Delta Data encode (parameter = parameter - 2*(paramter%16))
|
||||
%i increment the first two parameters by one
|
||||
%n xor the first two parameters by 0140
|
||||
(GNU) %m xor the first two parameters by 0177
|
||||
%r swap the first two parameters
|
||||
(GNU) %b backup to previous parameter
|
||||
(GNU) %f skip this parameter
|
||||
|
||||
Note the two definitions of %a, the GNU defintion is used if the characters
|
||||
after the 'a' are valid, otherwise the UW definition is used.
|
||||
|
||||
(GNU) used by GNU Emacs termcap libraries
|
||||
(UW) used by the University of Waterloo (MFCF) termcap libraries
|
||||
|
||||
*/
|
||||
|
||||
char *tparm(const char *str, ...) {
|
||||
static char OOPS[] = "OOPS";
|
||||
static char buf[MAX_LINE];
|
||||
register const char *sp;
|
||||
register char *dp;
|
||||
register char *fmt;
|
||||
char conv_char;
|
||||
char scan_for;
|
||||
int scan_depth = 0, if_depth;
|
||||
static int i, j;
|
||||
static char *s, c;
|
||||
char fmt_buf[MAX_LINE];
|
||||
char sbuf[MAX_LINE];
|
||||
|
||||
va_start(tparm_args, str);
|
||||
|
||||
sp = str;
|
||||
dp = buf;
|
||||
scan_for = 0;
|
||||
if_depth = 0;
|
||||
argcnt = 0;
|
||||
pos = 0;
|
||||
termcap = 1;
|
||||
while (*sp != '\0') {
|
||||
switch(*sp) {
|
||||
case '\\':
|
||||
if (scan_for) {
|
||||
if (*++sp != '\0')
|
||||
sp++;
|
||||
break;
|
||||
}
|
||||
*dp++ = *sp++;
|
||||
if (*sp != '\0')
|
||||
*dp++ = *sp++;
|
||||
break;
|
||||
case '%':
|
||||
sp++;
|
||||
if (scan_for) {
|
||||
if (*sp == scan_for && if_depth == scan_depth) {
|
||||
if (scan_for == ';')
|
||||
if_depth--;
|
||||
scan_for = 0;
|
||||
} else if (*sp == '?')
|
||||
if_depth++;
|
||||
else if (*sp == ';') {
|
||||
if (if_depth == 0)
|
||||
return OOPS;
|
||||
else
|
||||
if_depth--;
|
||||
}
|
||||
sp++;
|
||||
break;
|
||||
}
|
||||
fmt = NULL;
|
||||
switch(*sp) {
|
||||
case '%':
|
||||
*dp++ = *sp++;
|
||||
break;
|
||||
case '+':
|
||||
if (!termcap) {
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i += j;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
}
|
||||
;/* FALLTHROUGH */
|
||||
case 'C':
|
||||
if (*sp == 'C') {
|
||||
if (getarg(termcap - 1, INTEGER, &i))
|
||||
return OOPS;
|
||||
if (i >= 96) {
|
||||
i /= 96;
|
||||
if (i == '$')
|
||||
*dp++ = '\\';
|
||||
*dp++ = i;
|
||||
}
|
||||
}
|
||||
fmt = "%c";
|
||||
/* FALLTHROUGH */
|
||||
case 'a':
|
||||
if (!termcap)
|
||||
return OOPS;
|
||||
if (getarg(termcap - 1, INTEGER, (anyptr) &i))
|
||||
return OOPS;
|
||||
if (*++sp == '\0')
|
||||
return OOPS;
|
||||
if ((sp[1] == 'p' || sp[1] == 'c')
|
||||
&& sp[2] != '\0' && fmt == NULL) {
|
||||
/* GNU aritmitic parameter, what they
|
||||
realy need is terminfo. */
|
||||
int val, lc;
|
||||
if (sp[1] == 'p'
|
||||
&& getarg(termcap - 1 + sp[2] - '@',
|
||||
INTEGER, (anyptr) &val))
|
||||
return OOPS;
|
||||
if (sp[1] == 'c') {
|
||||
lc = cvtchar(sp + 2, &c) + 2;
|
||||
/* Mask out 8th bit so \200 can be
|
||||
used for \0 as per GNU doc's */
|
||||
val = c & 0177;
|
||||
} else
|
||||
lc = 2;
|
||||
switch(sp[0]) {
|
||||
case '=':
|
||||
break;
|
||||
case '+':
|
||||
val = i + val;
|
||||
break;
|
||||
case '-':
|
||||
val = i - val;
|
||||
break;
|
||||
case '*':
|
||||
val = i * val;
|
||||
break;
|
||||
case '/':
|
||||
val = i / val;
|
||||
break;
|
||||
default:
|
||||
/* Not really GNU's %a after all... */
|
||||
lc = cvtchar(sp, &c);
|
||||
val = c + i;
|
||||
break;
|
||||
}
|
||||
arg_list[termcap - 1].integer = val;
|
||||
sp += lc;
|
||||
break;
|
||||
}
|
||||
sp += cvtchar(sp, &c);
|
||||
arg_list[termcap - 1].integer = c + i;
|
||||
if (fmt == NULL)
|
||||
break;
|
||||
sp--;
|
||||
/* FALLTHROUGH */
|
||||
case '-':
|
||||
if (!termcap) {
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i -= j;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
}
|
||||
fmt = "%c";
|
||||
/* FALLTHROUGH */
|
||||
case 's':
|
||||
if (termcap && (fmt == NULL || *sp == '-')) {
|
||||
if (getarg(termcap - 1, INTEGER, &i))
|
||||
return OOPS;
|
||||
if (*++sp == '\0')
|
||||
return OOPS;
|
||||
sp += cvtchar(sp, &c);
|
||||
arg_list[termcap - 1].integer = c - i;
|
||||
if (fmt == NULL)
|
||||
break;
|
||||
sp--;
|
||||
}
|
||||
if (!termcap)
|
||||
return OOPS;
|
||||
;/* FALLTHROUGH */
|
||||
case '.':
|
||||
if (termcap && fmt == NULL)
|
||||
fmt = "%c";
|
||||
;/* FALLTHROUGH */
|
||||
case 'd':
|
||||
if (termcap && fmt == NULL)
|
||||
fmt = "%d";
|
||||
;/* FALLTHROUGH */
|
||||
case '2':
|
||||
if (termcap && fmt == NULL)
|
||||
fmt = "%02d";
|
||||
;/* FALLTHROUGH */
|
||||
case '3':
|
||||
if (termcap && fmt == NULL)
|
||||
fmt = "%03d";
|
||||
;/* FALLTHROUGH */
|
||||
case ':': case ' ': case '#': case 'u':
|
||||
case 'x': case 'X': case 'o': case 'c':
|
||||
case '0': case '1': case '4': case '5':
|
||||
case '6': case '7': case '8': case '9':
|
||||
if (fmt == NULL) {
|
||||
if (termcap)
|
||||
return OOPS;
|
||||
if (*sp == ':')
|
||||
sp++;
|
||||
fmt = fmt_buf;
|
||||
*fmt++ = '%';
|
||||
while(*sp != 's' && *sp != 'x' && *sp != 'X' && *sp != 'd' && *sp != 'o' && *sp != 'c' && *sp != 'u') {
|
||||
if (*sp == '\0')
|
||||
return OOPS;
|
||||
*fmt++ = *sp++;
|
||||
}
|
||||
*fmt++ = *sp;
|
||||
*fmt = '\0';
|
||||
fmt = fmt_buf;
|
||||
}
|
||||
conv_char = fmt[strlen(fmt) - 1];
|
||||
if (conv_char == 's') {
|
||||
if (popstring(&s))
|
||||
return OOPS;
|
||||
sprintf(sbuf, fmt, s);
|
||||
} else {
|
||||
if (termcap) {
|
||||
if (getarg(termcap++ - 1,
|
||||
INTEGER, &i))
|
||||
return OOPS;
|
||||
} else
|
||||
if (popnum(&i))
|
||||
return OOPS;
|
||||
if (i == 0 && conv_char == 'c')
|
||||
*sbuf = 0;
|
||||
else
|
||||
sprintf(sbuf, fmt, i);
|
||||
}
|
||||
sp++;
|
||||
fmt = sbuf;
|
||||
while(*fmt != '\0') {
|
||||
if (*fmt == '$')
|
||||
*dp++ = '\\';
|
||||
*dp++ = *fmt++;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (!termcap || getarg(1, INTEGER, &i))
|
||||
return OOPS;
|
||||
arg_list[1].integer = arg_list[0].integer;
|
||||
arg_list[0].integer = i;
|
||||
sp++;
|
||||
break;
|
||||
case 'i':
|
||||
if (getarg(1, INTEGER, &i)
|
||||
|| arg_list[0].type != INTEGER)
|
||||
return OOPS;
|
||||
arg_list[1].integer++;
|
||||
arg_list[0].integer++;
|
||||
sp++;
|
||||
break;
|
||||
case 'n':
|
||||
if (!termcap || getarg(1, INTEGER, &i))
|
||||
return OOPS;
|
||||
arg_list[0].integer ^= 0140;
|
||||
arg_list[1].integer ^= 0140;
|
||||
sp++;
|
||||
break;
|
||||
case '>':
|
||||
if (!termcap) {
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i = (i > j);
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
}
|
||||
if (getarg(termcap-1, INTEGER, &i))
|
||||
return OOPS;
|
||||
sp += cvtchar(sp, &c);
|
||||
if (i > c) {
|
||||
sp += cvtchar(sp, &c);
|
||||
arg_list[termcap-1].integer += c;
|
||||
} else
|
||||
sp += cvtchar(sp, &c);
|
||||
sp++;
|
||||
break;
|
||||
case 'B':
|
||||
if (!termcap || getarg(termcap-1, INTEGER, &i))
|
||||
return OOPS;
|
||||
arg_list[termcap-1].integer = 16*(i/10)+i%10;
|
||||
sp++;
|
||||
break;
|
||||
case 'D':
|
||||
if (!termcap || getarg(termcap-1, INTEGER, &i))
|
||||
return OOPS;
|
||||
arg_list[termcap-1].integer = i - 2 * (i % 16);
|
||||
sp++;
|
||||
break;
|
||||
case 'p':
|
||||
if (termcap > 1)
|
||||
return OOPS;
|
||||
if (*++sp == '\0')
|
||||
return OOPS;
|
||||
if (*sp == '0')
|
||||
i = 9;
|
||||
else
|
||||
i = *sp - '1';
|
||||
if (i < 0 || i > 9)
|
||||
return OOPS;
|
||||
if (pusharg(i))
|
||||
return OOPS;
|
||||
termcap = 0;
|
||||
sp++;
|
||||
break;
|
||||
case 'P':
|
||||
if (termcap || *++sp == '\0')
|
||||
return OOPS;
|
||||
i = *sp++ - 'a';
|
||||
if (i < 0 || i > 25)
|
||||
return OOPS;
|
||||
if (pos-- == 0)
|
||||
return OOPS;
|
||||
switch(vars[i].type = S[pos].type) {
|
||||
case ARG:
|
||||
vars[i].argnum = S[pos].argnum;
|
||||
break;
|
||||
case NUM:
|
||||
vars[i].value = S[pos].value;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
if (termcap || *++sp == '\0')
|
||||
return OOPS;
|
||||
i = *sp++ - 'a';
|
||||
if (i < 0 || i > 25)
|
||||
return OOPS;
|
||||
switch(vars[i].type) {
|
||||
case ARG:
|
||||
if (pusharg(vars[i].argnum))
|
||||
return OOPS;
|
||||
break;
|
||||
case NUM:
|
||||
if (pushnum(vars[i].value))
|
||||
return OOPS;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case '\'':
|
||||
if (termcap > 1)
|
||||
return OOPS;
|
||||
if (*++sp == '\0')
|
||||
return OOPS;
|
||||
sp += cvtchar(sp, &c);
|
||||
if (pushnum(c) || *sp++ != '\'')
|
||||
return OOPS;
|
||||
termcap = 0;
|
||||
break;
|
||||
case '{':
|
||||
if (termcap > 1)
|
||||
return OOPS;
|
||||
i = 0;
|
||||
sp++;
|
||||
while(isdigit(*sp))
|
||||
i = 10 * i + *sp++ - '0';
|
||||
if (*sp++ != '}' || pushnum(i))
|
||||
return OOPS;
|
||||
termcap = 0;
|
||||
break;
|
||||
case 'l':
|
||||
if (termcap || popstring(&s))
|
||||
return OOPS;
|
||||
i = strlen(s);
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '*':
|
||||
if (termcap || popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i *= j;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '/':
|
||||
if (termcap || popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i /= j;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case 'm':
|
||||
if (termcap) {
|
||||
if (getarg(1, INTEGER, &i))
|
||||
return OOPS;
|
||||
arg_list[0].integer ^= 0177;
|
||||
arg_list[1].integer ^= 0177;
|
||||
sp++;
|
||||
break;
|
||||
}
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i %= j;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '&':
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i &= j;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '|':
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i |= j;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '^':
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i ^= j;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '=':
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i = (i == j);
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '<':
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i = (i < j);
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case 'A':
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i = (i && j);
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case 'O':
|
||||
if (popnum(&j) || popnum(&i))
|
||||
return OOPS;
|
||||
i = (i || j);
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '!':
|
||||
if (popnum(&i))
|
||||
return OOPS;
|
||||
i = !i;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '~':
|
||||
if (popnum(&i))
|
||||
return OOPS;
|
||||
i = ~i;
|
||||
if (pushnum(i))
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case '?':
|
||||
if (termcap > 1)
|
||||
return OOPS;
|
||||
termcap = 0;
|
||||
if_depth++;
|
||||
sp++;
|
||||
break;
|
||||
case 't':
|
||||
if (popnum(&i) || if_depth == 0)
|
||||
return OOPS;
|
||||
if (!i) {
|
||||
scan_for = 'e';
|
||||
scan_depth = if_depth;
|
||||
}
|
||||
sp++;
|
||||
break;
|
||||
case 'e':
|
||||
if (if_depth == 0)
|
||||
return OOPS;
|
||||
scan_for = ';';
|
||||
scan_depth = if_depth;
|
||||
sp++;
|
||||
break;
|
||||
case ';':
|
||||
if (if_depth-- == 0)
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case 'b':
|
||||
if (--termcap < 1)
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
case 'f':
|
||||
if (!termcap++)
|
||||
return OOPS;
|
||||
sp++;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (scan_for)
|
||||
sp++;
|
||||
else
|
||||
*dp++ = *sp++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(tparm_args);
|
||||
*dp = '\0';
|
||||
return buf;
|
||||
}
|
Loading…
Reference in New Issue
Block a user