New silcconfig library and server parser. Merged silc-newconfig-final.patch.
[crypto.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 static int resized;
45
46 static int init_screen_int(void);
47 static void deinit_screen_int(void);
48
49 #ifdef SIGWINCH
50 static void sig_winch(int p)
51 {
52         resized = TRUE;
53 }
54 #endif
55
56 static void screen_resize(void)
57 {
58 #if defined (TIOCGWINSZ) && defined (HAVE_CURSES_RESIZETERM)
59         struct winsize ws;
60
61         /* Get new window size */
62         if (ioctl(0, TIOCGWINSZ, &ws) < 0)
63                 return;
64
65         if (ws.ws_row == LINES && ws.ws_col == COLS) {
66                 /* Same size, abort. */
67                 return;
68         }
69
70         if (ws.ws_col < MIN_SCREEN_WIDTH)
71                 ws.ws_col = MIN_SCREEN_WIDTH;
72
73         /* Resize curses terminal */
74         resizeterm(ws.ws_row, ws.ws_col);
75 #else
76         deinit_screen_int();
77         init_screen_int();
78         mainwindows_recreate();
79 #endif
80
81         mainwindows_resize(COLS, LINES);
82 }
83
84 void screen_check_resizes(void)
85 {
86         if (!resized)
87                 return;
88         screen_resize();
89         resized = FALSE;
90 }
91
92 static void read_signals(void)
93 {
94 #ifndef WIN32
95         int signals[] = {
96                 SIGHUP, SIGINT, SIGQUIT, SIGTERM,
97                 SIGALRM, SIGUSR1, SIGUSR2
98         };
99         char *signames[] = {
100                 "hup", "int", "quit", "term",
101                 "alrm", "usr1", "usr2"
102         };
103
104         const char *ignores;
105         struct sigaction act;
106         int n;
107
108         ignores = settings_get_str("ignore_signals");
109
110         sigemptyset (&act.sa_mask);
111         act.sa_flags = 0;
112
113         for (n = 0; n < sizeof(signals)/sizeof(signals[0]); n++) {
114                 act.sa_handler = find_substr(ignores, signames[n]) ?
115                         SIG_IGN : SIG_DFL;
116                 sigaction(signals[n], &act, NULL);
117         }
118 #endif
119 }
120
121 static void read_settings(void)
122 {
123         int old_colors = use_colors;
124
125         use_colors = settings_get_bool("colors");
126         read_signals();
127         if (use_colors && !has_colors())
128                 use_colors = FALSE;
129
130         if (use_colors != old_colors)
131                 irssi_redraw();
132 }
133
134 static int init_curses(void)
135 {
136         char ansi_tab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
137         int num;
138 #ifndef WIN32
139         struct sigaction act;
140 #endif
141
142         if (!initscr())
143                 return FALSE;
144
145         if (COLS < MIN_SCREEN_WIDTH)
146                 COLS = MIN_SCREEN_WIDTH;
147
148 #ifdef SIGWINCH
149         sigemptyset (&act.sa_mask);
150         act.sa_flags = 0;
151         act.sa_handler = sig_winch;
152         sigaction(SIGWINCH, &act, NULL);
153 #endif
154         raw(); noecho(); idlok(stdscr, 1);
155 #ifdef HAVE_CURSES_IDCOK
156         idcok(stdscr, 1);
157 #endif
158         intrflush(stdscr, FALSE); nodelay(stdscr, TRUE);
159
160         if (has_colors())
161                 start_color();
162         else if (use_colors)
163                 use_colors = FALSE;
164
165 #ifdef HAVE_NCURSES_USE_DEFAULT_COLORS
166         /* this lets us to use the "default" background color for colors <= 7 so
167            background pixmaps etc. show up right */
168         use_default_colors();
169
170         for (num = 1; num < COLOR_PAIRS; num++)
171                 init_pair(num, ansi_tab[num & 7], num <= 7 ? -1 : ansi_tab[num >> 3]);
172
173         init_pair(63, 0, -1); /* hm.. not THAT good idea, but probably more
174                                  people want dark grey than white on white.. */
175 #else
176         for (num = 1; num < COLOR_PAIRS; num++)
177                 init_pair(num, ansi_tab[num & 7], ansi_tab[num >> 3]);
178         init_pair(63, 0, 0);
179 #endif
180
181         clear();
182         return TRUE;
183 }
184
185 static int init_screen_int(void)
186 {
187         use_colors = settings_get_bool("colors");
188         read_signals();
189
190         scrx = scry = 0;
191         freeze_refresh = 0;
192
193         return init_curses();
194 }
195
196 static void deinit_screen_int(void)
197 {
198         endwin();
199 }
200
201 /* Initialize screen, detect screen length */
202 int init_screen(void)
203 {
204         settings_add_bool("lookandfeel", "colors", TRUE);
205         settings_add_str("misc", "ignore_signals", "");
206         signal_add("setup changed", (SIGNAL_FUNC) read_settings);
207
208         return init_screen_int();
209 }
210
211 /* Deinitialize screen */
212 void deinit_screen(void)
213 {
214         deinit_screen_int();
215         signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
216 }
217
218 void set_color(WINDOW *window, int col)
219 {
220         int attr;
221
222         if (!use_colors)
223                 attr = (col & 0x70) ? A_REVERSE : 0;
224         else if (col & ATTR_COLOR8)
225                 attr = (A_DIM | COLOR_PAIR(63));
226         else if ((col & 0x77) == 0)
227                 attr = A_NORMAL;
228         else
229                 attr = (COLOR_PAIR((col&7) + (col&0x70)/2));
230
231         if (col & 0x08) attr |= A_BOLD;
232         if (col & 0x80) attr |= A_BLINK;
233
234         if (col & ATTR_UNDERLINE) attr |= A_UNDERLINE;
235         if (col & ATTR_REVERSE) attr |= A_REVERSE;
236
237         wattrset(window, attr);
238 }
239
240 void set_bg(WINDOW *window, int col)
241 {
242         int attr;
243
244         if (!use_colors)
245                 attr = (col & 0x70) ? A_REVERSE : 0;
246         else {
247                 attr = (col == 8) ?
248                         (A_DIM | COLOR_PAIR(63)) :
249                         (COLOR_PAIR((col&7) + (col&0x70)/2));
250         }
251
252         if (col & 0x08) attr |= A_BOLD;
253         if (col & 0x80) attr |= A_BLINK;
254
255         wbkgdset(window, ' ' | attr);
256 }
257
258 void move_cursor(int y, int x)
259 {
260         scry = y;
261         scrx = x;
262 }
263
264 void screen_refresh_freeze(void)
265 {
266         freeze_refresh++;
267 }
268
269 void screen_refresh_thaw(void)
270 {
271         if (freeze_refresh > 0) {
272                 freeze_refresh--;
273                 if (freeze_refresh == 0) screen_refresh(NULL);
274         }
275 }
276
277 void screen_refresh(WINDOW *window)
278 {
279         if (window != NULL)
280                 wnoutrefresh(window);
281         if (freeze_refresh == 0) {
282                 move(scry, scrx);
283                 wnoutrefresh(stdscr);
284                 doupdate();
285         }
286 }