1 /*
2  term.c : irssi
3 
4     Copyright (C) 2001 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 along
17     with this program; if not, write to the Free Software Foundation, Inc.,
18     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20 
21 #include "module.h"
22 #include "signals.h"
23 #include "commands.h"
24 #include "settings.h"
25 
26 #include "term.h"
27 #include "mainwindows.h"
28 
29 #ifdef HAVE_SYS_IOCTL_H
30 #  include <sys/ioctl.h>
31 #endif
32 #include <signal.h>
33 #include <termios.h>
34 
35 #define MIN_SCREEN_WIDTH 20
36 
37 int term_width, term_height;
38 
39 int term_use_colors;
40 int term_use_colors24;
41 int term_type;
42 
43 static int force_colors;
44 static int resize_dirty;
45 
term_get_size(int * width,int * height)46 int term_get_size(int *width, int *height)
47 {
48 #ifdef TIOCGWINSZ
49 	struct winsize ws;
50 
51 	/* Get new window size */
52 	if (ioctl(0, TIOCGWINSZ, &ws) < 0)
53 		return FALSE;
54 
55 	if (ws.ws_row == 0 && ws.ws_col == 0)
56 		return FALSE;
57 
58 	*width = ws.ws_col;
59         *height = ws.ws_row;
60 
61 	if (*width < MIN_SCREEN_WIDTH)
62 		*width = MIN_SCREEN_WIDTH;
63 	if (*height < 1)
64                 *height = 1;
65 	return TRUE;
66 #else
67         return FALSE;
68 #endif
69 }
70 
71 /* Resize the terminal if needed */
term_resize_dirty(void)72 void term_resize_dirty(void)
73 {
74         int width, height;
75 
76 	if (!resize_dirty)
77 		return;
78 
79         resize_dirty = FALSE;
80 
81 	if (!term_get_size(&width, &height))
82 		width = height = -1;
83 
84 	term_resize(width, height);
85 	mainwindows_resize(term_width, term_height);
86 	term_resize_final(width, height);
87 }
88 
89 #ifdef SIGWINCH
sig_winch(int p)90 static void sig_winch(int p)
91 {
92         irssi_set_dirty();
93         resize_dirty = TRUE;
94 }
95 #endif
96 
cmd_resize(void)97 static void cmd_resize(void)
98 {
99 	resize_dirty = TRUE;
100         term_resize_dirty();
101 }
102 
cmd_redraw(void)103 static void cmd_redraw(void)
104 {
105 	irssi_redraw();
106 }
107 
108 int term_color256map[] = {
109 	 0, 4, 2, 6, 1, 5, 3, 7, 8,12,10,14, 9,13,11,15,
110 	 0, 0, 1, 1, 1, 1, 0, 0, 3, 1, 1, 9, 2, 2, 3, 3, 3, 3,
111 	 2, 2, 3, 3, 3, 3, 2, 2, 3, 3, 3,11,10,10, 3, 3,11,11,
112 	 0, 0, 5, 1, 1, 9, 0, 8, 8, 8, 9, 9, 2, 8, 8, 8, 9, 9,
113 	 2, 8, 8, 8, 9, 9, 2, 8, 8, 3, 3,11,10,10, 3, 3,11,11,
114 	 4, 4, 5, 5, 5, 5, 4, 8, 8, 8, 9, 9, 6, 8, 8, 8, 9, 9,
115 	 6, 8, 8, 8, 8, 9, 6, 8, 8, 8, 7, 7, 6, 6, 8, 7, 7, 7,
116 	 4, 4, 5, 5, 5, 5, 4, 8, 8, 8, 9, 9, 6, 8, 8, 8, 8, 9,
117 	 6, 8, 8, 8, 7, 7, 6, 6, 8, 7, 7, 7, 6, 6, 7, 7, 7, 7,
118 	 4, 4, 5, 5, 5,13, 4, 8, 8, 5, 5,13, 6, 8, 8, 8, 7, 7,
119 	 6, 6, 8, 7, 7, 7, 6, 6, 7, 7, 7, 7,14,14, 7, 7, 7, 7,
120 	12,12, 5, 5,13,13,12,12, 5, 5,13,13, 6, 6, 8, 7, 7, 7,
121 	 6, 6, 7, 7, 7, 7,14,14, 7, 7, 7, 7,14,14, 7, 7, 7,15,
122 	 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
123 	 7, 7, 7, 7, 7, 7, 0 };
124 
read_settings(void)125 static void read_settings(void)
126 {
127         const char *str;
128 	int old_colors = term_use_colors;
129 	int old_colors24 = term_use_colors24;
130         int old_type = term_type;
131 
132         /* set terminal type */
133 	str = settings_get_str("term_charset");
134 	if (g_ascii_strcasecmp(str, "utf-8") == 0)
135 		term_type = TERM_TYPE_UTF8;
136 	else if (g_ascii_strcasecmp(str, "big5") == 0)
137 		term_type = TERM_TYPE_BIG5;
138 	else
139 		term_type = TERM_TYPE_8BIT;
140 
141 	if (old_type != term_type)
142                 term_set_input_type(term_type);
143 
144         /* change color stuff */
145 	if (force_colors != settings_get_bool("term_force_colors")) {
146 		force_colors = settings_get_bool("term_force_colors");
147 		term_force_colors(force_colors);
148 	}
149 
150 	term_use_colors = settings_get_bool("colors") &&
151 		(force_colors || term_has_colors());
152 
153 #ifdef TERM_TRUECOLOR
154 	term_use_colors24 = settings_get_bool("colors_ansi_24bit") &&
155 		(force_colors || term_has_colors());
156 #else
157 	term_use_colors24 = FALSE;
158 #endif
159 
160 	if (term_use_colors != old_colors || term_use_colors24 != old_colors24)
161 		irssi_redraw();
162 }
163 
term_common_init(void)164 void term_common_init(void)
165 {
166 	const char *dummy;
167 #ifdef SIGWINCH
168 	struct sigaction act;
169 #endif
170 	settings_add_bool("lookandfeel", "colors", TRUE);
171 	settings_add_bool("lookandfeel", "term_force_colors", FALSE);
172         settings_add_bool("lookandfeel", "mirc_blink_fix", FALSE);
173 
174 	force_colors = FALSE;
175 	term_use_colors = term_has_colors() && settings_get_bool("colors");
176 #ifdef TERM_TRUECOLOR
177 	settings_add_bool("lookandfeel", "colors_ansi_24bit", FALSE);
178 	term_use_colors24 = term_has_colors() && settings_get_bool("colors_ansi_24bit");
179 #else
180 	term_use_colors24 = FALSE;
181 #endif
182         read_settings();
183 
184 	if (g_get_charset(&dummy)) {
185 		term_type = TERM_TYPE_UTF8;
186 		term_set_input_type(TERM_TYPE_UTF8);
187 	}
188 
189 	signal_add("beep", (SIGNAL_FUNC) term_beep);
190 	signal_add("setup changed", (SIGNAL_FUNC) read_settings);
191 	command_bind("resize", NULL, (SIGNAL_FUNC) cmd_resize);
192 	command_bind("redraw", NULL, (SIGNAL_FUNC) cmd_redraw);
193 
194 #ifdef SIGWINCH
195 	sigemptyset (&act.sa_mask);
196 	act.sa_flags = 0;
197 	act.sa_handler = sig_winch;
198 	sigaction(SIGWINCH, &act, NULL);
199 #endif
200 }
201 
term_common_deinit(void)202 void term_common_deinit(void)
203 {
204 	command_unbind("resize", (SIGNAL_FUNC) cmd_resize);
205 	command_unbind("redraw", (SIGNAL_FUNC) cmd_redraw);
206 	signal_remove("beep", (SIGNAL_FUNC) term_beep);
207 	signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
208 }
209