diff options
Diffstat (limited to 'src/fe-text/term-curses.c')
-rw-r--r-- | src/fe-text/term-curses.c | 368 |
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; +} |