Statistics
| Revision:

root / branches / nntpgrab-0.7 / client / gui / main.c @ 1922

History | View | Annotate | Download (19.7 KB)

1
/* 
2
    Copyright (C) 2005-2010  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#include 
20
#include 
21
#include 
22
#include 
23
#include "gui.h"
24
#include "config_gui.h"
25
#include "donate.xpm"
26

                
27
#ifdef DARWIN
28
#include 
29
#endif
30

                
31
#ifdef WIN32
32
#include 
33
#endif
34

                
35
NntpgrabGlue *glue = NULL;
36

                
37
void debug_initialize(void);
38
void info_initialize(void);
39
void config_initialize(void);
40
void config_gui_initialize(void);
41
void config_display_initialize(void);
42
void queue_initialize(void);
43
void callbacks_initialize(void);
44
void nzb_initialize(void);
45
void connections_initialize(void);
46
void notify_initialize(void);
47
void monitor_initialize(void);
48
void gui_par2_initialize(void);
49
void nzbcreator_initialize(void);
50
void auto_import_initialize(void);
51
void autoshutdown_initialize(void);
52
void gui_plugins_initialize(void);
53

                
54
gboolean    ipc_initialize(void);
55
void        ipc_cleanup(void);
56
void        ipc_send_open_nzb_file_request(const char *nzb_file);
57
gboolean    ipc_test_is_nntpgrab_already_running(gboolean also_check_server);
58

                
59
// auto_import.c
60
void    disable_auto_import(void);
61

                
62
static const char *nzb_file = NULL;
63
static gboolean initialized = FALSE;
64

                
65
#if !GTK_CHECK_VERSION(2,12,0)
66
/* The libglade used in RHEL 5 doesn't know the GtkLinkButton widget */
67
GtkWidget *
68
linkbutton_plugin_url_create(gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2)
69
{
70
    GtkWidget *button = gtk_link_button_new("");
71
    gtk_widget_show(button);
72

                
73
    return button;
74
}
75
#endif
76

                
77
G_MODULE_EXPORT void
78
on_btnQuit_clicked(GtkWidget *caller, gpointer data)
79
{
80
    GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
81

                
82
    gtk_widget_hide(windowMain);
83
    gtk_main_quit();
84
}
85

                
86
static void
87
load_auto_load_plugins(void)
88
{
89
    ConfigGUIOpts opts = config_gui_get_opts();
90
    NNTPGrabPluginInfo info;
91
    GList *list;
92

                
93
    list = opts.auto_load_plugins;
94
    while (list) {
95
        char *errmsg = NULL;
96
        const char *plugin_name = list->data;
97

                
98
        if (!nntpgrab_glue_plugins_get_plugin_info(glue, plugin_name, &info) ||
99
            info.is_loaded == TRUE) {
100

                
101
            /* Plugin isn't found or is already loaded. Ignore */
102
            list = g_list_next(list);
103
            continue;
104
        }
105

                
106
        if (!nntpgrab_glue_plugins_load_plugin(glue, plugin_name, &errmsg)) {
107
            GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
108
            char msg[1024];
109

                
110
            memset(&msg, 0, sizeof(msg));
111
            snprintf(msg, sizeof(msg) - 1, _("Unable to load plugin '%s': %s"), plugin_name, errmsg);
112
            nntpgrab_gui_base_dialog_show(windowMain, msg, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
113
            g_free(errmsg);
114
        }
115

                
116
        list = g_list_next(list);
117
    }
118
}
119

                
120
static gboolean
121
initialisation(gpointer data)
122
{
123
    GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
124
    GtkWidget *windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
125
    char *errmsg = NULL;
126
    GtkWidget *cmbConnectHostname;
127
    GtkWidget *spinConnectPort;
128
    char *hostname;
129
    int port;
130
    char *warnings = NULL;
131
#if GTK_CHECK_VERSION(2,90,0)
132
    GtkTreeIter iter;
133
    GtkTreeModel *model;
134
#endif
135

                
136
    gtk_widget_show(windowMain);
137

                
138
    cmbConnectHostname = nntpgrab_gui_base_get_widget("cmbConnectHostname");
139
    spinConnectPort = nntpgrab_gui_base_get_widget("spinConnectPort");
140
#if GTK_CHECK_VERSION(2,90,0)
141
    hostname = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cmbConnectHostname)))));
142
#else
143
    hostname = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cmbConnectHostname));
144
#endif
145
    port = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spinConnectPort));
146

                
147
    glue = nntpgrab_glue_new();
148

                
149
    if (!nntpgrab_glue_init(glue, NNTPGRAB_GLUE_VERSION, &errmsg)) {
150
        nntpgrab_glue_destroy(glue);
151
        glue = NULL;
152
        g_free(hostname);
153
        g_critical(_("NNTPGrab Initialisation FAILED:\n%s\n"), errmsg);
154
        g_free(errmsg);
155
        g_idle_add((GSourceFunc) gtk_main_quit, NULL);
156
        return FALSE;
157
    }
158

                
159
    if (GPOINTER_TO_INT(data) == 0) {       // Standalone mode
160
#if GTK_CHECK_VERSION(2,12,0)
161
        GObject *menuitemKillServer = nntpgrab_gui_base_get_object("menuitemKillServer");
162
        GValue val;
163
        memset(&val, 0, sizeof(val));
164
        g_value_init(&val, G_TYPE_BOOLEAN);
165
        g_value_set_boolean (&val, FALSE);
166
        g_object_set_property(G_OBJECT(menuitemKillServer), "sensitive", &val);
167
#else
168
        GtkWidget *menuitemKillServer = nntpgrab_gui_base_get_widget("menuitemKillServer");
169
        gtk_widget_set_sensitive(menuitemKillServer, FALSE);
170
#endif
171

                
172
        if (hostname) {
173
            g_free(hostname);
174
            hostname = NULL;
175
        }
176
    }
177

                
178
    if (!nntpgrab_glue_connect(glue, hostname, port, NULL, NULL, FALSE, &errmsg, &warnings)) {
179
        if (warnings) {
180
            GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
181
            nntpgrab_gui_base_dialog_show(windowMain, warnings, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
182
            g_free(warnings);
183
        }
184

                
185
        g_free(hostname);
186
        g_critical(_("Unable to connect to NNTPGrab server:\n%s"), errmsg);
187
        g_free(errmsg);
188
        g_idle_add((GSourceFunc) gtk_main_quit, NULL);
189
        return FALSE;
190
    }
191

                
192
    if (warnings) {
193
        GtkWidget *windowMain = nntpgrab_gui_base_get_widget("windowMain");
194
        nntpgrab_gui_base_dialog_show(windowMain, warnings, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK);
195
        g_free(warnings);
196
    }
197

                
198
    g_free(hostname);
199

                
200
    gtk_widget_destroy(windowConnect);
201

                
202
#ifndef DARWIN
203
    if (!ipc_initialize()) {
204
        // There is already another NNTPGrab process active!
205
        g_idle_add((GSourceFunc) gtk_main_quit, NULL);
206
        return FALSE;
207
    }
208
#endif
209

                
210
    debug_initialize();
211
    callbacks_initialize();
212
    config_initialize();
213
    config_display_initialize();
214
#ifndef DARWIN
215
    nzb_initialize();
216
#endif
217
    connections_initialize();
218
    queue_initialize();
219
    notify_initialize();
220
    monitor_initialize();
221
    gui_par2_initialize();
222
    nzbcreator_initialize();
223
    auto_import_initialize();
224
    autoshutdown_initialize();
225
    gui_plugins_initialize();
226

                
227
    /* Load any optional plugins which need to be auto-loaded */
228
    load_auto_load_plugins();
229

                
230
    // Did we receive a NZB file on the command line ?
231
    if (nzb_file) {
232
        do_open_nzb_file(nzb_file);
233
        nzb_file = NULL;
234
    }
235

                
236
    initialized = TRUE;
237

                
238
    return FALSE;
239
}
240

                
241
G_MODULE_EXPORT void
242
on_btnConnectToServer_clicked(GtkWidget *caller, gpointer data)
243
{
244
    GtkWidget *windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
245

                
246
    // Save the hostname into the GUI Configuration
247
    ConfigGUIOpts opts = config_gui_get_opts();
248
    GtkWidget *cmbConnectHostname = nntpgrab_gui_base_get_widget("cmbConnectHostname");
249
    char *hostname = NULL;
250

                
251
#if GTK_CHECK_VERSION(2,90,0)
252
    hostname = g_strdup(gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(cmbConnectHostname)))));
253
#else
254
    hostname = gtk_combo_box_get_active_text(GTK_COMBO_BOX(cmbConnectHostname));
255
#endif
256

                
257
    // Have we seen this hostname before ?
258
    if (!strcmp(hostname, opts.hostname1)) {
259
        // No need to do anything, item is already at the top of the list
260
    } else if (!strcmp(hostname, opts.hostname2)) {
261
        // Swap positions
262
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
263
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
264
    } else if (!strcmp(hostname, opts.hostname3)) {
265
        // Push items 1 and 2 one place down and set the first item to the hostname
266
        strncpy(opts.hostname3, opts.hostname2, sizeof(opts.hostname3));
267
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
268
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
269
    } else if (!strcmp(hostname, opts.hostname4)) {
270
        strncpy(opts.hostname4, opts.hostname3, sizeof(opts.hostname4));
271
        strncpy(opts.hostname3, opts.hostname2, sizeof(opts.hostname3));
272
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
273
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
274
    } else if (!strcmp(hostname, opts.hostname5)) {
275
        strncpy(opts.hostname5, opts.hostname4, sizeof(opts.hostname5));
276
        strncpy(opts.hostname4, opts.hostname3, sizeof(opts.hostname4));
277
        strncpy(opts.hostname3, opts.hostname2, sizeof(opts.hostname3));
278
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
279
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
280
    } else {
281
        // Hostname not seen at all, move all the items one place down (forget
282
        // about the last item) and put the hostname in front
283
        strncpy(opts.hostname5, opts.hostname4, sizeof(opts.hostname5));
284
        strncpy(opts.hostname4, opts.hostname3, sizeof(opts.hostname4));
285
        strncpy(opts.hostname3, opts.hostname2, sizeof(opts.hostname3));
286
        strncpy(opts.hostname2, opts.hostname1, sizeof(opts.hostname2));
287
        strncpy(opts.hostname1, hostname, sizeof(opts.hostname1));
288
    }
289

                
290
    g_free(hostname);
291

                
292
    config_gui_set_opts(opts);
293

                
294
    gtk_widget_set_sensitive(windowConnect, FALSE);
295
    g_idle_add(initialisation, GINT_TO_POINTER(1));
296
}
297

                
298
G_MODULE_EXPORT void
299
on_btnStartStandalone_clicked(GtkWidget *caller, gpointer data)
300
{
301
    GtkWidget *windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
302

                
303
    gtk_widget_set_sensitive(windowConnect, FALSE);
304
    g_idle_add(initialisation, GINT_TO_POINTER(0));
305
}
306

                
307
G_MODULE_EXPORT void
308
on_btnConnectQuit_clicked(GtkWidget *caller, gpointer data)
309
{
310
    GtkWidget *windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
311

                
312
    gtk_widget_destroy(windowConnect);
313

                
314
    gtk_main_quit();
315
}
316

                
317
G_MODULE_EXPORT void
318
on_menuitemManagePlugins_activate(GtkWidget *caller, gpointer data)
319
{
320
    GtkWidget *windowPlugins = nntpgrab_gui_base_get_widget("windowPlugins");
321

                
322
    gtk_window_present(GTK_WINDOW(windowPlugins));
323
}
324

                
325
G_MODULE_EXPORT void
326
on_menuitemKillServer_activate(GtkWidget *caller, gpointer data)
327
{
328
    nntpgrab_glue_kill_server(glue);
329
}
330

                
331
#ifdef _MSC_VER
332
void AppInvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line,        uintptr_t pReserved ) {
333
        fprintf(
334
                stderr,
335
                "Invalid parameter detected in function %s. File: %s Line: %d\n",
336
                function,
337
                file,
338
                line
339
        );
340
        fprintf(
341
                stderr,
342
                "Expression: %s\n",
343
                expression
344
        );
345
        // Cause a Debug Breakpoint.
346
        DebugBreak();
347
}
348
#endif
349

                
350
gboolean
351
gui_get_is_initialized()
352
{
353
    return initialized;
354
}
355

                
356
int
357
main(int argc, char *argv[])
358
{
359
    GtkWidget *btnDonate;
360
    GtkWidget *icon;
361
    GdkPixbuf *pixbuf;
362
    int i;
363
    GtkWidget *windowConnect;
364
    GtkWidget *cmbConnectHostname;
365
    GtkListStore *store;
366
    ConfigGUIOpts opts;
367
    GtkTreeIter iter;
368
#ifdef WIN32
369
    WORD wVersionRequested;
370
    WSADATA wsaData;
371
    int ret;
372
#endif
373
#ifdef DARWIN
374
    GtkWidget *quit_menu_widget;
375
#endif
376

                
377
#ifdef WIN32
378
#ifdef _MSC_VER
379
    _set_invalid_parameter_handler(AppInvalidParameterHandler);
380
#else
381
    // exchndl.dll is part of Dr. MinGW. By loading this DLL, every time the
382
    // program crashes a .RPT file will be created containing the backtrace
383
    LoadLibraryA("exchndl.dll");
384
#endif
385
#endif
386

                
387
    g_set_application_name("NNTPGrab");
388
    g_set_prgname("NNTPGrab");
389

                
390
    nntpgrab_utils_perform_base_initialization();
391

                
392
    gtk_init(&argc, &argv);
393

                
394
#ifdef WIN32
395
    // Initialise Winsock
396
    wVersionRequested = MAKEWORD(2, 2);
397

                
398
    ret = WSAStartup(wVersionRequested, &wsaData);
399
    if (ret != 0) {
400
        /* Tell the user that we could not find a usable */
401
        /* WinSock DLL. */
402
        g_error(_("Winsock could not be initialised"));
403
        return -1;
404
    }
405

                
406
    /* Confirm that the WinSock DLL supports 2.2. */
407
    /* Note that if the DLL supports versions greater */
408
    /* than 2.2 in addition to 2.2, it will still return */
409
    /* 2.2 in wVersion since that is the version we */
410
    /* requested. */
411

                
412
    if (LOBYTE( wsaData.wVersion ) != 2 ||
413
        HIBYTE( wsaData.wVersion ) != 2) {
414
        /* Tell the user that we could not find a usable */
415
        /* WinSock DLL. */
416
        WSACleanup();
417

                
418
        g_error(_("Winsock 2.2 or higher is required for this program"));
419

                
420
        return -1;
421
    }
422
#endif
423

                
424
    if (argc > 1) {
425
        // We have an extra argument! Probably the location of a NZB file
426
        // Is one our arguments really a filename ?
427
        for (i = 1; i < argc; i++) {
428
            char *filename;
429

                
430
            if (!strncmp(argv[i], "--debug", 7)) {
431
                g_setenv("NNTPGRAB_DEBUG", "1", TRUE);
432
            }
433

                
434
#ifdef WIN32
435
            filename = g_convert(argv[i], -1, "utf-8", "windows-1252", NULL, NULL, NULL);
436
#else
437
            filename = g_strdup(argv[i]);
438
#endif
439
            if (g_file_test(filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
440
                nzb_file = g_strdup(filename);
441
            }
442
            g_free(filename);
443
        }
444

                
445
        if (nzb_file) {
446
            // Is there already another NNTPGrab instance running ?
447
            if (ipc_test_is_nntpgrab_already_running(FALSE)) {
448
                // Send a message to that other process and commit suicide
449
                ipc_send_open_nzb_file_request(nzb_file);
450
                return(1);
451
            }
452

                
453
            // Nope, open the NZB Import dialog as soon as we're ready to go
454
            // This will be done automatically due to the fact that nzb_file is a global variable
455
        }
456
    }
457

                
458
    /* Initialize libxml now to prevent possible race conditions */
459
    xmlInitGlobals();
460
    xmlInitParser();
461

                
462
    nntpgrab_gui_base_create_ui("nntpgrab_gui");
463

                
464
#ifdef DARWIN
465
    ige_mac_menu_set_global_key_handler_enabled (TRUE);
466
    ige_mac_menu_connect_window_key_handler (GTK_WINDOW(nntpgrab_gui_base_get_widget("windowMain")));
467

                
468
#if GTK_CHECK_VERSION(2,12,0)
469
   quit_menu_widget = gtk_ui_manager_get_widget(GTK_UI_MANAGER(nntpgrab_gui_base_get_object("uimanager1")), "ui/menubar1/menuitem1/imagemenuitem5");
470
   g_warn_if_fail(quit_menu_widget != NULL);
471
#else
472
   quit_menu_widget = nntpgrab_gui_base_get_widget("imagemenuitem5");
473
#endif
474

                
475
    ige_mac_menu_set_quit_menu_item (GTK_MENU_ITEM (quit_menu_widget));
476

                
477
    ige_mac_menu_set_menu_bar(GTK_MENU_SHELL(nntpgrab_gui_base_get_widget("menubar1")));
478
    gtk_widget_hide(nntpgrab_gui_base_get_widget("menubar1"));
479
#endif
480

                
481
    // Set the donate icon of the window
482
    btnDonate = nntpgrab_gui_base_get_widget("btnDonate");
483
    pixbuf = gdk_pixbuf_new_from_xpm_data((const char **) &donate_xpm);
484
    icon = gtk_image_new_from_pixbuf(pixbuf);
485
    gtk_widget_show(icon);
486
    gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(btnDonate), icon);
487
    g_object_unref(pixbuf);
488

                
489
#ifdef DARWIN
490
    // Due to the way file associations work on Mac OS X, we need to make
491
    // sure the NZB dialog can be used before the file association is set up
492
    nzb_initialize();
493

                
494
    // And the file assocation needs to be set up as soon as possible..
495
    if (!ipc_initialize()) {
496
        // There is already another NNTPGrab process active!
497
        return -1;
498
    }
499
#endif
500

                
501
    // We need to have the GUI configuration loaded at this point because the
502
    // Network GUI requires data from it
503
    config_gui_initialize();
504

                
505
    opts = config_gui_get_opts();
506

                
507
    if (opts.show_connect_dialog || nntpgrab_utils_test_is_server_already_running()) {
508
        // Show the connect dialog so the user can enter where the NNTPGrab server is running
509
        windowConnect = nntpgrab_gui_base_get_widget("windowConnect");
510
        cmbConnectHostname = nntpgrab_gui_base_get_widget("cmbConnectHostname");
511

                
512
        gtk_widget_show(windowConnect);
513

                
514
        store = gtk_list_store_new(1, G_TYPE_STRING);
515
        gtk_combo_box_set_model(GTK_COMBO_BOX(cmbConnectHostname), GTK_TREE_MODEL(store));
516
#if GTK_CHECK_VERSION(2,90,0)
517
        gtk_combo_box_set_entry_text_column(GTK_COMBO_BOX(cmbConnectHostname), 0);
518
#else
519
        gtk_combo_box_entry_set_text_column(GTK_COMBO_BOX_ENTRY(cmbConnectHostname), 0);
520
#endif
521

                
522
        if (strlen(opts.hostname1) > 0) {
523
            gtk_list_store_append(store, &iter);
524
            gtk_list_store_set(store, &iter, 0, opts.hostname1, -1);
525
        }
526

                
527
        if (strlen(opts.hostname2) > 0) {
528
            gtk_list_store_append(store, &iter);
529
            gtk_list_store_set(store, &iter, 0, opts.hostname2, -1);
530
        }
531

                
532
        if (strlen(opts.hostname3) > 0) {
533
            gtk_list_store_append(store, &iter);
534
            gtk_list_store_set(store, &iter, 0, opts.hostname3, -1);
535
        }
536

                
537
        if (strlen(opts.hostname4) > 0) {
538
            gtk_list_store_append(store, &iter);
539
            gtk_list_store_set(store, &iter, 0, opts.hostname4, -1);
540
        }
541

                
542
        if (strlen(opts.hostname5) > 0) {
543
            gtk_list_store_append(store, &iter);
544
            gtk_list_store_set(store, &iter, 0, opts.hostname5, -1);
545
        }
546

                
547
        gtk_combo_box_set_active(GTK_COMBO_BOX(cmbConnectHostname), 0);
548

                
549
        if (!opts.show_connect_dialog) {
550
            /* If we got here, the user is running the NNTPGrab Server */
551
            GtkWidget *chkAlwaysStandalone = nntpgrab_gui_base_get_widget("chkAlwaysStandalone");
552
            gtk_widget_hide(chkAlwaysStandalone);
553
        }
554

                
555
        // If the NNTPGrab Server is also running on localhost, disable the 'Standalone' button
556
        if (nntpgrab_utils_test_is_server_already_running()) {
557
            GtkWidget *btnStartStandalone = nntpgrab_gui_base_get_widget("btnStartStandalone");
558
            GtkWidget *btnConnectToServer = nntpgrab_gui_base_get_widget("btnConnectToServer");
559
            gtk_widget_set_sensitive(btnStartStandalone, FALSE);
560
#if GTK_CHECK_VERSION(2,18,0)
561
            gtk_widget_set_can_default(btnConnectToServer, TRUE);
562
#else
563
            GTK_WIDGET_SET_FLAGS(btnConnectToServer, GTK_CAN_DEFAULT);
564
#endif
565
            gtk_widget_grab_default(btnConnectToServer);
566
        }
567
    } else {
568
        g_idle_add(initialisation, GINT_TO_POINTER(0));
569
    }
570

                
571
    /* The update information can already be fetched now */
572
    info_initialize();
573

                
574
    /* start the event loop */
575
    gtk_main();
576

                
577
#if GTK_CHECK_VERSION(2,10,0)
578
    if (nntpgrab_gui_base_tray_icon_get_is_shown()) {
579
        nntpgrab_gui_base_tray_destroy();
580
    }
581
#endif
582

                
583
    if (glue) {
584
        // Always try to disable the auto import even if it isn't in use
585
        if (initialized) {
586
            disable_auto_import();
587
        }
588

                
589
        nntpgrab_glue_destroy(glue);
590
    }
591

                
592
    gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowMain"));
593
    gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowConfig"));
594
    gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowNZB"));
595
    gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowDebug"));
596
    gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowSetCollectionName"));
597
    gtk_widget_destroy(nntpgrab_gui_base_get_widget("windowPlugins"));
598

                
599
    nntpgrab_gui_base_destroy_ui();
600

                
601
    return 0;
602
}
603

                
604
#ifdef WIN32
605
static HINSTANCE instance = NULL;
606

                
607
HINSTANCE
608
get_hinstance(void)
609
{
610
    return instance;
611
}
612

                
613
int _stdcall
614
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, char *lpszCmdLine, int nCmdShow)
615
{
616
    instance = hInstance;
617
    return main(__argc, __argv);
618
}
619

                
620
#endif