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