2000-04-26 04:03:38 -04:00
|
|
|
/*
|
2000-05-04 06:32:42 -04:00
|
|
|
screen.c : irssi
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
Copyright (C) 1999-2000 Timo Sirainen
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
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"
|
2000-06-01 19:30:40 -04:00
|
|
|
#include "misc.h"
|
2000-04-26 04:03:38 -04:00
|
|
|
#include "settings.h"
|
2001-08-28 08:24:46 -04:00
|
|
|
#include "commands.h"
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
#include "screen.h"
|
|
|
|
#include "gui-readline.h"
|
2000-05-04 06:32:42 -04:00
|
|
|
#include "mainwindows.h"
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
#ifdef HAVE_SYS_IOCTL_H
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#endif
|
|
|
|
#include <signal.h>
|
|
|
|
|
2001-06-01 17:49:07 -04:00
|
|
|
#if defined(USE_NCURSES) && !defined(RENAMED_NCURSES)
|
|
|
|
# include <ncurses.h>
|
|
|
|
#else
|
|
|
|
# include <curses.h>
|
|
|
|
#endif
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
#ifndef COLOR_PAIRS
|
2001-07-28 22:25:55 -04:00
|
|
|
# define COLOR_PAIRS 64
|
2000-04-26 04:03:38 -04:00
|
|
|
#endif
|
|
|
|
|
2001-07-28 22:25:55 -04:00
|
|
|
#if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM)
|
|
|
|
# define USE_RESIZE_TERM
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#define RESIZE_TIMEOUT 500 /* how often to check if the terminal has been resized */
|
2000-04-26 04:03:38 -04:00
|
|
|
#define MIN_SCREEN_WIDTH 20
|
|
|
|
|
2001-06-01 17:49:07 -04:00
|
|
|
struct _SCREEN_WINDOW {
|
2001-10-13 12:11:13 -04:00
|
|
|
int x, y;
|
|
|
|
int width, height;
|
|
|
|
WINDOW *win;
|
2001-06-01 17:49:07 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
SCREEN_WINDOW *screen_root;
|
|
|
|
int screen_width, screen_height;
|
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
static int scrx, scry;
|
|
|
|
static int use_colors;
|
|
|
|
static int freeze_refresh;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2001-01-15 17:47:51 -05:00
|
|
|
static int init_screen_int(void);
|
|
|
|
static void deinit_screen_int(void);
|
|
|
|
|
2000-04-26 04:03:38 -04:00
|
|
|
#ifdef SIGWINCH
|
2001-08-28 08:24:46 -04:00
|
|
|
static int resize_timeout_tag;
|
|
|
|
#endif
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2001-08-28 08:24:46 -04:00
|
|
|
static int resize_needed;
|
2001-07-28 22:25:55 -04:00
|
|
|
|
|
|
|
static int resize_timeout(void)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
2001-07-28 22:25:55 -04:00
|
|
|
#ifdef USE_RESIZE_TERM
|
2001-01-15 17:47:51 -05:00
|
|
|
struct winsize ws;
|
2001-07-28 22:25:55 -04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!resize_needed)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
resize_needed = FALSE;
|
|
|
|
|
|
|
|
#ifdef USE_RESIZE_TERM
|
2001-01-15 17:47:51 -05:00
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
/* Get new window size */
|
|
|
|
if (ioctl(0, TIOCGWINSZ, &ws) < 0)
|
2001-07-28 22:25:55 -04:00
|
|
|
return TRUE;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
if (ws.ws_row == LINES && ws.ws_col == COLS) {
|
|
|
|
/* Same size, abort. */
|
2001-07-28 22:25:55 -04:00
|
|
|
return TRUE;
|
2000-05-04 06:32:42 -04:00
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
if (ws.ws_col < MIN_SCREEN_WIDTH)
|
|
|
|
ws.ws_col = MIN_SCREEN_WIDTH;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
/* Resize curses terminal */
|
|
|
|
resizeterm(ws.ws_row, ws.ws_col);
|
2000-04-26 04:03:38 -04:00
|
|
|
#else
|
2001-01-15 17:47:51 -05:00
|
|
|
deinit_screen_int();
|
|
|
|
init_screen_int();
|
2000-08-10 16:01:32 -04:00
|
|
|
mainwindows_recreate();
|
2000-04-26 04:03:38 -04:00
|
|
|
#endif
|
|
|
|
|
2001-07-28 22:25:55 -04:00
|
|
|
screen_width = COLS;
|
|
|
|
screen_height = LINES;
|
2001-04-14 18:24:56 -04:00
|
|
|
mainwindows_resize(COLS, LINES);
|
2001-07-28 22:25:55 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2001-08-28 08:24:46 -04:00
|
|
|
#ifdef SIGWINCH
|
2001-07-28 22:25:55 -04:00
|
|
|
static void sig_winch(int p)
|
|
|
|
{
|
|
|
|
resize_needed = TRUE;
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2001-08-28 08:24:46 -04:00
|
|
|
static void cmd_resize(void)
|
|
|
|
{
|
|
|
|
resize_needed = TRUE;
|
|
|
|
resize_timeout();
|
|
|
|
}
|
|
|
|
|
2000-06-05 13:38:27 -04:00
|
|
|
static void read_settings(void)
|
|
|
|
{
|
2000-07-03 20:44:45 -04:00
|
|
|
int old_colors = use_colors;
|
|
|
|
|
2000-06-05 13:38:27 -04:00
|
|
|
use_colors = settings_get_bool("colors");
|
2001-03-14 21:26:12 -05:00
|
|
|
if (use_colors && !has_colors())
|
|
|
|
use_colors = FALSE;
|
|
|
|
|
|
|
|
if (use_colors != old_colors)
|
|
|
|
irssi_redraw();
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
2000-10-08 08:54:26 -04:00
|
|
|
static int init_curses(void)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
2000-05-04 06:32:42 -04:00
|
|
|
char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
|
|
|
|
int num;
|
2001-07-28 22:25:55 -04:00
|
|
|
#if !defined (WIN32) && defined(SIGWINCH)
|
2000-10-27 14:37:32 -04:00
|
|
|
struct sigaction act;
|
2000-11-18 10:32:59 -05:00
|
|
|
#endif
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-10-08 08:54:26 -04:00
|
|
|
if (!initscr())
|
|
|
|
return FALSE;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
if (COLS < MIN_SCREEN_WIDTH)
|
|
|
|
COLS = MIN_SCREEN_WIDTH;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2001-05-17 07:47:21 -04:00
|
|
|
#ifdef SIGWINCH
|
2000-10-27 14:37:32 -04:00
|
|
|
sigemptyset (&act.sa_mask);
|
|
|
|
act.sa_flags = 0;
|
|
|
|
act.sa_handler = sig_winch;
|
|
|
|
sigaction(SIGWINCH, &act, NULL);
|
2000-10-08 08:54:26 -04:00
|
|
|
#endif
|
2001-05-17 07:24:33 -04:00
|
|
|
raw(); noecho(); idlok(stdscr, 1);
|
2000-04-26 04:03:38 -04:00
|
|
|
#ifdef HAVE_CURSES_IDCOK
|
2001-09-10 11:34:49 -04:00
|
|
|
/*idcok(stdscr, 1); - disabled currently, causes redrawing problems with NetBSD */
|
2000-04-26 04:03:38 -04:00
|
|
|
#endif
|
2001-05-06 15:28:15 -04:00
|
|
|
intrflush(stdscr, FALSE); nodelay(stdscr, TRUE);
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-10-08 08:54:26 -04:00
|
|
|
if (has_colors())
|
|
|
|
start_color();
|
2001-03-14 21:26:12 -05:00
|
|
|
else if (use_colors)
|
|
|
|
use_colors = FALSE;
|
2000-04-26 04:03:38 -04:00
|
|
|
|
|
|
|
#ifdef HAVE_NCURSES_USE_DEFAULT_COLORS
|
2000-05-04 06:32:42 -04:00
|
|
|
/* this lets us to use the "default" background color for colors <= 7 so
|
|
|
|
background pixmaps etc. show up right */
|
|
|
|
use_default_colors();
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
for (num = 1; num < COLOR_PAIRS; num++)
|
|
|
|
init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]);
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more
|
|
|
|
people want dark grey than white on white.. */
|
2000-04-26 04:03:38 -04:00
|
|
|
#else
|
2000-05-04 06:32:42 -04:00
|
|
|
for (num = 1; num < COLOR_PAIRS; num++)
|
|
|
|
init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]);
|
|
|
|
init_pair(63, 0, 0);
|
2000-04-26 04:03:38 -04:00
|
|
|
#endif
|
|
|
|
|
2000-10-08 08:54:26 -04:00
|
|
|
clear();
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2001-01-15 17:47:51 -05:00
|
|
|
static int init_screen_int(void)
|
2000-10-08 08:54:26 -04:00
|
|
|
{
|
2001-06-01 17:49:07 -04:00
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = init_curses();
|
|
|
|
if (!ret) return 0;
|
|
|
|
|
2000-10-08 08:54:26 -04:00
|
|
|
use_colors = settings_get_bool("colors");
|
|
|
|
|
|
|
|
scrx = scry = 0;
|
2000-05-04 06:32:42 -04:00
|
|
|
freeze_refresh = 0;
|
2000-10-08 08:54:26 -04:00
|
|
|
|
2001-06-01 17:49:07 -04:00
|
|
|
screen_root = g_new0(SCREEN_WINDOW, 1);
|
|
|
|
screen_root->win = stdscr;
|
|
|
|
|
|
|
|
screen_width = COLS;
|
|
|
|
screen_height = LINES;
|
|
|
|
return ret;
|
2001-01-15 17:47:51 -05:00
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
|
2001-01-15 17:47:51 -05:00
|
|
|
static void deinit_screen_int(void)
|
|
|
|
{
|
|
|
|
endwin();
|
2001-06-01 17:49:07 -04:00
|
|
|
g_free_and_null(screen_root);
|
2001-01-15 17:47:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Initialize screen, detect screen length */
|
|
|
|
int init_screen(void)
|
|
|
|
{
|
|
|
|
settings_add_bool("lookandfeel", "colors", TRUE);
|
2001-06-01 17:49:07 -04:00
|
|
|
|
|
|
|
signal_add("beep", (SIGNAL_FUNC) beep);
|
2000-05-04 06:32:42 -04:00
|
|
|
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
|
2001-08-28 08:24:46 -04:00
|
|
|
command_bind("resize", NULL, (SIGNAL_FUNC) cmd_resize);
|
2001-01-15 17:47:51 -05:00
|
|
|
|
2001-07-28 22:25:55 -04:00
|
|
|
#ifdef SIGWINCH
|
|
|
|
resize_timeout_tag = g_timeout_add(RESIZE_TIMEOUT,
|
|
|
|
(GSourceFunc) resize_timeout, NULL);
|
|
|
|
#endif
|
|
|
|
return init_screen_int();
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Deinitialize screen */
|
|
|
|
void deinit_screen(void)
|
|
|
|
{
|
2001-06-01 17:49:07 -04:00
|
|
|
deinit_screen_int();
|
|
|
|
|
2001-07-28 22:25:55 -04:00
|
|
|
#ifdef SIGWINCH
|
|
|
|
g_source_remove(resize_timeout_tag);
|
|
|
|
#endif
|
|
|
|
|
2001-08-28 08:24:46 -04:00
|
|
|
command_unbind("resize", (SIGNAL_FUNC) cmd_resize);
|
2001-06-01 17:49:07 -04:00
|
|
|
signal_remove("beep", (SIGNAL_FUNC) beep);
|
2000-05-04 06:32:42 -04:00
|
|
|
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
2001-06-01 17:49:07 -04:00
|
|
|
int screen_has_colors(void)
|
|
|
|
{
|
|
|
|
return has_colors();
|
|
|
|
}
|
|
|
|
|
|
|
|
void screen_clear(void)
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
SCREEN_WINDOW *screen_window_create(int x, int y, int width, int height)
|
|
|
|
{
|
2001-10-13 12:11:13 -04:00
|
|
|
SCREEN_WINDOW *window;
|
2001-06-01 17:49:07 -04:00
|
|
|
|
2001-10-13 12:11:13 -04:00
|
|
|
window = g_new0(SCREEN_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);
|
2001-06-01 17:49:07 -04:00
|
|
|
|
2001-10-13 12:11:13 -04:00
|
|
|
return window;
|
2001-06-01 17:49:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void screen_window_destroy(SCREEN_WINDOW *window)
|
|
|
|
{
|
|
|
|
delwin(window->win);
|
|
|
|
g_free(window);
|
|
|
|
}
|
|
|
|
|
|
|
|
void screen_window_clear(SCREEN_WINDOW *window)
|
|
|
|
{
|
|
|
|
werase(window->win);
|
|
|
|
}
|
|
|
|
|
|
|
|
void screen_window_move(SCREEN_WINDOW *window, int x, int y,
|
|
|
|
int width, int height)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_CURSES_WRESIZE
|
2001-10-13 12:11:13 -04:00
|
|
|
if (window->width != width || window->height != height)
|
|
|
|
wresize(window->win, height, width);
|
|
|
|
if (window->x != x || window->y != y)
|
|
|
|
mvwin(window->win, y, x);
|
2001-06-01 17:49:07 -04:00
|
|
|
#else
|
2001-10-13 12:11:13 -04:00
|
|
|
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);
|
|
|
|
}
|
2001-06-01 17:49:07 -04:00
|
|
|
#endif
|
2001-10-13 12:11:13 -04:00
|
|
|
window->x = x; window->y = y;
|
|
|
|
window->width = width; window->height = height;
|
2001-06-01 17:49:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void screen_window_scroll(SCREEN_WINDOW *window, int count)
|
|
|
|
{
|
|
|
|
scrollok(window->win, TRUE);
|
|
|
|
wscrl(window->win, count);
|
|
|
|
scrollok(window->win, FALSE);
|
|
|
|
}
|
|
|
|
|
2001-10-13 12:11:13 -04:00
|
|
|
static int get_attr(int color)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
2000-05-04 06:32:42 -04:00
|
|
|
int attr;
|
|
|
|
|
|
|
|
if (!use_colors)
|
2001-10-13 12:11:13 -04:00
|
|
|
attr = (color & 0x70) ? A_REVERSE : 0;
|
|
|
|
else if (color & ATTR_COLOR8)
|
2001-02-10 05:19:47 -05:00
|
|
|
attr = (A_DIM | COLOR_PAIR(63));
|
2001-10-13 12:11:13 -04:00
|
|
|
else if ((color & 0x77) == 0)
|
2001-02-10 05:19:47 -05:00
|
|
|
attr = A_NORMAL;
|
|
|
|
else
|
2001-10-13 12:11:13 -04:00
|
|
|
attr = (COLOR_PAIR((color&7) + (color&0x70)/2));
|
2000-05-04 06:32:42 -04:00
|
|
|
|
2001-10-13 12:11:13 -04:00
|
|
|
if (color & 0x08) attr |= A_BOLD;
|
|
|
|
if (color & 0x80) attr |= A_BLINK;
|
2000-05-04 06:32:42 -04:00
|
|
|
|
2001-10-13 12:11:13 -04:00
|
|
|
if (color & ATTR_UNDERLINE) attr |= A_UNDERLINE;
|
|
|
|
if (color & ATTR_REVERSE) attr |= A_REVERSE;
|
|
|
|
return attr;
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
2001-10-13 12:11:13 -04:00
|
|
|
void screen_set_color(SCREEN_WINDOW *window, int color)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
2001-10-13 12:11:13 -04:00
|
|
|
wattrset(window->win, get_attr(color));
|
|
|
|
}
|
2000-05-04 06:32:42 -04:00
|
|
|
|
2001-10-13 12:11:13 -04:00
|
|
|
void screen_set_bg(SCREEN_WINDOW *window, int color)
|
|
|
|
{
|
|
|
|
wbkgdset(window->win, ' ' | get_attr(color));
|
2001-06-01 17:49:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void screen_move(SCREEN_WINDOW *window, int x, int y)
|
|
|
|
{
|
|
|
|
wmove(window->win, y, x);
|
|
|
|
}
|
|
|
|
|
|
|
|
void screen_addch(SCREEN_WINDOW *window, int chr)
|
|
|
|
{
|
|
|
|
waddch(window->win, chr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void screen_addstr(SCREEN_WINDOW *window, char *str)
|
|
|
|
{
|
|
|
|
waddstr(window->win, str);
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
2001-06-01 17:49:07 -04:00
|
|
|
void screen_clrtoeol(SCREEN_WINDOW *window)
|
|
|
|
{
|
|
|
|
wclrtoeol(window->win);
|
|
|
|
}
|
|
|
|
|
|
|
|
void screen_move_cursor(int x, int y)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
2000-05-04 06:32:42 -04:00
|
|
|
scry = y;
|
|
|
|
scrx = x;
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void screen_refresh_freeze(void)
|
|
|
|
{
|
2000-05-04 06:32:42 -04:00
|
|
|
freeze_refresh++;
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void screen_refresh_thaw(void)
|
|
|
|
{
|
2000-05-04 06:32:42 -04:00
|
|
|
if (freeze_refresh > 0) {
|
|
|
|
freeze_refresh--;
|
2000-07-26 19:29:34 -04:00
|
|
|
if (freeze_refresh == 0) screen_refresh(NULL);
|
2000-05-04 06:32:42 -04:00
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
|
|
|
|
2001-06-01 17:49:07 -04:00
|
|
|
void screen_refresh(SCREEN_WINDOW *window)
|
2000-04-26 04:03:38 -04:00
|
|
|
{
|
2000-07-26 19:29:34 -04:00
|
|
|
if (window != NULL)
|
2001-06-01 17:49:07 -04:00
|
|
|
wnoutrefresh(window->win);
|
|
|
|
|
2000-05-04 06:32:42 -04:00
|
|
|
if (freeze_refresh == 0) {
|
|
|
|
move(scry, scrx);
|
2000-07-26 19:29:34 -04:00
|
|
|
wnoutrefresh(stdscr);
|
|
|
|
doupdate();
|
2000-05-04 06:32:42 -04:00
|
|
|
}
|
2000-04-26 04:03:38 -04:00
|
|
|
}
|
2001-06-01 17:49:07 -04:00
|
|
|
|
|
|
|
int screen_getch(void)
|
|
|
|
{
|
|
|
|
int key;
|
|
|
|
|
|
|
|
key = getch();
|
|
|
|
if (key == ERR)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#ifdef KEY_RESIZE
|
|
|
|
if (key == KEY_RESIZE)
|
|
|
|
return -1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return key;
|
|
|
|
}
|