1 /* curs_term.c
2 *
3 * copyright (c) 2000-2003 SeaD
4 * see GPL for copying info
5 *
6 */
7
8 #include <string.h>
9 #include <curses.h>
10 #include "echat.h"
11 #include "curs_term.h"
12
13 #ifdef DEBUG
14 # include <errno.h>
15 #endif /* DEBUG */
16
17 WINDOW *room_win = NULL;
18 WINDOW *users_win = NULL;
19 WINDOW *input_win = NULL;
20 WINDOW *stat_win = NULL;
21 WINDOW *text_win = NULL;
22 WINDOW *read_win = NULL;
23
24 char *string = NULL;
25
term_init(void)26 void term_init(void) {
27 if ((string = (char *) malloc(STR_SIZE+2)) == NULL) {
28 #ifdef DEBUG
29 fprintf(debug_file, "malloc(): %s\n", strerror(errno));
30 #endif /* DEBUG */
31 exit(EXIT_FAILURE);
32 }
33 status->strn = status->strn_end = status->strn_cur = 0;
34 *string = *buf = '\0';
35 if (!*config->ps) {
36 strncpy(status->ps, config->nick, NICK_MAXLEN);
37 strncat(status->ps, ": ", STR_SIZE);
38 *config->head_nick = '\0';
39 } else {
40 strncpy(status->ps, config->ps, STR_SIZE);
41 if (!*config->head_nick) *config->head_nick = ' ';
42 }
43 if (!*config->head_top) *config->head_top = ' ';
44 if (!*config->head_users) *config->head_users = ' ';
45 config->head_users[config->users_width-3] = '\0';
46 status->percent = 100;
47 initscr();
48 curs_set(1); cbreak(); noecho(); nl();
49 start_color();
50 init_pair(COL_BORDER, config->color_border, config->color_bkgr);
51 init_pair(COL_HEAD, config->color_head, config->color_bkgr);
52 init_pair(COL_STATUS, config->color_status, config->color_bkgr);
53 init_pair(COL_SYSTEM, config->color_system, config->color_bkgr);
54 init_pair(COL_ERROR, config->color_error, config->color_bkgr);
55 init_pair(COL_MESG, config->color_mesg, config->color_bkgr);
56 init_pair(COL_MY, config->color_my, config->color_bkgr);
57 init_pair(COL_CHAT, config->color_chat, config->color_bkgr);
58 #ifdef DEBUG
59 fprintf(debug_file, "ncurses: Initialization complete.\n");
60 fflush(debug_file);
61 #endif /* DEBUG */
62 }
63
term_kill(void)64 void term_kill(void) {
65 status_ok(TERM_SQUIT);
66 endwin();
67 free(string);
68 #ifdef DEBUG
69 fprintf(debug_file, "ncurses: Shutdown complete.\n");
70 fflush(debug_file);
71 #endif /* DEBUG */
72 }
73
window_init(void)74 void window_init(void) {
75 if (config->style) {
76 if ((room_win = newwin(LINES-4, COLS-(config->users_width+2), 0, 0)) == NULL) {
77 #ifdef DEBUG
78 fprintf(debug_file, "ncurses: room_win = newwin(): %s.\n", strerror(errno));
79 #endif /* DEBUG */
80 exit(EXIT_FAILURE);
81 }
82 } else {
83 if ((room_win = newwin((config->status_str ? LINES-3 : LINES-2), COLS-config->users_width, 0, 0)) == NULL) {
84 #ifdef DEBUG
85 fprintf(debug_file, "ncurses: room_win = newwin(): %s.\n", strerror(errno));
86 #endif /* DEBUG */
87 exit(EXIT_FAILURE);
88 }
89 }
90
91 if (config->style) {
92 if ((input_win = newwin(3, COLS, LINES-4, 0)) == NULL) {
93 #ifdef DEBUG
94 fprintf(debug_file, "ncurses: input_win = newwin(): %s.\n", strerror(errno));
95 #endif /* DEBUG */
96 exit(EXIT_FAILURE);
97 }
98 } else {
99 if ((input_win = newwin(2, COLS, (config->status_str ? LINES-3 : LINES-2), 0)) == NULL) {
100 #ifdef DEBUG
101 fprintf(debug_file, "ncurses: input_win = newwin(): %s.\n", strerror(errno));
102 #endif /* DEBUG */
103 exit(EXIT_FAILURE);
104 }
105 }
106
107 if ((config->users_width < 10) || (config->users_width > 22)) config->users_width = 12;
108 if (config->style) {
109 if ((users_win = newwin(LINES-4, config->users_width+2, 0, COLS-(config->users_width+2))) == NULL) {
110 #ifdef DEBUG
111 fprintf(debug_file, "ncurses: users_win = newwin(): %s.\n", strerror(errno));
112 #endif /* DEBUG */
113 exit(EXIT_FAILURE);
114 }
115 } else {
116 if ((users_win = newwin((config->status_str ? LINES-3 : LINES-2), config->users_width, 0, COLS-config->users_width)) == NULL) {
117 #ifdef DEBUG
118 fprintf(debug_file, "ncurses: users_win = newwin(): %s.\n", strerror(errno));
119 #endif /* DEBUG */
120 exit(EXIT_FAILURE);
121 }
122 }
123
124 if (config->style) {
125 if ((text_win = subwin(room_win, LINES-6, COLS-(config->users_width+4), 1, 1)) == NULL) {
126 #ifdef DEBUG
127 fprintf(debug_file, "ncurses: text_win = subwin(room_win): %s.\n", strerror(errno));
128 #endif /* DEBUG */
129 exit(EXIT_FAILURE);
130 }
131 if ((status->scrn_width = COLS - (config->users_width+4)) > LINE_SIZE)
132 status->scrn_width = LINE_SIZE;
133 wsetscrreg(text_win, 0, LINES-5);
134 } else {
135 if ((text_win = subwin(room_win, (config->status_str ? LINES-4 : LINES-3), COLS-(config->users_width+1), 1, 0)) == NULL) {
136 #ifdef DEBUG
137 fprintf(debug_file, "ncurses: text_win = subwin(room_win): %s.\n", strerror(errno));
138 #endif /* DEBUG */
139 exit(EXIT_FAILURE);
140 }
141 if ((status->scrn_width = COLS - config->users_width) > LINE_SIZE)
142 status->scrn_width = LINE_SIZE;
143 wsetscrreg(text_win, 0, (config->status_str ? LINES-5 : LINES-4));
144 }
145 wbkgdset(text_win, ' ' | COLOR_PAIR(COL_BORDER));
146 wattrset(text_win, COLOR_PAIR(COL_SYSTEM) | A_BOLD);
147 werase(text_win);
148 leaveok(text_win, TRUE);
149 scrollok(text_win, TRUE);
150
151 if (config->style) {
152 if ((read_win = subwin(input_win, 1, status->strn_width=COLS-(strlen(status->ps)+3), LINES-3, strlen(status->ps)+2)) == NULL) {
153 #ifdef DEBUG
154 fprintf(debug_file, "ncurses: read_win = subwin(input_win): %s.\n", strerror(errno));
155 #endif /* DEBUG */
156 exit(EXIT_FAILURE);
157 }
158 } else {
159 if ((read_win = subwin(input_win, 1, status->strn_width=COLS-strlen(status->ps), (config->status_str ? LINES-2 : LINES-1), strlen(status->ps))) == NULL) {
160 #ifdef DEBUG
161 fprintf(debug_file, "ncurses: read_win = subwin(input_win): %s.\n", strerror(errno));
162 #endif /* DEBUG */
163 exit(EXIT_FAILURE);
164 }
165 }
166 keypad(read_win, TRUE);
167 leaveok(read_win, FALSE);
168 scrollok(read_win, TRUE);
169 wtimeout(read_win, READ_TIMEOUT);
170 wbkgdset(read_win, ' ' | COLOR_PAIR(COL_MY));
171 wattrset(read_win, COLOR_PAIR(COL_MY) | A_BOLD);
172 werase(read_win);
173
174 if (config->style || config->status_str) {
175 if ((stat_win = newwin(1, COLS, LINES-1, 0)) == NULL) {
176 #ifdef DEBUG
177 fprintf(debug_file, "ncurses: stat_win = newwin(): %s.\n", strerror(errno));
178 #endif /* DEBUG */
179 exit(EXIT_FAILURE);
180 }
181 snprintf(message, STR_SIZE, "%s v%s.", NAME, VERSION);
182 status_ok(message);
183 }
184 }
185
refresh_users(void)186 void refresh_users(void) {
187 register int n;
188
189 wbkgdset(users_win, ' ' | COLOR_PAIR(COL_BORDER));
190 werase(users_win);
191 wattrset(users_win, COLOR_PAIR(COL_BORDER));
192 if (config->style) {
193 if (config->ascii) wborder(users_win, '|', '|', '-', '-', '+', '+', '+', '+');
194 else wborder(users_win, 0, 0, 0, 0, 0, 0, 0, 0);
195 wmove(users_win, 0, 2);
196 } else {
197 if (config->ascii) wborder(users_win, ' ', ' ', '-', ' ', '-', '-', ' ', ' ');
198 else wborder(users_win, ' ', ' ', ACS_HLINE, ' ', ACS_HLINE, ACS_HLINE, ' ', ' ');
199 wmove(users_win, 0, 0);
200 }
201 wprintw(users_win, config->head_users);
202 if (status->users < 2) wattrset(users_win, COLOR_PAIR(COL_HEAD));
203 else wattrset(users_win, COLOR_PAIR(COL_HEAD) | A_BOLD);
204 wprintw(users_win, "%d ", status->users);
205 for (n = 0; (n < (config->status_str ? LINES-4 : LINES-3)) && (n < status->users); n++) {
206 wmove(users_win, (config->style ? n+2 : n+1), (config->style ? 1 : 0));
207 if (status->user[n].active) wattrset(users_win, COLOR_PAIR(COL_SYSTEM) | A_BOLD);
208 else wattrset(users_win, COLOR_PAIR(COL_SYSTEM));
209 if (status->user[n].ignore)
210 wattrset(users_win, COLOR_PAIR(COL_ERROR) | A_BOLD);
211 if (status->user[n].mode == MOD_NORMAL) waddch(users_win, CHR_NORMAL);
212 if (status->user[n].mode == MOD_DND) waddch(users_win, CHR_DND);
213 if (status->user[n].mode == MOD_AWAY) waddch(users_win, CHR_AWAY);
214 if (status->user[n].mode == MOD_OFF) waddch(users_win, CHR_OFF);
215 wattrset(users_win, COLOR_PAIR(COL_CHAT) | A_BOLD);
216 if (strlen(status->user[n].nick) < config->users_width) {
217 wmove(users_win, (config->style ? n+2 : n+1), (config->style ? 2 : 1));
218 waddnstr(users_win, status->user[n].nick, config->users_width);
219 } else {
220 wmove(users_win, (config->style ? n+2 : n+1), (config->style ? 2 : 1));
221 waddnstr(users_win, status->user[n].nick, config->users_width-2);
222 wattrset(users_win, COLOR_PAIR(COL_SYSTEM) | A_BOLD);
223 waddch(users_win, CHR_BIGNICK);
224 wattrset(users_win, COLOR_PAIR(COL_CHAT) | A_BOLD);
225 }
226 }
227 wrefresh(users_win);
228 }
229
refresh_room(void)230 void refresh_room(void) {
231 int topmove, toplen;
232
233 wattrset(room_win, COLOR_PAIR(COL_BORDER));
234 if (config->style) {
235 if (config->ascii) wborder(room_win, '|', '|', '-', '-', '+', '+', '+', '+');
236 else wborder(room_win, 0, 0, 0, 0, 0, 0, 0, 0);
237 } else {
238 if (config->ascii) wborder(room_win, ' ', '|', '-', ' ', '-', '-', ' ', '|');
239 else wborder(room_win, ' ', ACS_VLINE, ACS_HLINE, ' ', ACS_HLINE, ACS_HLINE, ' ', ACS_VLINE);
240 }
241 wmove(room_win, 0, 2);
242 wprintw(room_win, config->head_nick);
243 if (config->mode == MOD_NORMAL) wattrset(room_win, COLOR_PAIR(COL_HEAD) | A_BOLD);
244 else wattrset(room_win, COLOR_PAIR(COL_HEAD));
245 if (*config->head_nick) {
246 waddnstr(room_win, config->nick, NICK_LEN);
247 waddch(room_win, ' ');
248 }
249 if (*status->room->name == CHR_CHNL) {
250 if (*config->head_nick) {
251 if ((topmove = strlen(config->nick)) > NICK_LEN) topmove = NICK_LEN;
252 topmove += (strlen(config->head_nick) + 4);
253 } else topmove = 2;
254 toplen = COLS - (config->users_width + strlen(config->head_top) +
255 topmove + (config->style ? 5 : 2));
256 wmove(room_win, 0, topmove);
257 wattrset(room_win, COLOR_PAIR(COL_HEAD));
258 wprintw(room_win, config->head_top);
259 wattrset(room_win, COLOR_PAIR(COL_HEAD) | A_BOLD);
260 if (config->packet_qchat)
261 waddnstr(room_win, status->chnl[0].topic, toplen);
262 else
263 waddnstr(room_win, status->room->topic, toplen);
264 waddch(room_win, ' ');
265 }
266 wrefresh(room_win);
267 }
268
refresh_text(void)269 void refresh_text(void) {
270 touchwin(room_win);
271 wrefresh(text_win);
272 }
273
refresh_input(void)274 void refresh_input(void) {
275 register int n;
276
277 wbkgdset(input_win, ' ' | COLOR_PAIR(COL_BORDER));
278 werase(input_win);
279 wattrset(input_win, COLOR_PAIR(COL_BORDER));
280 if (config->style) {
281 if (config->ascii) wborder(input_win, '|', '|', '-', '-', '+', '+', '+', '+');
282 else wborder(input_win, 0, 0, 0, 0, 0, 0, 0, 0);
283 } else {
284 if (config->ascii) wborder(input_win, ' ', ' ', '-', ' ', '-', '-', ' ', ' ');
285 else wborder(input_win, ' ', ' ', ACS_HLINE, ' ', ACS_HLINE, ACS_HLINE, ' ', ' ');
286 }
287 wmove(input_win, 0, 2);
288 for (n = 0; n < status->channels; n++) {
289 waddch(input_win, ' ');
290 if (n) {
291 wattrset(input_win, COLOR_PAIR(COL_HEAD));
292 waddch(input_win, ACS_HLINE);
293 waddch(input_win, ' ');
294 }
295 if (!strncmp(status->chnl[n].name, status->room->name, CHANNEL_MAXLEN)) {
296 wattrset(input_win, COLOR_PAIR(COL_HEAD) | A_BOLD);
297 waddnstr(input_win, status->chnl[n].name, CHANNEL_MAXLEN);
298 } else {
299 wattrset(input_win, COLOR_PAIR(COL_HEAD));
300 waddnstr(input_win, status->chnl[n].name, 8);
301 }
302 }
303 waddch(input_win, ' ');
304 wattrset(input_win, COLOR_PAIR(COL_MY) | A_BOLD);
305 wmove(input_win, 1, (config->style ? 2 : 0));
306 waddnstr(input_win, status->ps, STR_SIZE);
307 wrefresh(input_win);
308 }
309
refresh_read(void)310 void refresh_read(void) {
311 touchwin(input_win);
312 wrefresh(read_win);
313 }
314
window_refresh(void)315 void window_refresh(void) {
316 refresh_users();
317 refresh_room();
318 screen_show();
319 refresh_input();
320 string_show();
321 }
322
status_ok(char * str)323 void status_ok(char *str) {
324 if (!config->verbose || (!config->style && !config->status_str)) return;
325 wbkgdset(stat_win, ' ' | COLOR_PAIR(COL_STATUS));
326 werase(stat_win);
327 wattrset(stat_win, COLOR_PAIR(COL_STATUS));
328 wmove(stat_win, 0, 0);
329 waddnstr(stat_win, str, STR_SIZE);
330 wrefresh(stat_win);
331 refresh_read();
332 }
333
status_error(char * str)334 void status_error(char *str) {
335 if (!config->style && !config->status_str) return;
336 wbkgdset(stat_win, ' ' | COLOR_PAIR(COL_ERROR));
337 werase(stat_win);
338 wattrset(stat_win, COLOR_PAIR(COL_ERROR) | A_BOLD);
339 wmove(stat_win, 0, 0);
340 waddnstr(stat_win, str, STR_SIZE);
341 wrefresh(stat_win);
342 refresh_read();
343 }
344
beep_system(void)345 void beep_system(void) {
346 #ifdef LINUX
347 if (config->beep_system) {
348 fprintf(stdout, "%s%s%u%s%s%s%u%s\a",
349 ESC, SND_TONE, SND_SYST_TONE, SND_END, ESC, SND_DUR, SND_SYST_DUR, SND_END);
350 fflush(stdout);
351 }
352 #endif /* LINUX */
353 #ifdef DEBUG
354 fprintf(debug_file, "ncurses: beep(system)\n");
355 fflush(debug_file);
356 #endif /* DEBUG */
357 }
358
beep_chat(void)359 void beep_chat(void) {
360 #ifdef LINUX
361 if (config->beep_chat) {
362 fprintf(stdout, "%s%s%u%s%s%s%u%s\a",
363 ESC, SND_TONE, SND_CHAT_TONE, SND_END, ESC, SND_DUR, SND_CHAT_DUR, SND_END);
364 fflush(stdout);
365 }
366 #endif /* LINUX */
367 #ifdef DEBUG
368 fprintf(debug_file, "ncurses: beep(chat)\n");
369 fflush(debug_file);
370 #endif /* DEBUG */
371 }
372
beep_join(void)373 void beep_join(void) {
374 #ifdef LINUX
375 if (config->beep_join) {
376 fprintf(stdout, "%s%s%u%s%s%s%u%s\a",
377 ESC, SND_TONE, SND_JOIN_TONE, SND_END, ESC, SND_DUR, SND_JOIN_DUR, SND_END);
378 fflush(stdout);
379 }
380 #endif /* LINUX */
381 #ifdef DEBUG
382 fprintf(debug_file, "ncurses: beep(join)\n");
383 fflush(debug_file);
384 #endif /* DEBUG */
385 }
386
beep_mesg(void)387 void beep_mesg(void) {
388 if (config->beep_mesg) {
389 #ifdef LINUX
390 fprintf(stdout, "%s%s%u%s%s%s%u%s\a",
391 ESC, SND_TONE, SND_MESG_TONE, SND_END, ESC, SND_DUR, SND_MESG_DUR, SND_END);
392 fflush(stdout);
393 #endif /* LINUX */
394 #ifdef FREEBSD
395 fprintf(stdout, "\a");
396 fflush(stdout);
397 #endif /* FREEBSD */
398 }
399 #ifdef DEBUG
400 fprintf(debug_file, "ncurses: beep(mesg)\n");
401 fflush(debug_file);
402 #endif /* DEBUG */
403 }
404
beep_beep(void)405 void beep_beep(void) {
406 if (config->beep_beep) {
407 #ifdef LINUX
408 fprintf(stdout, "%s%s%u%s%s%s%u%s\a",
409 ESC, SND_TONE, SND_BEEP_TONE, SND_END, ESC, SND_DUR, SND_BEEP_DUR, SND_END);
410 fflush(stdout);
411 #endif /* LINUX */
412 #ifdef FREEBSD
413 fprintf(stdout, "\a");
414 fflush(stdout);
415 #endif /* FREEBSD */
416 }
417 #ifdef DEBUG
418 fprintf(debug_file, "ncurses: beep(beep)\n");
419 fflush(debug_file);
420 #endif /* DEBUG */
421 }
422