Statistics
| Revision:

root / src / prefs_filter_edit.c @ 1

History | View | Annotate | Download (57.3 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2004 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 <gtk/gtk.h>
28
#include <gdk/gdkkeysyms.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <errno.h>
33

    
34
#include "intl.h"
35
#include "main.h"
36
#include "prefs.h"
37
#include "prefs_filter.h"
38
#include "prefs_filter_edit.h"
39
#include "prefs_common.h"
40
#include "mainwindow.h"
41
#include "foldersel.h"
42
#include "colorlabel.h"
43
#include "manage_window.h"
44
#include "procheader.h"
45
#include "menu.h"
46
#include "filter.h"
47
#include "utils.h"
48
#include "gtkutils.h"
49
#include "stock_pixmap.h"
50
#include "alertpanel.h"
51
#include "folder.h"
52

    
53
typedef enum
54
{
55
        PF_COND_HEADER,
56
        PF_COND_TO_OR_CC,
57
        PF_COND_ANY_HEADER,
58
        PF_COND_BODY,
59
        PF_COND_CMD_TEST,
60
        PF_COND_SIZE,
61
        PF_COND_AGE,
62
        PF_COND_ACCOUNT,
63
        PF_COND_EDIT_HEADER,
64
        PF_COND_SEPARATOR,
65
        PF_COND_NONE
66
} CondMenuType;
67

    
68
typedef enum
69
{
70
        PF_MATCH_CONTAIN,
71
        PF_MATCH_NOT_CONTAIN,
72
        PF_MATCH_EQUAL,
73
        PF_MATCH_NOT_EQUAL,
74
        PF_MATCH_REGEX,
75
        PF_MATCH_NOT_REGEX,
76
        PF_MATCH_NONE
77
} MatchMenuType;
78

    
79
typedef enum
80
{
81
        PF_SIZE_LARGER,
82
        PF_SIZE_SMALLER
83
} SizeMatchType;
84

    
85
typedef enum
86
{
87
        PF_AGE_LONGER,
88
        PF_AGE_SHORTER
89
} AgeMatchType;
90

    
91
typedef enum
92
{
93
        PF_ACTION_MOVE,
94
        PF_ACTION_COPY,
95
        PF_ACTION_NOT_RECEIVE,
96
        PF_ACTION_DELETE,
97
        PF_ACTION_EXEC,
98
        PF_ACTION_EXEC_ASYNC,
99
        PF_ACTION_MARK,
100
        PF_ACTION_COLOR_LABEL,
101
        PF_ACTION_MARK_READ,
102
        PF_ACTION_FORWARD,
103
        PF_ACTION_FORWARD_AS_ATTACHMENT,
104
        PF_ACTION_REDIRECT,
105
        PF_ACTION_STOP_EVAL,
106
        PF_ACTION_SEPARATOR,
107
        PF_ACTION_NONE
108
} ActionMenuType;
109

    
110
static struct FilterRuleEditWindow {
111
        GtkWidget *window;
112

    
113
        GtkWidget *name_entry;
114
        GtkWidget *bool_op_optmenu;
115

    
116
        GtkWidget *cond_scrolled_win;
117
        GtkWidget *cond_vbox;
118
        GSList *cond_hbox_list;
119

    
120
        GtkWidget *action_scrolled_win;
121
        GtkWidget *action_vbox;
122
        GSList *action_hbox_list;
123

    
124
        GtkWidget *ok_btn;
125
        GtkWidget *cancel_btn;
126

    
127
        GSList *hdr_list;
128
        GSList *rule_hdr_list;
129

    
130
        FilterRule *new_rule;
131
        gboolean edit_finished;
132
} rule_edit_window;
133

    
134
static struct FilterEditHeaderListDialog {
135
        GtkWidget *window;
136
        GtkWidget *clist;
137
        GtkWidget *entry;
138

    
139
        gboolean finished;
140
        gboolean ok;
141
} edit_header_list_dialog;
142

    
143
typedef struct _CondHBox {
144
        GtkWidget *hbox;
145

    
146
        GtkWidget *cond_type_optmenu;
147
        GtkWidget *match_type_optmenu;
148
        GtkWidget *size_match_optmenu;
149
        GtkWidget *age_match_optmenu;
150
        GtkWidget *key_entry;
151
        GtkWidget *spin_btn;
152
        GtkWidget *label;
153

    
154
        GtkWidget *del_btn;
155
        GtkWidget *add_btn;
156

    
157
        CondMenuType cur_type;
158
        gchar *cur_header_name;
159
} CondHBox;
160

    
161
typedef struct _ActionHBox {
162
        GtkWidget *hbox;
163

    
164
        GtkWidget *action_type_optmenu;
165
        GtkWidget *label;
166
        GtkWidget *folder_entry;
167
        GtkWidget *cmd_entry;
168
        GtkWidget *address_entry;
169
        GtkWidget *clabel_optmenu;
170

    
171
        GtkWidget *folder_sel_btn;
172

    
173
        GtkWidget *action_type_menu_items[PF_ACTION_NONE];
174

    
175
        GtkWidget *del_btn;
176
        GtkWidget *add_btn;
177
} ActionHBox;
178

    
179
static void prefs_filter_edit_create                (void);
180
static void prefs_filter_edit_clear                (void);
181
static void prefs_filter_edit_rule_to_dialog        (FilterRule        *rule);
182
static void prefs_filter_edit_set_header_list        (FilterRule        *rule);
183
static void prefs_filter_edit_update_header_list(void);
184

    
185
static CondHBox *prefs_filter_edit_cond_hbox_create        (void);
186
static ActionHBox *prefs_filter_edit_action_hbox_create        (void);
187
static void prefs_filter_edit_cond_hbox_set                (CondHBox        *hbox,
188
                                                         FilterCond        *cond);
189
static void prefs_filter_edit_action_hbox_set                (ActionHBox        *hbox,
190
                                                         FilterAction        *action);
191

    
192
static void prefs_filter_edit_cond_hbox_select        (CondHBox        *hbox,
193
                                                 CondMenuType         type,
194
                                                 const gchar        *header_name);
195

    
196
static void prefs_filter_edit_set_cond_hbox_widgets        (CondHBox        *hbox,
197
                                                         CondMenuType         type);
198
static void prefs_filter_edit_set_action_hbox_widgets        (ActionHBox        *hbox,
199
                                                         ActionMenuType         type);
200

    
201
static void prefs_filter_edit_set_action_hbox_menu_sensitive
202
                                                (ActionHBox        *hbox,
203
                                                 ActionMenuType         type,
204
                                                 gboolean         sensitive);
205
static void prefs_filter_edit_set_action_hbox_menus_sensitive
206
                                                (void);
207

    
208
static void prefs_filter_edit_get_action_hbox_menus_selection
209
                                                (gboolean        *selection);
210
static ActionMenuType prefs_filter_edit_get_action_hbox_type
211
                                                (ActionHBox        *hbox);
212

    
213
static void prefs_filter_edit_insert_cond_hbox        (CondHBox        *hbox,
214
                                                 gint                 pos);
215
static void prefs_filter_edit_insert_action_hbox(ActionHBox        *hbox,
216
                                                 gint                 pos);
217
static void prefs_filter_edit_remove_cond_hbox        (CondHBox        *hbox);
218
static void prefs_filter_edit_remove_action_hbox(ActionHBox        *hbox);
219

    
220
static void prefs_filter_edit_add_rule_cond        (FilterRule        *rule);
221
static void prefs_filter_edit_add_rule_action        (FilterRule        *rule);
222

    
223
static void prefs_filter_edit_set_cond_header_menu
224
                                                (CondHBox        *hbox);
225

    
226
static void prefs_filter_edit_activate_cond_header
227
                                                (const gchar        *header);
228

    
229
static void prefs_filter_edit_edit_header_list                (void);
230

    
231
static FilterRule *prefs_filter_edit_dialog_to_rule        (void);
232

    
233
/* callback functions */
234
static gint prefs_filter_edit_deleted                (GtkWidget        *widget,
235
                                                 GdkEventAny        *event,
236
                                                 gpointer         data);
237
static gboolean prefs_filter_edit_key_pressed        (GtkWidget        *widget,
238
                                                 GdkEventKey        *event,
239
                                                 gpointer         data);
240
static void prefs_filter_edit_ok                (void);
241
static void prefs_filter_edit_cancel                (void);
242

    
243
static void prefs_filter_cond_activated_cb        (GtkWidget        *widget,
244
                                                 gpointer         data);
245
static void prefs_filter_action_activated_cb        (GtkWidget        *widget,
246
                                                 gpointer         data);
247

    
248
static void prefs_filter_action_select_dest_cb        (GtkWidget        *widget,
249
                                                 gpointer         data);
250

    
251
static void prefs_filter_cond_del_cb                (GtkWidget        *widget,
252
                                                 gpointer         data);
253
static void prefs_filter_cond_add_cb                (GtkWidget        *widget,
254
                                                 gpointer         data);
255
static void prefs_filter_action_del_cb                (GtkWidget        *widget,
256
                                                 gpointer         data);
257
static void prefs_filter_action_add_cb                (GtkWidget        *widget,
258
                                                 gpointer         data);
259

    
260

    
261
FilterRule *prefs_filter_edit_open(FilterRule *rule, const gchar *header)
262
{
263
        FilterRule *new_rule;
264

    
265
        if (!rule_edit_window.window)
266
                prefs_filter_edit_create();
267

    
268
        manage_window_set_transient(GTK_WINDOW(rule_edit_window.window));
269

    
270
        prefs_filter_edit_set_header_list(rule);
271
        prefs_filter_edit_rule_to_dialog(rule);
272
        if (header)
273
                prefs_filter_edit_activate_cond_header(header);
274
        gtk_widget_show(rule_edit_window.window);
275

    
276
        rule_edit_window.new_rule = NULL;
277
        rule_edit_window.edit_finished = FALSE;
278
        while (rule_edit_window.edit_finished == FALSE)
279
                gtk_main_iteration();
280

    
281
        prefs_filter_edit_clear();
282
        prefs_filter_set_msg_header_list(NULL);
283
        gtk_widget_hide(rule_edit_window.window);
284

    
285
        new_rule = rule_edit_window.new_rule;
286
        rule_edit_window.new_rule = NULL;
287

    
288
        if (new_rule)
289
                debug_print("new rule created: %s\n", new_rule->name);
290

    
291
        return new_rule;
292
}
293

    
294
static void prefs_filter_edit_create(void)
295
{
296
        GtkWidget *window;
297

    
298
        GtkWidget *vbox;
299

    
300
        GtkWidget *hbox;
301
        GtkWidget *label;
302
        GtkWidget *name_entry;
303

    
304
        GtkWidget *bool_op_optmenu;
305
        GtkWidget *menu;
306
        GtkWidget *menuitem;
307

    
308
        GtkWidget *cond_scrolled_win;
309
        GtkWidget *cond_vbox;
310

    
311
        GtkWidget *action_scrolled_win;
312
        GtkWidget *action_vbox;
313

    
314
        GtkWidget *ok_btn;
315
        GtkWidget *cancel_btn;
316
        GtkWidget *confirm_area;
317

    
318
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
319
        gtk_container_set_border_width(GTK_CONTAINER(window), 8);
320
        gtk_widget_set_size_request(window, 632, 405);
321
        gtk_window_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
322
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
323
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
324
        gtk_widget_realize(window);
325

    
326
        vbox = gtk_vbox_new(FALSE, 6);
327
        gtk_widget_show(vbox);
328
        gtk_container_add(GTK_CONTAINER(window), vbox);
329

    
330
        gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
331
                                &cancel_btn, _("Cancel"), NULL, NULL);
332
        gtk_widget_show(confirm_area);
333
        gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
334
        gtk_widget_grab_default(ok_btn);
335

    
336
        gtk_window_set_title(GTK_WINDOW(window),
337
                             _("Filter rule"));
338
        g_signal_connect(G_OBJECT(window), "delete_event",
339
                         G_CALLBACK(prefs_filter_edit_deleted), NULL);
340
        g_signal_connect(G_OBJECT(window), "key_press_event",
341
                         G_CALLBACK(prefs_filter_edit_key_pressed), NULL);
342
        MANAGE_WINDOW_SIGNALS_CONNECT (window);
343
        g_signal_connect(G_OBJECT(ok_btn), "clicked",
344
                         G_CALLBACK(prefs_filter_edit_ok), NULL);
345
        g_signal_connect(G_OBJECT(cancel_btn), "clicked",
346
                         G_CALLBACK(prefs_filter_edit_cancel), NULL);
347

    
348
        hbox = gtk_hbox_new(FALSE, 4);
349
        gtk_widget_show(hbox);
350
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
351

    
352
        label = gtk_label_new(_("Name:"));
353
        gtk_widget_show(label);
354
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
355

    
356
        name_entry = gtk_entry_new();
357
        gtk_widget_show(name_entry);
358
        gtk_box_pack_start(GTK_BOX(hbox), name_entry, TRUE, TRUE, 0);
359

    
360
        hbox = gtk_hbox_new(FALSE, 4);
361
        gtk_widget_show(hbox);
362
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
363

    
364
        bool_op_optmenu = gtk_option_menu_new();
365
        gtk_widget_show(bool_op_optmenu);
366
        gtk_box_pack_start(GTK_BOX(hbox), bool_op_optmenu, FALSE, FALSE, 0);
367

    
368
        menu = gtk_menu_new();
369
        MENUITEM_ADD(menu, menuitem,
370
                     _("If any of the following condition matches"), FLT_OR);
371
        MENUITEM_ADD(menu, menuitem,
372
                     _("If all of the following conditions match"), FLT_AND);
373
        gtk_option_menu_set_menu(GTK_OPTION_MENU(bool_op_optmenu), menu);
374

    
375
        cond_scrolled_win = gtk_scrolled_window_new(NULL, NULL);
376
        gtk_widget_show(cond_scrolled_win);
377
        gtk_widget_set_size_request(cond_scrolled_win, -1, 125);
378
        gtk_box_pack_start(GTK_BOX(vbox), cond_scrolled_win, TRUE, TRUE, 0);
379
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(cond_scrolled_win),
380
                                       GTK_POLICY_AUTOMATIC,
381
                                       GTK_POLICY_AUTOMATIC);
382

    
383
        cond_vbox = gtk_vbox_new(FALSE, 2);
384
        gtk_widget_show(cond_vbox);
385
        gtk_container_set_border_width(GTK_CONTAINER(cond_vbox), 2);
386
        gtk_scrolled_window_add_with_viewport
387
                (GTK_SCROLLED_WINDOW(cond_scrolled_win), cond_vbox);
388

    
389
        hbox = gtk_hbox_new(FALSE, 4);
390
        gtk_widget_show(hbox);
391
        gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
392

    
393
        label = gtk_label_new(_("Perform the following actions:"));
394
        gtk_widget_show(label);
395
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
396

    
397
        action_scrolled_win = gtk_scrolled_window_new(NULL, NULL);
398
        gtk_widget_show(action_scrolled_win);
399
        gtk_box_pack_start(GTK_BOX(vbox), action_scrolled_win, TRUE, TRUE, 0);
400
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(action_scrolled_win),
401
                                       GTK_POLICY_AUTOMATIC,
402
                                       GTK_POLICY_AUTOMATIC);
403

    
404
        action_vbox = gtk_vbox_new(FALSE, 2);
405
        gtk_widget_show(action_vbox);
406
        gtk_container_set_border_width(GTK_CONTAINER(action_vbox), 2);
407
        gtk_scrolled_window_add_with_viewport
408
                (GTK_SCROLLED_WINDOW(action_scrolled_win), action_vbox);
409

    
410
        rule_edit_window.window = window;
411
        rule_edit_window.name_entry = name_entry;
412

    
413
        rule_edit_window.bool_op_optmenu = bool_op_optmenu;
414
        rule_edit_window.cond_scrolled_win = cond_scrolled_win;
415
        rule_edit_window.cond_vbox = cond_vbox;
416
        rule_edit_window.action_scrolled_win = action_scrolled_win;
417
        rule_edit_window.action_vbox = action_vbox;
418

    
419
        rule_edit_window.ok_btn = ok_btn;
420
        rule_edit_window.cancel_btn = cancel_btn;
421
}
422

    
423
static void prefs_filter_edit_clear(void)
424
{
425
        while (rule_edit_window.cond_hbox_list) {
426
                CondHBox *hbox =
427
                        (CondHBox *)rule_edit_window.cond_hbox_list->data;
428
                prefs_filter_edit_remove_cond_hbox(hbox);
429
        }
430
        while (rule_edit_window.action_hbox_list) {
431
                ActionHBox *hbox =
432
                        (ActionHBox *)rule_edit_window.action_hbox_list->data;
433
                prefs_filter_edit_remove_action_hbox(hbox);
434
        }
435

    
436
        g_slist_free(rule_edit_window.hdr_list);
437
        rule_edit_window.hdr_list = NULL;
438
        procheader_header_list_destroy(rule_edit_window.rule_hdr_list);
439
        rule_edit_window.rule_hdr_list = NULL;
440
}
441

    
442
static void prefs_filter_edit_rule_to_dialog(FilterRule *rule)
443
{
444
        gint index = 0;
445
        static gint count = 1;
446

    
447
        if (rule && rule->name)
448
                gtk_entry_set_text(GTK_ENTRY(rule_edit_window.name_entry),
449
                                   rule->name);
450
        else {
451
                gchar rule_name[32];
452
                g_snprintf(rule_name, sizeof(rule_name), "Rule %d", count++);
453
                gtk_entry_set_text(GTK_ENTRY(rule_edit_window.name_entry),
454
                                   rule_name);
455
        }
456

    
457
        if (rule) {
458
                index = menu_find_option_menu_index
459
                        (GTK_OPTION_MENU(rule_edit_window.bool_op_optmenu),
460
                         GINT_TO_POINTER(rule->bool_op), NULL);
461
                if (index < 0)
462
                        index = 0;
463
        }
464
        if (index >= 0) {
465
                gtk_option_menu_set_history
466
                        (GTK_OPTION_MENU(rule_edit_window.bool_op_optmenu),
467
                         index);
468
        }
469

    
470
        prefs_filter_edit_add_rule_cond(rule);
471
        prefs_filter_edit_add_rule_action(rule);
472
}
473

    
474
static void prefs_filter_edit_set_header_list(FilterRule *rule)
475
{
476
        GSList *list;
477
        GSList *rule_hdr_list = NULL;
478
        GSList *cur;
479
        FilterCond *cond;
480

    
481
        g_slist_free(rule_edit_window.hdr_list);
482
        rule_edit_window.hdr_list = NULL;
483
        procheader_header_list_destroy(rule_edit_window.rule_hdr_list);
484
        rule_edit_window.rule_hdr_list = NULL;
485

    
486
        list = prefs_filter_get_header_list();
487
        rule_edit_window.hdr_list = list;
488

    
489
        if (!rule)
490
                return;
491

    
492
        for (cur = rule->cond_list; cur != NULL; cur = cur->next) {
493
                cond = (FilterCond *)cur->data;
494

    
495
                if (cond->type == FLT_COND_HEADER &&
496
                    procheader_find_header_list
497
                        (rule_hdr_list, cond->header_name) < 0)
498
                        rule_hdr_list = procheader_add_header_list
499
                                (rule_hdr_list, cond->header_name, NULL);
500
        }
501

    
502
        rule_edit_window.rule_hdr_list = rule_hdr_list;
503

    
504
        rule_edit_window.hdr_list =
505
                procheader_merge_header_list(list, rule_hdr_list);
506
}
507

    
508
static void prefs_filter_edit_update_header_list(void)
509
{
510
        GSList *list;
511

    
512
        g_slist_free(rule_edit_window.hdr_list);
513
        rule_edit_window.hdr_list = NULL;
514

    
515
        list = prefs_filter_get_header_list();
516
        rule_edit_window.hdr_list = list;
517

    
518
        rule_edit_window.hdr_list =
519
                procheader_merge_header_list(list,
520
                                             rule_edit_window.rule_hdr_list);
521
}
522

    
523
static CondHBox *prefs_filter_edit_cond_hbox_create(void)
524
{
525
        CondHBox *cond_hbox;
526
        GtkWidget *hbox;
527
        GtkWidget *cond_type_optmenu;
528
        GtkWidget *match_type_optmenu;
529
        GtkWidget *size_match_optmenu;
530
        GtkWidget *age_match_optmenu;
531
        GtkWidget *menu;
532
        GtkWidget *menuitem;
533
        GtkWidget *key_entry;
534
        GtkObject *spin_btn_adj;
535
        GtkWidget *spin_btn;
536
        GtkWidget *label;
537
        GtkWidget *del_btn;
538
        GtkWidget *add_btn;
539
        GtkWidget *del_pixmap;
540
        GtkWidget *add_pixmap;
541

    
542
        cond_hbox = g_new0(CondHBox, 1);
543

    
544
        hbox = gtk_hbox_new(FALSE, 4);
545
        gtk_widget_show(hbox);
546

    
547
        cond_type_optmenu = gtk_option_menu_new();
548
        gtk_widget_show(cond_type_optmenu);
549
        gtk_box_pack_start(GTK_BOX(hbox), cond_type_optmenu, FALSE, FALSE, 0);
550

    
551
#define COND_MENUITEM_ADD(str, action)                                            \
552
{                                                                            \
553
        MENUITEM_ADD(menu, menuitem, str, action);                            \
554
        g_signal_connect(G_OBJECT(menuitem), "activate",                    \
555
                         G_CALLBACK(prefs_filter_cond_activated_cb),            \
556
                         cond_hbox);                                            \
557
}
558

    
559
        menu = gtk_menu_new();
560
        MENUITEM_ADD(menu, menuitem, NULL,        PF_COND_SEPARATOR);
561
        COND_MENUITEM_ADD(_("To or Cc"),          PF_COND_TO_OR_CC);
562
        COND_MENUITEM_ADD(_("Any header"),        PF_COND_ANY_HEADER);
563
        COND_MENUITEM_ADD(_("Edit header..."),    PF_COND_EDIT_HEADER);
564

    
565
        MENUITEM_ADD(menu, menuitem, NULL,        PF_COND_SEPARATOR);
566
        COND_MENUITEM_ADD(_("Message body"),      PF_COND_BODY);
567
        COND_MENUITEM_ADD(_("Result of command"), PF_COND_CMD_TEST);
568
        COND_MENUITEM_ADD(_("Size"),              PF_COND_SIZE);
569
        COND_MENUITEM_ADD(_("Age"),               PF_COND_AGE);
570
        /* COND_MENUITEM_ADD(_("Account"),           PF_COND_ACCOUNT); */
571

    
572
        gtk_option_menu_set_menu(GTK_OPTION_MENU(cond_type_optmenu), menu);
573

    
574
#undef COND_MENUITEM_ADD
575

    
576
        match_type_optmenu = gtk_option_menu_new();
577
        gtk_widget_show(match_type_optmenu);
578
        gtk_box_pack_start(GTK_BOX(hbox), match_type_optmenu, FALSE, FALSE, 0);
579

    
580
        menu = gtk_menu_new();
581
        MENUITEM_ADD(menu, menuitem, _("contains"),
582
                     PF_MATCH_CONTAIN);
583
        MENUITEM_ADD(menu, menuitem, _("doesn't contain"),
584
                     PF_MATCH_NOT_CONTAIN);
585
        MENUITEM_ADD(menu, menuitem, _("is"),
586
                     PF_MATCH_EQUAL);
587
        MENUITEM_ADD(menu, menuitem, _("is not"),
588
                     PF_MATCH_NOT_EQUAL);
589
        MENUITEM_ADD(menu, menuitem, _("match to regex"),
590
                     PF_MATCH_REGEX);
591
        MENUITEM_ADD(menu, menuitem, _("doesn't match to regex"),
592
                     PF_MATCH_NOT_REGEX);
593
        gtk_option_menu_set_menu(GTK_OPTION_MENU(match_type_optmenu), menu);
594

    
595
        size_match_optmenu = gtk_option_menu_new();
596
        gtk_box_pack_start(GTK_BOX(hbox), size_match_optmenu, FALSE, FALSE, 0);
597

    
598
        menu = gtk_menu_new();
599
        MENUITEM_ADD(menu, menuitem, _("is larger than"), PF_SIZE_LARGER);
600
        MENUITEM_ADD(menu, menuitem, _("is smaller than"), PF_SIZE_SMALLER);
601
        gtk_option_menu_set_menu(GTK_OPTION_MENU(size_match_optmenu), menu);
602

    
603
        age_match_optmenu = gtk_option_menu_new();
604
        gtk_box_pack_start(GTK_BOX(hbox), age_match_optmenu, FALSE, FALSE, 0);
605

    
606
        menu = gtk_menu_new();
607
        MENUITEM_ADD(menu, menuitem, _("is longer than"), PF_AGE_LONGER);
608
        MENUITEM_ADD(menu, menuitem, _("is shorter than"), PF_AGE_SHORTER);
609
        gtk_option_menu_set_menu(GTK_OPTION_MENU(age_match_optmenu), menu);
610

    
611
        key_entry = gtk_entry_new();
612
        gtk_widget_show(key_entry);
613
        gtk_box_pack_start(GTK_BOX(hbox), key_entry, TRUE, TRUE, 0);
614

    
615
        spin_btn_adj = gtk_adjustment_new(0, 0, 99999, 1, 10, 100);
616
        spin_btn = gtk_spin_button_new(GTK_ADJUSTMENT(spin_btn_adj), 1, 0);
617
        gtk_box_pack_start(GTK_BOX(hbox), spin_btn, FALSE, FALSE, 0);
618
        gtk_widget_set_size_request(spin_btn, 64, -1);
619
        gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin_btn), TRUE);
620

    
621
        label = gtk_label_new(_("KB"));
622
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
623

    
624
        del_pixmap = stock_pixmap_widget(rule_edit_window.window,
625
                                         STOCK_PIXMAP_REMOVE);
626
        gtk_widget_show(del_pixmap);
627

    
628
        del_btn = gtk_button_new();
629
        gtk_container_add(GTK_CONTAINER(del_btn), del_pixmap);
630
        gtk_widget_show(del_btn);
631
        gtk_box_pack_end(GTK_BOX(hbox), del_btn, FALSE, FALSE, 0);
632

    
633
        add_pixmap = stock_pixmap_widget(rule_edit_window.window,
634
                                         STOCK_PIXMAP_ADD);
635
        gtk_widget_show(add_pixmap);
636

    
637
        add_btn = gtk_button_new();
638
        gtk_container_add(GTK_CONTAINER(add_btn), add_pixmap);
639
        gtk_widget_show(add_btn);
640
        gtk_box_pack_end(GTK_BOX(hbox), add_btn, FALSE, FALSE, 0);
641

    
642
        g_signal_connect(G_OBJECT(del_btn), "clicked",
643
                         G_CALLBACK(prefs_filter_cond_del_cb), cond_hbox);
644
        g_signal_connect(G_OBJECT(add_btn), "clicked",
645
                         G_CALLBACK(prefs_filter_cond_add_cb), cond_hbox);
646

    
647
        cond_hbox->hbox = hbox;
648
        cond_hbox->cond_type_optmenu = cond_type_optmenu;
649
        cond_hbox->match_type_optmenu = match_type_optmenu;
650
        cond_hbox->size_match_optmenu = size_match_optmenu;
651
        cond_hbox->age_match_optmenu = age_match_optmenu;
652
        cond_hbox->key_entry = key_entry;
653
        cond_hbox->spin_btn = spin_btn;
654
        cond_hbox->label = label;
655
        cond_hbox->del_btn = del_btn;
656
        cond_hbox->add_btn = add_btn;
657
        cond_hbox->cur_type = PF_COND_HEADER;
658
        cond_hbox->cur_header_name = NULL;
659

    
660
        prefs_filter_edit_set_cond_header_menu(cond_hbox);
661
        gtk_option_menu_set_history(GTK_OPTION_MENU(cond_type_optmenu), 0);
662

    
663
        return cond_hbox;
664
}
665

    
666
static ActionHBox *prefs_filter_edit_action_hbox_create(void)
667
{
668
        ActionHBox *action_hbox;
669
        GtkWidget *hbox;
670
        GtkWidget *action_type_optmenu;
671
        GtkWidget *menu;
672
        GtkWidget *menuitem;
673
        GtkWidget *label;
674
        GtkWidget *folder_entry;
675
        GtkWidget *cmd_entry;
676
        GtkWidget *address_entry;
677
        GtkWidget *folder_pixmap;
678
        GtkWidget *folder_sel_btn;
679
        GtkWidget *clabel_optmenu;
680
        GtkWidget *del_btn;
681
        GtkWidget *add_btn;
682
        GtkWidget *del_pixmap;
683
        GtkWidget *add_pixmap;
684

    
685
        action_hbox = g_new0(ActionHBox, 1);
686

    
687
        hbox = gtk_hbox_new(FALSE, 4);
688
        gtk_widget_show(hbox);
689

    
690
        action_type_optmenu = gtk_option_menu_new();
691
        gtk_widget_show(action_type_optmenu);
692
        gtk_box_pack_start(GTK_BOX(hbox), action_type_optmenu, FALSE, FALSE, 0);
693

    
694
        memset(action_hbox->action_type_menu_items, 0,
695
               sizeof(action_hbox->action_type_menu_items));
696

    
697
#define ACTION_MENUITEM_ADD(str, action)                                      \
698
{                                                                              \
699
        MENUITEM_ADD(menu, menuitem, str, action);                              \
700
        action_hbox->action_type_menu_items[action] = menuitem;                      \
701
        g_signal_connect(G_OBJECT(menuitem), "activate",                      \
702
                         G_CALLBACK(prefs_filter_action_activated_cb),              \
703
                         action_hbox);                                              \
704
}
705

    
706
        menu = gtk_menu_new();
707
        ACTION_MENUITEM_ADD(_("Move to"),               PF_ACTION_MOVE);
708
        ACTION_MENUITEM_ADD(_("Copy to"),               PF_ACTION_COPY);
709
        ACTION_MENUITEM_ADD(_("Don't receive"),         PF_ACTION_NOT_RECEIVE);
710
        ACTION_MENUITEM_ADD(_("Delete from server"),    PF_ACTION_DELETE);
711

    
712
        MENUITEM_ADD(menu, menuitem, NULL,              PF_ACTION_SEPARATOR);
713
        ACTION_MENUITEM_ADD(_("Set mark"),              PF_ACTION_MARK);
714
        ACTION_MENUITEM_ADD(_("Set color"),             PF_ACTION_COLOR_LABEL);
715
        ACTION_MENUITEM_ADD(_("Mark as read"),          PF_ACTION_MARK_READ);
716

    
717
#if 0
718
        MENUITEM_ADD(menu, menuitem, NULL,              PF_ACTION_SEPARATOR);
719
        ACTION_MENUITEM_ADD(_("Forward"),               PF_ACTION_FORWARD);
720
        ACTION_MENUITEM_ADD(_("Forward as attachment"), PF_ACTION_FORWARD_AS_ATTACHMENT);
721
        ACTION_MENUITEM_ADD(_("Redirect"),              PF_ACTION_REDIRECT);
722
#endif
723

    
724
        MENUITEM_ADD(menu, menuitem, NULL,              PF_ACTION_SEPARATOR);
725
        ACTION_MENUITEM_ADD(_("Execute command"),       PF_ACTION_EXEC);
726

    
727
        MENUITEM_ADD(menu, menuitem, NULL,              PF_ACTION_SEPARATOR);
728
        ACTION_MENUITEM_ADD(_("Stop rule evaluation"),  PF_ACTION_STOP_EVAL);
729

    
730
        gtk_option_menu_set_menu(GTK_OPTION_MENU(action_type_optmenu), menu);
731

    
732
#undef ACTION_MENUITEM_ADD
733

    
734
        label = gtk_label_new(_("folder:"));
735
        gtk_widget_show(label);
736
        gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);
737

    
738
        folder_entry = gtk_entry_new();
739
        gtk_widget_show(folder_entry);
740
        gtk_box_pack_start(GTK_BOX(hbox), folder_entry, TRUE, TRUE, 0);
741

    
742
        folder_pixmap = stock_pixmap_widget(rule_edit_window.window,
743
                                            STOCK_PIXMAP_DIR_OPEN);
744
        gtk_widget_show(folder_pixmap);
745

    
746
        folder_sel_btn = gtk_button_new();
747
        gtk_container_add(GTK_CONTAINER(folder_sel_btn), folder_pixmap);
748
        gtk_widget_show(folder_sel_btn);
749
        gtk_box_pack_start(GTK_BOX(hbox), folder_sel_btn, FALSE, FALSE, 0);
750

    
751
        cmd_entry = gtk_entry_new();
752
        gtk_widget_show(cmd_entry);
753
        gtk_box_pack_start(GTK_BOX(hbox), cmd_entry, TRUE, TRUE, 0);
754

    
755
        address_entry = gtk_entry_new();
756
        gtk_widget_show(address_entry);
757
        gtk_box_pack_start(GTK_BOX(hbox), address_entry, TRUE, TRUE, 0);
758

    
759
        clabel_optmenu = gtk_option_menu_new();
760
        gtk_widget_show(clabel_optmenu);
761
        gtk_box_pack_start(GTK_BOX(hbox), clabel_optmenu, FALSE, FALSE, 0);
762

    
763
        menu = colorlabel_create_color_menu();
764
        gtk_option_menu_set_menu(GTK_OPTION_MENU(clabel_optmenu), menu);
765

    
766
        del_pixmap = stock_pixmap_widget(rule_edit_window.window,
767
                                         STOCK_PIXMAP_REMOVE);
768
        gtk_widget_show(del_pixmap);
769

    
770
        del_btn = gtk_button_new();
771
        gtk_container_add(GTK_CONTAINER(del_btn), del_pixmap);
772
        gtk_widget_show(del_btn);
773
        gtk_box_pack_end(GTK_BOX(hbox), del_btn, FALSE, FALSE, 0);
774

    
775
        add_pixmap = stock_pixmap_widget(rule_edit_window.window,
776
                                         STOCK_PIXMAP_ADD);
777
        gtk_widget_show(add_pixmap);
778

    
779
        add_btn = gtk_button_new();
780
        gtk_container_add(GTK_CONTAINER(add_btn), add_pixmap);
781
        gtk_widget_show(add_btn);
782
        gtk_box_pack_end(GTK_BOX(hbox), add_btn, FALSE, FALSE, 0);
783

    
784
        g_signal_connect(G_OBJECT(folder_sel_btn), "clicked",
785
                         G_CALLBACK(prefs_filter_action_select_dest_cb),
786
                         action_hbox);
787
        g_signal_connect(G_OBJECT(del_btn), "clicked",
788
                         G_CALLBACK(prefs_filter_action_del_cb), action_hbox);
789
        g_signal_connect(G_OBJECT(add_btn), "clicked",
790
                         G_CALLBACK(prefs_filter_action_add_cb), action_hbox);
791

    
792
        action_hbox->hbox = hbox;
793
        action_hbox->action_type_optmenu = action_type_optmenu;
794
        action_hbox->label = label;
795
        action_hbox->folder_entry = folder_entry;
796
        action_hbox->cmd_entry = cmd_entry;
797
        action_hbox->address_entry = address_entry;
798
        action_hbox->folder_sel_btn = folder_sel_btn;
799
        action_hbox->clabel_optmenu = clabel_optmenu;
800
        action_hbox->del_btn = del_btn;
801
        action_hbox->add_btn = add_btn;
802

    
803
        return action_hbox;
804
}
805

    
806
static void prefs_filter_edit_cond_hbox_set(CondHBox *hbox, FilterCond *cond)
807
{
808
        GtkOptionMenu *cond_type_optmenu =
809
                GTK_OPTION_MENU(hbox->cond_type_optmenu);
810
        GtkOptionMenu *match_type_optmenu =
811
                GTK_OPTION_MENU(hbox->match_type_optmenu);
812
        gint cond_index = -1;
813
        gint match_index = -1;
814
        CondMenuType cond_type = PF_COND_NONE;
815
        MatchMenuType match_type = PF_MATCH_NONE;
816
        SizeMatchType size_type = PF_SIZE_LARGER;
817
        AgeMatchType age_type = PF_AGE_LONGER;
818

    
819
        switch (cond->type) {
820
        case FLT_COND_HEADER:
821
                cond_type = PF_COND_HEADER; break;
822
        case FLT_COND_TO_OR_CC:
823
                cond_type = PF_COND_TO_OR_CC; break;
824
        case FLT_COND_ANY_HEADER:
825
                cond_type = PF_COND_ANY_HEADER; break;
826
        case FLT_COND_BODY:
827
                cond_type = PF_COND_BODY; break;
828
        case FLT_COND_CMD_TEST:
829
                cond_type = PF_COND_CMD_TEST; break;
830
        case FLT_COND_SIZE_GREATER:
831
                cond_type = PF_COND_SIZE;
832
                if (FLT_IS_NOT_MATCH(cond->match_flag))
833
                        size_type = PF_SIZE_SMALLER;
834
                else
835
                        size_type = PF_SIZE_LARGER;
836
                break;
837
        case FLT_COND_AGE_GREATER:
838
                cond_type = PF_COND_AGE;
839
                if (FLT_IS_NOT_MATCH(cond->match_flag))
840
                        age_type = PF_AGE_SHORTER;
841
                else
842
                        age_type = PF_AGE_LONGER;
843
                break;
844
        case FLT_COND_ACCOUNT:
845
                cond_type = PF_COND_ACCOUNT; break;
846
        default:
847
                break;
848
        }
849

    
850
        switch (cond->type) {
851
        case FLT_COND_HEADER:
852
        case FLT_COND_TO_OR_CC:
853
        case FLT_COND_ANY_HEADER:
854
        case FLT_COND_BODY:
855
                switch (cond->match_type) {
856
                case FLT_CONTAIN:
857
                        if (FLT_IS_NOT_MATCH(cond->match_flag))
858
                                match_type = PF_MATCH_NOT_CONTAIN;
859
                        else
860
                                match_type = PF_MATCH_CONTAIN;
861
                        break;
862
                case FLT_EQUAL:
863
                        if (FLT_IS_NOT_MATCH(cond->match_flag))
864
                                match_type = PF_MATCH_NOT_EQUAL;
865
                        else
866
                                match_type = PF_MATCH_EQUAL;
867
                        break;
868
                case FLT_REGEX:
869
                        if (FLT_IS_NOT_MATCH(cond->match_flag))
870
                                match_type = PF_MATCH_NOT_REGEX;
871
                        else
872
                                match_type = PF_MATCH_REGEX;
873
                        break;
874
                }
875
                break;
876
        default:
877
                break;
878
        }
879

    
880
        if (cond_type == PF_COND_HEADER)
881
                cond_index = procheader_find_header_list
882
                        (rule_edit_window.hdr_list, cond->header_name);
883
        else
884
                cond_index = menu_find_option_menu_index
885
                        (cond_type_optmenu, GINT_TO_POINTER(cond_type), NULL);
886
        if (cond_index >= 0) {
887
                GtkWidget *menuitem;
888

    
889
                if (cond_type == PF_COND_SIZE || cond_type == PF_COND_AGE) {
890
                        gtk_spin_button_set_value
891
                                (GTK_SPIN_BUTTON(hbox->spin_btn),
892
                                 (gfloat)cond->int_value);
893
                } else {
894
                        gtk_entry_set_text(GTK_ENTRY(hbox->key_entry),
895
                                           cond->str_value ?
896
                                           cond->str_value : "");
897
                }
898
                gtk_option_menu_set_history(cond_type_optmenu, cond_index);
899
                menuitem = gtk_menu_get_active
900
                        (GTK_MENU(gtk_option_menu_get_menu(cond_type_optmenu)));
901
                gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
902
        }
903

    
904
        match_index = menu_find_option_menu_index
905
                (match_type_optmenu, GINT_TO_POINTER(match_type), NULL);
906
        if (match_index >= 0)
907
                gtk_option_menu_set_history(match_type_optmenu, match_index);
908
        if (cond_type == PF_COND_SIZE)
909
                gtk_option_menu_set_history
910
                        (GTK_OPTION_MENU(hbox->size_match_optmenu), size_type);
911
        else if (cond_type == PF_COND_AGE)
912
                gtk_option_menu_set_history
913
                        (GTK_OPTION_MENU(hbox->age_match_optmenu), age_type);
914
}
915

    
916
static void prefs_filter_edit_action_hbox_set(ActionHBox *hbox,
917
                                              FilterAction *action)
918
{
919
        GtkOptionMenu *type_optmenu = GTK_OPTION_MENU(hbox->action_type_optmenu);
920
        GtkWidget *menu;
921
        ActionMenuType type = PF_ACTION_NONE;
922

    
923
        menu = gtk_option_menu_get_menu(type_optmenu);
924

    
925
        switch (action->type) {
926
        case FLT_ACTION_MOVE:
927
                type = PF_ACTION_MOVE; break;
928
        case FLT_ACTION_COPY:
929
                type = PF_ACTION_COPY; break;
930
        case FLT_ACTION_NOT_RECEIVE:
931
                type = PF_ACTION_NOT_RECEIVE; break;
932
        case FLT_ACTION_DELETE:
933
                type = PF_ACTION_DELETE; break;
934
        case FLT_ACTION_EXEC:
935
                type = PF_ACTION_EXEC; break;
936
        case FLT_ACTION_MARK:
937
                type = PF_ACTION_MARK; break;
938
        case FLT_ACTION_COLOR_LABEL:
939
                type = PF_ACTION_COLOR_LABEL; break;
940
        case FLT_ACTION_MARK_READ:
941
                type = PF_ACTION_MARK_READ; break;
942
        case FLT_ACTION_STOP_EVAL:
943
                type = PF_ACTION_STOP_EVAL; break;
944
        default:
945
                break;
946
        }
947

    
948
        switch (type) {
949
        case PF_ACTION_MOVE:
950
        case PF_ACTION_COPY:
951
                gtk_entry_set_text(GTK_ENTRY(hbox->folder_entry),
952
                                   action->str_value ? action->str_value : "");
953
                break;
954
        case PF_ACTION_EXEC:
955
                gtk_entry_set_text(GTK_ENTRY(hbox->cmd_entry),
956
                                   action->str_value ? action->str_value : "");
957
                break;
958
        case PF_ACTION_COLOR_LABEL:
959
                gtk_option_menu_set_history
960
                        (GTK_OPTION_MENU(hbox->clabel_optmenu),
961
                         action->int_value - 1);
962
                break;
963
        default:
964
                break;
965
        }
966

    
967
        prefs_filter_edit_set_action_hbox_widgets(hbox, type);
968
}
969

    
970
static void prefs_filter_edit_cond_hbox_select(CondHBox *hbox,
971
                                               CondMenuType type,
972
                                               const gchar *header_name)
973
{
974
        gint index;
975
        GtkOptionMenu *cond_type_optmenu =
976
                GTK_OPTION_MENU(hbox->cond_type_optmenu);
977
        GtkWidget *menu;
978

    
979
        if (type == PF_COND_HEADER) {
980
                if (header_name)
981
                        index = procheader_find_header_list
982
                                (rule_edit_window.hdr_list, header_name);
983
                else
984
                        index = 0;
985
        } else
986
                index = menu_find_option_menu_index
987
                        (cond_type_optmenu, GINT_TO_POINTER(type), NULL);
988

    
989
        if (index < 0)
990
                index = 0;
991

    
992
        menu = gtk_option_menu_get_menu(cond_type_optmenu);
993
        gtk_option_menu_set_history(cond_type_optmenu, index);
994
}
995

    
996
static void prefs_filter_edit_set_cond_hbox_widgets(CondHBox *hbox,
997
                                                    CondMenuType type)
998
{
999
        switch (type) {
1000
        case PF_COND_HEADER:
1001
        case PF_COND_TO_OR_CC:
1002
        case PF_COND_ANY_HEADER:
1003
        case PF_COND_BODY:
1004
                gtk_widget_show(hbox->match_type_optmenu);
1005
                gtk_widget_hide(hbox->size_match_optmenu);
1006
                gtk_widget_hide(hbox->age_match_optmenu);
1007
                gtk_widget_show(hbox->key_entry);
1008
                gtk_widget_hide(hbox->spin_btn);
1009
                gtk_widget_hide(hbox->label);
1010
                break;
1011
        case PF_COND_CMD_TEST:
1012
                gtk_widget_hide(hbox->match_type_optmenu);
1013
                gtk_widget_hide(hbox->size_match_optmenu);
1014
                gtk_widget_hide(hbox->age_match_optmenu);
1015
                gtk_widget_show(hbox->key_entry);
1016
                gtk_widget_hide(hbox->spin_btn);
1017
                gtk_widget_hide(hbox->label);
1018
                break;
1019
        case PF_COND_SIZE:
1020
                gtk_widget_hide(hbox->match_type_optmenu);
1021
                gtk_widget_show(hbox->size_match_optmenu);
1022
                gtk_widget_hide(hbox->age_match_optmenu);
1023
                gtk_widget_hide(hbox->key_entry);
1024
                gtk_widget_show(hbox->spin_btn);
1025
                gtk_widget_show(hbox->label);
1026
                break;
1027
        case PF_COND_AGE:
1028
                gtk_widget_hide(hbox->match_type_optmenu);
1029
                gtk_widget_hide(hbox->size_match_optmenu);
1030
                gtk_widget_show(hbox->age_match_optmenu);
1031
                gtk_widget_hide(hbox->key_entry);
1032
                gtk_widget_show(hbox->spin_btn);
1033
                gtk_widget_hide(hbox->label);
1034
                break;
1035
        case PF_COND_ACCOUNT:
1036
                gtk_widget_hide(hbox->match_type_optmenu);
1037
                gtk_widget_hide(hbox->size_match_optmenu);
1038
                gtk_widget_hide(hbox->age_match_optmenu);
1039
                gtk_widget_hide(hbox->key_entry);
1040
                /* gtk_widget_show(hbox->account_optmenu); */
1041
                gtk_widget_hide(hbox->spin_btn);
1042
                gtk_widget_hide(hbox->label);
1043
                break;
1044
        default:
1045
                break;
1046
        }
1047
}
1048

    
1049
static void prefs_filter_edit_set_action_hbox_widgets(ActionHBox *hbox,
1050
                                                      ActionMenuType type)
1051
{
1052
        GtkOptionMenu *type_optmenu = GTK_OPTION_MENU(hbox->action_type_optmenu);
1053
        gint index;
1054

    
1055
        switch (type) {
1056
        case PF_ACTION_MOVE:
1057
        case PF_ACTION_COPY:
1058
                gtk_widget_show(hbox->label);
1059
                gtk_label_set_text(GTK_LABEL(hbox->label), _("folder:"));
1060
                gtk_widget_show(hbox->folder_entry);
1061
                gtk_widget_show(hbox->folder_sel_btn);
1062
                gtk_widget_hide(hbox->cmd_entry);
1063
                gtk_widget_hide(hbox->address_entry);
1064
                gtk_widget_hide(hbox->clabel_optmenu);
1065
                break;
1066
        case PF_ACTION_NOT_RECEIVE:
1067
        case PF_ACTION_DELETE:
1068
        case PF_ACTION_MARK:
1069
        case PF_ACTION_MARK_READ:
1070
        case PF_ACTION_STOP_EVAL:
1071
                gtk_widget_hide(hbox->label);
1072
                gtk_widget_hide(hbox->folder_entry);
1073
                gtk_widget_hide(hbox->folder_sel_btn);
1074
                gtk_widget_hide(hbox->cmd_entry);
1075
                gtk_widget_hide(hbox->address_entry);
1076
                gtk_widget_hide(hbox->clabel_optmenu);
1077
                break;
1078
        case PF_ACTION_EXEC:
1079
        case PF_ACTION_EXEC_ASYNC:
1080
                gtk_widget_hide(hbox->label);
1081
                gtk_widget_hide(hbox->folder_entry);
1082
                gtk_widget_hide(hbox->folder_sel_btn);
1083
                gtk_widget_show(hbox->cmd_entry);
1084
                gtk_widget_hide(hbox->address_entry);
1085
                gtk_widget_hide(hbox->clabel_optmenu);
1086
                break;
1087
        case PF_ACTION_COLOR_LABEL:
1088
                gtk_widget_hide(hbox->label);
1089
                gtk_widget_hide(hbox->folder_entry);
1090
                gtk_widget_hide(hbox->folder_sel_btn);
1091
                gtk_widget_hide(hbox->cmd_entry);
1092
                gtk_widget_hide(hbox->address_entry);
1093
                gtk_widget_show(hbox->clabel_optmenu);
1094
                break;
1095
        case PF_ACTION_FORWARD:
1096
        case PF_ACTION_FORWARD_AS_ATTACHMENT:
1097
        case PF_ACTION_REDIRECT:
1098
                gtk_widget_show(hbox->label);
1099
                gtk_label_set_text(GTK_LABEL(hbox->label), _("address:"));
1100
                gtk_widget_hide(hbox->folder_entry);
1101
                gtk_widget_hide(hbox->folder_sel_btn);
1102
                gtk_widget_hide(hbox->cmd_entry);
1103
                gtk_widget_show(hbox->address_entry);
1104
                gtk_widget_hide(hbox->clabel_optmenu);
1105
                break;
1106
        default:
1107
                break;
1108
        }
1109

    
1110
        index = menu_find_option_menu_index(type_optmenu, GINT_TO_POINTER(type),
1111
                                            NULL);
1112
        gtk_option_menu_set_history(type_optmenu, index);
1113
        prefs_filter_edit_set_action_hbox_menus_sensitive();
1114
}
1115

    
1116
static void prefs_filter_edit_set_action_hbox_menu_sensitive
1117
        (ActionHBox *hbox, ActionMenuType type, gboolean sensitive)
1118
{
1119
        GtkWidget *menuitem;
1120

    
1121
        menuitem = hbox->action_type_menu_items[type];
1122
        if (menuitem)
1123
                gtk_widget_set_sensitive(menuitem, sensitive);
1124
}
1125

    
1126
static void prefs_filter_edit_set_action_hbox_menus_sensitive(void)
1127
{
1128
        GSList *cur;
1129
        ActionHBox *cur_hbox;
1130
        ActionMenuType menu_type;
1131
        ActionMenuType cur_type;
1132
        gboolean action_menu_selection[PF_ACTION_NONE];
1133
        gboolean action_menu_sensitive[PF_ACTION_NONE];
1134

    
1135
        prefs_filter_edit_get_action_hbox_menus_selection
1136
                (action_menu_selection);
1137

    
1138
        for (cur = rule_edit_window.action_hbox_list; cur != NULL;
1139
             cur = cur->next) {
1140
                cur_hbox = (ActionHBox *)cur->data;
1141
                menu_type = prefs_filter_edit_get_action_hbox_type(cur_hbox);
1142
                for (cur_type = PF_ACTION_MOVE; cur_type < PF_ACTION_NONE;
1143
                     cur_type++)
1144
                        action_menu_sensitive[cur_type] = TRUE;
1145

    
1146
                for (cur_type = PF_ACTION_MOVE; cur_type < PF_ACTION_NONE;
1147
                     cur_type++) {
1148
                        switch (cur_type) {
1149
                        case PF_ACTION_MOVE:
1150
                        case PF_ACTION_NOT_RECEIVE:
1151
                        case PF_ACTION_DELETE:
1152
                                if (action_menu_selection[cur_type] == TRUE &&
1153
                                    menu_type != cur_type) {
1154
                                        action_menu_sensitive[PF_ACTION_MOVE] = FALSE;
1155
                                        action_menu_sensitive[PF_ACTION_NOT_RECEIVE] = FALSE;
1156
                                        action_menu_sensitive[PF_ACTION_DELETE] = FALSE;
1157
                                }
1158
                                break;
1159
                        case PF_ACTION_MARK:
1160
                        case PF_ACTION_COLOR_LABEL:
1161
                        case PF_ACTION_MARK_READ:
1162
                        case PF_ACTION_STOP_EVAL:
1163
                                if (action_menu_selection[cur_type] == TRUE &&
1164
                                    menu_type != cur_type)
1165
                                        action_menu_sensitive[cur_type] = FALSE;
1166
                                break;
1167
                        default:
1168
                                break;
1169
                        }
1170
                }
1171

    
1172
                for (cur_type = PF_ACTION_MOVE; cur_type < PF_ACTION_NONE;
1173
                     cur_type++) {
1174
                        prefs_filter_edit_set_action_hbox_menu_sensitive
1175
                                (cur_hbox, cur_type,
1176
                                 action_menu_sensitive[cur_type]);
1177
                }
1178
        }
1179
}
1180

    
1181
static void prefs_filter_edit_get_action_hbox_menus_selection(gboolean *selection)
1182
{
1183
        GSList *cur;
1184
        ActionHBox *cur_hbox;
1185
        ActionMenuType menu_type;
1186
        ActionMenuType cur_type;
1187

    
1188
        for (cur_type = PF_ACTION_MOVE; cur_type < PF_ACTION_NONE; cur_type++)
1189
                selection[cur_type] = FALSE;
1190

    
1191
        for (cur = rule_edit_window.action_hbox_list; cur != NULL;
1192
             cur = cur->next) {
1193
                cur_hbox = (ActionHBox *)cur->data;
1194
                menu_type = prefs_filter_edit_get_action_hbox_type(cur_hbox);
1195
                if (menu_type >= PF_ACTION_MOVE && menu_type < PF_ACTION_NONE)
1196
                        selection[menu_type] = TRUE;
1197
        }
1198
}
1199

    
1200
static ActionMenuType prefs_filter_edit_get_action_hbox_type(ActionHBox *hbox)
1201
{
1202
        GtkWidget *menuitem;
1203
        ActionMenuType type;
1204

    
1205
        g_return_val_if_fail(hbox != NULL, PF_ACTION_NONE);
1206

    
1207
        menuitem = gtk_menu_get_active
1208
                (GTK_MENU(gtk_option_menu_get_menu
1209
                        (GTK_OPTION_MENU(hbox->action_type_optmenu))));
1210
        type = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(menuitem),
1211
                                                 MENU_VAL_ID));
1212

    
1213
        return type;
1214
}
1215

    
1216
static void prefs_filter_edit_insert_cond_hbox(CondHBox *hbox, gint pos)
1217
{
1218
        g_return_if_fail(hbox != NULL);
1219

    
1220
        if (!rule_edit_window.cond_hbox_list) {
1221
                gtk_widget_set_sensitive(hbox->del_btn, FALSE);
1222
        } else if (rule_edit_window.cond_hbox_list &&
1223
                   !rule_edit_window.cond_hbox_list->next) {
1224
                CondHBox *top_hbox =
1225
                        (CondHBox *)rule_edit_window.cond_hbox_list->data;
1226
                gtk_widget_set_sensitive(top_hbox->del_btn, TRUE);
1227
        }
1228

    
1229
        gtk_box_pack_start(GTK_BOX(rule_edit_window.cond_vbox),
1230
                           hbox->hbox, FALSE, FALSE, 0);
1231
        if (pos >= 0) {
1232
                gtk_box_reorder_child(GTK_BOX(rule_edit_window.cond_vbox),
1233
                                      hbox->hbox, pos);
1234
        }
1235

    
1236
        rule_edit_window.cond_hbox_list =
1237
                g_slist_insert(rule_edit_window.cond_hbox_list, hbox, pos);
1238
}
1239

    
1240
static void prefs_filter_edit_insert_action_hbox(ActionHBox *hbox, gint pos)
1241
{
1242
        g_return_if_fail(hbox != NULL);
1243

    
1244
        if (!rule_edit_window.action_hbox_list) {
1245
                gtk_widget_set_sensitive(hbox->del_btn, FALSE);
1246
        } else if (rule_edit_window.action_hbox_list &&
1247
                   !rule_edit_window.action_hbox_list->next) {
1248
                ActionHBox *top_hbox =
1249
                        (ActionHBox *)rule_edit_window.action_hbox_list->data;
1250
                gtk_widget_set_sensitive(top_hbox->del_btn, TRUE);
1251
        }
1252

    
1253
        gtk_box_pack_start(GTK_BOX(rule_edit_window.action_vbox),
1254
                           hbox->hbox, FALSE, FALSE, 0);
1255
        if (pos >= 0) {
1256
                gtk_box_reorder_child(GTK_BOX(rule_edit_window.action_vbox),
1257
                                      hbox->hbox, pos);
1258
        }
1259

    
1260
        rule_edit_window.action_hbox_list =
1261
                g_slist_insert(rule_edit_window.action_hbox_list, hbox, pos);
1262
}
1263

    
1264
static void prefs_filter_edit_remove_cond_hbox(CondHBox *hbox)
1265
{
1266
        g_return_if_fail(hbox != NULL);
1267
        g_return_if_fail(rule_edit_window.cond_hbox_list != NULL);
1268

    
1269
        rule_edit_window.cond_hbox_list =
1270
                g_slist_remove(rule_edit_window.cond_hbox_list, hbox);
1271
        gtk_widget_destroy(hbox->hbox);
1272
        g_free(hbox);
1273

    
1274
        if (rule_edit_window.cond_hbox_list &&
1275
            !rule_edit_window.cond_hbox_list->next) {
1276
                hbox = (CondHBox *)rule_edit_window.cond_hbox_list->data;
1277
                gtk_widget_set_sensitive(hbox->del_btn, FALSE);
1278
        }
1279
}
1280

    
1281
static void prefs_filter_edit_remove_action_hbox(ActionHBox *hbox)
1282
{
1283
        g_return_if_fail(hbox != NULL);
1284
        g_return_if_fail(rule_edit_window.action_hbox_list != NULL);
1285

    
1286
        rule_edit_window.action_hbox_list =
1287
                g_slist_remove(rule_edit_window.action_hbox_list, hbox);
1288
        gtk_widget_destroy(hbox->hbox);
1289
        g_free(hbox);
1290

    
1291
        prefs_filter_edit_set_action_hbox_menus_sensitive();
1292

    
1293
        if (rule_edit_window.action_hbox_list &&
1294
            !rule_edit_window.action_hbox_list->next) {
1295
                hbox = (ActionHBox *)rule_edit_window.action_hbox_list->data;
1296
                gtk_widget_set_sensitive(hbox->del_btn, FALSE);
1297
        }
1298
}
1299

    
1300
static void prefs_filter_edit_add_rule_cond(FilterRule *rule)
1301
{
1302
        CondHBox *hbox;
1303
        GSList *cur;
1304
        FilterCond *cond;
1305

    
1306
        if (!rule || !rule->cond_list) {
1307
                hbox = prefs_filter_edit_cond_hbox_create();
1308
                prefs_filter_edit_set_cond_hbox_widgets(hbox, PF_COND_HEADER);
1309
                prefs_filter_edit_insert_cond_hbox(hbox, -1);
1310
                return;
1311
        }
1312

    
1313
        for (cur = rule->cond_list; cur != NULL; cur = cur->next) {
1314
                cond = (FilterCond *)cur->data;
1315

    
1316
                hbox = prefs_filter_edit_cond_hbox_create();
1317
                prefs_filter_edit_cond_hbox_set(hbox, cond);
1318
                prefs_filter_edit_insert_cond_hbox(hbox, -1);
1319
        }
1320
}
1321

    
1322
static void prefs_filter_edit_add_rule_action(FilterRule *rule)
1323
{
1324
        ActionHBox *hbox;
1325
        GSList *cur;
1326

    
1327
        if (!rule || !rule->action_list) {
1328
                hbox = prefs_filter_edit_action_hbox_create();
1329
                prefs_filter_edit_insert_action_hbox(hbox, -1);
1330
                prefs_filter_edit_set_action_hbox_widgets(hbox, PF_ACTION_MOVE);
1331
                return;
1332
        }
1333

    
1334
        for (cur = rule->action_list; cur != NULL; cur = cur->next) {
1335
                FilterAction *action = (FilterAction *)cur->data;
1336

    
1337
                hbox = prefs_filter_edit_action_hbox_create();
1338
                prefs_filter_edit_insert_action_hbox(hbox, -1);
1339
                prefs_filter_edit_action_hbox_set(hbox, action);
1340
        }
1341
}
1342

    
1343
static void prefs_filter_edit_set_cond_header_menu(CondHBox *hbox)
1344
{
1345
        GSList *cur;
1346
        GtkWidget *menu;
1347
        GtkWidget *menuitem;
1348
        gint pos = 0;
1349
        GList *child;
1350

    
1351
        menu = gtk_option_menu_get_menu
1352
                (GTK_OPTION_MENU(hbox->cond_type_optmenu));
1353

    
1354
        /* destroy header items */
1355
        child = GTK_MENU_SHELL(menu)->children;
1356
        while (child != NULL) {
1357
                GList *next = child->next;
1358
                menuitem = GTK_WIDGET(child->data);
1359
                if (!g_object_get_data(G_OBJECT(menuitem), "header_str"))
1360
                        break;
1361
                gtk_widget_destroy(menuitem);
1362
                child = next;
1363
        }
1364

    
1365
        for (cur = rule_edit_window.hdr_list; cur != NULL;
1366
             cur = cur->next, pos++) {
1367
                Header *header = (Header *)cur->data;
1368

    
1369
                menuitem = gtk_menu_item_new_with_label(header->name);
1370
                gtk_widget_show(menuitem);
1371
                gtk_menu_insert(GTK_MENU(menu), menuitem, pos);
1372
                g_object_set_data(G_OBJECT(menuitem), MENU_VAL_ID,
1373
                                  GINT_TO_POINTER(PF_COND_HEADER));
1374
                g_object_set_data(G_OBJECT(menuitem), "header_str",
1375
                                  header->name);
1376
                g_signal_connect(G_OBJECT(menuitem), "activate",
1377
                                 G_CALLBACK(prefs_filter_cond_activated_cb),
1378
                                 hbox);
1379
        }
1380

    
1381
        if (hbox->cur_type == PF_COND_HEADER)
1382
                prefs_filter_edit_cond_hbox_select
1383
                        (hbox, hbox->cur_type, hbox->cur_header_name);
1384
}
1385

    
1386
static void prefs_filter_edit_activate_cond_header(const gchar *header)
1387
{
1388
        gint index;
1389
        CondHBox *hbox;
1390
        GtkWidget *menu;
1391
        GtkWidget *menuitem;
1392
        GList *cur;
1393
        gchar *menu_header;
1394

    
1395
        g_return_if_fail(header != NULL);
1396
        g_return_if_fail(rule_edit_window.cond_hbox_list != NULL);
1397

    
1398
        hbox = (CondHBox *)rule_edit_window.cond_hbox_list->data;
1399
        menu = gtk_option_menu_get_menu
1400
                (GTK_OPTION_MENU(hbox->cond_type_optmenu));
1401

    
1402
        for (cur = GTK_MENU_SHELL(menu)->children, index = 0;
1403
             cur != NULL; cur = cur->next, index++) {
1404
                menuitem = GTK_WIDGET(cur->data);
1405
                menu_header = g_object_get_data(G_OBJECT(menuitem),
1406
                                                "header_str");
1407
                if (!menu_header)
1408
                        break;
1409
                if (!g_strcasecmp(menu_header, header)) {
1410
                        gtk_option_menu_set_history
1411
                                (GTK_OPTION_MENU(hbox->cond_type_optmenu),
1412
                                 index);
1413
                        gtk_menu_item_activate(GTK_MENU_ITEM(menuitem));
1414
                        break;
1415
                }
1416
        }
1417
}
1418

    
1419
static gint edit_header_list_dialog_deleted(GtkWidget *widget,
1420
                                            GdkEventAny *event, gpointer data)
1421
{
1422
        edit_header_list_dialog.finished = TRUE;
1423
        return TRUE;
1424
}
1425

    
1426
static gboolean edit_header_list_dialog_key_pressed(GtkWidget *widget,
1427
                                                    GdkEventKey *event,
1428
                                                    gpointer data)
1429
{
1430
        if (event && event->keyval == GDK_Escape)
1431
                edit_header_list_dialog.finished = TRUE;
1432
        return FALSE;
1433
}
1434

    
1435
static void edit_header_list_dialog_add(void)
1436
{
1437
        GtkCList *clist = GTK_CLIST(edit_header_list_dialog.clist);
1438
        const gchar *text;
1439
        gchar *ctext[1];
1440
        gint row;
1441
        gchar *row_text;
1442

    
1443
        text = gtk_entry_get_text(GTK_ENTRY(edit_header_list_dialog.entry));
1444
        if (text[0] == '\0') return;
1445

    
1446
        for (row = 0; gtk_clist_get_text(clist, row, 0, &row_text) != 0;
1447
             row++) {
1448
                if (g_strcasecmp(row_text, text) == 0) return;
1449
        }
1450

    
1451
        ctext[0] = (gchar *)text;
1452
        gtk_clist_append(clist, ctext);
1453
}
1454

    
1455
static void edit_header_list_dialog_delete(void)
1456
{
1457
        GtkCList *clist = GTK_CLIST(edit_header_list_dialog.clist);
1458
        gint row;
1459

    
1460
        if (!clist->selection) return;
1461

    
1462
        row = GPOINTER_TO_INT(clist->selection->data);
1463
        gtk_clist_remove(clist, row);
1464
}
1465

    
1466
static void edit_header_list_dialog_ok(void)
1467
{
1468
        edit_header_list_dialog.finished = TRUE;
1469
        edit_header_list_dialog.ok = TRUE;
1470
}
1471

    
1472
static void edit_header_list_dialog_cancel(void)
1473
{
1474
        edit_header_list_dialog.finished = TRUE;
1475
}
1476

    
1477
static void prefs_filter_edit_edit_header_list_dialog_create(void)
1478
{
1479
        GtkWidget *window;
1480
        GtkWidget *vbox;
1481
        GtkWidget *hbox;
1482

    
1483
        GtkWidget *vbox2;
1484
        GtkWidget *scrwin;
1485
        GtkWidget *clist;
1486

    
1487
        GtkWidget *entry_hbox;
1488
        GtkWidget *label;
1489
        GtkWidget *entry;
1490

    
1491
        GtkWidget *btn_vbox;
1492
        GtkWidget *add_btn;
1493
        GtkWidget *del_btn;
1494

    
1495
        GtkWidget *confirm_area;
1496
        GtkWidget *ok_btn;
1497
        GtkWidget *cancel_btn;
1498

    
1499
        gchar *title[1];
1500

    
1501
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1502
        gtk_container_set_border_width(GTK_CONTAINER(window), 8);
1503
        gtk_window_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
1504
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
1505
        gtk_window_set_policy(GTK_WINDOW(window), FALSE, TRUE, FALSE);
1506
        gtk_window_set_title(GTK_WINDOW(window), _("Edit header list"));
1507

    
1508
        g_signal_connect(G_OBJECT(window), "delete_event",
1509
                         G_CALLBACK(edit_header_list_dialog_deleted), NULL);
1510
        g_signal_connect(G_OBJECT(window), "key_press_event",
1511
                         G_CALLBACK(edit_header_list_dialog_key_pressed), NULL);
1512

    
1513
        vbox = gtk_vbox_new(FALSE, 6);
1514
        gtk_container_add(GTK_CONTAINER(window), vbox);
1515

    
1516
        hbox = gtk_hbox_new(FALSE, 8);
1517
        gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
1518

    
1519
        vbox2 = gtk_vbox_new(FALSE, 8);
1520
        gtk_box_pack_start(GTK_BOX(hbox), vbox2, TRUE, TRUE, 0);
1521

    
1522
        scrwin = gtk_scrolled_window_new(NULL, NULL);
1523
        gtk_widget_set_size_request(scrwin, 120, 160);
1524
        gtk_box_pack_start(GTK_BOX(vbox2), scrwin, TRUE, TRUE, 0);
1525
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrwin),
1526
                                       GTK_POLICY_AUTOMATIC,
1527
                                       GTK_POLICY_AUTOMATIC);
1528

    
1529
        title[0] = _("Headers");
1530
        clist = gtk_clist_new_with_titles(1, title);
1531
        gtk_container_add(GTK_CONTAINER(scrwin), clist);
1532
        gtk_clist_set_column_width(GTK_CLIST(clist), 0, 80);
1533
        gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_BROWSE);
1534
        GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(clist)->column[0].button,
1535
                               GTK_CAN_FOCUS);
1536

    
1537
        entry_hbox = gtk_hbox_new(FALSE, 8);
1538
        gtk_box_pack_start(GTK_BOX(vbox), entry_hbox, FALSE, TRUE, 0);
1539

    
1540
        label = gtk_label_new(_("Header:"));
1541
        gtk_box_pack_start(GTK_BOX(entry_hbox), label, FALSE, FALSE, 0);
1542

    
1543
        entry = gtk_entry_new();
1544
        gtk_box_pack_start(GTK_BOX(entry_hbox), entry, TRUE, TRUE, 0);
1545

    
1546
        btn_vbox = gtk_vbox_new(FALSE, 8);
1547
        gtk_box_pack_start(GTK_BOX(hbox), btn_vbox, FALSE, FALSE, 0);
1548

    
1549
        add_btn = gtk_button_new_with_label(_("Add"));
1550
        gtk_box_pack_start(GTK_BOX(btn_vbox), add_btn, FALSE, FALSE, 0);
1551

    
1552
        del_btn = gtk_button_new_with_label(_(" Delete "));
1553
        gtk_box_pack_start(GTK_BOX(btn_vbox), del_btn, FALSE, FALSE, 0);
1554

    
1555
        gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
1556
                                &cancel_btn, _("Cancel"), NULL, NULL);
1557
        gtk_box_pack_end(GTK_BOX(vbox), confirm_area, FALSE, FALSE, 0);
1558
        gtk_widget_grab_default(ok_btn);
1559

    
1560
        g_signal_connect(G_OBJECT(add_btn), "clicked",
1561
                         G_CALLBACK(edit_header_list_dialog_add), NULL);
1562
        g_signal_connect(G_OBJECT(del_btn), "clicked",
1563
                         G_CALLBACK(edit_header_list_dialog_delete), NULL);
1564
        g_signal_connect(G_OBJECT(ok_btn), "clicked",
1565
                         G_CALLBACK(edit_header_list_dialog_ok), NULL);
1566
        g_signal_connect(G_OBJECT(cancel_btn), "clicked",
1567
                         G_CALLBACK(edit_header_list_dialog_cancel), NULL);
1568

    
1569
        manage_window_set_transient(GTK_WINDOW(window));
1570

    
1571
        gtk_widget_show_all(window);
1572

    
1573
        edit_header_list_dialog.window = window;
1574
        edit_header_list_dialog.clist = clist;
1575
        edit_header_list_dialog.entry = entry;
1576
        edit_header_list_dialog.finished = FALSE;
1577
        edit_header_list_dialog.ok = FALSE;
1578
}
1579

    
1580
static void prefs_filter_edit_edit_header_list_dialog_set(void)
1581
{
1582
        GtkCList *clist = GTK_CLIST(edit_header_list_dialog.clist);
1583
        GSList *list;
1584
        GSList *cur;
1585
        gchar *text[1];
1586

    
1587
        gtk_clist_freeze(clist);
1588

    
1589
        list = prefs_filter_get_user_header_list();
1590
        for (cur = list; cur != NULL; cur = cur->next) {
1591
                Header *header = (Header *)cur->data;
1592
                text[0] = header->name;
1593
                gtk_clist_append(clist, text);
1594
        }
1595

    
1596
        gtk_clist_thaw(clist);
1597
}
1598

    
1599
static GSList *prefs_filter_edit_edit_header_list_dialog_get(void)
1600
{
1601
        GtkCList *clist = GTK_CLIST(edit_header_list_dialog.clist);
1602
        gint row;
1603
        gchar *text;
1604
        GSList *list = NULL;
1605

    
1606
        for (row = 0; gtk_clist_get_text(clist, row, 0, &text) != 0; row++)
1607
                list = procheader_add_header_list(list, text, NULL);
1608

    
1609
        return list;
1610
}
1611

    
1612
static void prefs_filter_edit_edit_header_list(void)
1613
{
1614
        GSList *list;
1615
        GSList *cur;
1616

    
1617
        prefs_filter_edit_edit_header_list_dialog_create();
1618
        prefs_filter_edit_edit_header_list_dialog_set();
1619

    
1620
        while (edit_header_list_dialog.finished == FALSE)
1621
                gtk_main_iteration();
1622

    
1623
        if (edit_header_list_dialog.ok == TRUE) {
1624
                list = prefs_filter_edit_edit_header_list_dialog_get();
1625
                prefs_filter_set_user_header_list(list);
1626
                prefs_filter_edit_update_header_list();
1627
                for (cur = rule_edit_window.cond_hbox_list; cur != NULL;
1628
                     cur = cur->next) {
1629
                        CondHBox *hbox = (CondHBox *)cur->data;
1630
                        prefs_filter_edit_set_cond_header_menu(hbox);
1631
                }
1632
        }
1633

    
1634
        gtk_widget_destroy(edit_header_list_dialog.window);
1635
        edit_header_list_dialog.window = NULL;
1636
        edit_header_list_dialog.clist = NULL;
1637
        edit_header_list_dialog.entry = NULL;
1638
        edit_header_list_dialog.finished = FALSE;
1639
        edit_header_list_dialog.ok = FALSE;
1640
}
1641

    
1642
static FilterRule *prefs_filter_edit_dialog_to_rule(void)
1643
{
1644
        FilterRule *rule = NULL;
1645
        GSList *cur;
1646
        const gchar *rule_name;
1647
        FilterBoolOp bool_op = FLT_OR;
1648
        GSList *cond_list = NULL;
1649
        GSList *action_list = NULL;
1650
        GtkWidget *bool_op_menuitem;
1651
        gchar *error_msg = NULL;
1652

    
1653
        rule_name = gtk_entry_get_text(GTK_ENTRY(rule_edit_window.name_entry));
1654
        if (!rule_name || *rule_name == '\0') {
1655
                error_msg = _("Rule name is not specified.");
1656
                goto error;
1657
        }
1658

    
1659
        bool_op_menuitem = gtk_menu_get_active
1660
                (GTK_MENU(gtk_option_menu_get_menu
1661
                        (GTK_OPTION_MENU(rule_edit_window.bool_op_optmenu))));
1662
        bool_op = GPOINTER_TO_INT
1663
                (g_object_get_data(G_OBJECT(bool_op_menuitem), MENU_VAL_ID));
1664

    
1665
        for (cur = rule_edit_window.cond_hbox_list; cur != NULL;
1666
             cur = cur->next) {
1667
                CondHBox *hbox = (CondHBox *)cur->data;
1668
                GtkWidget *cond_type_menuitem;
1669
                CondMenuType cond_menu_type;
1670
                MatchMenuType match_menu_type;
1671
                const gchar *header_name;
1672
                const gchar *key_str;
1673
                gint int_value;
1674
                FilterCond *cond = NULL;
1675
                FilterMatchType match_type = FLT_CONTAIN;
1676
                FilterMatchFlag match_flag = 0;
1677
                SizeMatchType size_type;
1678
                AgeMatchType age_type;
1679

    
1680
                cond_type_menuitem = gtk_menu_get_active
1681
                        (GTK_MENU(gtk_option_menu_get_menu
1682
                                (GTK_OPTION_MENU(hbox->cond_type_optmenu))));
1683
                cond_menu_type = GPOINTER_TO_INT
1684
                        (g_object_get_data
1685
                                (G_OBJECT(cond_type_menuitem), MENU_VAL_ID));
1686

    
1687
                match_menu_type = menu_get_option_menu_active_index
1688
                        (GTK_OPTION_MENU(hbox->match_type_optmenu));
1689

    
1690
                key_str = gtk_entry_get_text(GTK_ENTRY(hbox->key_entry));
1691

    
1692
                switch (match_menu_type) {
1693
                case PF_MATCH_CONTAIN:
1694
                        match_type = FLT_CONTAIN;
1695
                        break;
1696
                case PF_MATCH_NOT_CONTAIN:
1697
                        match_type = FLT_CONTAIN;
1698
                        match_flag |= FLT_NOT_MATCH;
1699
                        break;
1700
                case PF_MATCH_EQUAL:
1701
                        match_type = FLT_EQUAL;
1702
                        break;
1703
                case PF_MATCH_NOT_EQUAL:
1704
                        match_type = FLT_EQUAL;
1705
                        match_flag |= FLT_NOT_MATCH;
1706
                        break;
1707
                case PF_MATCH_REGEX:
1708
                        match_type = FLT_REGEX;
1709
                        break;
1710
                case PF_MATCH_NOT_REGEX:
1711
                        match_type = FLT_REGEX;
1712
                        match_flag |= FLT_NOT_MATCH;
1713
                        break;
1714
                default:
1715
                        break;
1716
                }
1717

    
1718
                switch (cond_menu_type) {
1719
                case PF_COND_HEADER:
1720
                        header_name = g_object_get_data
1721
                                (G_OBJECT(cond_type_menuitem), "header_str");
1722
                        cond = filter_cond_new(FLT_COND_HEADER,
1723
                                               match_type, match_flag,
1724
                                               header_name, key_str);
1725
                        break;
1726
                case PF_COND_TO_OR_CC:
1727
                        cond = filter_cond_new(FLT_COND_TO_OR_CC, match_type,
1728
                                               match_flag, NULL, key_str);
1729
                        break;
1730
                case PF_COND_ANY_HEADER:
1731
                        cond = filter_cond_new(FLT_COND_ANY_HEADER, match_type,
1732
                                               match_flag, NULL, key_str);
1733
                        break;
1734
                case PF_COND_BODY:
1735
                        cond = filter_cond_new(FLT_COND_BODY, match_type,
1736
                                               match_flag, NULL, key_str);
1737
                        break;
1738
                case PF_COND_CMD_TEST:
1739
                        if (key_str && *key_str)
1740
                                cond = filter_cond_new(FLT_COND_CMD_TEST,
1741
                                                       0, 0, NULL, key_str);
1742
                        else
1743
                                error_msg = _("Command is not specified.");
1744
                        break;
1745
                case PF_COND_SIZE:
1746
                        size_type = menu_get_option_menu_active_index
1747
                                 (GTK_OPTION_MENU(hbox->size_match_optmenu));
1748
                        match_flag = size_type == PF_SIZE_LARGER
1749
                                ? 0 : FLT_NOT_MATCH;
1750
                        int_value = gtk_spin_button_get_value_as_int
1751
                                (GTK_SPIN_BUTTON(hbox->spin_btn));
1752
                        cond = filter_cond_new(FLT_COND_SIZE_GREATER,
1753
                                               0, match_flag, NULL,
1754
                                               itos(int_value));
1755
                        break;
1756
                case PF_COND_AGE:
1757
                        age_type = menu_get_option_menu_active_index
1758
                                 (GTK_OPTION_MENU(hbox->age_match_optmenu));
1759
                        match_flag = age_type == PF_AGE_LONGER
1760
                                ? 0 : FLT_NOT_MATCH;
1761
                        int_value = gtk_spin_button_get_value_as_int
1762
                                (GTK_SPIN_BUTTON(hbox->spin_btn));
1763
                        cond = filter_cond_new(FLT_COND_AGE_GREATER,
1764
                                               0, match_flag, NULL,
1765
                                               itos(int_value));
1766
                        break;
1767
                case PF_COND_ACCOUNT:
1768
                case PF_COND_EDIT_HEADER:
1769
                default:
1770
                        break;
1771
                }
1772

    
1773
                if (cond)
1774
                        cond_list = g_slist_append(cond_list, cond);
1775
                else {
1776
                        if (!error_msg)
1777
                                error_msg = _("Invalid condition exists.");
1778
                        goto error;
1779
                }
1780
        }
1781

    
1782
        for (cur = rule_edit_window.action_hbox_list; cur != NULL;
1783
             cur = cur->next) {
1784
                ActionHBox *hbox = (ActionHBox *)cur->data;
1785
                ActionMenuType action_menu_type;
1786
                const gchar *str;
1787
                guint color;
1788
                FilterAction *action = NULL;
1789

    
1790
                action_menu_type = prefs_filter_edit_get_action_hbox_type(hbox);
1791

    
1792
                switch (action_menu_type) {
1793
                case PF_ACTION_MOVE:
1794
                        str = gtk_entry_get_text(GTK_ENTRY(hbox->folder_entry));
1795
                        if (str && *str)
1796
                                action = filter_action_new(FLT_ACTION_MOVE,
1797
                                                           str);
1798
                        else
1799
                                error_msg = _("Destination folder is not specified.");
1800
                        break;
1801
                case PF_ACTION_COPY:
1802
                        str = gtk_entry_get_text(GTK_ENTRY(hbox->folder_entry));
1803
                        if (str && *str)
1804
                                action = filter_action_new(FLT_ACTION_COPY,
1805
                                                           str);
1806
                        else
1807
                                error_msg = _("Destination folder is not specified.");
1808
                        break;
1809
                case PF_ACTION_NOT_RECEIVE:
1810
                        action = filter_action_new(FLT_ACTION_NOT_RECEIVE,
1811
                                                   NULL);
1812
                        break;
1813
                case PF_ACTION_DELETE:
1814
                        action = filter_action_new(FLT_ACTION_DELETE, NULL);
1815
                        break;
1816
                case PF_ACTION_EXEC:
1817
                        str = gtk_entry_get_text(GTK_ENTRY(hbox->cmd_entry));
1818
                        if (str && *str)
1819
                                action = filter_action_new(FLT_ACTION_EXEC,
1820
                                                           str);
1821
                        else
1822
                                error_msg = _("Command is not specified.");
1823
                        break;
1824
                case PF_ACTION_EXEC_ASYNC:
1825
                        str = gtk_entry_get_text(GTK_ENTRY(hbox->cmd_entry));
1826
                        if (str && *str)
1827
                                action = filter_action_new
1828
                                        (FLT_ACTION_EXEC_ASYNC, str);
1829
                        else
1830
                                error_msg = _("Command is not specified.");
1831
                        break;
1832
                case PF_ACTION_MARK:
1833
                        action = filter_action_new(FLT_ACTION_MARK, NULL);
1834
                        break;
1835
                case PF_ACTION_COLOR_LABEL:
1836
                        color = colorlabel_get_color_menu_active_item
1837
                                (gtk_option_menu_get_menu
1838
                                 (GTK_OPTION_MENU(hbox->clabel_optmenu)));
1839
                        action = filter_action_new(FLT_ACTION_COLOR_LABEL,
1840
                                                   itos(color));
1841
                        break;
1842
                case PF_ACTION_MARK_READ:
1843
                        action = filter_action_new(FLT_ACTION_MARK_READ, NULL);
1844
                        break;
1845
                case PF_ACTION_FORWARD:
1846
                case PF_ACTION_FORWARD_AS_ATTACHMENT:
1847
                case PF_ACTION_REDIRECT:
1848
                        break;
1849
                case PF_ACTION_STOP_EVAL:
1850
                        action = filter_action_new(FLT_ACTION_STOP_EVAL, NULL);
1851
                        break;
1852
                case PF_ACTION_SEPARATOR:
1853
                default:
1854
                        break;
1855
                }
1856

    
1857
                if (action)
1858
                        action_list = g_slist_append(action_list, action);
1859
                else {
1860
                        if (!error_msg)
1861
                                error_msg = _("Invalid action exists.");
1862
                        goto error;
1863
                }
1864
        }
1865

    
1866
error:
1867
        if (error_msg || !cond_list || !action_list) {
1868
                if (!error_msg) {
1869
                        if (!cond_list)
1870
                                error_msg = _("Condition not exist.");
1871
                        else
1872
                                error_msg = _("Action not exist.");
1873
                }
1874
                alertpanel_error("%s", error_msg);
1875
                if (cond_list)
1876
                        filter_cond_list_free(cond_list);
1877
                if (action_list)
1878
                        filter_action_list_free(action_list);
1879
                return NULL;
1880
        }
1881

    
1882
        rule = filter_rule_new(rule_name, bool_op, cond_list, action_list);
1883

    
1884
        return rule;
1885
}
1886

    
1887
/* callback functions */
1888

    
1889
static gint prefs_filter_edit_deleted(GtkWidget *widget, GdkEventAny *event,
1890
                                      gpointer data)
1891
{
1892
        prefs_filter_edit_cancel();
1893
        return TRUE;
1894
}
1895

    
1896
static gboolean prefs_filter_edit_key_pressed(GtkWidget *widget,
1897
                                              GdkEventKey *event,
1898
                                              gpointer data)
1899
{
1900
        if (event && event->keyval == GDK_Escape)
1901
                prefs_filter_edit_cancel();
1902
        return FALSE;
1903
}
1904

    
1905
static void prefs_filter_edit_ok(void)
1906
{
1907
        FilterRule *rule;
1908

    
1909
        rule = prefs_filter_edit_dialog_to_rule();
1910
        if (rule) {
1911
                rule_edit_window.new_rule = rule;
1912
                rule_edit_window.edit_finished = TRUE;
1913
        }
1914
}
1915

    
1916
static void prefs_filter_edit_cancel(void)
1917
{
1918
        rule_edit_window.new_rule = NULL;
1919
        rule_edit_window.edit_finished = TRUE;
1920
}
1921

    
1922
static void prefs_filter_cond_activated_cb(GtkWidget *widget, gpointer data)
1923
{
1924
        CondHBox *hbox = (CondHBox *)data;
1925
        CondMenuType type;
1926

    
1927
        type = GPOINTER_TO_INT
1928
                (g_object_get_data(G_OBJECT(widget), MENU_VAL_ID));
1929

    
1930
        if (type == PF_COND_EDIT_HEADER) {
1931
                prefs_filter_edit_edit_header_list();
1932
                prefs_filter_edit_cond_hbox_select
1933
                        (hbox, hbox->cur_type, hbox->cur_header_name);
1934
        } else {
1935
                hbox->cur_type = type;
1936
                g_free(hbox->cur_header_name);
1937
                hbox->cur_header_name = NULL;
1938

    
1939
                prefs_filter_edit_set_cond_hbox_widgets(hbox, type);
1940
                if (type == PF_COND_HEADER) {
1941
                        gchar *header_name;
1942
                        gchar *header_field;
1943

    
1944
                        header_name = (gchar *)g_object_get_data
1945
                                (G_OBJECT(widget), "header_str");
1946
                        header_field = prefs_filter_get_msg_header_field
1947
                                (header_name);
1948
                        if (header_field)
1949
                                gtk_entry_set_text(GTK_ENTRY(hbox->key_entry),
1950
                                                   header_field);
1951
                        hbox->cur_header_name = g_strdup(header_name);
1952
                }
1953
        }
1954
}
1955

    
1956
static void prefs_filter_action_activated_cb(GtkWidget *widget, gpointer data)
1957
{
1958
        ActionHBox *hbox = (ActionHBox *)data;
1959
        ActionMenuType type;
1960

    
1961
        type = GPOINTER_TO_INT
1962
                (g_object_get_data(G_OBJECT(widget), MENU_VAL_ID));
1963
        prefs_filter_edit_set_action_hbox_widgets(hbox, type);
1964
}
1965

    
1966
static void prefs_filter_action_select_dest_cb(GtkWidget *widget, gpointer data)
1967
{
1968
        ActionHBox *hbox = (ActionHBox *)data;
1969

    
1970
        FolderItem *dest;
1971
        gchar *id;
1972

    
1973
        dest = foldersel_folder_sel(NULL, FOLDER_SEL_COPY, NULL);
1974
        if (!dest || !dest->path) return;
1975

    
1976
        id = folder_item_get_identifier(dest);
1977
        if (id) {
1978
                gtk_entry_set_text(GTK_ENTRY(hbox->folder_entry), id);
1979
                g_free(id);
1980
        }
1981
}
1982

    
1983
static void prefs_filter_cond_del_cb(GtkWidget *widget, gpointer data)
1984
{
1985
        CondHBox *hbox = (CondHBox *)data;
1986

    
1987
        if (rule_edit_window.cond_hbox_list &&
1988
            rule_edit_window.cond_hbox_list->next)
1989
                prefs_filter_edit_remove_cond_hbox(hbox);
1990
}
1991

    
1992
static void prefs_filter_cond_add_cb(GtkWidget *widget, gpointer data)
1993
{
1994
        CondHBox *hbox = (CondHBox *)data;
1995
        CondHBox *new_hbox;
1996
        gint index;
1997

    
1998
        index = g_slist_index(rule_edit_window.cond_hbox_list, hbox);
1999
        g_return_if_fail(index >= 0);
2000
        new_hbox = prefs_filter_edit_cond_hbox_create();
2001
        prefs_filter_edit_set_cond_hbox_widgets(new_hbox, PF_COND_HEADER);
2002
        prefs_filter_edit_insert_cond_hbox(new_hbox, index + 1);
2003
}
2004

    
2005
static void prefs_filter_action_del_cb(GtkWidget *widget, gpointer data)
2006
{
2007
        ActionHBox *hbox = (ActionHBox *)data;
2008

    
2009
        if (rule_edit_window.action_hbox_list &&
2010
            rule_edit_window.action_hbox_list->next)
2011
                prefs_filter_edit_remove_action_hbox(hbox);
2012
}
2013

    
2014
static void prefs_filter_action_add_cb(GtkWidget *widget, gpointer data)
2015
{
2016
        ActionHBox *hbox = (ActionHBox *)data;
2017
        ActionHBox *new_hbox;
2018
        gboolean action_menu_selection[PF_ACTION_NONE];
2019
        gint index;
2020

    
2021
        prefs_filter_edit_get_action_hbox_menus_selection(action_menu_selection);
2022

    
2023
        index = g_slist_index(rule_edit_window.action_hbox_list, hbox);
2024
        g_return_if_fail(index >= 0);
2025
        new_hbox = prefs_filter_edit_action_hbox_create();
2026
        prefs_filter_edit_insert_action_hbox(new_hbox, index + 1);
2027
        if (action_menu_selection[PF_ACTION_MOVE] == TRUE ||
2028
            action_menu_selection[PF_ACTION_NOT_RECEIVE] == TRUE ||
2029
            action_menu_selection[PF_ACTION_DELETE] == TRUE)
2030
                prefs_filter_edit_set_action_hbox_widgets(new_hbox,
2031
                                                          PF_ACTION_COPY);
2032
        else
2033
                prefs_filter_edit_set_action_hbox_widgets(new_hbox,
2034
                                                          PF_ACTION_MOVE);
2035
}