5378b5c9e48a7aa5004ea4408da5a7206ccda9cf
[silc.git] / apps / irssi / src / fe-text / screen.c
1 /*
2  screen.c : irssi
3
4     Copyright (C) 1999-2000 Timo Sirainen
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #include "module.h"
22 #include "signals.h"
23 #include "misc.h"
24 #include "settings.h"
25
26 #include "screen.h"
27 #include "gui-readline.h"
28 #include "mainwindows.h"
29
30 #ifdef HAVE_SYS_IOCTL_H
31 #include <sys/ioctl.h>
32 #endif
33 #include <signal.h>
34
35 #ifndef COLOR_PAIRS
36 #define COLOR_PAIRS 64
37 #endif
38
39 #define MIN_SCREEN_WIDTH 20
40
41 static int scrx, scry;
42 static int use_colors;
43 static int freeze_refresh;
44
45 static int init_screen_int(void);
46 static void deinit_screen_int(void);
47
48 #ifdef SIGWINCH
49
50 static void sig_winch(int p)
51 {
52 #if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM)
53         struct winsize ws;
54
55         /* Get new window size */
56         if (ioctl(0, TIOCGWINSZ, &ws) < 0)
57                 return;
58
59         if (ws.ws_row == LINES && ws.ws_col == COLS) {
60                 /* Same size, abort. */
61                 return;
62         }
63
64         if (ws.ws_col < MIN_SCREEN_WIDTH)
65                 ws.ws_col = MIN_SCREEN_WIDTH;
66
67         /* Resize curses terminal */
68         resizeterm(ws.ws_row, ws.ws_col);
69 #else
70         deinit_screen_int();
71         init_screen_int();
72         mainwindows_recreate();
73 #endif
74
75         mainwindows_resize(COLS, LINES);
76 }
77 #endif
78
79 static void read_signals(void)
80 {
81 #ifndef WIN32
82         int signals[] = {
83                 SIGHUP, SIGINT, SIGQUIT, SIGTERM,
84                 SIGALRM, SIGUSR1, SIGUSR2
85         };
86         char *signames[] = {
87                 "hup", "int", "quit", "term",
88                 "alrm", "usr1", "usr2"
89         };
90
91         const char *ignores;
92         struct sigaction act;
93         int n;
94
95         ignores = settings_get_str("ignore_signals");
96
97         sigemptyset (&act.sa_mask);
98         act.sa_flags = 0;
99
100         for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) {
101                 act.sa_handler = find_substr(ignores, signames[n]) ?
102                         SIG_IGN : SIG_DFL;
103                 sigaction(signals[n], &act, NULL);
104         }
105 #endif
106 }
107
108 static void read_settings(void)
109 {
110         int old_colors = use_colors;
111
112         use_colors = settings_get_bool("colors");
113         read_signals();
114         if (use_colors && !has_colors())
115                 use_colors = FALSE;
116
117         if (use_colors != old_colors)
118                 irssi_redraw();
119 }
120
121 static int init_curses(void)
122 {
123         char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
124         int num;
125 #ifndef WIN32
126         struct sigaction act;
127 #endif
128
129         if (!initscr())
130                 return FALSE;
131
132         if (COLS < MIN_SCREEN_WIDTH)
133                 COLS = MIN_SCREEN_WIDTH;
134
135 #ifdef SIGWINCH
136         sigemptyset (&act.sa_mask);
137         act.sa_flags = 0;
138         act.sa_handler = sig_winch;
139         sigaction(SIGWINCH, &act, NULL);
140 #endif
141         raw(); noecho(); idlok(stdscr, 1);
142 #ifdef HAVE_CURSES_IDCOK
143         idcok(stdscr, 1);
144 #endif
145         intrflush(stdscr, FALSE); nodelay(stdscr, TRUE);
146
147         if (has_colors())
148                 start_color();
149         else if (use_colors)
150                 use_colors = FALSE;
151
152 #ifdef HAVE_NCURSES_USE_DEFAULT_COLORS
153         /* this lets us to use the "default" background color for colors <= 7 so
154            background pixmaps etc. show up right */
155         use_default_colors();
156
157         for (num = 1; num < COLOR_PAIRS; num++)
158                 init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]);
159
160         init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more
161                                  people want dark grey than white on white.. */
162 #else
163         for (num = 1; num < COLOR_PAIRS; num++)
164                 init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]);
165         init_pair(63, 0, 0);
166 #endif
167
168         clear();
169         return TRUE;
170 }
171
172 static int init_screen_int(void)
173 {
174         use_colors = settings_get_bool("colors");
175         read_signals();
176
177         scrx = scry = 0;
178         freeze_refresh = 0;
179
180         return init_curses();
181 }
182
183 static void deinit_screen_int(void)
184 {
185         endwin();
186 }
187
188 /* Initialize screen, detect screen length */
189 int init_screen(void)
190 {
191         settings_add_bool("lookandfeel", "colors", TRUE);
192         settings_add_str("misc", "ignore_signals", "");
193         signal_add("setup changed", (SIGNAL_FUNC) read_settings);
194
195         return init_screen_int();
196 }
197
198 /* Deinitialize screen */
199 void deinit_screen(void)
200 {
201         deinit_screen_int();
202         signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
203 }
204
205 void set_color(WINDOW *window, int col)
206 {
207         int attr;
208
209         if (!use_colors)
210                 attr = (col & 0x70) ? A_REVERSE : 0;
211         else if (col & ATTR_COLOR8)
212                 attr = (A_DIM | COLOR_PAIR(63));
213         else if ((col & 0x77) == 0)
214                 attr = A_NORMAL;
215         else
216                 attr = (COLOR_PAIR((col&7) + (col&0x70)/2));
217
218         if (col & 0x08) attr |= A_BOLD;
219         if (col & 0x80) attr |= A_BLINK;
220
221         if (col & ATTR_UNDERLINE) attr |= A_UNDERLINE;
222         if (col & ATTR_REVERSE) attr |= A_REVERSE;
223
224         wattrset(window, attr);
225 }
226
227 void set_bg(WINDOW *window, int col)
228 {
229         int attr;
230
231         if (!use_colors)
232                 attr = (col & 0x70) ? A_REVERSE : 0;
233         else {
234                 attr = (col == 8) ?
235                         (A_DIM | COLOR_PAIR(63)) :
236                         (COLOR_PAIR((col&7) + (col&0x70)/2));
237         }
238
239         if (col & 0x08) attr |= A_BOLD;
240         if (col & 0x80) attr |= A_BLINK;
241
242         wbkgdset(window, ' ' | attr);
243 }
244
245 void move_cursor(int y, int x)
246 {
247         scry = y;
248         scrx = x;
249 }
250
251 void screen_refresh_freeze(void)
252 {
253         freeze_refresh++;
254 }
255
256 void screen_refresh_thaw(void)
257 {
258         if (freeze_refresh > 0) {
259                 freeze_refresh--;
260                 if (freeze_refresh == 0) screen_refresh(NULL);
261         }
262 }
263
264 void screen_refresh(WINDOW *window)
265 {
266         if (window != NULL)
267                 wnoutrefresh(window);
268         if (freeze_refresh == 0) {
269                 move(scry, scrx);
270                 wnoutrefresh(stdscr);
271                 doupdate();
272         }
273 }