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