Merge Irssi 0.8.16-rc1
[silc.git] / apps / irssi / src / fe-common / core / fe-common-core.c
1 /*
2  fe-common-core.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 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 "module-formats.h"
23 #include "args.h"
24 #include "misc.h"
25 #include "levels.h"
26 #include "settings.h"
27
28 #include "servers.h"
29 #include "channels.h"
30 #include "servers-setup.h"
31
32 #include "special-vars.h"
33 #include "fe-core-commands.h"
34 #include "fe-queries.h"
35 #include "hilight-text.h"
36 #include "command-history.h"
37 #include "completion.h"
38 #include "keyboard.h"
39 #include "printtext.h"
40 #include "formats.h"
41 #include "themes.h"
42 #include "fe-channels.h"
43 #include "fe-windows.h"
44 #include "window-activity.h"
45 #include "window-items.h"
46 #include "windows-layout.h"
47 #include "fe-recode.h"
48
49 #include <signal.h>
50
51 static char *autocon_server;
52 static char *autocon_password;
53 static int autocon_port;
54 static int no_autoconnect;
55 static char *cmdline_nick;
56 static char *cmdline_hostname;
57
58 void fe_core_log_init(void);
59 void fe_core_log_deinit(void);
60
61 void fe_exec_init(void);
62 void fe_exec_deinit(void);
63
64 void fe_expandos_init(void);
65 void fe_expandos_deinit(void);
66
67 void fe_help_init(void);
68 void fe_help_deinit(void);
69
70 void fe_ignore_init(void);
71 void fe_ignore_deinit(void);
72
73 void fe_ignore_messages_init(void);
74 void fe_ignore_messages_deinit(void);
75
76 void fe_log_init(void);
77 void fe_log_deinit(void);
78
79 void fe_messages_init(void);
80 void fe_messages_deinit(void);
81
82 void fe_modules_init(void);
83 void fe_modules_deinit(void);
84
85 void fe_server_init(void);
86 void fe_server_deinit(void);
87
88 void fe_settings_init(void);
89 void fe_settings_deinit(void);
90
91 void window_commands_init(void);
92 void window_commands_deinit(void);
93
94 static void sig_setup_changed(void);
95
96 static void sig_connected(SERVER_REC *server)
97 {
98         MODULE_DATA_SET(server, g_new0(MODULE_SERVER_REC, 1));
99 }
100
101 static void sig_disconnected(SERVER_REC *server)
102 {
103         void *data = MODULE_DATA(server);
104         g_free(data);
105         MODULE_DATA_UNSET(server);
106 }
107
108 static void sig_channel_created(CHANNEL_REC *channel)
109 {
110         MODULE_DATA_SET(channel, g_new0(MODULE_CHANNEL_REC, 1));
111 }
112
113 static void sig_channel_destroyed(CHANNEL_REC *channel)
114 {
115         void *data = MODULE_DATA(channel);
116
117         g_free(data);
118         MODULE_DATA_UNSET(channel);
119 }
120
121 void fe_common_core_register_options(void)
122 {
123         static GOptionEntry options[] = {
124                 { "connect", 'c', 0, G_OPTION_ARG_STRING, &autocon_server, "Automatically connect to server/network", "SERVER" },
125                 { "password", 'w', 0, G_OPTION_ARG_STRING, &autocon_password, "Autoconnect password", "PASSWORD" },
126                 { "port", 'p', 0, G_OPTION_ARG_INT, &autocon_port, "Autoconnect port", "PORT" },
127                 { "noconnect", '!', 0, G_OPTION_ARG_NONE, &no_autoconnect, "Disable autoconnecting", NULL },
128                 { "nick", 'n', 0, G_OPTION_ARG_STRING, &cmdline_nick, "Specify nick to use", NULL },
129                 { "hostname", 'h', 0, G_OPTION_ARG_STRING, &cmdline_hostname, "Specify host name to use", NULL },
130                 { NULL }
131         };
132
133         autocon_server = NULL;
134         autocon_password = NULL;
135         autocon_port = 0;
136         no_autoconnect = FALSE;
137         cmdline_nick = NULL;
138         cmdline_hostname = NULL;
139         args_register(options);
140 }
141
142 void fe_common_core_init(void)
143 {
144         const char *str;
145
146         settings_add_bool("lookandfeel", "timestamps", TRUE);
147         settings_add_level("lookandfeel", "timestamp_level", "ALL");
148         settings_add_time("lookandfeel", "timestamp_timeout", "0");
149
150         settings_add_bool("lookandfeel", "bell_beeps", FALSE);
151         settings_add_level("lookandfeel", "beep_msg_level", "");
152         settings_add_bool("lookandfeel", "beep_when_window_active", TRUE);
153         settings_add_bool("lookandfeel", "beep_when_away", TRUE);
154
155         settings_add_bool("lookandfeel", "hide_text_style", FALSE);
156         settings_add_bool("lookandfeel", "hide_colors", FALSE);
157         settings_add_bool("lookandfeel", "hide_server_tags", FALSE);
158
159         settings_add_bool("lookandfeel", "use_status_window", TRUE);
160         settings_add_bool("lookandfeel", "use_msgs_window", FALSE);
161         g_get_charset(&str);
162         settings_add_str("lookandfeel", "term_charset", str);
163         themes_init();
164         theme_register(fecommon_core_formats);
165
166         command_history_init();
167         completion_init();
168         keyboard_init();
169         printtext_init();
170         formats_init();
171 #ifndef WIN32
172         fe_exec_init();
173 #endif
174         fe_expandos_init();
175         fe_help_init();
176         fe_ignore_init();
177         fe_log_init();
178         fe_modules_init();
179         fe_server_init();
180         fe_settings_init();
181         windows_init();
182         window_activity_init();
183         window_commands_init();
184         window_items_init();
185         windows_layout_init();
186         fe_core_commands_init();
187
188         fe_channels_init();
189         fe_queries_init();
190
191         fe_messages_init();
192         hilight_text_init();
193         fe_ignore_messages_init();
194         fe_recode_init();
195
196         settings_check();
197
198         signal_add_first("server connected", (SIGNAL_FUNC) sig_connected);
199         signal_add_last("server disconnected", (SIGNAL_FUNC) sig_disconnected);
200         signal_add_first("channel created", (SIGNAL_FUNC) sig_channel_created);
201         signal_add_last("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
202
203         module_register("core", "fe");
204 }
205
206 void fe_common_core_deinit(void)
207 {
208         hilight_text_deinit();
209         command_history_deinit();
210         completion_deinit();
211         keyboard_deinit();
212         printtext_deinit();
213         formats_deinit();
214 #ifndef WIN32
215         fe_exec_deinit();
216 #endif
217         fe_expandos_deinit();
218         fe_help_deinit();
219         fe_ignore_deinit();
220         fe_log_deinit();
221         fe_modules_deinit();
222         fe_server_deinit();
223         fe_settings_deinit();
224         windows_deinit();
225         window_activity_deinit();
226         window_commands_deinit();
227         window_items_deinit();
228         windows_layout_deinit();
229         fe_core_commands_deinit();
230
231         fe_channels_deinit();
232         fe_queries_deinit();
233
234         fe_messages_deinit();
235         fe_ignore_messages_deinit();
236         fe_recode_deinit();
237
238         theme_unregister();
239         themes_deinit();
240
241         signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed);
242         signal_remove("server connected", (SIGNAL_FUNC) sig_connected);
243         signal_remove("server disconnected", (SIGNAL_FUNC) sig_disconnected);
244         signal_remove("channel created", (SIGNAL_FUNC) sig_channel_created);
245         signal_remove("channel destroyed", (SIGNAL_FUNC) sig_channel_destroyed);
246 }
247
248 void glog_func(const char *log_domain, GLogLevelFlags log_level,
249                const char *message)
250 {
251         const char *reason;
252
253         switch (log_level) {
254         case G_LOG_LEVEL_WARNING:
255                 reason = "warning";
256                 break;
257         case G_LOG_LEVEL_CRITICAL:
258                 reason = "critical";
259                 break;
260         default:
261                 reason = "error";
262                 break;
263         }
264
265         if (windows == NULL)
266                 fprintf(stderr, "GLib %s: %s\n", reason, message);
267         else {
268                 printformat(NULL, NULL, MSGLEVEL_CLIENTERROR,
269                             TXT_GLIB_ERROR, reason, message);
270         }
271 }
272
273 #define MSGS_WINDOW_LEVELS (MSGLEVEL_MSGS|MSGLEVEL_ACTIONS|MSGLEVEL_DCCMSGS)
274
275 static void create_windows(void)
276 {
277         WINDOW_REC *window;
278         int have_status = settings_get_bool("use_status_window");
279
280         window = window_find_name("(status)");
281         if (have_status) {
282                 if (window == NULL) {
283                         window = window_create(NULL, TRUE);
284                         window_set_refnum(window, 1);
285                         window_set_name(window, "(status)");
286                         window_set_level(window, MSGLEVEL_ALL ^
287                                          (settings_get_bool("use_msgs_window") ?
288                                           MSGS_WINDOW_LEVELS : 0));
289                         window_set_immortal(window, TRUE);
290                 }
291         } else {
292                 if (window != NULL) {
293                         window_set_name(window, NULL);
294                         window_set_level(window, 0);
295                         window_set_immortal(window, FALSE);
296                 }
297         }
298
299         window = window_find_name("(msgs)");
300         if (settings_get_bool("use_msgs_window")) {
301                 if (window == NULL) {
302                         window = window_create(NULL, TRUE);
303                         window_set_refnum(window, have_status ? 2 : 1);
304                         window_set_name(window, "(msgs)");
305                         window_set_level(window, MSGS_WINDOW_LEVELS);
306                         window_set_immortal(window, TRUE);
307                 }
308         } else {
309                 if (window != NULL) {
310                         window_set_name(window, NULL);
311                         window_set_level(window, 0);
312                         window_set_immortal(window, FALSE);
313                 }
314         }
315
316         if (windows == NULL) {
317                 /* we have to have at least one window.. */
318                 window = window_create(NULL, TRUE);
319         }
320 }
321
322 static void autoconnect_servers(void)
323 {
324         GSList *tmp, *chatnets;
325         char *str;
326
327         if (autocon_server != NULL) {
328                 /* connect to specified server */
329                 str = g_strdup_printf(autocon_password == NULL ? "%s %d" : "%s %d %s",
330                                       autocon_server, autocon_port, autocon_password);
331                 signal_emit("command connect", 1, str);
332                 g_free(str);
333                 return;
334         }
335
336         if (no_autoconnect) {
337                 /* don't autoconnect */
338                 return;
339         }
340
341         /* connect to autoconnect servers */
342         chatnets = NULL;
343         for (tmp = setupservers; tmp != NULL; tmp = tmp->next) {
344                 SERVER_SETUP_REC *rec = tmp->data;
345
346                 if (rec->autoconnect &&
347                     (rec->chatnet == NULL ||
348                      gslist_find_icase_string(chatnets, rec->chatnet) == NULL)) {
349                         if (rec->chatnet != NULL) {
350                                 chatnets = g_slist_append(chatnets, rec->chatnet);
351                                 str = g_strdup_printf("-network %s %s %d", rec->chatnet, rec->address, rec->port);
352                         } else {
353                                 str = g_strdup_printf("%s %d", rec->address, rec->port);
354                         }
355
356                         signal_emit("command connect", 1, str);
357                         g_free(str);
358                 }
359         }
360
361         g_slist_free(chatnets);
362 }
363
364 static void sig_setup_changed(void)
365 {
366         static int firsttime = TRUE;
367         static int status_window = FALSE, msgs_window = FALSE;
368         int changed = FALSE;
369
370         if (settings_get_bool("use_status_window") != status_window) {
371                 status_window = !status_window;
372                 changed = TRUE;
373         }
374         if (settings_get_bool("use_msgs_window") != msgs_window) {
375                 msgs_window = !msgs_window;
376                 changed = TRUE;
377         }
378
379         if (firsttime) {
380                 firsttime = FALSE;
381                 changed = TRUE;
382
383                 windows_layout_restore();
384                 if (windows != NULL)
385                         return;
386         }
387
388         if (changed)
389                 create_windows();
390 }
391
392 static void autorun_startup(void)
393 {
394         char *path;
395         GIOChannel *handle;
396         GString *buf;
397         gsize tpos;
398
399         /* open ~/.irssi/startup and run all commands in it */
400         path = g_strdup_printf("%s/startup", get_irssi_dir());
401         handle = g_io_channel_new_file(path, "r", NULL);
402         g_free(path);
403         if (handle == NULL) {
404                 /* file not found */
405                 return;
406         }
407
408         g_io_channel_set_encoding(handle, NULL, NULL);
409         buf = g_string_sized_new(512);
410         while (g_io_channel_read_line_string(handle, buf, &tpos, NULL) == G_IO_STATUS_NORMAL) {
411                 buf->str[tpos] = '\0';
412                 if (buf->str[0] != '#') {
413                         eval_special_string(buf->str, "",
414                                             active_win->active_server,
415                                             active_win->active);
416                 }
417         }
418         g_string_free(buf, TRUE);
419
420         g_io_channel_unref(handle);
421 }
422
423 void fe_common_core_finish_init(void)
424 {
425         int setup_changed;
426
427         signal_emit("irssi init read settings", 0);
428
429 #ifdef SIGPIPE
430         signal(SIGPIPE, SIG_IGN);
431 #endif
432
433         setup_changed = FALSE;
434         if (cmdline_nick != NULL && *cmdline_nick != '\0') {
435                 /* override nick found from setup */
436                 settings_set_str("nick", cmdline_nick);
437                 setup_changed = TRUE;
438         }
439
440         if (cmdline_hostname != NULL) {
441                 /* override host name found from setup */
442                 settings_set_str("hostname", cmdline_hostname);
443                 setup_changed = TRUE;
444         }
445
446         sig_setup_changed();
447         signal_add_first("setup changed", (SIGNAL_FUNC) sig_setup_changed);
448
449         /* _after_ windows are created.. */
450 #if GLIB_CHECK_VERSION(2,6,0)
451         g_log_set_default_handler((GLogFunc) glog_func, NULL);
452 #else
453         g_log_set_handler(G_LOG_DOMAIN,
454                           (GLogLevelFlags) (G_LOG_LEVEL_CRITICAL |
455                                             G_LOG_LEVEL_WARNING),
456                           (GLogFunc) glog_func, NULL);
457         g_log_set_handler("GLib",
458                           (GLogLevelFlags) (G_LOG_LEVEL_CRITICAL |
459                                             G_LOG_LEVEL_WARNING),
460                           (GLogFunc) glog_func, NULL); /* send glib errors to the same place */
461 #endif
462
463         if (setup_changed)
464                 signal_emit("setup changed", 0);
465
466         autorun_startup();
467         autoconnect_servers();
468 }
469
470 gboolean strarray_find_dest(char **array, const TEXT_DEST_REC *dest)
471 {
472         g_return_val_if_fail(array != NULL, FALSE);
473
474         if (strarray_find(array, dest->target) != -1)
475                 return TRUE;
476
477         if (dest->server_tag != NULL) {
478                 char *tagtarget = g_strdup_printf("%s/%s", dest->server_tag, dest->target);
479                 int ret = strarray_find(array, tagtarget);
480                 g_free(tagtarget);
481                 if (ret != -1)
482                         return TRUE;
483         }
484         return FALSE;
485 }