New silcconfig library and server parser. Merged silc-newconfig-final.patch.
[crypto.git] / apps / irssi / src / fe-common / core / printtext.c
1 /*
2  printtext.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 "module-formats.h"
23 #include "modules.h"
24 #include "signals.h"
25 #include "commands.h"
26 #include "settings.h"
27
28 #include "levels.h"
29 #include "servers.h"
30
31 #include "themes.h"
32 #include "fe-windows.h"
33 #include "printtext.h"
34
35 static int beep_msg_level, beep_when_away, beep_when_window_active;
36
37 static int signal_gui_print_text_finished;
38 static int signal_print_starting;
39 static int signal_print_text;
40 static int signal_print_format;
41
42 static int sending_print_starting;
43
44 static void print_line(TEXT_DEST_REC *dest, const char *text);
45
46 void printformat_module_dest_args(const char *module, TEXT_DEST_REC *dest,
47                                   int formatnum, va_list va)
48 {
49         char *arglist[MAX_FORMAT_PARAMS];
50         char buffer[DEFAULT_FORMAT_ARGLIST_SIZE];
51         FORMAT_REC *formats;
52         THEME_REC *theme;
53         char *str;
54
55         theme = window_get_theme(dest->window);
56
57         formats = g_hash_table_lookup(default_formats, module);
58         format_read_arglist(va, &formats[formatnum],
59                             arglist, sizeof(arglist)/sizeof(char *),
60                             buffer, sizeof(buffer));
61
62         if (!sending_print_starting) {
63                 sending_print_starting = TRUE;
64                 signal_emit_id(signal_print_starting, 1, dest);
65                 sending_print_starting = FALSE;
66         }
67
68         signal_emit_id(signal_print_format, 5, theme, module,
69                        dest, GINT_TO_POINTER(formatnum), arglist);
70
71         str = format_get_text_theme_charargs(theme, module, dest,
72                                              formatnum, arglist);
73         if (*str != '\0') print_line(dest, str);
74         g_free(str);
75 }
76
77 void printformat_module_dest(const char *module, TEXT_DEST_REC *dest,
78                              int formatnum, ...)
79 {
80         va_list va;
81
82         va_start(va, formatnum);
83         printformat_module_dest_args(module, dest, formatnum, va);
84         va_end(va);
85 }
86
87 void printformat_module_args(const char *module, void *server,
88                              const char *target, int level,
89                              int formatnum, va_list va)
90 {
91         TEXT_DEST_REC dest;
92
93         format_create_dest(&dest, server, target, level, NULL);
94         printformat_module_dest_args(module, &dest, formatnum, va);
95 }
96
97 void printformat_module(const char *module, void *server, const char *target,
98                         int level, int formatnum, ...)
99 {
100         va_list va;
101
102         va_start(va, formatnum);
103         printformat_module_args(module, server, target, level, formatnum, va);
104         va_end(va);
105 }
106
107 void printformat_module_window_args(const char *module, WINDOW_REC *window,
108                                     int level, int formatnum, va_list va)
109 {
110         TEXT_DEST_REC dest;
111
112         format_create_dest(&dest, NULL, NULL, level, window);
113         printformat_module_dest_args(module, &dest, formatnum, va);
114 }
115
116 void printformat_module_window(const char *module, WINDOW_REC *window,
117                                int level, int formatnum, ...)
118 {
119         va_list va;
120
121         va_start(va, formatnum);
122         printformat_module_window_args(module, window, level, formatnum, va);
123         va_end(va);
124 }
125
126 void printformat_module_gui_args(const char *module, int formatnum, va_list va)
127 {
128         TEXT_DEST_REC dest;
129         char *arglist[MAX_FORMAT_PARAMS];
130         char buffer[DEFAULT_FORMAT_ARGLIST_SIZE];
131         FORMAT_REC *formats;
132         char *str;
133
134         g_return_if_fail(module != NULL);
135
136         memset(&dest, 0, sizeof(dest));
137
138         formats = g_hash_table_lookup(default_formats, module);
139         format_read_arglist(va, &formats[formatnum],
140                             arglist, sizeof(arglist)/sizeof(char *),
141                             buffer, sizeof(buffer));
142
143         str = format_get_text_theme_charargs(window_get_theme(dest.window),
144                                              module, &dest,
145                                              formatnum, arglist);
146         if (*str != '\0') format_send_to_gui(&dest, str);
147         g_free(str);
148 }
149
150 void printformat_module_gui(const char *module, int formatnum, ...)
151 {
152         va_list va;
153
154         va_start(va, formatnum);
155         printformat_module_gui_args(module, formatnum, va);
156         va_end(va);
157 }
158
159 static void print_line(TEXT_DEST_REC *dest, const char *text)
160 {
161         char *str, *tmp, *stripped;
162
163         g_return_if_fail(dest != NULL);
164         g_return_if_fail(text != NULL);
165
166         tmp = format_get_level_tag(window_get_theme(dest->window), dest);
167         str = format_add_linestart(text, tmp);
168         g_free_not_null(tmp);
169
170         /* send both the formatted + stripped (for logging etc.) */
171         stripped = strip_codes(str);
172         signal_emit_id(signal_print_text, 3, dest, str, stripped);
173         g_free_and_null(dest->hilight_color);
174
175         g_free(str);
176         g_free(stripped);
177 }
178
179 /* append string to `out', expand newlines. */
180 static void printtext_append_str(TEXT_DEST_REC *dest, GString *out,
181                                  const char *str)
182 {
183         while (*str != '\0') {
184                 if (*str != '\n')
185                         g_string_append_c(out, *str);
186                 else {
187                         print_line(dest, out->str);
188                         g_string_truncate(out, 0);
189                 }
190                 str++;
191         }
192 }
193
194 static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str,
195                                 va_list va)
196 {
197         GString *out;
198         char *ret;
199
200         out = g_string_new(NULL);
201         for (; *str != '\0'; str++) {
202                 if (*str != '%') {
203                         g_string_append_c(out, *str);
204                         continue;
205                 }
206
207                 if (*++str == '\0')
208                         break;
209
210                 /* standard parameters */
211                 switch (*str) {
212                 case 's': {
213                         char *s = (char *) va_arg(va, char *);
214                         if (s && *s) printtext_append_str(dest, out, s);
215                         break;
216                 }
217                 case 'd': {
218                         int d = (int) va_arg(va, int);
219                         g_string_sprintfa(out, "%d", d);
220                         break;
221                 }
222                 case 'f': {
223                         double f = (double) va_arg(va, double);
224                         g_string_sprintfa(out, "%0.2f", f);
225                         break;
226                 }
227                 case 'u': {
228                         unsigned int d =
229                                 (unsigned int) va_arg(va, unsigned int);
230                         g_string_sprintfa(out, "%u", d);
231                         break;
232                 }
233                 case 'l': {
234                         long d = (long) va_arg(va, long);
235
236                         if (*++str != 'd' && *str != 'u') {
237                                 g_string_sprintfa(out, "%ld", d);
238                                 str--;
239                         } else {
240                                 if (*str == 'd')
241                                         g_string_sprintfa(out, "%ld", d);
242                                 else
243                                         g_string_sprintfa(out, "%lu", d);
244                         }
245                         break;
246                 }
247                 default:
248                         if (!format_expand_styles(out, &str, &dest->flags)) {
249                                 g_string_append_c(out, '%');
250                                 g_string_append_c(out, *str);
251                         }
252                         break;
253                 }
254         }
255
256         ret = out->str;
257         g_string_free(out, FALSE);
258         return ret;
259 }
260
261 static char *printtext_expand_formats(const char *str, int *flags)
262 {
263         GString *out;
264         char *ret;
265
266         out = g_string_new(NULL);
267         for (; *str != '\0'; str++) {
268                 if (*str != '%') {
269                         g_string_append_c(out, *str);
270                         continue;
271                 }
272
273                 if (*++str == '\0')
274                         break;
275
276                 if (!format_expand_styles(out, &str, flags)) {
277                         g_string_append_c(out, '%');
278                         g_string_append_c(out, *str);
279                 }
280         }
281
282         ret = out->str;
283         g_string_free(out, FALSE);
284         return ret;
285 }
286
287 static void printtext_dest_args(TEXT_DEST_REC *dest, const char *text, va_list va)
288 {
289         char *str;
290
291         if (!sending_print_starting) {
292                 sending_print_starting = TRUE;
293                 signal_emit_id(signal_print_starting, 1, dest);
294                 sending_print_starting = FALSE;
295         }
296
297         str = printtext_get_args(dest, text, va);
298         print_line(dest, str);
299         g_free(str);
300 }
301
302 void printtext_dest(TEXT_DEST_REC *dest, const char *text, ...)
303 {
304         va_list va;
305
306         va_start(va, text);
307         printtext_dest_args(dest, text, va);
308         va_end(va);
309 }
310
311 /* Write text to target - convert color codes */
312 void printtext(void *server, const char *target, int level, const char *text, ...)
313 {
314         TEXT_DEST_REC dest;
315         va_list va;
316
317         g_return_if_fail(text != NULL);
318
319         format_create_dest(&dest, server, target, level, NULL);
320
321         va_start(va, text);
322         printtext_dest_args(&dest, text, va);
323         va_end(va);
324 }
325
326 /* Like printtext(), but don't handle %s etc. */
327 void printtext_string(void *server, const char *target, int level, const char *text)
328 {
329         TEXT_DEST_REC dest;
330         char *str;
331
332         g_return_if_fail(text != NULL);
333
334         format_create_dest(&dest, server, target, level, NULL);
335
336         if (!sending_print_starting) {
337                 sending_print_starting = TRUE;
338                 signal_emit_id(signal_print_starting, 1, dest);
339                 sending_print_starting = FALSE;
340         }
341
342         str = printtext_expand_formats(text, &dest.flags);
343         print_line(&dest, str);
344         g_free(str);
345 }
346
347 /* Like printtext_window(), but don't handle %s etc. */
348 void printtext_string_window(WINDOW_REC *window, int level, const char *text)
349 {
350         TEXT_DEST_REC dest;
351         char *str;
352
353         g_return_if_fail(text != NULL);
354
355         format_create_dest(&dest, NULL, NULL, level,
356                            window != NULL ? window : active_win);
357
358         if (!sending_print_starting) {
359                 sending_print_starting = TRUE;
360                 signal_emit_id(signal_print_starting, 1, dest);
361                 sending_print_starting = FALSE;
362         }
363
364         str = printtext_expand_formats(text, &dest.flags);
365         print_line(&dest, str);
366         g_free(str);
367 }
368
369 void printtext_window(WINDOW_REC *window, int level, const char *text, ...)
370 {
371         TEXT_DEST_REC dest;
372         va_list va;
373
374         g_return_if_fail(text != NULL);
375
376         format_create_dest(&dest, NULL, NULL, level,
377                            window != NULL ? window : active_win);
378
379         va_start(va, text);
380         printtext_dest_args(&dest, text, va);
381         va_end(va);
382 }
383
384 void printtext_gui(const char *text)
385 {
386         TEXT_DEST_REC dest;
387         char *str;
388
389         g_return_if_fail(text != NULL);
390
391         memset(&dest, 0, sizeof(dest));
392
393         str = printtext_expand_formats(text, &dest.flags);
394         format_send_to_gui(&dest, str);
395         g_free(str);
396 }
397
398 static void msg_beep_check(TEXT_DEST_REC *dest)
399 {
400         if (dest->level != 0 && (dest->level & MSGLEVEL_NO_ACT) == 0 &&
401             (beep_msg_level & dest->level) &&
402             (beep_when_away || (dest->server != NULL &&
403                                 !dest->server->usermode_away)) &&
404             (beep_when_window_active || dest->window != active_win)) {
405                 signal_emit("beep", 0);
406         }
407 }
408
409 static void sig_print_text(TEXT_DEST_REC *dest, const char *text)
410 {
411         char *str, *tmp;
412
413         g_return_if_fail(dest != NULL);
414         g_return_if_fail(dest->window != NULL);
415         g_return_if_fail(text != NULL);
416
417         msg_beep_check(dest);
418
419         dest->window->last_line = time(NULL);
420
421         /* add timestamp/server tag here - if it's done in print_line()
422            it would be written to log files too */
423         tmp = format_get_line_start(window_get_theme(dest->window),
424                                     dest, time(NULL));
425         str = format_add_linestart(text, tmp);
426         g_free_not_null(tmp);
427
428         format_send_to_gui(dest, str);
429         g_free(str);
430
431         signal_emit_id(signal_gui_print_text_finished, 1, dest->window);
432 }
433
434 void printtext_multiline(void *server, const char *target, int level,
435                          const char *format, const char *text)
436 {
437         char **lines, **tmp;
438
439         g_return_if_fail(format != NULL);
440         g_return_if_fail(text != NULL);
441
442         lines = g_strsplit(text, "\n", -1);
443         for (tmp = lines; *tmp != NULL; tmp++)
444                 printtext(NULL, NULL, level, format, *tmp);
445         g_strfreev(lines);
446 }
447
448 static void sig_gui_dialog(const char *type, const char *text)
449 {
450         char *format;
451
452         if (g_strcasecmp(type, "warning") == 0)
453                 format = "%_Warning:%_ %s";
454         else if (g_strcasecmp(type, "error") == 0)
455                 format = "%_Error:%_ %s";
456         else
457                 format = "%s";
458
459         printtext_multiline(NULL, NULL, MSGLEVEL_NEVER, format, text);
460 }
461
462 static void read_settings(void)
463 {
464         beep_msg_level = level2bits(settings_get_str("beep_msg_level"));
465         beep_when_away = settings_get_bool("beep_when_away");
466         beep_when_window_active = settings_get_bool("beep_when_window_active");
467 }
468
469 void printtext_init(void)
470 {
471         sending_print_starting = FALSE;
472         signal_gui_print_text_finished = signal_get_uniq_id("gui print text finished");
473         signal_print_starting = signal_get_uniq_id("print starting");
474         signal_print_text = signal_get_uniq_id("print text");
475         signal_print_format = signal_get_uniq_id("print format");
476
477         read_settings();
478         signal_add("print text", (SIGNAL_FUNC) sig_print_text);
479         signal_add("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
480         signal_add("setup changed", (SIGNAL_FUNC) read_settings);
481 }
482
483 void printtext_deinit(void)
484 {
485         signal_remove("print text", (SIGNAL_FUNC) sig_print_text);
486         signal_remove("gui dialog", (SIGNAL_FUNC) sig_gui_dialog);
487         signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
488 }