summaryrefslogtreecommitdiff
path: root/src/fe-text/term-curses.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-text/term-curses.c')
-rw-r--r--src/fe-text/term-curses.c368
1 files changed, 368 insertions, 0 deletions
diff --git a/src/fe-text/term-curses.c b/src/fe-text/term-curses.c
new file mode 100644
index 00000000..02ac826b
--- /dev/null
+++ b/src/fe-text/term-curses.c
@@ -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;
+}