mirror of
https://github.com/irssi/irssi.git
synced 2024-12-04 14:46:39 -05:00
a6d61a0b2b
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@2502 dbcabf3a-b0e7-0310-adc4-f8d773084564
398 lines
8.4 KiB
C
398 lines
8.4 KiB
C
/*
|
|
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;
|
|
|
|
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, TCSADRAIN, &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, TCSADRAIN, &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();
|
|
#ifdef HAVE_CURSES_RESIZETERM
|
|
} else if (term_width != width || term_height != height) {
|
|
term_width = width;
|
|
term_height = height;
|
|
resizeterm(term_height, term_width);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void term_resize_final(int width, int height)
|
|
{
|
|
#ifdef HAVE_CURSES_RESIZETERM
|
|
if (width < 0 || height < 0)
|
|
mainwindows_recreate();
|
|
#else
|
|
mainwindows_recreate();
|
|
#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)
|
|
{
|
|
term_set_color(root_window, 0);
|
|
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);
|
|
if (window->win == NULL)
|
|
g_error("newwin() failed: %d,%d %d,%d", x, y, width, height);
|
|
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_add_unichar(TERM_WINDOW *window, unichar chr)
|
|
{
|
|
waddch(window->win, chr);
|
|
}
|
|
|
|
void term_addstr(TERM_WINDOW *window, const char *str)
|
|
{
|
|
waddstr(window->win, (const char *) 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();
|
|
}
|
|
|
|
void term_auto_detach(int set)
|
|
{
|
|
}
|
|
|
|
void term_set_input_type(int type)
|
|
{
|
|
}
|
|
|
|
int term_gets(unichar *buffer, int size)
|
|
{
|
|
int key, count;
|
|
|
|
for (count = 0; count < size; ) {
|
|
key = getch();
|
|
#ifdef KEY_RESIZE
|
|
if (key == KEY_RESIZE)
|
|
continue;
|
|
#endif
|
|
|
|
if (key == ERR)
|
|
break;
|
|
|
|
buffer[count] = key;
|
|
count++;
|
|
}
|
|
|
|
return count;
|
|
}
|