/* screen.c : irssi Copyright (C) 1999-2000 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 "misc.h" #include "settings.h" #include "screen.h" #include "gui-readline.h" #include "mainwindows.h" #ifdef HAVE_SYS_IOCTL_H #include #endif #include #ifndef COLOR_PAIRS #define COLOR_PAIRS 64 #endif #define MIN_SCREEN_WIDTH 20 static int scrx, scry; static int use_colors; static int freeze_refresh; static int resized; static int init_screen_int(void); static void deinit_screen_int(void); #ifdef SIGWINCH static void sig_winch(int p) { resized = TRUE; } #endif void screen_check_resizes(void) { #if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM) struct winsize ws; /* Get new window size */ if (ioctl(0, TIOCGWINSZ, &ws) < 0) return; if (ws.ws_row == LINES && ws.ws_col == COLS) { /* Same size, abort. */ return; } if (ws.ws_col < MIN_SCREEN_WIDTH) ws.ws_col = MIN_SCREEN_WIDTH; /* Resize curses terminal */ resizeterm(ws.ws_row, ws.ws_col); #else deinit_screen_int(); init_screen_int(); mainwindows_recreate(); #endif mainwindows_resize(COLS, LINES); resized = FALSE; } static void read_signals(void) { #ifndef WIN32 int signals[] = { SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGALRM, SIGUSR1, SIGUSR2 }; char *signames[] = { "hup", "int", "quit", "term", "alrm", "usr1", "usr2" }; const char *ignores; struct sigaction act; int n; ignores = settings_get_str("ignore_signals"); sigemptyset (&act.sa_mask); act.sa_flags = 0; for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) { act.sa_handler = find_substr(ignores, signames[n]) ? SIG_IGN : SIG_DFL; sigaction(signals[n], &act, NULL); } #endif } static void read_settings(void) { int old_colors = use_colors; use_colors = settings_get_bool("colors"); read_signals(); if (use_colors && !has_colors()) use_colors = FALSE; if (use_colors != old_colors) irssi_redraw(); } static int init_curses(void) { char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; int num; #ifndef WIN32 struct sigaction act; #endif if (!initscr()) return FALSE; if (COLS < MIN_SCREEN_WIDTH) COLS = MIN_SCREEN_WIDTH; #ifdef SIGWINCH sigemptyset (&act.sa_mask); act.sa_flags = 0; act.sa_handler = sig_winch; sigaction(SIGWINCH, &act, NULL); #endif raw(); noecho(); idlok(stdscr, 1); #ifdef HAVE_CURSES_IDCOK idcok(stdscr, 1); #endif intrflush(stdscr, FALSE); nodelay(stdscr, TRUE); if (has_colors()) start_color(); else if (use_colors) 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 init_screen_int(void) { use_colors = settings_get_bool("colors"); read_signals(); scrx = scry = 0; freeze_refresh = 0; return init_curses(); } static void deinit_screen_int(void) { endwin(); } /* Initialize screen, detect screen length */ int init_screen(void) { settings_add_bool("lookandfeel", "colors", TRUE); settings_add_str("misc", "ignore_signals", ""); signal_add("setup changed", (SIGNAL_FUNC) read_settings); return init_screen_int(); } /* Deinitialize screen */ void deinit_screen(void) { deinit_screen_int(); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); } void set_color(WINDOW *window, int col) { int attr; if (!use_colors) attr = (col & 0x70) ? A_REVERSE : 0; else if (col & ATTR_COLOR8) attr = (A_DIM | COLOR_PAIR(63)); else if ((col & 0x77) == 0) attr = A_NORMAL; else attr = (COLOR_PAIR((col&7) + (col&0x70)/2)); if (col & 0x08) attr |= A_BOLD; if (col & 0x80) attr |= A_BLINK; if (col & ATTR_UNDERLINE) attr |= A_UNDERLINE; if (col & ATTR_REVERSE) attr |= A_REVERSE; wattrset(window, attr); } void set_bg(WINDOW *window, int col) { int attr; if (!use_colors) attr = (col & 0x70) ? A_REVERSE : 0; else { attr = (col == 8) ? (A_DIM | COLOR_PAIR(63)) : (COLOR_PAIR((col&7) + (col&0x70)/2)); } if (col & 0x08) attr |= A_BOLD; if (col & 0x80) attr |= A_BLINK; wbkgdset(window, ' ' | attr); } void move_cursor(int y, int x) { scry = y; scrx = x; } void screen_refresh_freeze(void) { freeze_refresh++; } void screen_refresh_thaw(void) { if (freeze_refresh > 0) { freeze_refresh--; if (freeze_refresh == 0) screen_refresh(NULL); } } void screen_refresh(WINDOW *window) { if (window != NULL) wnoutrefresh(window); if (freeze_refresh == 0) { move(scry, scrx); wnoutrefresh(stdscr); doupdate(); } }