Statistics
| Revision:

root / src / main.c @ 3217

History | View | Annotate | Download (47.1 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2013 Hiroyuki Yamamoto
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19

    
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23

    
24
#include "defs.h"
25

    
26
#include <glib.h>
27
#include <glib/gi18n.h>
28
#include <gtk/gtkmain.h>
29
#include <gtk/gtkrc.h>
30
#include <gtk/gtkstock.h>
31
#include <gtk/gtkaccelmap.h>
32

    
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <ctype.h>
37
#include <unistd.h>
38
#include <time.h>
39
#include <sys/stat.h>
40
#include <sys/types.h>
41
#ifdef G_OS_UNIX
42
#  include <signal.h>
43
#endif
44

    
45
#if HAVE_LOCALE_H
46
#  include <locale.h>
47
#endif
48

    
49
#if USE_GPGME
50
#  include <gpgme.h>
51
#endif
52

    
53
#include "main.h"
54
#include "mainwindow.h"
55
#include "folderview.h"
56
#include "summaryview.h"
57
#include "prefs_common.h"
58
#include "prefs_account.h"
59
#include "prefs_actions.h"
60
#include "prefs_display_header.h"
61
#include "account.h"
62
#include "account_dialog.h"
63
#include "procmsg.h"
64
#include "procheader.h"
65
#include "filter.h"
66
#include "send_message.h"
67
#include "inc.h"
68
#include "manage_window.h"
69
#include "alertpanel.h"
70
#include "inputdialog.h"
71
#include "statusbar.h"
72
#include "addressbook.h"
73
#include "addrindex.h"
74
#include "compose.h"
75
#include "logwindow.h"
76
#include "folder.h"
77
#include "setup.h"
78
#include "sylmain.h"
79
#include "utils.h"
80
#include "gtkutils.h"
81
#include "socket.h"
82
#include "stock_pixmap.h"
83
#include "trayicon.h"
84
#include "notificationwindow.h"
85
#include "plugin.h"
86
#include "plugin_manager.h"
87
#include "foldersel.h"
88
#include "update_check.h"
89
#include "colorlabel.h"
90

    
91
#if USE_GPGME
92
#  include "rfc2015.h"
93
#endif
94
#if USE_SSL
95
#  include "ssl.h"
96
#  include "sslmanager.h"
97
#endif
98

    
99
#ifdef G_OS_WIN32
100
#  include <windows.h>
101
#  include <pbt.h>
102
#  include <fcntl.h>
103
#  include <conio.h>
104
#endif
105

    
106
#include "version.h"
107

    
108
gchar *prog_version;
109

    
110
#ifdef G_OS_WIN32
111
static gboolean init_console_done = FALSE;
112
#endif
113

    
114
static gint lock_socket = -1;
115
static gint lock_socket_tag = 0;
116
static GIOChannel *lock_ch = NULL;
117
static gchar *instance_id = NULL;
118

    
119
#if USE_THREADS
120
static GThread *main_thread;
121
#endif
122

    
123
static struct RemoteCmd {
124
        gboolean receive;
125
        gboolean receive_all;
126
        gboolean compose;
127
        const gchar *compose_mailto;
128
        GPtrArray *attach_files;
129
        gboolean send;
130
        gboolean status;
131
        gboolean status_full;
132
        GPtrArray *status_folders;
133
        GPtrArray *status_full_folders;
134
        gchar *open_msg;
135
        gboolean configdir;
136
        gboolean safe_mode;
137
        gboolean exit;
138
        gboolean restart;
139
        gchar *argv0;
140
#ifdef G_OS_WIN32
141
        gushort ipcport;
142
#endif
143
} cmd;
144

    
145
#define STATUSBAR_PUSH(mainwin, str) \
146
{ \
147
        gtk_statusbar_push(GTK_STATUSBAR(mainwin->statusbar), \
148
                           mainwin->mainwin_cid, str); \
149
        gtkut_widget_draw_now(mainwin->statusbar); \
150
}
151

    
152
#define STATUSBAR_POP(mainwin) \
153
{ \
154
        gtk_statusbar_pop(GTK_STATUSBAR(mainwin->statusbar), \
155
                          mainwin->mainwin_cid); \
156
}
157

    
158
#if defined(G_OS_WIN32) || defined(__APPLE__)
159
static void fix_font_setting                (void);
160
#endif
161

    
162
static void parse_cmd_opt                (int                 argc,
163
                                         char                *argv[]);
164

    
165
static void app_init                        (void);
166
static void parse_gtkrc_files                (void);
167
static void setup_rc_dir                (void);
168
static void check_gpg                        (void);
169
static void set_log_handlers                (gboolean         enable);
170
static void register_system_events        (void);
171
static void plugin_init                        (void);
172

    
173
static gchar *get_socket_name                (void);
174
static gint prohibit_duplicate_launch        (void);
175
static gint lock_socket_remove                (void);
176
static gboolean lock_socket_input_cb        (GIOChannel        *source,
177
                                         GIOCondition         condition,
178
                                         gpointer         data);
179

    
180
static void remote_command_exec                (void);
181

    
182
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
183
static void migrate_old_config                (void);
184
#endif
185

    
186
static void open_compose_new                (const gchar        *address,
187
                                         GPtrArray        *attach_files);
188
static void open_message                (const gchar        *path);
189

    
190
static void send_queue                        (void);
191

    
192
#define MAKE_DIR_IF_NOT_EXIST(dir)                                        \
193
{                                                                        \
194
        if (!is_dir_exist(dir)) {                                        \
195
                if (is_file_exist(dir)) {                                \
196
                        alertpanel_warning                                \
197
                                (_("File `%s' already exists.\n"        \
198
                                   "Can't create folder."),                \
199
                                 dir);                                        \
200
                        exit(1);                                        \
201
                }                                                        \
202
                if (make_dir(dir) < 0)                                        \
203
                        exit(1);                                        \
204
        }                                                                \
205
}
206

    
207
#define CHDIR_EXIT_IF_FAIL(dir, val)        \
208
{                                        \
209
        if (change_dir(dir) < 0)        \
210
                exit(val);                \
211
}
212

    
213
static void load_cb(GObject *obj, GModule *module, gpointer data)
214
{
215
        debug_print("load_cb: %p (%s), %p\n", module, module ? g_module_name(module) : "(null)", data);
216
}
217

    
218
int main(int argc, char *argv[])
219
{
220
        MainWindow *mainwin;
221
        FolderView *folderview;
222
        GdkPixbuf *icon;
223
#ifdef G_OS_WIN32
224
        GList *iconlist = NULL;
225
#endif
226
        GObject *syl_app;
227
        PrefsAccount *new_account = NULL;
228
        gboolean first_run = FALSE;
229

    
230
        app_init();
231
        parse_cmd_opt(argc, argv);
232

    
233
        /* check and create (unix domain) socket for remote operation */
234
        lock_socket = prohibit_duplicate_launch();
235
        if (lock_socket < 0) return 0;
236

    
237
        if (cmd.status || cmd.status_full) {
238
                puts("0 Sylpheed not running.");
239
                lock_socket_remove();
240
                return 0;
241
        }
242

    
243
#if USE_THREADS
244
        gdk_threads_enter();
245
#endif
246
        gtk_set_locale();
247
        gtk_init(&argc, &argv);
248

    
249
        syl_app = syl_app_create();
250

    
251
        gdk_rgb_init();
252
        gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
253
        gtk_widget_set_default_visual(gdk_rgb_get_visual());
254

    
255
        parse_gtkrc_files();
256
        setup_rc_dir();
257

    
258
        if (is_file_exist("sylpheed.log")) {
259
                if (rename_force("sylpheed.log", "sylpheed.log.bak") < 0)
260
                        FILE_OP_ERROR("sylpheed.log", "rename");
261
        }
262
        set_log_file("sylpheed.log");
263

    
264
        set_ui_update_func(gtkut_events_flush);
265
        set_progress_func(main_window_progress_show);
266
        set_input_query_password_func(input_dialog_query_password);
267
#if USE_SSL
268
        ssl_init();
269
        ssl_set_verify_func(ssl_manager_verify_cert);
270
#endif
271

    
272
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
273

    
274
        prefs_common_read_config();
275
        filter_set_addressbook_func(addressbook_has_address);
276
        filter_read_config();
277
        prefs_actions_read_config();
278
        prefs_display_header_read_config();
279
        colorlabel_read_config();
280

    
281
        prefs_common.user_agent_str = g_strdup_printf
282
                ("%s (GTK+ %d.%d.%d; %s)",
283
                 prog_version,
284
                 gtk_major_version, gtk_minor_version, gtk_micro_version,
285
                 TARGET_ALIAS);
286

    
287
#if defined(G_OS_WIN32) || defined(__APPLE__)
288
        fix_font_setting();
289
#endif
290

    
291
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
292

    
293
        check_gpg();
294

    
295
        sock_set_io_timeout(prefs_common.io_timeout_secs);
296

    
297
        gtkut_widget_init();
298

    
299
#ifdef G_OS_WIN32
300
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_32, &icon);
301
        iconlist = g_list_append(iconlist, icon);
302
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_SMALL, &icon);
303
        iconlist = g_list_append(iconlist, icon);
304
        gtk_window_set_default_icon_list(iconlist);
305
        g_list_free(iconlist);
306
#else
307
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED, &icon);
308
        gtk_window_set_default_icon(icon);
309
#endif
310

    
311
        mainwin = main_window_create
312
                (prefs_common.sep_folder | prefs_common.sep_msg << 1);
313
        folderview = mainwin->folderview;
314

    
315
        /* register the callback of socket input */
316
        if (lock_socket > 0) {
317
                lock_ch = g_io_channel_unix_new(lock_socket);
318
                lock_socket_tag = g_io_add_watch(lock_ch,
319
                                                 G_IO_IN|G_IO_PRI|G_IO_ERR,
320
                                                 lock_socket_input_cb, mainwin);
321
        }
322

    
323
        set_log_handlers(TRUE);
324

    
325
        account_read_config_all();
326
        account_set_menu();
327
        main_window_reflect_prefs_all();
328

    
329
        if (folder_read_list() < 0) {
330
                first_run = TRUE;
331
                setup_mailbox();
332
                folder_write_list();
333
        }
334
        if (!account_get_list()) {
335
                new_account = setup_account();
336
        }
337

    
338
        account_set_menu();
339
        main_window_reflect_prefs_all();
340

    
341
        account_set_missing_folder();
342
        folder_set_missing_folders();
343
        folderview_set(folderview);
344
        if (new_account && new_account->folder)
345
                folder_write_list();
346

    
347
        addressbook_read_file();
348

    
349
        register_system_events();
350

    
351
        inc_autocheck_timer_init(mainwin);
352

    
353
        plugin_init();
354

    
355
        g_signal_emit_by_name(syl_app, "init-done");
356

    
357
        if (first_run) {
358
                setup_import_data();
359
                setup_import_addressbook();
360
        }
361

    
362
        remote_command_exec();
363

    
364
#if USE_UPDATE_CHECK
365
        if (prefs_common.auto_update_check)
366
                update_check(FALSE);
367
#endif
368

    
369
        gtk_main();
370
#if USE_THREADS
371
        gdk_threads_leave();
372
#endif
373

    
374
        return 0;
375
}
376

    
377
static void init_console(void)
378
{
379
#ifdef G_OS_WIN32
380
        gint fd;
381
        FILE *fp;
382

    
383
        if (init_console_done)
384
                return;
385

    
386
        if (!AllocConsole()) {
387
                g_warning("AllocConsole() failed\n");
388
                return;
389
        }
390

    
391
        fd = _open_osfhandle((glong)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
392
        _dup2(fd, 1);
393
        fp = _fdopen(fd, "w");
394
        *stdout = *fp;
395
        setvbuf(stdout, NULL, _IONBF, 0);
396
        fd = _open_osfhandle((glong)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT);
397
        _dup2(fd, 2);
398
        fp = _fdopen(fd, "w");
399
        *stderr = *fp;
400
        setvbuf(stderr, NULL, _IONBF, 0);
401

    
402
        init_console_done = TRUE;
403
#endif
404
}
405

    
406
static void cleanup_console(void)
407
{
408
#ifdef G_OS_WIN32
409
        FreeConsole();
410
#endif
411
}
412

    
413
#ifdef G_OS_WIN32
414
static void read_ini_file(void)
415
{
416
        static gushort ipcport = REMOTE_CMD_PORT;
417
        static gchar *confdir = NULL;
418

    
419
        static PrefParam param[] = {
420
                {"ipcport", "50215", &ipcport, P_USHORT},
421
                {"configdir", NULL, &confdir, P_STRING},
422

    
423
                {NULL, NULL, NULL, P_OTHER}
424
        };
425

    
426
        gchar *file;
427

    
428
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, "sylpheed.ini",
429
                           NULL);
430
        if (!is_file_exist(file)) {
431
                g_free(file);
432
                return;
433
        }
434

    
435
        prefs_read_config(param, "Sylpheed", file,
436
                          conv_get_locale_charset_str());
437
        g_free(file);
438

    
439
        cmd.ipcport = ipcport;
440
        if (confdir) {
441
                set_rc_dir(confdir);
442
                g_free(confdir);
443
                confdir = NULL;
444
                cmd.configdir = TRUE;
445
        }
446
}
447
#endif /* G_OS_WIN32 */
448

    
449
#if defined(G_OS_WIN32) || defined(__APPLE__)
450
static void fix_font_setting(void)
451
{
452
        const gchar *str = NULL;
453

    
454
        if (!conv_is_ja_locale())
455
                return;
456

    
457
        if (prefs_common.textfont &&
458
            strcmp(prefs_common.textfont, DEFAULT_MESSAGE_FONT) != 0) {
459
                if (gtkut_font_can_load(prefs_common.textfont)) {
460
                        debug_print("font '%s' load ok\n", prefs_common.textfont);
461
                        return;
462
                }
463
                debug_print("font '%s' load failed\n", prefs_common.textfont);
464
        }
465

    
466
        debug_print("fixing prefs_common.textfont setting\n");
467

    
468
#ifdef G_OS_WIN32
469
        str = "MS Gothic 12";
470
#else /* __APPLE__ */
471
        str = "Hiragino Kaku Gothic Pro Light 13";
472
#endif
473

    
474
        if (!gtkut_font_can_load(str)) {
475
#ifdef G_OS_WIN32
476
                debug_print("font '%s' load failed\n", str);
477
                str = "\xef\xbc\xad\xef\xbc\xb3 \xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf 12";
478
                if (!gtkut_font_can_load(str)) {
479
                        debug_print("font '%s' load failed\n", str);
480
                        str = NULL;
481
                }
482
#else /* __APPLE__ */
483
                debug_print("font '%s' load failed\n", str);
484
                str = NULL;
485
#endif
486
        }
487

    
488
        if (str) {
489
                debug_print("font '%s' load ok\n", str);
490
                g_free(prefs_common.textfont);
491
                prefs_common.textfont = g_strdup(str);
492
        } else
493
                g_warning("failed to load text font!");
494
}
495
#endif
496

    
497
static void parse_cmd_opt(int argc, char *argv[])
498
{
499
        gint i;
500

    
501
        for (i = 1; i < argc; i++) {
502
                if (!strncmp(argv[i], "--debug", 7)) {
503
                        init_console();
504
                        set_debug_mode(TRUE);
505
                } else if (!strncmp(argv[i], "--receive-all", 13))
506
                        cmd.receive_all = TRUE;
507
                else if (!strncmp(argv[i], "--receive", 9))
508
                        cmd.receive = TRUE;
509
                else if (!strncmp(argv[i], "--compose", 9)) {
510
                        const gchar *p = argv[i + 1];
511

    
512
                        cmd.compose = TRUE;
513
                        cmd.compose_mailto = NULL;
514
                        if (p && *p != '\0' && *p != '-') {
515
                                if (!strncmp(p, "mailto:", 7))
516
                                        cmd.compose_mailto = p + 7;
517
                                else
518
                                        cmd.compose_mailto = p;
519
                                i++;
520
                        }
521
                } else if (!strncmp(argv[i], "--attach", 8)) {
522
                        const gchar *p = argv[i + 1];
523
                        gchar *file;
524

    
525
                        while (p && *p != '\0' && *p != '-') {
526
                                if (!cmd.attach_files)
527
                                        cmd.attach_files = g_ptr_array_new();
528
                                if (!g_path_is_absolute(p))
529
                                        file = g_strconcat(get_startup_dir(),
530
                                                           G_DIR_SEPARATOR_S,
531
                                                           p, NULL);
532
                                else
533
                                        file = g_strdup(p);
534
                                g_ptr_array_add(cmd.attach_files, file);
535
                                i++;
536
                                p = argv[i + 1];
537
                        }
538
                } else if (!strncmp(argv[i], "--send", 6)) {
539
                        cmd.send = TRUE;
540
                } else if (!strncmp(argv[i], "--version", 9)) {
541
                        puts("Sylpheed version " VERSION);
542
                        exit(0);
543
                } else if (!strncmp(argv[i], "--status-full", 13)) {
544
                        const gchar *p = argv[i + 1];
545

    
546
                        cmd.status_full = TRUE;
547
                        while (p && *p != '\0' && *p != '-') {
548
                                if (!cmd.status_full_folders)
549
                                        cmd.status_full_folders =
550
                                                g_ptr_array_new();
551
                                g_ptr_array_add(cmd.status_full_folders,
552
                                                g_strdup(p));
553
                                i++;
554
                                p = argv[i + 1];
555
                        }
556
                } else if (!strncmp(argv[i], "--status", 8)) {
557
                        const gchar *p = argv[i + 1];
558

    
559
                        cmd.status = TRUE;
560
                        while (p && *p != '\0' && *p != '-') {
561
                                if (!cmd.status_folders)
562
                                        cmd.status_folders = g_ptr_array_new();
563
                                g_ptr_array_add(cmd.status_folders,
564
                                                g_strdup(p));
565
                                i++;
566
                                p = argv[i + 1];
567
                        }
568
                } else if (!strncmp(argv[i], "--open", 6)) {
569
                        const gchar *p = argv[i + 1];
570

    
571
                        if (p && *p != '\0' && *p != '-') {
572
                                if (cmd.open_msg)
573
                                        g_free(cmd.open_msg);
574
                                cmd.open_msg = g_locale_to_utf8
575
                                        (p, -1, NULL, NULL, NULL);
576
                                i++;
577
                        }
578
                } else if (!strncmp(argv[i], "--configdir", 11)) {
579
                        const gchar *p = argv[i + 1];
580

    
581
                        if (p && *p != '\0' && *p != '-') {
582
                                /* this must only be done at startup */
583
#ifdef G_OS_WIN32
584
                                gchar *utf8dir;
585

    
586
                                utf8dir = g_locale_to_utf8
587
                                        (p, -1, NULL, NULL, NULL);
588
                                if (utf8dir) {
589
                                        set_rc_dir(utf8dir);
590
                                        g_free(utf8dir);
591
                                } else
592
                                        set_rc_dir(p);
593
#else
594
                                set_rc_dir(p);
595
#endif
596
                                cmd.configdir = TRUE;
597
                                i++;
598
                        }
599
#ifdef G_OS_WIN32
600
                } else if (!strncmp(argv[i], "--ipcport", 9)) {
601
                        if (argv[i + 1]) {
602
                                cmd.ipcport = atoi(argv[i + 1]);
603
                                i++;
604
                        }
605
#endif
606
                } else if (!strncmp(argv[i], "--instance-id", 13)) {
607
                        if (argv[i + 1]) {
608
                                instance_id = g_locale_to_utf8
609
                                        (argv[i + 1], -1, NULL, NULL, NULL);
610
                                i++;
611
                        }
612
                } else if (!strncmp(argv[i], "--safe-mode", 11)) {
613
                        cmd.safe_mode = TRUE;
614
                } else if (!strncmp(argv[i], "--exit", 6)) {
615
                        cmd.exit = TRUE;
616
                } else if (!strncmp(argv[i], "--help", 6)) {
617
                        init_console();
618

    
619
                        g_print(_("Usage: %s [OPTIONS ...] [URL]\n"),
620
                                g_basename(argv[0]));
621

    
622
                        g_print("%s\n", _("  --compose [mailto URL] open composition window"));
623
                        g_print("%s\n", _("  --attach file1 [file2]...\n"
624
                                "                         open composition window with specified files\n"
625
                                "                         attached"));
626
                        g_print("%s\n", _("  --receive              receive new messages"));
627
                        g_print("%s\n", _("  --receive-all          receive new messages of all accounts"));
628
                        g_print("%s\n", _("  --send                 send all queued messages"));
629
                        g_print("%s\n", _("  --status [folder]...   show the total number of messages"));
630
                        g_print("%s\n", _("  --status-full [folder]...\n"
631
                                "                         show the status of each folder"));
632
                        g_print("%s\n", _("  --open folderid/msgnum open existing message in a new window"));
633
                        g_print("%s\n", _("  --open <file URL>      open an rfc822 message file in a new window"));
634
                        g_print("%s\n", _("  --configdir dirname    specify directory which stores configuration files"));
635
#ifdef G_OS_WIN32
636
                        g_print("%s\n", _("  --ipcport portnum      specify port for IPC remote commands"));
637
#endif
638
                        g_print("%s\n", _("  --exit                 exit Sylpheed"));
639
                        g_print("%s\n", _("  --debug                debug mode"));
640
                        g_print("%s\n", _("  --safe-mode            safe mode"));
641
                        g_print("%s\n", _("  --help                 display this help and exit"));
642
                        g_print("%s\n", _("  --version              output version information and exit"));
643

    
644
#ifdef G_OS_WIN32
645
                        g_print("\n");
646
                        g_print(_("Press any key..."));
647
                        _getch();
648
#endif
649

    
650
                        cleanup_console();
651
                        exit(1);
652
                } else {
653
                        /* file or URL */
654
                        const gchar *p = argv[i];
655

    
656
                        if (p && *p != '\0') {
657
                                if (!strncmp(p, "mailto:", 7)) {
658
                                        cmd.compose = TRUE;
659
                                        cmd.compose_mailto = p + 7;
660
                                } else {
661
                                        if (cmd.open_msg)
662
                                                g_free(cmd.open_msg);
663
                                        cmd.open_msg = g_locale_to_utf8
664
                                                (p, -1, NULL, NULL, NULL);
665
                                }
666
                        }
667
                }
668
        }
669

    
670
        if (cmd.attach_files && cmd.compose == FALSE) {
671
                cmd.compose = TRUE;
672
                cmd.compose_mailto = NULL;
673
        }
674

    
675
        cmd.argv0 = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
676
        if (!cmd.argv0)
677
                cmd.argv0 = g_strdup(argv[0]);
678
}
679

    
680
static gint get_queued_message_num(void)
681
{
682
        FolderItem *queue;
683

    
684
        queue = folder_get_default_queue();
685
        if (!queue) return -1;
686

    
687
        folder_item_scan(queue);
688
        return queue->total;
689
}
690

    
691
#if USE_THREADS
692
/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */
693
static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT;
694

    
695
static void thread_enter_func(void)
696
{
697
        g_static_rec_mutex_lock(&syl_mutex);
698
#if 0
699
        syl_mutex_lock_count++;
700
        if (syl_mutex_lock_count > 1)
701
                g_print("enter: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
702
#endif
703
}
704

    
705
static void thread_leave_func(void)
706
{
707
#if 0
708
        syl_mutex_lock_count--;
709
        if (syl_mutex_lock_count > 0)
710
                g_print("leave: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
711
#endif
712
        g_static_rec_mutex_unlock(&syl_mutex);
713
}
714

    
715
static void event_loop_iteration_func(void)
716
{
717
        if (g_thread_self() != main_thread) {
718
                g_fprintf(stderr, "event_loop_iteration_func called from non-main thread (%p)\n", g_thread_self());
719
                g_usleep(10000);
720
                return;
721
        }
722
        gtk_main_iteration();
723
}
724
#endif
725

    
726
static void app_init(void)
727
{
728
#if USE_THREADS
729
        if (!g_thread_supported())
730
                g_thread_init(NULL);
731
        if (!g_thread_supported())
732
                g_error("g_thread is not supported by glib.");
733
        else {
734
                gdk_threads_set_lock_functions(thread_enter_func,
735
                                               thread_leave_func);
736
                gdk_threads_init();
737
                main_thread = g_thread_self();
738
        }
739
#endif
740
        syl_init();
741

    
742
#if USE_THREADS
743
        set_event_loop_func(event_loop_iteration_func);
744
#endif
745
        prog_version = PROG_VERSION;
746

    
747
#ifdef G_OS_WIN32
748
        read_ini_file();
749
#endif
750
}
751

    
752
static void parse_gtkrc_files(void)
753
{
754
        gchar *userrc;
755

    
756
        /* parse gtkrc files */
757
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
758
                             NULL);
759
        gtk_rc_parse(userrc);
760
        g_free(userrc);
761
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
762
                             G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
763
        gtk_rc_parse(userrc);
764
        g_free(userrc);
765
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
766
        gtk_rc_parse(userrc);
767
        g_free(userrc);
768

    
769
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
770
        gtk_accel_map_load(userrc);
771
        g_free(userrc);
772
}
773

    
774
static void setup_rc_dir(void)
775
{
776
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
777
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
778

    
779
        /* backup if old rc file exists */
780
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
781
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
782
                        FILE_OP_ERROR(RC_DIR, "rename");
783
        }
784

    
785
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
786
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
787
                const gchar *envstr;
788
                AlertValue val;
789

    
790
                /* check for filename encoding */
791
                if (conv_get_locale_charset() != C_UTF_8) {
792
                        envstr = g_getenv("G_FILENAME_ENCODING");
793
                        if (!envstr)
794
                                envstr = g_getenv("G_BROKEN_FILENAMES");
795
                        if (!envstr) {
796
                                val = alertpanel(_("Filename encoding"),
797
                                                 _("The locale encoding is not UTF-8, but the environmental variable G_FILENAME_ENCODING is not set.\n"
798
                                                   "If the locale encoding is used for file name or directory name, it will not work correctly.\n"
799
                                                   "In that case, you must set the following environmental variable (see README for detail):\n"
800
                                                   "\n"
801
                                                   "\tG_FILENAME_ENCODING=@locale\n"
802
                                                   "\n"
803
                                                   "Continue?"),
804
                                                 GTK_STOCK_OK, GTK_STOCK_QUIT,
805
                                                 NULL);
806
                                if (G_ALERTDEFAULT != val)
807
                                        exit(1);
808
                        }
809
                }
810

    
811
                if (make_dir(RC_DIR) < 0)
812
                        exit(1);
813
                if (is_dir_exist(OLD_RC_DIR))
814
                        migrate_old_config();
815
        }
816
#endif /* !G_OS_WIN32 && !__APPLE__ */
817

    
818
        syl_setup_rc_dir();
819
}
820

    
821
static void app_restart(void)
822
{
823
        gchar *cmdline;
824
        GError *error = NULL;
825
#ifdef G_OS_WIN32
826
        if (cmd.configdir) {
827
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\" --ipcport %d",
828
                                          cmd.argv0,
829
                                          get_debug_mode() ? " --debug" : "",
830
                                          get_rc_dir(),
831
                                          cmd.ipcport);
832
        } else {
833
                cmdline = g_strdup_printf("\"%s\"%s --ipcport %d",
834
                                          cmd.argv0,
835
                                          get_debug_mode() ? " --debug" : "",
836
                                          cmd.ipcport);
837
        }
838
#else
839
        if (cmd.configdir) {
840
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\"",
841
                                          cmd.argv0,
842
                                          get_debug_mode() ? " --debug" : "",
843
                                          get_rc_dir());
844
        } else {
845
                cmdline = g_strdup_printf("\"%s\"%s",
846
                                          cmd.argv0,
847
                                          get_debug_mode() ? " --debug" : "");
848
        }
849
#endif
850
        if (!g_spawn_command_line_async(cmdline, &error)) {
851
                alertpanel_error("restart failed\n'%s'\n%s", cmdline, error->message);
852
                g_error_free(error);
853
        }
854
        g_free(cmdline);
855
}
856

    
857
void app_will_restart(gboolean force)
858
{
859
        cmd.restart = TRUE;
860
        app_will_exit(force);
861
        /* canceled */
862
        cmd.restart = FALSE;
863
}
864

    
865
void app_will_exit(gboolean force)
866
{
867
        MainWindow *mainwin;
868
        gchar *filename;
869
        static gboolean on_exit = FALSE;
870
        GList *cur;
871

    
872
        if (on_exit)
873
                return;
874
        on_exit = TRUE;
875

    
876
        mainwin = main_window_get();
877

    
878
        if (!force && compose_get_compose_list()) {
879
                if (alertpanel(_("Notice"),
880
                               _("Composing message exists. Really quit?"),
881
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
882
                    != G_ALERTDEFAULT) {
883
                        on_exit = FALSE;
884
                        return;
885
                }
886
                manage_window_focus_in(mainwin->window, NULL, NULL);
887
        }
888

    
889
        if (!force &&
890
            prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
891
                if (alertpanel(_("Queued messages"),
892
                               _("Some unsent messages are queued. Exit now?"),
893
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
894
                    != G_ALERTDEFAULT) {
895
                        on_exit = FALSE;
896
                        return;
897
                }
898
                manage_window_focus_in(mainwin->window, NULL, NULL);
899
        }
900

    
901
        if (force)
902
                g_signal_emit_by_name(syl_app_get(), "app-force-exit");
903
        g_signal_emit_by_name(syl_app_get(), "app-exit");
904

    
905
        inc_autocheck_timer_remove();
906

    
907
        if (prefs_common.clean_on_exit)
908
                main_window_empty_trash(mainwin,
909
                                        !force && prefs_common.ask_on_clean);
910

    
911
        for (cur = account_get_list(); cur != NULL; cur = cur->next) {
912
                PrefsAccount *ac = (PrefsAccount *)cur->data;
913
                if (ac->protocol == A_IMAP4 && ac->imap_clear_cache_on_exit &&
914
                    ac->folder)
915
                        procmsg_remove_all_cached_messages(FOLDER(ac->folder));
916
        }
917

    
918
        syl_plugin_unload_all();
919

    
920
        trayicon_destroy(mainwin->tray_icon);
921

    
922
        /* save all state before exiting */
923
        summary_write_cache(mainwin->summaryview);
924
        main_window_get_size(mainwin);
925
        main_window_get_position(mainwin);
926
        syl_save_all_state();
927
        addressbook_export_to_file();
928

    
929
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
930
        gtk_accel_map_save(filename);
931
        g_free(filename);
932

    
933
        /* remove temporary files, close log file, socket cleanup */
934
#if USE_SSL
935
        ssl_done();
936
#endif
937
        syl_cleanup();
938
        lock_socket_remove();
939

    
940
#ifdef USE_UPDATE_CHECK_PLUGIN
941
#ifdef G_OS_WIN32
942
        cur = gtk_window_list_toplevels();
943
        g_list_foreach(cur, (GFunc)gtk_widget_hide, NULL);
944
        g_list_free(cur);
945
        update_check_spawn_plugin_updater();
946
#endif
947
#endif
948

    
949
        cleanup_console();
950

    
951
        if (gtk_main_level() > 0)
952
                gtk_main_quit();
953

    
954
        if (cmd.restart)
955
                app_restart();
956

    
957
        exit(0);
958
}
959

    
960
#if 0
961
#if USE_GPGME
962
static void idle_function_for_gpgme(void)
963
{
964
        while (gtk_events_pending())
965
                gtk_main_iteration();
966
}
967
#endif /* USE_GPGME */
968
#endif /* 0 */
969

    
970
static void check_gpg(void)
971
{
972
#if USE_GPGME
973
        const gchar *version;
974
        gpgme_error_t err = 0;
975

    
976
        version = gpgme_check_version("1.0.0");
977
        if (version) {
978
                debug_print("GPGME Version: %s\n", version);
979
                err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
980
                if (err)
981
                        debug_print("gpgme_engine_check_version: %s\n",
982
                                    gpgme_strerror(err));
983
        }
984

    
985
        if (version && !err) {
986
                /* Also does some gpgme init */
987
                gpgme_engine_info_t engineInfo;
988

    
989
#if HAVE_LOCALE_H
990
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
991
                gpgme_set_locale(NULL, LC_MESSAGES,
992
                                 setlocale(LC_MESSAGES, NULL));
993
#endif
994

    
995
                if (!gpgme_get_engine_info(&engineInfo)) {
996
                        while (engineInfo) {
997
                                debug_print("GPGME Protocol: %s\n      Version: %s\n",
998
                                            gpgme_get_protocol_name
999
                                                (engineInfo->protocol),
1000
                                            engineInfo->version ?
1001
                                            engineInfo->version : "(unknown)");
1002
                                engineInfo = engineInfo->next;
1003
                        }
1004
                }
1005

    
1006
                procmsg_set_decrypt_message_func
1007
                        (rfc2015_open_message_decrypted);
1008
                procmsg_set_auto_decrypt_message(TRUE);
1009
        } else {
1010
                rfc2015_disable_all();
1011

    
1012
                if (prefs_common.gpg_warning) {
1013
                        AlertValue val;
1014

    
1015
                        val = alertpanel_message_with_disable
1016
                                (_("Warning"),
1017
                                 _("GnuPG is not installed properly, or its version is too old.\n"
1018
                                   "OpenPGP support disabled."),
1019
                                 ALERT_WARNING);
1020
                        if (val & G_ALERTDISABLE)
1021
                                prefs_common.gpg_warning = FALSE;
1022
                }
1023
        }
1024
        /* FIXME: This function went away.  We can either block until gpgme
1025
         * operations finish (currently implemented) or register callbacks
1026
         * with the gtk main loop via the gpgme io callback interface instead.
1027
         *
1028
         * gpgme_register_idle(idle_function_for_gpgme);
1029
         */
1030
#endif
1031
}
1032

    
1033
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
1034
                             const gchar *message, gpointer user_data)
1035
{
1036
        gchar *prefix = "";
1037
        gchar *file_prefix = "";
1038
        LogType level = LOG_NORMAL;
1039
        gchar *str;
1040
        const gchar *message_;
1041

    
1042
        switch (log_level) {
1043
        case G_LOG_LEVEL_ERROR:
1044
                prefix = "ERROR";
1045
                file_prefix = "*** ";
1046
                level = LOG_ERROR;
1047
                break;
1048
        case G_LOG_LEVEL_CRITICAL:
1049
                prefix = "CRITICAL";
1050
                file_prefix = "** ";
1051
                level = LOG_WARN;
1052
                break;
1053
        case G_LOG_LEVEL_WARNING:
1054
                prefix = "WARNING";
1055
                file_prefix = "** ";
1056
                level = LOG_WARN;
1057
                break;
1058
        case G_LOG_LEVEL_MESSAGE:
1059
                prefix = "Message";
1060
                file_prefix = "* ";
1061
                level = LOG_MSG;
1062
                break;
1063
        case G_LOG_LEVEL_INFO:
1064
                prefix = "INFO";
1065
                file_prefix = "* ";
1066
                level = LOG_MSG;
1067
                break;
1068
        case G_LOG_LEVEL_DEBUG:
1069
                prefix = "DEBUG";
1070
                break;
1071
        default:
1072
                prefix = "LOG";
1073
                break;
1074
        }
1075

    
1076
        if (!message)
1077
                message_ = "(NULL) message";
1078
        else
1079
                message_ = message;
1080
        if (log_domain)
1081
                str = g_strconcat(log_domain, "-", prefix, ": ", message_, "\n",
1082
                                  NULL);
1083
        else
1084
                str = g_strconcat(prefix, ": ", message_, "\n", NULL);
1085
        log_window_append(str, level);
1086
        log_write(str, file_prefix);
1087
        g_free(str);
1088

    
1089
        g_log_default_handler(log_domain, log_level, message, user_data);
1090
}
1091

    
1092
static void set_log_handlers(gboolean enable)
1093
{
1094
#if GLIB_CHECK_VERSION(2, 6, 0)
1095
        if (enable)
1096
                g_log_set_default_handler(default_log_func, NULL);
1097
        else
1098
                g_log_set_default_handler(g_log_default_handler, NULL);
1099
#else
1100
        static guint handler_id[4] = {0, 0, 0, 0};
1101

    
1102
        if (enable) {
1103
                handler_id[0] = g_log_set_handler
1104
                        ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1105
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1106
                handler_id[1] = g_log_set_handler
1107
                        ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1108
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1109
                handler_id[2] = g_log_set_handler
1110
                        ("LibSylph", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1111
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1112
                handler_id[3] = g_log_set_handler
1113
                        ("Sylpheed", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1114
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1115
        } else {
1116
                g_log_remove_handler("GLib", handler_id[0]);
1117
                g_log_remove_handler("Gtk", handler_id[1]);
1118
                g_log_remove_handler("LibSylph", handler_id[2]);
1119
                g_log_remove_handler("Sylpheed", handler_id[3]);
1120
                handler_id[0] = 0;
1121
                handler_id[1] = 0;
1122
                handler_id[2] = 0;
1123
                handler_id[3] = 0;
1124
        }
1125
#endif
1126
}
1127

    
1128
#ifdef G_OS_WIN32
1129
static BOOL WINAPI
1130
ctrl_handler(DWORD dwctrltype)
1131
{
1132
        log_print("ctrl_handler: received %d\n", dwctrltype);
1133
        app_will_exit(TRUE);
1134

    
1135
        return TRUE;
1136
}
1137

    
1138
static LRESULT CALLBACK
1139
wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1140
{
1141
        switch (message) {
1142
        case WM_POWERBROADCAST:
1143
                debug_print("WM_POWERBROADCAST received: wparam = %d\n",
1144
                            wparam);
1145
                if (wparam == PBT_APMSUSPEND || wparam == PBT_APMSTANDBY) {
1146
                        debug_print("suspend now\n");
1147
                        inc_autocheck_timer_remove();
1148
                } else if (wparam == PBT_APMRESUMESUSPEND ||
1149
                           wparam == PBT_APMRESUMESTANDBY) {
1150
                        debug_print("resume now\n");
1151
                        inc_autocheck_timer_set();
1152
                }
1153
                break;
1154
        case WM_ENDSESSION:
1155
                if (wparam == 1) {
1156
                        log_print("WM_ENDSESSION received: system is quitting\n");
1157
                        app_will_exit(TRUE);
1158
                }
1159
                break;
1160
        default:
1161
                break;
1162
        }
1163

    
1164
        return DefWindowProc(hwnd, message, wparam, lparam);
1165
}
1166

    
1167
static void register_system_events(void)
1168
{
1169
        WNDCLASS wclass;
1170
        static HWND hwnd = NULL;
1171
        static BOOL ctrl_handler_set = FALSE;
1172
        ATOM klass;
1173
        HINSTANCE hmodule = GetModuleHandle(NULL);
1174

    
1175
        if (init_console_done && !ctrl_handler_set) {
1176
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
1177
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
1178
                if (!ctrl_handler_set)
1179
                        g_warning("SetConsoleCtrlHandler() failed\n");
1180
        }
1181

    
1182
        if (hwnd)
1183
                return;
1184

    
1185
        debug_print("register_system_events(): RegisterClass\n");
1186

    
1187
        memset(&wclass, 0, sizeof(WNDCLASS));
1188
        wclass.lpszClassName = "sylpheed-observer";
1189
        wclass.lpfnWndProc   = wndproc;
1190
        wclass.hInstance     = hmodule;
1191

    
1192
        klass = RegisterClass(&wclass);
1193
        if (!klass)
1194
                return;
1195

    
1196
        hwnd = CreateWindow(MAKEINTRESOURCE(klass), NULL, WS_POPUP,
1197
                            0, 0, 1, 1, NULL, NULL, hmodule, NULL);
1198
        if (!hwnd)
1199
                UnregisterClass(MAKEINTRESOURCE(klass), hmodule);
1200
}
1201
#else /* G_OS_WIN32 */
1202
static void sig_handler(gint signum)
1203
{
1204
        debug_print("signal %d received\n", signum);
1205

    
1206
        switch (signum) {
1207
        case SIGHUP:
1208
        case SIGINT:
1209
        case SIGTERM:
1210
        case SIGQUIT:
1211
                app_will_exit(TRUE);
1212
                break;
1213
        default:
1214
                break;
1215
        }
1216
}
1217

    
1218
static void register_system_events(void)
1219
{
1220
        struct sigaction sa;
1221

    
1222
        memset(&sa, 0, sizeof(sa));
1223
        sa.sa_handler = sig_handler;
1224
        sa.sa_flags = SA_RESTART;
1225

    
1226
        sigemptyset(&sa.sa_mask);
1227
        sigaddset(&sa.sa_mask, SIGHUP);
1228
        sigaddset(&sa.sa_mask, SIGINT);
1229
        sigaddset(&sa.sa_mask, SIGTERM);
1230
        sigaddset(&sa.sa_mask, SIGQUIT);
1231
        sigaddset(&sa.sa_mask, SIGPIPE);
1232

    
1233
        sigaction(SIGHUP, &sa, NULL);
1234
        sigaction(SIGINT, &sa, NULL);
1235
        sigaction(SIGTERM, &sa, NULL);
1236
        sigaction(SIGQUIT, &sa, NULL);
1237
        sigaction(SIGPIPE, &sa, NULL);
1238
}
1239
#endif
1240

    
1241
#define ADD_SYM(sym)        syl_plugin_add_symbol(#sym, sym)
1242

    
1243
static void plugin_init(void)
1244
{
1245
        MainWindow *mainwin;
1246
        gchar *path;
1247

    
1248
        mainwin = main_window_get();
1249

    
1250
        STATUSBAR_PUSH(mainwin, _("Loading plug-ins..."));
1251

    
1252
        if (syl_plugin_init_lib() != 0) {
1253
                STATUSBAR_POP(mainwin);
1254
                return;
1255
        }
1256

    
1257
        if (cmd.safe_mode) {
1258
                debug_print("plugin_init: safe mode enabled, skipping plug-in loading.\n");
1259
                STATUSBAR_POP(mainwin);
1260
                return;
1261
        }
1262

    
1263
        ADD_SYM(prog_version);
1264
        ADD_SYM(app_will_exit);
1265

    
1266
        ADD_SYM(main_window_lock);
1267
        ADD_SYM(main_window_unlock);
1268
        ADD_SYM(main_window_get);
1269
        ADD_SYM(main_window_popup);
1270

    
1271
        syl_plugin_add_symbol("main_window_menu_factory",
1272
                              mainwin->menu_factory);
1273
        syl_plugin_add_symbol("main_window_statusbar", mainwin->statusbar);
1274

    
1275
        ADD_SYM(folderview_get);
1276
        ADD_SYM(folderview_add_sub_widget);
1277
        ADD_SYM(folderview_select);
1278
        ADD_SYM(folderview_unselect);
1279
        ADD_SYM(folderview_select_next_unread);
1280
        ADD_SYM(folderview_get_selected_item);
1281
        ADD_SYM(folderview_check_new);
1282
        ADD_SYM(folderview_check_new_item);
1283
        ADD_SYM(folderview_check_new_all);
1284
        ADD_SYM(folderview_update_item);
1285
        ADD_SYM(folderview_update_item_foreach);
1286
        ADD_SYM(folderview_update_all_updated);
1287
        ADD_SYM(folderview_check_new_selected);
1288

    
1289
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1290
                              mainwin->folderview->mail_factory);
1291
        syl_plugin_add_symbol("folderview_imap_popup_factory",
1292
                              mainwin->folderview->imap_factory);
1293
        syl_plugin_add_symbol("folderview_news_popup_factory",
1294
                              mainwin->folderview->news_factory);
1295

    
1296
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1297
        syl_plugin_add_symbol("summaryview_popup_factory",
1298
                              mainwin->summaryview->popupfactory);
1299

    
1300
        ADD_SYM(summary_select_by_msgnum);
1301
        ADD_SYM(summary_select_by_msginfo);
1302
        ADD_SYM(summary_lock);
1303
        ADD_SYM(summary_unlock);
1304
        ADD_SYM(summary_is_locked);
1305
        ADD_SYM(summary_is_read_locked);
1306
        ADD_SYM(summary_write_lock);
1307
        ADD_SYM(summary_write_unlock);
1308
        ADD_SYM(summary_is_write_locked);
1309
        ADD_SYM(summary_get_current_folder);
1310
        ADD_SYM(summary_get_selection_type);
1311
        ADD_SYM(summary_get_selected_msg_list);
1312
        ADD_SYM(summary_get_msg_list);
1313
        ADD_SYM(summary_show_queued_msgs);
1314
        ADD_SYM(summary_redisplay_msg);
1315
        ADD_SYM(summary_open_msg);
1316
        ADD_SYM(summary_view_source);
1317
        ADD_SYM(summary_reedit);
1318
        ADD_SYM(summary_update_selected_rows);
1319
        ADD_SYM(summary_update_by_msgnum);
1320

    
1321
        ADD_SYM(messageview_create_with_new_window);
1322
        ADD_SYM(messageview_show);
1323

    
1324
        ADD_SYM(compose_new);
1325
        ADD_SYM(compose_entry_set);
1326
        ADD_SYM(compose_entry_append);
1327
        ADD_SYM(compose_entry_get_text);
1328
        ADD_SYM(compose_lock);
1329
        ADD_SYM(compose_unlock);
1330

    
1331
        ADD_SYM(foldersel_folder_sel);
1332
        ADD_SYM(foldersel_folder_sel_full);
1333

    
1334
        ADD_SYM(input_dialog);
1335
        ADD_SYM(input_dialog_with_invisible);
1336

    
1337
        ADD_SYM(manage_window_set_transient);
1338
        ADD_SYM(manage_window_signals_connect);
1339
        ADD_SYM(manage_window_get_focus_window);
1340

    
1341
        ADD_SYM(inc_mail);
1342
        ADD_SYM(inc_is_active);
1343
        ADD_SYM(inc_lock);
1344
        ADD_SYM(inc_unlock);
1345

    
1346
#if USE_UPDATE_CHECK
1347
        ADD_SYM(update_check);
1348
        ADD_SYM(update_check_set_check_url);
1349
        ADD_SYM(update_check_get_check_url);
1350
        ADD_SYM(update_check_set_download_url);
1351
        ADD_SYM(update_check_get_download_url);
1352
        ADD_SYM(update_check_set_jump_url);
1353
        ADD_SYM(update_check_get_jump_url);
1354
#ifdef USE_UPDATE_CHECK_PLUGIN
1355
        ADD_SYM(update_check_set_check_plugin_url);
1356
        ADD_SYM(update_check_get_check_plugin_url);
1357
        ADD_SYM(update_check_set_jump_plugin_url);
1358
        ADD_SYM(update_check_get_jump_plugin_url);
1359
#endif /* USE_UPDATE_CHECK_PLUGIN */
1360
#endif
1361

    
1362
        ADD_SYM(alertpanel_full);
1363
        ADD_SYM(alertpanel);
1364
        ADD_SYM(alertpanel_message);
1365
        ADD_SYM(alertpanel_message_with_disable);
1366

    
1367
        ADD_SYM(send_message);
1368
        ADD_SYM(send_message_queue_all);
1369
        ADD_SYM(send_message_set_reply_flag);
1370
        ADD_SYM(send_message_set_forward_flags);
1371

    
1372
        ADD_SYM(notification_window_open);
1373
        ADD_SYM(notification_window_set_message);
1374
        ADD_SYM(notification_window_close);
1375

    
1376
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1377

    
1378
        /* loading plug-ins from user plug-in directory */
1379
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1380
        syl_plugin_load_all(path);
1381
        g_free(path);
1382

    
1383
        /* loading plug-ins from system plug-in directory */
1384
#ifdef G_OS_WIN32
1385
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR,
1386
                           NULL);
1387
        syl_plugin_load_all(path);
1388
        g_free(path);
1389
#else
1390
        syl_plugin_load_all(PLUGINDIR);
1391
#endif
1392

    
1393
        STATUSBAR_POP(mainwin);
1394
}
1395

    
1396
static gchar *get_socket_name(void)
1397
{
1398
        static gchar *filename = NULL;
1399

    
1400
        if (filename == NULL) {
1401
                filename = g_strdup_printf("%s%c%s-%d",
1402
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1403
                                           instance_id ? instance_id : "sylpheed",
1404
#if HAVE_GETUID
1405
                                           getuid());
1406
#else
1407
                                           0);
1408
#endif
1409
        }
1410

    
1411
        return filename;
1412
}
1413

    
1414
static gint prohibit_duplicate_launch(void)
1415
{
1416
        gint sock;
1417

    
1418
#ifdef G_OS_WIN32
1419
        HANDLE hmutex;
1420
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1421
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1422

    
1423
        debug_print("prohibit_duplicate_launch: checking mutex: %s\n", ins_id);
1424
        hmutex = CreateMutexA(NULL, FALSE, ins_id);
1425
        if (!hmutex) {
1426
                g_warning("cannot create Mutex: %s\n", ins_id);
1427
                return -1;
1428
        }
1429
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
1430
                debug_print("prohibit_duplicate_launch: creating socket: port %d\n", port);
1431
                sock = fd_open_inet(port);
1432
                if (sock < 0)
1433
                        return 0;
1434
                return sock;
1435
        }
1436

    
1437
        debug_print("prohibit_duplicate_launch: connecting to socket: port %d\n", port);
1438
        sock = fd_connect_inet(port);
1439
        if (sock < 0)
1440
                return -1;
1441
#else
1442
        gchar *path;
1443

    
1444
        path = get_socket_name();
1445
        debug_print("prohibit_duplicate_launch: checking socket: %s\n", path);
1446
        sock = fd_connect_unix(path);
1447
        if (sock < 0) {
1448
                debug_print("prohibit_duplicate_launch: creating socket: %s\n", path);
1449
                g_unlink(path);
1450
                return fd_open_unix(path);
1451
        }
1452
#endif
1453

    
1454
        /* remote command mode */
1455

    
1456
        debug_print(_("another Sylpheed is already running.\n"));
1457

    
1458
        if (cmd.receive_all)
1459
                fd_write_all(sock, "receive_all\n", 12);
1460
        else if (cmd.receive)
1461
                fd_write_all(sock, "receive\n", 8);
1462
        else if (cmd.compose && cmd.attach_files) {
1463
                gchar *str, *compose_str;
1464
                gint i;
1465

    
1466
                if (cmd.compose_mailto)
1467
                        compose_str = g_strdup_printf("compose_attach %s\n",
1468
                                                      cmd.compose_mailto);
1469
                else
1470
                        compose_str = g_strdup("compose_attach\n");
1471

    
1472
                fd_write_all(sock, compose_str, strlen(compose_str));
1473
                g_free(compose_str);
1474

    
1475
                for (i = 0; i < cmd.attach_files->len; i++) {
1476
                        str = g_ptr_array_index(cmd.attach_files, i);
1477
                        fd_write_all(sock, str, strlen(str));
1478
                        fd_write_all(sock, "\n", 1);
1479
                }
1480

    
1481
                fd_write_all(sock, ".\n", 2);
1482
        } else if (cmd.compose) {
1483
                gchar *compose_str;
1484

    
1485
                if (cmd.compose_mailto)
1486
                        compose_str = g_strdup_printf
1487
                                ("compose %s\n", cmd.compose_mailto);
1488
                else
1489
                        compose_str = g_strdup("compose\n");
1490

    
1491
                fd_write_all(sock, compose_str, strlen(compose_str));
1492
                g_free(compose_str);
1493
        } else if (cmd.send) {
1494
                fd_write_all(sock, "send\n", 5);
1495
        } else if (cmd.status || cmd.status_full) {
1496
                gchar buf[BUFFSIZE];
1497
                gint i;
1498
                const gchar *command;
1499
                GPtrArray *folders;
1500
                gchar *folder;
1501

    
1502
                command = cmd.status_full ? "status-full\n" : "status\n";
1503
                folders = cmd.status_full ? cmd.status_full_folders :
1504
                        cmd.status_folders;
1505

    
1506
                fd_write_all(sock, command, strlen(command));
1507
                for (i = 0; folders && i < folders->len; ++i) {
1508
                        folder = g_ptr_array_index(folders, i);
1509
                        fd_write_all(sock, folder, strlen(folder));
1510
                        fd_write_all(sock, "\n", 1);
1511
                }
1512
                fd_write_all(sock, ".\n", 2);
1513
                for (;;) {
1514
                        fd_gets(sock, buf, sizeof(buf));
1515
                        if (!strncmp(buf, ".\n", 2)) break;
1516
                        fputs(buf, stdout);
1517
                }
1518
        } else if (cmd.open_msg) {
1519
                gchar *str;
1520

    
1521
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1522
                fd_write_all(sock, str, strlen(str));
1523
                g_free(str);
1524
        } else if (cmd.exit) {
1525
                fd_write_all(sock, "exit\n", 5);
1526
        } else {
1527
#ifdef G_OS_WIN32
1528
                HWND hwnd;
1529

    
1530
                fd_write_all(sock, "popup\n", 6);
1531
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1532
                        SetForegroundWindow(hwnd);
1533
#else
1534
                fd_write_all(sock, "popup\n", 6);
1535
#endif
1536
        }
1537

    
1538
        fd_close(sock);
1539
        return -1;
1540
}
1541

    
1542
static gint lock_socket_remove(void)
1543
{
1544
#ifndef G_OS_WIN32
1545
        gchar *filename;
1546
#endif
1547

    
1548
        if (lock_socket < 0) return -1;
1549

    
1550
        if (lock_socket_tag > 0)
1551
                g_source_remove(lock_socket_tag);
1552
        if (lock_ch) {
1553
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1554
                g_io_channel_unref(lock_ch);
1555
                lock_ch = NULL;
1556
        }
1557

    
1558
#ifndef G_OS_WIN32
1559
        filename = get_socket_name();
1560
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1561
        g_unlink(filename);
1562
#endif
1563

    
1564
        return 0;
1565
}
1566

    
1567
static GPtrArray *get_folder_item_list(gint sock)
1568
{
1569
        gchar buf[BUFFSIZE];
1570
        FolderItem *item;
1571
        GPtrArray *folders = NULL;
1572

    
1573
        for (;;) {
1574
                fd_gets(sock, buf, sizeof(buf));
1575
                if (!strncmp(buf, ".\n", 2)) break;
1576
                strretchomp(buf);
1577
                if (!folders) folders = g_ptr_array_new();
1578
                item = folder_find_item_from_identifier(buf);
1579
                if (item)
1580
                        g_ptr_array_add(folders, item);
1581
                else
1582
                        g_warning("no such folder: %s\n", buf);
1583
        }
1584

    
1585
        return folders;
1586
}
1587

    
1588
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1589
                                     gpointer data)
1590
{
1591
        MainWindow *mainwin = (MainWindow *)data;
1592
        gint fd, sock;
1593
        gchar buf[BUFFSIZE];
1594

    
1595
#if USE_THREADS
1596
        gdk_threads_enter();
1597
#endif
1598

    
1599
        fd = g_io_channel_unix_get_fd(source);
1600
        sock = fd_accept(fd);
1601
        fd_gets(sock, buf, sizeof(buf));
1602

    
1603
        if (!strncmp(buf, "popup", 5)) {
1604
#ifdef G_OS_WIN32
1605
                HWND hwnd;
1606

    
1607
                hwnd = (HWND)gdk_win32_drawable_get_handle
1608
                        (GDK_DRAWABLE(mainwin->window->window));
1609
                fd_write(sock, (gchar *)&hwnd, sizeof(hwnd));
1610
                if (mainwin->window_hidden)
1611
                        main_window_popup(mainwin);
1612
#else
1613
                main_window_popup(mainwin);
1614
#endif
1615
        } else if (!strncmp(buf, "receive_all", 11)) {
1616
                main_window_popup(mainwin);
1617
                if (!gtkut_window_modal_exist())
1618
                        inc_all_account_mail(mainwin, FALSE);
1619
        } else if (!strncmp(buf, "receive", 7)) {
1620
                main_window_popup(mainwin);
1621
                if (!gtkut_window_modal_exist())
1622
                        inc_mail(mainwin);
1623
        } else if (!strncmp(buf, "compose_attach", 14)) {
1624
                GPtrArray *files;
1625
                gchar *mailto;
1626

    
1627
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
1628
                files = g_ptr_array_new();
1629
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1630
                        if (buf[0] == '.' && buf[1] == '\n') break;
1631
                        strretchomp(buf);
1632
                        g_ptr_array_add(files, g_strdup(buf));
1633
                }
1634
                open_compose_new(mailto, files);
1635
                ptr_array_free_strings(files);
1636
                g_ptr_array_free(files, TRUE);
1637
                g_free(mailto);
1638
        } else if (!strncmp(buf, "compose", 7)) {
1639
                open_compose_new(buf + strlen("compose") + 1, NULL);
1640
        } else if (!strncmp(buf, "send", 4)) {
1641
                send_queue();
1642
        } else if (!strncmp(buf, "status-full", 11) ||
1643
                   !strncmp(buf, "status", 6)) {
1644
                gchar *status;
1645
                GPtrArray *folders;
1646

    
1647
                folders = get_folder_item_list(sock);
1648
                status = folder_get_status
1649
                        (folders, !strncmp(buf, "status-full", 11));
1650
                fd_write_all(sock, status, strlen(status));
1651
                fd_write_all(sock, ".\n", 2);
1652
                g_free(status);
1653
                if (folders) g_ptr_array_free(folders, TRUE);
1654
        } else if (!strncmp(buf, "open", 4)) {
1655
                strretchomp(buf);
1656
                if (strlen(buf) < 6 || buf[4] != ' ') {
1657
                        fd_close(sock);
1658
#if USE_THREADS
1659
                        gdk_threads_leave();
1660
#endif
1661
                        return TRUE;
1662
                }
1663
                open_message(buf + 5);
1664
        } else if (!strncmp(buf, "exit", 4)) {
1665
                fd_close(sock);
1666
                app_will_exit(TRUE);
1667
        }
1668

    
1669
        fd_close(sock);
1670

    
1671
#if USE_THREADS
1672
        gdk_threads_leave();
1673
#endif
1674

    
1675
        return TRUE;
1676
}
1677

    
1678
static void remote_command_exec(void)
1679
{
1680
        MainWindow *mainwin;
1681

    
1682
        mainwin = main_window_get();
1683

    
1684
        if (prefs_common.open_inbox_on_startup) {
1685
                FolderItem *item;
1686
                PrefsAccount *ac;
1687

    
1688
                ac = account_get_default();
1689
                if (!ac)
1690
                        ac = cur_account;
1691
                item = ac && ac->inbox
1692
                        ? folder_find_item_from_identifier(ac->inbox)
1693
                        : folder_get_default_inbox();
1694
                folderview_select(mainwin->folderview, item);
1695
        }
1696

    
1697
        if (!gtkut_window_modal_exist()) {
1698
                if (cmd.compose)
1699
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1700

    
1701
                if (cmd.open_msg)
1702
                        open_message(cmd.open_msg);
1703

    
1704
                if (cmd.receive_all)
1705
                        inc_all_account_mail(mainwin, FALSE);
1706
                else if (prefs_common.chk_on_startup)
1707
                        inc_all_account_mail(mainwin, TRUE);
1708
                else if (cmd.receive)
1709
                        inc_mail(mainwin);
1710

    
1711
                if (cmd.send)
1712
                        send_queue();
1713
        }
1714

    
1715
        if (cmd.attach_files) {
1716
                ptr_array_free_strings(cmd.attach_files);
1717
                g_ptr_array_free(cmd.attach_files, TRUE);
1718
                cmd.attach_files = NULL;
1719
        }
1720
        if (cmd.status_folders) {
1721
                g_ptr_array_free(cmd.status_folders, TRUE);
1722
                cmd.status_folders = NULL;
1723
        }
1724
        if (cmd.status_full_folders) {
1725
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1726
                cmd.status_full_folders = NULL;
1727
        }
1728
        if (cmd.open_msg) {
1729
                g_free(cmd.open_msg);
1730
                cmd.open_msg = NULL;
1731
        }
1732
        if (cmd.exit) {
1733
                app_will_exit(TRUE);
1734
        }
1735
}
1736

    
1737
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
1738
static void migrate_old_config(void)
1739
{
1740
        GDir *dir;
1741
        const gchar *dir_name;
1742
        GPatternSpec *pspec;
1743

    
1744
        if (alertpanel(_("Migration of configuration"),
1745
                       _("The previous version of configuration found.\n"
1746
                         "Do you want to migrate it?"),
1747
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1748
                return;
1749

    
1750
        debug_print("Migrating old configuration...\n");
1751

    
1752
#define COPY_FILE(rcfile)                                                \
1753
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1754
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1755
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1756
                               conv_get_locale_charset_str());                \
1757
        }
1758

    
1759
        COPY_FILE(ACCOUNT_RC);
1760
        COPY_FILE(ACTIONS_RC);
1761
        COPY_FILE(COMMON_RC);
1762
        COPY_FILE(CUSTOM_HEADER_RC);
1763
        COPY_FILE(DISPLAY_HEADER_RC);
1764
        COPY_FILE(FILTER_HEADER_RC);
1765
        COPY_FILE(COMMAND_HISTORY);
1766

    
1767
#undef COPY_FILE
1768

    
1769
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1770
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1771
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1772
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1773
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1774
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1775
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1776
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1777
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1778

    
1779
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1780
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1781
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1782
                              conv_get_locale_charset_str());
1783
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1784
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1785
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1786

    
1787
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1788
                return;
1789

    
1790
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1791
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1792
                return;
1793
        }
1794

    
1795
        pspec = g_pattern_spec_new("addrbook-*.xml");
1796

    
1797
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1798
                if (g_pattern_match_string(pspec, dir_name)) {
1799
                        gchar *old_file;
1800
                        gchar *new_file;
1801

    
1802
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1803
                                               dir_name, NULL);
1804
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1805
                                               dir_name, NULL);
1806
                        copy_file(old_file, new_file, FALSE);
1807
                        g_free(new_file);
1808
                        g_free(old_file);
1809
                }
1810
        }
1811

    
1812
        g_pattern_spec_free(pspec);
1813
        g_dir_close(dir);
1814
}
1815
#endif /* !G_OS_WIN32 && !__APPLE__ */
1816

    
1817
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1818
{
1819
        gchar *utf8addr = NULL;
1820
#ifdef G_OS_WIN32
1821
        GPtrArray *utf8files = NULL;
1822
#endif
1823

    
1824
        if (gtkut_window_modal_exist())
1825
                return;
1826

    
1827
        if (address) {
1828
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1829
                if (utf8addr)
1830
                        g_strstrip(utf8addr);
1831
                debug_print("open compose: %s\n", utf8addr ? utf8addr : "");
1832
        }
1833

    
1834
#ifdef G_OS_WIN32
1835
        if (attach_files) {
1836
                gint i;
1837
                gchar *file, *utf8file;
1838

    
1839
                utf8files = g_ptr_array_new();
1840
                for (i = 0; i < attach_files->len; i++) {
1841
                        file = g_ptr_array_index(attach_files, i);
1842
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1843
                        if (utf8file)
1844
                                g_ptr_array_add(utf8files, utf8file);
1845
                }
1846
        }
1847

    
1848
        compose_new(NULL, NULL, utf8addr, utf8files);
1849
        if (utf8files) {
1850
                ptr_array_free_strings(utf8files);
1851
                g_ptr_array_free(utf8files, TRUE);
1852
        }
1853
#else
1854
        compose_new(NULL, NULL, utf8addr, attach_files);
1855
#endif
1856

    
1857
        g_free(utf8addr);
1858
}
1859

    
1860
static void open_message_file(const gchar *file)
1861
{
1862
        MsgInfo *msginfo;
1863
        MsgFlags flags = {0};
1864
        MessageView *msgview;
1865

    
1866
        g_return_if_fail(file != NULL);
1867

    
1868
        debug_print("open message file: %s\n", file);
1869

    
1870
        if (!is_file_exist(file) || get_file_size(file) <= 0) {
1871
                debug_print("file not found: %s\n", file);
1872
                return;
1873
        }
1874

    
1875
        msginfo = procheader_parse_file(file, flags, FALSE);
1876
        if (msginfo) {
1877
                msginfo->file_path = g_strdup(file);
1878
                msgview = messageview_create_with_new_window();
1879
                messageview_show(msgview, msginfo, FALSE);
1880
                procmsg_msginfo_free(msginfo);
1881
        } else
1882
                debug_print("cannot open message: %s\n", file);
1883
}
1884

    
1885
static void open_message(const gchar *path)
1886
{
1887
        gchar *fid;
1888
        gchar *msg;
1889
        gint num;
1890
        FolderItem *item;
1891
        MsgInfo *msginfo;
1892
        MessageView *msgview;
1893
        gchar *file;
1894

    
1895
        g_return_if_fail(path != NULL);
1896

    
1897
        if (gtkut_window_modal_exist())
1898
                return;
1899

    
1900
        debug_print("open message: %s\n", path);
1901

    
1902
        if (!strncmp(path, "file:", 5)) {
1903
                file = g_filename_from_uri(path, NULL, NULL);
1904
                open_message_file(file);
1905
                g_free(file);
1906
                return;
1907
        } else if (g_path_is_absolute(path)) {
1908
                open_message_file(path);
1909
                return;
1910
        }
1911

    
1912
        /* relative path, or folder identifier */
1913

    
1914
        fid = g_path_get_dirname(path);
1915
        msg = g_path_get_basename(path);
1916
        num = to_number(msg);
1917
        item = folder_find_item_from_identifier(fid);
1918

    
1919
        if (num > 0 && item) {
1920
                debug_print("open folder id: %s (msg %d)\n", fid, num);
1921
                msginfo = folder_item_get_msginfo(item, num);
1922
                if (msginfo) {
1923
                        msgview = messageview_create_with_new_window();
1924
                        messageview_show(msgview, msginfo, FALSE);
1925
                        procmsg_msginfo_free(msginfo);
1926
                        g_free(msg);
1927
                        g_free(fid);
1928
                        return;
1929
                } else
1930
                        debug_print("message %d not found\n", num);
1931
        }
1932

    
1933
        g_free(msg);
1934
        g_free(fid);
1935

    
1936
        /* relative path */
1937

    
1938
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, path, NULL);
1939
        open_message_file(file);
1940
        g_free(file);
1941
}
1942

    
1943
static void send_queue(void)
1944
{
1945
        GList *list;
1946

    
1947
        if (gtkut_window_modal_exist())
1948
                return;
1949
        if (!main_window_toggle_online_if_offline(main_window_get()))
1950
                return;
1951

    
1952
        for (list = folder_get_list(); list != NULL; list = list->next) {
1953
                Folder *folder = list->data;
1954

    
1955
                if (folder->queue) {
1956
                        gint ret;
1957

    
1958
                        ret = send_message_queue_all(folder->queue,
1959
                                                     prefs_common.savemsg,
1960
                                                     prefs_common.filter_sent);
1961
                        statusbar_pop_all();
1962
                        if (ret > 0)
1963
                                folder_item_scan(folder->queue);
1964
                }
1965
        }
1966

    
1967
        folderview_update_all_updated(TRUE);
1968
        main_window_set_menu_sensitive(main_window_get());
1969
        main_window_set_toolbar_sensitive(main_window_get());
1970
}