Statistics
| Revision:

root / src / main.c @ 3200

History | View | Annotate | Download (46.9 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 "plugin.h"
85
#include "plugin_manager.h"
86
#include "foldersel.h"
87
#include "update_check.h"
88
#include "colorlabel.h"
89

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

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

    
105
#include "version.h"
106

    
107
gchar *prog_version;
108

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

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

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

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

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

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

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

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

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

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

    
179
static void remote_command_exec                (void);
180

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

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

    
189
static void send_queue                        (void);
190

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

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

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

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

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

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

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

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

    
248
        syl_app = syl_app_create();
249

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

    
254
        parse_gtkrc_files();
255
        setup_rc_dir();
256

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

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

    
271
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
272

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

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

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

    
290
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
291

    
292
        check_gpg();
293

    
294
        sock_set_io_timeout(prefs_common.io_timeout_secs);
295

    
296
        gtkut_widget_init();
297

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

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

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

    
322
        set_log_handlers(TRUE);
323

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

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

    
337
        account_set_menu();
338
        main_window_reflect_prefs_all();
339

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

    
346
        addressbook_read_file();
347

    
348
        register_system_events();
349

    
350
        inc_autocheck_timer_init(mainwin);
351

    
352
        plugin_init();
353

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

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

    
361
        remote_command_exec();
362

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

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

    
373
        return 0;
374
}
375

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

    
382
        if (init_console_done)
383
                return;
384

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

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

    
401
        init_console_done = TRUE;
402
#endif
403
}
404

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

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

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

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

    
425
        gchar *file;
426

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
817
        syl_setup_rc_dir();
818
}
819

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

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

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

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

    
875
        mainwin = main_window_get();
876

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

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

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

    
904
        inc_autocheck_timer_remove();
905

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

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

    
917
        syl_plugin_unload_all();
918

    
919
        trayicon_destroy(mainwin->tray_icon);
920

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

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

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

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

    
948
        cleanup_console();
949

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

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

    
956
        exit(0);
957
}
958

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1134
        return TRUE;
1135
}
1136

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

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

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

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

    
1181
        if (hwnd)
1182
                return;
1183

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

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

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

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

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

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

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

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

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

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

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

    
1247
        mainwin = main_window_get();
1248

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1371
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1372

    
1373
        /* loading plug-ins from user plug-in directory */
1374
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1375
        syl_plugin_load_all(path);
1376
        g_free(path);
1377

    
1378
        /* loading plug-ins from system plug-in directory */
1379
#ifdef G_OS_WIN32
1380
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR,
1381
                           NULL);
1382
        syl_plugin_load_all(path);
1383
        g_free(path);
1384
#else
1385
        syl_plugin_load_all(PLUGINDIR);
1386
#endif
1387

    
1388
        STATUSBAR_POP(mainwin);
1389
}
1390

    
1391
static gchar *get_socket_name(void)
1392
{
1393
        static gchar *filename = NULL;
1394

    
1395
        if (filename == NULL) {
1396
                filename = g_strdup_printf("%s%c%s-%d",
1397
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1398
                                           instance_id ? instance_id : "sylpheed",
1399
#if HAVE_GETUID
1400
                                           getuid());
1401
#else
1402
                                           0);
1403
#endif
1404
        }
1405

    
1406
        return filename;
1407
}
1408

    
1409
static gint prohibit_duplicate_launch(void)
1410
{
1411
        gint sock;
1412

    
1413
#ifdef G_OS_WIN32
1414
        HANDLE hmutex;
1415
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1416
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1417

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

    
1432
        debug_print("prohibit_duplicate_launch: connecting to socket: port %d\n", port);
1433
        sock = fd_connect_inet(port);
1434
        if (sock < 0)
1435
                return -1;
1436
#else
1437
        gchar *path;
1438

    
1439
        path = get_socket_name();
1440
        debug_print("prohibit_duplicate_launch: checking socket: %s\n", path);
1441
        sock = fd_connect_unix(path);
1442
        if (sock < 0) {
1443
                debug_print("prohibit_duplicate_launch: creating socket: %s\n", path);
1444
                g_unlink(path);
1445
                return fd_open_unix(path);
1446
        }
1447
#endif
1448

    
1449
        /* remote command mode */
1450

    
1451
        debug_print(_("another Sylpheed is already running.\n"));
1452

    
1453
        if (cmd.receive_all)
1454
                fd_write_all(sock, "receive_all\n", 12);
1455
        else if (cmd.receive)
1456
                fd_write_all(sock, "receive\n", 8);
1457
        else if (cmd.compose && cmd.attach_files) {
1458
                gchar *str, *compose_str;
1459
                gint i;
1460

    
1461
                if (cmd.compose_mailto)
1462
                        compose_str = g_strdup_printf("compose_attach %s\n",
1463
                                                      cmd.compose_mailto);
1464
                else
1465
                        compose_str = g_strdup("compose_attach\n");
1466

    
1467
                fd_write_all(sock, compose_str, strlen(compose_str));
1468
                g_free(compose_str);
1469

    
1470
                for (i = 0; i < cmd.attach_files->len; i++) {
1471
                        str = g_ptr_array_index(cmd.attach_files, i);
1472
                        fd_write_all(sock, str, strlen(str));
1473
                        fd_write_all(sock, "\n", 1);
1474
                }
1475

    
1476
                fd_write_all(sock, ".\n", 2);
1477
        } else if (cmd.compose) {
1478
                gchar *compose_str;
1479

    
1480
                if (cmd.compose_mailto)
1481
                        compose_str = g_strdup_printf
1482
                                ("compose %s\n", cmd.compose_mailto);
1483
                else
1484
                        compose_str = g_strdup("compose\n");
1485

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

    
1497
                command = cmd.status_full ? "status-full\n" : "status\n";
1498
                folders = cmd.status_full ? cmd.status_full_folders :
1499
                        cmd.status_folders;
1500

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

    
1516
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1517
                fd_write_all(sock, str, strlen(str));
1518
                g_free(str);
1519
        } else if (cmd.exit) {
1520
                fd_write_all(sock, "exit\n", 5);
1521
        } else {
1522
#ifdef G_OS_WIN32
1523
                HWND hwnd;
1524

    
1525
                fd_write_all(sock, "popup\n", 6);
1526
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1527
                        SetForegroundWindow(hwnd);
1528
#else
1529
                fd_write_all(sock, "popup\n", 6);
1530
#endif
1531
        }
1532

    
1533
        fd_close(sock);
1534
        return -1;
1535
}
1536

    
1537
static gint lock_socket_remove(void)
1538
{
1539
#ifndef G_OS_WIN32
1540
        gchar *filename;
1541
#endif
1542

    
1543
        if (lock_socket < 0) return -1;
1544

    
1545
        if (lock_socket_tag > 0)
1546
                g_source_remove(lock_socket_tag);
1547
        if (lock_ch) {
1548
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1549
                g_io_channel_unref(lock_ch);
1550
                lock_ch = NULL;
1551
        }
1552

    
1553
#ifndef G_OS_WIN32
1554
        filename = get_socket_name();
1555
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1556
        g_unlink(filename);
1557
#endif
1558

    
1559
        return 0;
1560
}
1561

    
1562
static GPtrArray *get_folder_item_list(gint sock)
1563
{
1564
        gchar buf[BUFFSIZE];
1565
        FolderItem *item;
1566
        GPtrArray *folders = NULL;
1567

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

    
1580
        return folders;
1581
}
1582

    
1583
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1584
                                     gpointer data)
1585
{
1586
        MainWindow *mainwin = (MainWindow *)data;
1587
        gint fd, sock;
1588
        gchar buf[BUFFSIZE];
1589

    
1590
#if USE_THREADS
1591
        gdk_threads_enter();
1592
#endif
1593

    
1594
        fd = g_io_channel_unix_get_fd(source);
1595
        sock = fd_accept(fd);
1596
        fd_gets(sock, buf, sizeof(buf));
1597

    
1598
        if (!strncmp(buf, "popup", 5)) {
1599
#ifdef G_OS_WIN32
1600
                HWND hwnd;
1601

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

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

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

    
1664
        fd_close(sock);
1665

    
1666
#if USE_THREADS
1667
        gdk_threads_leave();
1668
#endif
1669

    
1670
        return TRUE;
1671
}
1672

    
1673
static void remote_command_exec(void)
1674
{
1675
        MainWindow *mainwin;
1676

    
1677
        mainwin = main_window_get();
1678

    
1679
        if (prefs_common.open_inbox_on_startup) {
1680
                FolderItem *item;
1681
                PrefsAccount *ac;
1682

    
1683
                ac = account_get_default();
1684
                if (!ac)
1685
                        ac = cur_account;
1686
                item = ac && ac->inbox
1687
                        ? folder_find_item_from_identifier(ac->inbox)
1688
                        : folder_get_default_inbox();
1689
                folderview_select(mainwin->folderview, item);
1690
        }
1691

    
1692
        if (!gtkut_window_modal_exist()) {
1693
                if (cmd.compose)
1694
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1695

    
1696
                if (cmd.open_msg)
1697
                        open_message(cmd.open_msg);
1698

    
1699
                if (cmd.receive_all)
1700
                        inc_all_account_mail(mainwin, FALSE);
1701
                else if (prefs_common.chk_on_startup)
1702
                        inc_all_account_mail(mainwin, TRUE);
1703
                else if (cmd.receive)
1704
                        inc_mail(mainwin);
1705

    
1706
                if (cmd.send)
1707
                        send_queue();
1708
        }
1709

    
1710
        if (cmd.attach_files) {
1711
                ptr_array_free_strings(cmd.attach_files);
1712
                g_ptr_array_free(cmd.attach_files, TRUE);
1713
                cmd.attach_files = NULL;
1714
        }
1715
        if (cmd.status_folders) {
1716
                g_ptr_array_free(cmd.status_folders, TRUE);
1717
                cmd.status_folders = NULL;
1718
        }
1719
        if (cmd.status_full_folders) {
1720
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1721
                cmd.status_full_folders = NULL;
1722
        }
1723
        if (cmd.open_msg) {
1724
                g_free(cmd.open_msg);
1725
                cmd.open_msg = NULL;
1726
        }
1727
        if (cmd.exit) {
1728
                app_will_exit(TRUE);
1729
        }
1730
}
1731

    
1732
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
1733
static void migrate_old_config(void)
1734
{
1735
        GDir *dir;
1736
        const gchar *dir_name;
1737
        GPatternSpec *pspec;
1738

    
1739
        if (alertpanel(_("Migration of configuration"),
1740
                       _("The previous version of configuration found.\n"
1741
                         "Do you want to migrate it?"),
1742
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1743
                return;
1744

    
1745
        debug_print("Migrating old configuration...\n");
1746

    
1747
#define COPY_FILE(rcfile)                                                \
1748
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1749
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1750
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1751
                               conv_get_locale_charset_str());                \
1752
        }
1753

    
1754
        COPY_FILE(ACCOUNT_RC);
1755
        COPY_FILE(ACTIONS_RC);
1756
        COPY_FILE(COMMON_RC);
1757
        COPY_FILE(CUSTOM_HEADER_RC);
1758
        COPY_FILE(DISPLAY_HEADER_RC);
1759
        COPY_FILE(FILTER_HEADER_RC);
1760
        COPY_FILE(COMMAND_HISTORY);
1761

    
1762
#undef COPY_FILE
1763

    
1764
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1765
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1766
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1767
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1768
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1769
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1770
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1771
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1772
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1773

    
1774
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1775
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1776
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1777
                              conv_get_locale_charset_str());
1778
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1779
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1780
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1781

    
1782
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1783
                return;
1784

    
1785
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1786
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1787
                return;
1788
        }
1789

    
1790
        pspec = g_pattern_spec_new("addrbook-*.xml");
1791

    
1792
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1793
                if (g_pattern_match_string(pspec, dir_name)) {
1794
                        gchar *old_file;
1795
                        gchar *new_file;
1796

    
1797
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1798
                                               dir_name, NULL);
1799
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1800
                                               dir_name, NULL);
1801
                        copy_file(old_file, new_file, FALSE);
1802
                        g_free(new_file);
1803
                        g_free(old_file);
1804
                }
1805
        }
1806

    
1807
        g_pattern_spec_free(pspec);
1808
        g_dir_close(dir);
1809
}
1810
#endif /* !G_OS_WIN32 && !__APPLE__ */
1811

    
1812
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1813
{
1814
        gchar *utf8addr = NULL;
1815
#ifdef G_OS_WIN32
1816
        GPtrArray *utf8files = NULL;
1817
#endif
1818

    
1819
        if (gtkut_window_modal_exist())
1820
                return;
1821

    
1822
        if (address) {
1823
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1824
                if (utf8addr)
1825
                        g_strstrip(utf8addr);
1826
                debug_print("open compose: %s\n", utf8addr ? utf8addr : "");
1827
        }
1828

    
1829
#ifdef G_OS_WIN32
1830
        if (attach_files) {
1831
                gint i;
1832
                gchar *file, *utf8file;
1833

    
1834
                utf8files = g_ptr_array_new();
1835
                for (i = 0; i < attach_files->len; i++) {
1836
                        file = g_ptr_array_index(attach_files, i);
1837
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1838
                        if (utf8file)
1839
                                g_ptr_array_add(utf8files, utf8file);
1840
                }
1841
        }
1842

    
1843
        compose_new(NULL, NULL, utf8addr, utf8files);
1844
        if (utf8files) {
1845
                ptr_array_free_strings(utf8files);
1846
                g_ptr_array_free(utf8files, TRUE);
1847
        }
1848
#else
1849
        compose_new(NULL, NULL, utf8addr, attach_files);
1850
#endif
1851

    
1852
        g_free(utf8addr);
1853
}
1854

    
1855
static void open_message_file(const gchar *file)
1856
{
1857
        MsgInfo *msginfo;
1858
        MsgFlags flags = {0};
1859
        MessageView *msgview;
1860

    
1861
        g_return_if_fail(file != NULL);
1862

    
1863
        debug_print("open message file: %s\n", file);
1864

    
1865
        if (!is_file_exist(file) || get_file_size(file) <= 0) {
1866
                debug_print("file not found: %s\n", file);
1867
                return;
1868
        }
1869

    
1870
        msginfo = procheader_parse_file(file, flags, FALSE);
1871
        if (msginfo) {
1872
                msginfo->file_path = g_strdup(file);
1873
                msgview = messageview_create_with_new_window();
1874
                messageview_show(msgview, msginfo, FALSE);
1875
                procmsg_msginfo_free(msginfo);
1876
        } else
1877
                debug_print("cannot open message: %s\n", file);
1878
}
1879

    
1880
static void open_message(const gchar *path)
1881
{
1882
        gchar *fid;
1883
        gchar *msg;
1884
        gint num;
1885
        FolderItem *item;
1886
        MsgInfo *msginfo;
1887
        MessageView *msgview;
1888
        gchar *file;
1889

    
1890
        g_return_if_fail(path != NULL);
1891

    
1892
        if (gtkut_window_modal_exist())
1893
                return;
1894

    
1895
        debug_print("open message: %s\n", path);
1896

    
1897
        if (!strncmp(path, "file:", 5)) {
1898
                file = g_filename_from_uri(path, NULL, NULL);
1899
                open_message_file(file);
1900
                g_free(file);
1901
                return;
1902
        } else if (g_path_is_absolute(path)) {
1903
                open_message_file(path);
1904
                return;
1905
        }
1906

    
1907
        /* relative path, or folder identifier */
1908

    
1909
        fid = g_path_get_dirname(path);
1910
        msg = g_path_get_basename(path);
1911
        num = to_number(msg);
1912
        item = folder_find_item_from_identifier(fid);
1913

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

    
1928
        g_free(msg);
1929
        g_free(fid);
1930

    
1931
        /* relative path */
1932

    
1933
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, path, NULL);
1934
        open_message_file(file);
1935
        g_free(file);
1936
}
1937

    
1938
static void send_queue(void)
1939
{
1940
        GList *list;
1941

    
1942
        if (gtkut_window_modal_exist())
1943
                return;
1944
        if (!main_window_toggle_online_if_offline(main_window_get()))
1945
                return;
1946

    
1947
        for (list = folder_get_list(); list != NULL; list = list->next) {
1948
                Folder *folder = list->data;
1949

    
1950
                if (folder->queue) {
1951
                        gint ret;
1952

    
1953
                        ret = send_message_queue_all(folder->queue,
1954
                                                     prefs_common.savemsg,
1955
                                                     prefs_common.filter_sent);
1956
                        statusbar_pop_all();
1957
                        if (ret > 0)
1958
                                folder_item_scan(folder->queue);
1959
                }
1960
        }
1961

    
1962
        folderview_update_all_updated(TRUE);
1963
        main_window_set_menu_sensitive(main_window_get());
1964
        main_window_set_toolbar_sensitive(main_window_get());
1965
}