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