Pixmap theming
[claws.git] / src / folderview.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2002 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 #include "defs.h"
21
22 #include <glib.h>
23 #include <gdk/gdkkeysyms.h>
24 #include <gtk/gtkwidget.h>
25 #include <gtk/gtkscrolledwindow.h>
26 #include <gtk/gtkctree.h>
27 #include <gtk/gtkcontainer.h>
28 #include <gtk/gtkclist.h>
29 #include <gtk/gtkstyle.h>
30 #include <gtk/gtksignal.h>
31 #include <gtk/gtkmain.h>
32 #include <gtk/gtkstatusbar.h>
33 #include <gtk/gtkmenu.h>
34 #include <gtk/gtkmenuitem.h>
35 #include <gtk/gtkitemfactory.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39
40 #include "intl.h"
41 #include "main.h"
42 #include "mainwindow.h"
43 #include "folderview.h"
44 #include "summaryview.h"
45 #include "summary_search.h"
46 #include "inputdialog.h"
47 #include "grouplistdialog.h"
48 #include "manage_window.h"
49 #include "alertpanel.h"
50 #include "menu.h"
51 #include "stock_pixmap.h"
52 #include "procmsg.h"
53 #include "utils.h"
54 #include "gtkutils.h"
55 #include "prefs_common.h"
56 #include "prefs_account.h"
57 #include "account.h"
58 #include "folder.h"
59 #include "inc.h"
60
61 typedef enum
62 {
63         COL_FOLDER      = 0,
64         COL_NEW         = 1,
65         COL_UNREAD      = 2,
66         COL_TOTAL       = 3
67 } FolderColumnPos;
68
69 #define N_FOLDER_COLS           4
70 #define COL_FOLDER_WIDTH        150
71 #define COL_NUM_WIDTH           32
72
73 #define STATUSBAR_PUSH(mainwin, str) \
74 { \
75         gtk_statusbar_push(GTK_STATUSBAR(mainwin->statusbar), \
76                            mainwin->folderview_cid, str); \
77         gtkut_widget_wait_for_draw(mainwin->hbox_stat); \
78 }
79
80 #define STATUSBAR_POP(mainwin) \
81 { \
82         gtk_statusbar_pop(GTK_STATUSBAR(mainwin->statusbar), \
83                           mainwin->folderview_cid); \
84 }
85
86 static GList *folderview_list = NULL;
87
88 static GdkFont *normalfont;
89 static GdkFont *boldfont;
90
91 static GtkStyle *normal_style;
92 static GtkStyle *normal_color_style;
93 static GtkStyle *bold_style;
94 static GtkStyle *bold_color_style;
95 static GtkStyle *bold_tgtfold_style;
96
97 static GdkBitmap *inboxxpm;
98 static GdkBitmap *inboxxpmmask;
99 static GdkPixmap *inboxhrmxpm;
100 static GdkBitmap *inboxhrmxpmmask;
101 static GdkPixmap *inboxopenxpm;
102 static GdkBitmap *inboxopenxpmmask;
103 static GdkPixmap *inboxopenhrmxpm;
104 static GdkBitmap *inboxopenhrmxpmmask;
105 static GdkPixmap *outboxxpm;
106 static GdkBitmap *outboxxpmmask;
107 static GdkPixmap *outboxhrmxpm;
108 static GdkBitmap *outboxhrmxpmmask;
109 static GdkPixmap *outboxopenxpm;
110 static GdkBitmap *outboxopenxpmmask;
111 static GdkPixmap *outboxopenhrmxpm;
112 static GdkBitmap *outboxopenhrmxpmmask;
113 static GdkPixmap *folderxpm;
114 static GdkBitmap *folderxpmmask;
115 static GdkPixmap *folderhrmxpm;
116 static GdkBitmap *folderhrmxpmmask;
117 static GdkPixmap *folderopenxpm;
118 static GdkBitmap *folderopenxpmmask;
119 static GdkPixmap *folderopenhrmxpm;
120 static GdkBitmap *folderopenhrmxpmmask;
121 static GdkPixmap *trashopenxpm;
122 static GdkBitmap *trashopenxpmmask;
123 static GdkPixmap *trashopenhrmxpm;
124 static GdkBitmap *trashopenhrmxpmmask;
125 static GdkPixmap *trashxpm;
126 static GdkBitmap *trashxpmmask;
127 static GdkPixmap *trashhrmxpm;
128 static GdkBitmap *trashhrmxpmmask;
129 static GdkPixmap *queuexpm;
130 static GdkBitmap *queuexpmmask;
131 static GdkPixmap *queuehrmxpm;
132 static GdkBitmap *queuehrmxpmmask;
133 static GdkPixmap *queueopenxpm;
134 static GdkBitmap *queueopenxpmmask;
135 static GdkPixmap *queueopenhrmxpm;
136 static GdkBitmap *queueopenhrmxpmmask;
137 static GdkPixmap *newxpm;
138 static GdkBitmap *newxpmmask;
139 static GdkPixmap *unreadxpm;
140 static GdkBitmap *unreadxpmmask;
141
142 static void folderview_select_node       (FolderView    *folderview,
143                                           GtkCTreeNode  *node);
144 static void folderview_set_folders       (FolderView    *folderview);
145 static void folderview_sort_folders      (FolderView    *folderview,
146                                           GtkCTreeNode  *root,
147                                           Folder        *folder);
148 static void folderview_append_folder     (FolderView    *folderview,
149                                           Folder        *folder);
150 static void folderview_update_node       (FolderView    *folderview,
151                                           GtkCTreeNode  *node);
152
153 static GtkCTreeNode *folderview_find_by_name    (GtkCTree       *ctree,
154                                                  GtkCTreeNode   *node,
155                                                  const gchar    *name);
156
157 static gint folderview_compare_name     (gconstpointer   a,
158                                          gconstpointer   b);
159
160 /* callback functions */
161 static void folderview_button_pressed   (GtkWidget      *ctree,
162                                          GdkEventButton *event,
163                                          FolderView     *folderview);
164 static void folderview_button_released  (GtkWidget      *ctree,
165                                          GdkEventButton *event,
166                                          FolderView     *folderview);
167 static void folderview_key_pressed      (GtkWidget      *widget,
168                                          GdkEventKey    *event,
169                                          FolderView     *folderview);
170 static void folderview_selected         (GtkCTree       *ctree,
171                                          GtkCTreeNode   *row,
172                                          gint            column,
173                                          FolderView     *folderview);
174 static void folderview_tree_expanded    (GtkCTree       *ctree,
175                                          GtkCTreeNode   *node,
176                                          FolderView     *folderview);
177 static void folderview_tree_collapsed   (GtkCTree       *ctree,
178                                          GtkCTreeNode   *node,
179                                          FolderView     *folderview);
180 static void folderview_popup_close      (GtkMenuShell   *menu_shell,
181                                          FolderView     *folderview);
182 static void folderview_col_resized      (GtkCList       *clist,
183                                          gint            column,
184                                          gint            width,
185                                          FolderView     *folderview);
186
187 static void folderview_update_tree_cb   (FolderView     *folderview,
188                                          guint           action,
189                                          GtkWidget      *widget);
190
191 static void mark_all_read_cb            (FolderView    *folderview,
192                                          guint           action,
193                                          GtkWidget      *widget);
194 static void folderview_new_folder_cb    (FolderView     *folderview,
195                                          guint           action,
196                                          GtkWidget      *widget);
197 static void folderview_new_mbox_folder_cb(FolderView *folderview,
198                                           guint action,
199                                           GtkWidget *widget);
200 static void folderview_rename_folder_cb (FolderView     *folderview,
201                                          guint           action,
202                                          GtkWidget      *widget);
203 static void folderview_rename_mbox_folder_cb(FolderView *folderview,
204                                              guint action,
205                                              GtkWidget *widget);
206 static void folderview_delete_folder_cb (FolderView     *folderview,
207                                          guint           action,
208                                          GtkWidget      *widget);
209 static void folderview_remove_mailbox_cb(FolderView     *folderview,
210                                          guint           action,
211                                          GtkWidget      *widget);
212
213 static void folderview_new_imap_folder_cb(FolderView    *folderview,
214                                           guint          action,
215                                           GtkWidget     *widget);
216 static void folderview_rm_imap_folder_cb (FolderView    *folderview,
217                                           guint          action,
218                                           GtkWidget     *widget);
219 static void folderview_rm_imap_server_cb (FolderView    *folderview,
220                                           guint          action,
221                                           GtkWidget     *widget);
222
223 static void folderview_new_news_group_cb(FolderView     *folderview,
224                                          guint           action,
225                                          GtkWidget      *widget);
226 static void folderview_rm_news_group_cb (FolderView     *folderview,
227                                          guint           action,
228                                          GtkWidget      *widget);
229 static void folderview_rm_news_server_cb(FolderView     *folderview,
230                                          guint           action,
231                                          GtkWidget      *widget);
232
233 static void folderview_search_cb        (FolderView     *folderview,
234                                          guint           action,
235                                          GtkWidget      *widget);
236
237 static gboolean folderview_drag_motion_cb(GtkWidget      *widget,
238                                           GdkDragContext *context,
239                                           gint            x,
240                                           gint            y,
241                                           guint           time,
242                                           FolderView     *folderview);
243 static void folderview_drag_leave_cb     (GtkWidget        *widget,
244                                           GdkDragContext   *context,
245                                           guint             time,
246                                           FolderView       *folderview);
247 static void folderview_drag_received_cb  (GtkWidget        *widget,
248                                           GdkDragContext   *drag_context,
249                                           gint              x,
250                                           gint              y,
251                                           GtkSelectionData *data,
252                                           guint             info,
253                                           guint             time,
254                                           FolderView       *folderview);
255 static void folderview_scoring_cb(FolderView *folderview, guint action,
256                                   GtkWidget *widget);
257 static void folderview_processing_cb(FolderView *folderview, guint action,
258                                      GtkWidget *widget);
259 static void folderview_property_cb(FolderView *folderview, guint action, GtkWidget *widget);
260
261 static GtkItemFactoryEntry folderview_mbox_popup_entries[] =
262 {
263         {N_("/Create _new folder..."),  NULL, folderview_new_mbox_folder_cb,    0, NULL},
264         {N_("/_Rename folder..."),      NULL, folderview_rename_mbox_folder_cb, 0, NULL},
265         {N_("/_Delete folder"),         NULL, folderview_delete_folder_cb, 0, NULL},
266         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
267         {N_("/Remove _mailbox"),        NULL, folderview_remove_mailbox_cb, 0, NULL},
268         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
269         {N_("/_Property..."),           NULL, NULL, 0, NULL},
270         {N_("/_Processing..."),         NULL, folderview_processing_cb, 0, NULL},
271         {N_("/_Scoring..."),            NULL, folderview_scoring_cb, 0, NULL}
272 };
273
274 static GtkItemFactoryEntry folderview_mail_popup_entries[] =
275 {
276         {N_("/Mark all _read"),         NULL, mark_all_read_cb, 0, NULL},
277         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
278         {N_("/Create _new folder..."),  NULL, folderview_new_folder_cb,    0, NULL},
279         {N_("/_Rename folder..."),      NULL, folderview_rename_folder_cb, 0, NULL},
280         {N_("/_Delete folder"),         NULL, folderview_delete_folder_cb, 0, NULL},
281         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
282         {N_("/_Check for new messages"),
283                                         NULL, folderview_update_tree_cb, 0, NULL},
284         {N_("/R_escan folder tree"),    NULL, folderview_update_tree_cb, 1, NULL},
285         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
286         {N_("/Remove _mailbox"),        NULL, folderview_remove_mailbox_cb, 0, NULL},
287         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
288         {N_("/_Search folder..."),      NULL, folderview_search_cb, 0, NULL},
289         {N_("/_Property..."),           NULL, folderview_property_cb, 0, NULL},
290         {N_("/_Processing..."),         NULL, folderview_processing_cb, 0, NULL},
291         {N_("/S_coring..."),            NULL, folderview_scoring_cb, 0, NULL}
292 };
293
294 static GtkItemFactoryEntry folderview_imap_popup_entries[] =
295 {
296         {N_("/Mark all _read"),         NULL, mark_all_read_cb, 0, NULL},
297         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
298         {N_("/Create _new folder..."),  NULL, folderview_new_imap_folder_cb, 0, NULL},
299         {N_("/_Rename folder..."),      NULL, NULL, 0, NULL},
300         {N_("/_Delete folder"),         NULL, folderview_rm_imap_folder_cb, 0, NULL},
301         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
302         {N_("/_Check for new messages"),
303                                         NULL, folderview_update_tree_cb, 0, NULL},
304         {N_("/R_escan folder tree"),    NULL, folderview_update_tree_cb, 1, NULL},
305         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
306         {N_("/Remove _IMAP4 account"),  NULL, folderview_rm_imap_server_cb, 0, NULL},
307         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
308         {N_("/_Search folder..."),      NULL, folderview_search_cb, 0, NULL},
309         {N_("/_Property..."),           NULL, NULL, 0, NULL},
310         {N_("/_Processing..."),         NULL, folderview_processing_cb, 0, NULL},
311         {N_("/S_coring..."),            NULL, folderview_scoring_cb, 0, NULL}
312 };
313
314 static GtkItemFactoryEntry folderview_news_popup_entries[] =
315 {
316         {N_("/Mark all _read"),         NULL, mark_all_read_cb, 0, NULL},
317         {N_("/---"),                    NULL, NULL, 0, "<Separator>"},
318         {N_("/_Subscribe to newsgroup..."),
319                                          NULL, folderview_new_news_group_cb, 0, NULL},
320         {N_("/_Remove newsgroup"),       NULL, folderview_rm_news_group_cb, 0, NULL},
321         {N_("/---"),                     NULL, NULL, 0, "<Separator>"},
322         {N_("/Remove _news account"),    NULL, folderview_rm_news_server_cb, 0, NULL},
323         {N_("/---"),                     NULL, NULL, 0, "<Separator>"},
324         {N_("/_Search folder..."),       NULL, folderview_search_cb, 0, NULL},
325         {N_("/_Property..."),            NULL, NULL, 0, NULL},
326         {N_("/_Processing..."),          NULL, folderview_processing_cb, 0, NULL},
327         {N_("/S_coring..."),            NULL, folderview_scoring_cb, 0, NULL}
328 };
329
330
331 FolderView *folderview_create(void)
332 {
333         FolderView *folderview;
334         GtkWidget *scrolledwin;
335         GtkWidget *ctree;
336         gchar *titles[N_FOLDER_COLS];
337         GtkWidget *mail_popup;
338         GtkWidget *news_popup;
339         GtkWidget *imap_popup;
340         GtkWidget *mbox_popup;
341         GtkItemFactory *mail_factory;
342         GtkItemFactory *news_factory;
343         GtkItemFactory *imap_factory;
344         GtkItemFactory *mbox_factory;
345         gint n_entries;
346         gint i;
347
348         debug_print(_("Creating folder view...\n"));
349         folderview = g_new0(FolderView, 1);
350
351         titles[COL_FOLDER] = _("Folder");
352         titles[COL_NEW]    = _("New");
353         titles[COL_UNREAD] = _("Unread");
354         titles[COL_TOTAL]  = _("#");
355
356         scrolledwin = gtk_scrolled_window_new(NULL, NULL);
357         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwin),
358                                        GTK_POLICY_AUTOMATIC,
359                                        GTK_POLICY_ALWAYS);
360         gtk_widget_set_usize(scrolledwin,
361                              prefs_common.folderview_width,
362                              prefs_common.folderview_height);
363
364         ctree = gtk_ctree_new_with_titles(N_FOLDER_COLS, COL_FOLDER, titles);
365         
366         gtk_container_add(GTK_CONTAINER(scrolledwin), ctree);
367         gtk_clist_set_selection_mode(GTK_CLIST(ctree), GTK_SELECTION_BROWSE);
368 #ifndef CLAWS /* text instead of pixmaps */
369         gtk_clist_set_column_justification(GTK_CLIST(ctree), COL_NEW,
370                                            GTK_JUSTIFY_RIGHT);
371         gtk_clist_set_column_justification(GTK_CLIST(ctree), COL_UNREAD,
372                                            GTK_JUSTIFY_RIGHT);
373 #endif                                     
374         gtk_clist_set_column_justification(GTK_CLIST(ctree), COL_TOTAL,
375                                            GTK_JUSTIFY_RIGHT);
376         gtk_clist_set_column_width(GTK_CLIST(ctree), COL_FOLDER,
377                                    prefs_common.folder_col_folder);
378         gtk_clist_set_column_width(GTK_CLIST(ctree), COL_NEW,
379                                    prefs_common.folder_col_new);
380         gtk_clist_set_column_width(GTK_CLIST(ctree), COL_UNREAD,        
381                                    prefs_common.folder_col_unread);
382         gtk_clist_set_column_width(GTK_CLIST(ctree), COL_TOTAL,
383                                    prefs_common.folder_col_total);
384         gtk_ctree_set_line_style(GTK_CTREE(ctree), GTK_CTREE_LINES_DOTTED);
385         gtk_ctree_set_expander_style(GTK_CTREE(ctree),
386                                      GTK_CTREE_EXPANDER_SQUARE);
387         gtk_ctree_set_indent(GTK_CTREE(ctree), CTREE_INDENT);
388
389         /* don't let title buttons take key focus */
390         for (i = 0; i < N_FOLDER_COLS; i++)
391                 GTK_WIDGET_UNSET_FLAGS(GTK_CLIST(ctree)->column[i].button,
392                                        GTK_CAN_FOCUS);
393
394         /* popup menu */
395         n_entries = sizeof(folderview_mail_popup_entries) /
396                 sizeof(folderview_mail_popup_entries[0]);
397         mail_popup = menu_create_items(folderview_mail_popup_entries,
398                                        n_entries,
399                                        "<MailFolder>", &mail_factory,
400                                        folderview);
401         n_entries = sizeof(folderview_imap_popup_entries) /
402                 sizeof(folderview_imap_popup_entries[0]);
403         imap_popup = menu_create_items(folderview_imap_popup_entries,
404                                        n_entries,
405                                        "<IMAPFolder>", &imap_factory,
406                                        folderview);
407         n_entries = sizeof(folderview_news_popup_entries) /
408                 sizeof(folderview_news_popup_entries[0]);
409         news_popup = menu_create_items(folderview_news_popup_entries,
410                                        n_entries,
411                                        "<NewsFolder>", &news_factory,
412                                        folderview);
413         n_entries = sizeof(folderview_mbox_popup_entries) /
414                 sizeof(folderview_mbox_popup_entries[0]);
415         mbox_popup = menu_create_items(folderview_mbox_popup_entries,
416                                        n_entries,
417                                        "<MailFolder>", &mbox_factory,
418                                        folderview);
419
420         gtk_signal_connect(GTK_OBJECT(ctree), "key_press_event",
421                            GTK_SIGNAL_FUNC(folderview_key_pressed),
422                            folderview);
423         gtk_signal_connect(GTK_OBJECT(ctree), "button_press_event",
424                            GTK_SIGNAL_FUNC(folderview_button_pressed),
425                            folderview);
426         gtk_signal_connect(GTK_OBJECT(ctree), "button_release_event",
427                            GTK_SIGNAL_FUNC(folderview_button_released),
428                            folderview);
429         gtk_signal_connect(GTK_OBJECT(ctree), "tree_select_row",
430                            GTK_SIGNAL_FUNC(folderview_selected), folderview);
431
432         gtk_signal_connect_after(GTK_OBJECT(ctree), "tree_expand",
433                                  GTK_SIGNAL_FUNC(folderview_tree_expanded),
434                                  folderview);
435         gtk_signal_connect_after(GTK_OBJECT(ctree), "tree_collapse",
436                                  GTK_SIGNAL_FUNC(folderview_tree_collapsed),
437                                  folderview);
438
439         gtk_signal_connect(GTK_OBJECT(ctree), "resize_column",
440                            GTK_SIGNAL_FUNC(folderview_col_resized),
441                            folderview);
442
443         gtk_signal_connect(GTK_OBJECT(mail_popup), "selection_done",
444                            GTK_SIGNAL_FUNC(folderview_popup_close),
445                            folderview);
446         gtk_signal_connect(GTK_OBJECT(imap_popup), "selection_done",
447                            GTK_SIGNAL_FUNC(folderview_popup_close),
448                            folderview);
449         gtk_signal_connect(GTK_OBJECT(news_popup), "selection_done",
450                            GTK_SIGNAL_FUNC(folderview_popup_close),
451                            folderview);
452         gtk_signal_connect(GTK_OBJECT(mbox_popup), "selection_done",
453                            GTK_SIGNAL_FUNC(folderview_popup_close),
454                            folderview);
455
456         /* drop callback */
457         gtk_drag_dest_set(ctree, GTK_DEST_DEFAULT_ALL &
458                           ~GTK_DEST_DEFAULT_HIGHLIGHT,
459                           summary_drag_types, 1,
460                           GDK_ACTION_MOVE|GDK_ACTION_COPY|GDK_ACTION_DEFAULT);
461         gtk_signal_connect(GTK_OBJECT(ctree), "drag_motion",
462                            GTK_SIGNAL_FUNC(folderview_drag_motion_cb),
463                            folderview);
464         gtk_signal_connect(GTK_OBJECT(ctree), "drag_leave",
465                            GTK_SIGNAL_FUNC(folderview_drag_leave_cb),
466                            folderview);
467         gtk_signal_connect(GTK_OBJECT(ctree), "drag_data_received",
468                            GTK_SIGNAL_FUNC(folderview_drag_received_cb),
469                            folderview);
470
471         folderview->scrolledwin  = scrolledwin;
472         folderview->ctree        = ctree;
473         folderview->mail_popup   = mail_popup;
474         folderview->mail_factory = mail_factory;
475         folderview->imap_popup   = imap_popup;
476         folderview->imap_factory = imap_factory;
477         folderview->news_popup   = news_popup;
478         folderview->news_factory = news_factory;
479         folderview->mbox_popup   = mbox_popup;
480         folderview->mbox_factory = mbox_factory;
481
482         gtk_widget_show_all(scrolledwin);
483
484         folderview_list = g_list_append(folderview_list, folderview);
485
486         return folderview;
487 }
488
489 void folderview_init(FolderView *folderview)
490 {
491         GtkWidget *ctree = folderview->ctree;
492         GtkWidget *label_new;
493         GtkWidget *label_unread;
494         GtkWidget *hbox_new;
495         GtkWidget *hbox_unread;
496
497         stock_pixmap_gdk(ctree, STOCK_PIXMAP_INBOX_CLOSE, &inboxxpm, &inboxxpmmask);
498         stock_pixmap_gdk(ctree, STOCK_PIXMAP_INBOX_CLOSE_HRM, &inboxhrmxpm, &inboxhrmxpmmask);
499         stock_pixmap_gdk(ctree, STOCK_PIXMAP_INBOX_OPEN, &inboxopenxpm, &inboxopenxpmmask);
500         stock_pixmap_gdk(ctree, STOCK_PIXMAP_INBOX_OPEN_HRM, &inboxopenhrmxpm, &inboxopenhrmxpmmask);
501         stock_pixmap_gdk(ctree, STOCK_PIXMAP_OUTBOX_CLOSE, &outboxxpm, &outboxxpmmask);
502         stock_pixmap_gdk(ctree, STOCK_PIXMAP_OUTBOX_CLOSE_HRM, &outboxhrmxpm, &outboxhrmxpmmask);
503         stock_pixmap_gdk(ctree, STOCK_PIXMAP_OUTBOX_OPEN, &outboxopenxpm, &outboxopenxpmmask);
504         stock_pixmap_gdk(ctree, STOCK_PIXMAP_OUTBOX_OPEN_HRM, &outboxopenhrmxpm, &outboxopenhrmxpmmask);
505         stock_pixmap_gdk(ctree, STOCK_PIXMAP_DIR_CLOSE, &folderxpm, &folderxpmmask);
506         stock_pixmap_gdk(ctree, STOCK_PIXMAP_DIR_CLOSE_HRM, &folderhrmxpm, &folderhrmxpmmask);
507         stock_pixmap_gdk(ctree, STOCK_PIXMAP_DIR_OPEN, &folderopenxpm, &folderopenxpmmask);
508         stock_pixmap_gdk(ctree, STOCK_PIXMAP_DIR_OPEN_HRM, &folderopenhrmxpm, &folderopenhrmxpmmask);
509         stock_pixmap_gdk(ctree, STOCK_PIXMAP_TRASH_OPEN, &trashopenxpm, &trashopenxpmmask);
510         stock_pixmap_gdk(ctree, STOCK_PIXMAP_TRASH_OPEN_HRM, &trashopenhrmxpm, &trashopenhrmxpmmask);
511         stock_pixmap_gdk(ctree, STOCK_PIXMAP_TRASH_CLOSE, &trashxpm, &trashxpmmask);
512         stock_pixmap_gdk(ctree, STOCK_PIXMAP_TRASH_CLOSE_HRM, &trashhrmxpm, &trashhrmxpmmask);
513         stock_pixmap_gdk(ctree, STOCK_PIXMAP_QUEUE_CLOSE, &queuexpm, &queuexpmmask);
514         stock_pixmap_gdk(ctree, STOCK_PIXMAP_QUEUE_CLOSE_HRM, &queuehrmxpm, &queuehrmxpmmask);
515         stock_pixmap_gdk(ctree, STOCK_PIXMAP_QUEUE_OPEN, &queueopenxpm, &queueopenxpmmask);
516         stock_pixmap_gdk(ctree, STOCK_PIXMAP_QUEUE_OPEN_HRM, &queueopenhrmxpm, &queueopenhrmxpmmask);
517
518         /* CLAWS: titles for "New" and "Unread" show new & unread pixmaps
519          * instead text (text overflows making them unreadable and ugly) */
520         stock_pixmap_gdk(ctree, STOCK_PIXMAP_NEW,
521                          &newxpm, &newxpmmask);
522         stock_pixmap_gdk(ctree, STOCK_PIXMAP_UNREAD,
523                          &unreadxpm, &unreadxpmmask);
524                 
525         label_new = gtk_pixmap_new(newxpm, newxpmmask);
526         label_unread = gtk_pixmap_new(unreadxpm, unreadxpmmask);
527
528         hbox_new = gtk_hbox_new(FALSE, 4);
529         hbox_unread = gtk_hbox_new(FALSE, 4);
530
531         /* left justified */
532         gtk_box_pack_start(GTK_BOX(hbox_new),label_new,FALSE,FALSE,0);
533         gtk_box_pack_start(GTK_BOX(hbox_unread),label_unread,FALSE,FALSE,0);
534
535         gtk_widget_show_all(hbox_new);
536         gtk_widget_show_all(hbox_unread);
537
538         gtk_clist_set_column_widget(GTK_CLIST(ctree),COL_NEW,hbox_new);
539         gtk_clist_set_column_widget(GTK_CLIST(ctree),COL_UNREAD,hbox_unread);
540                         
541
542
543         if (!normalfont)
544                 normalfont = gdk_fontset_load(NORMAL_FONT);
545         if (!boldfont)
546                 boldfont = gdk_fontset_load(BOLD_FONT);
547
548         if (!bold_style) {
549                 bold_style = gtk_style_copy(gtk_widget_get_style(ctree));
550                 bold_style->font = boldfont;
551                 bold_color_style = gtk_style_copy(bold_style);
552                 bold_color_style->fg[GTK_STATE_NORMAL] = folderview->color_new;
553
554                 bold_tgtfold_style = gtk_style_copy(bold_style);
555                 bold_tgtfold_style->fg[GTK_STATE_NORMAL] = folderview->color_op;
556         }
557         if (!normal_style) {
558                 normal_style = gtk_style_copy(gtk_widget_get_style(ctree));
559                 normal_style->font = normalfont;
560                 normal_color_style = gtk_style_copy(normal_style);
561                 normal_color_style->fg[GTK_STATE_NORMAL] = folderview->color_new;
562         }
563 }
564
565 void folderview_set(FolderView *folderview)
566 {
567         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
568         MainWindow *mainwin = folderview->mainwin;
569
570         debug_print(_("Setting folder info...\n"));
571         STATUSBAR_PUSH(mainwin, _("Setting folder info..."));
572
573         main_window_cursor_wait(mainwin);
574
575         folderview->selected = NULL;
576         folderview->opened = NULL;
577
578         gtk_clist_freeze(GTK_CLIST(ctree));
579         gtk_clist_clear(GTK_CLIST(ctree));
580         gtk_clist_thaw(GTK_CLIST(ctree));
581         gtk_clist_freeze(GTK_CLIST(ctree));
582
583         folderview_set_folders(folderview);
584
585         gtk_clist_thaw(GTK_CLIST(ctree));
586         main_window_cursor_normal(mainwin);
587         STATUSBAR_POP(mainwin);
588 }
589
590 void folderview_set_all(void)
591 {
592         GList *list;
593
594         for (list = folderview_list; list != NULL; list = list->next)
595                 folderview_set((FolderView *)list->data);
596 }
597
598 void folderview_select(FolderView *folderview, FolderItem *item)
599 {
600         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
601         GtkCTreeNode *node;
602         GtkCTreeNode *old_selected = folderview->selected;
603
604         if (!item) return;
605
606         node = gtk_ctree_find_by_row_data(ctree, NULL, item);
607         if (node) folderview_select_node(folderview, node);
608
609         if (old_selected != node)
610                 folder_update_op_count();
611 }
612
613 static void mark_all_read_cb(FolderView *folderview, guint action,
614                              GtkWidget *widget)
615 {
616         if (folderview->selected)
617                 summary_mark_all_read(folderview->summaryview);
618 }
619
620 static void folderview_select_node(FolderView *folderview, GtkCTreeNode *node)
621 {
622         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
623
624         g_return_if_fail(node != NULL);
625
626         folderview->open_folder = TRUE;
627         gtkut_ctree_set_focus_row(ctree, node);
628         gtk_ctree_select(ctree, node);
629         if (folderview->summaryview->messages > 0)
630                 gtk_widget_grab_focus(folderview->summaryview->ctree);
631         else
632                 gtk_widget_grab_focus(folderview->ctree);
633
634         gtkut_ctree_expand_parent_all(ctree, node);
635 }
636
637 void folderview_unselect(FolderView *folderview)
638 {
639         if (folderview->opened && !GTK_CTREE_ROW(folderview->opened)->children)
640                 gtk_ctree_collapse
641                         (GTK_CTREE(folderview->ctree), folderview->opened);
642
643         folderview->selected = folderview->opened = NULL;
644 }
645
646 static GtkCTreeNode *folderview_find_next_unread(GtkCTree *ctree,
647                                                  GtkCTreeNode *node)
648 {
649         FolderItem *item;
650
651         if (node)
652                 node = gtkut_ctree_node_next(ctree, node);
653         else
654                 node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
655
656         for (; node != NULL; node = gtkut_ctree_node_next(ctree, node)) {
657                 item = gtk_ctree_node_get_row_data(ctree, node);
658                 if (item && item->unread > 0 && item->stype != F_TRASH)
659                         return node;
660         }
661
662         return NULL;
663 }
664
665 void folderview_select_next_unread(FolderView *folderview)
666 {
667         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
668         GtkCTreeNode *node = NULL;
669
670         if ((node = folderview_find_next_unread(ctree, folderview->opened))
671             != NULL) {
672                 folderview_select_node(folderview, node);
673                 return;
674         }
675
676         if (!folderview->opened ||
677             folderview->opened == GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list))
678                 return;
679         /* search again from the first node */
680         if ((node = folderview_find_next_unread(ctree, NULL)) != NULL)
681                 folderview_select_node(folderview, node);
682 }
683
684 void folderview_update_msg_num(FolderView *folderview, GtkCTreeNode *row,
685                                gint new, gint unread, gint total)
686 {
687         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
688         static GtkCTreeNode *prev_row = NULL;
689         FolderItem *item;
690
691         if (!row) return;
692
693         item = gtk_ctree_node_get_row_data(ctree, row);
694         if (!item) return;
695
696         /* CLAWS: don't know why but this always seems to be true
697          * when deleting messages. Somewhere claws does a folder
698          * scan which sets all new, unread & total to the correct
699          * values. It then enters this function, but leaves it
700          * because new, unread and total are the same... */
701 #ifndef CLAWS    
702         if (prev_row     == row    &&
703             item->new    == new    &&
704             item->unread == unread &&
705             item->total  == total) 
706                 return;
707 #endif          
708
709         prev_row = row;
710
711         item->new    = new;
712         item->unread = unread;
713         item->total  = total;
714
715         folderview_update_node(folderview, row);
716 }
717
718 static void folderview_set_folders(FolderView *folderview)
719 {
720         GList *list;
721
722         list = folder_get_list();
723
724         for (; list != NULL; list = list->next)
725                 folderview_append_folder(folderview, FOLDER(list->data));
726 }
727
728 static void folderview_scan_tree_func(Folder *folder, FolderItem *item,
729                                       gpointer data)
730 {
731         GList *list;
732         gchar *rootpath;
733
734         if (FOLDER_IS_LOCAL(folder))
735                 rootpath = LOCAL_FOLDER(folder)->rootpath;
736         else if (folder->type == F_IMAP && folder->account &&
737                  folder->account->recv_server)
738                 rootpath = folder->account->recv_server;
739         else
740                 return;
741
742         for (list = folderview_list; list != NULL; list = list->next) {
743                 FolderView *folderview = (FolderView *)list->data;
744                 MainWindow *mainwin = folderview->mainwin;
745                 gchar *str;
746
747                 if (item->path)
748                         str = g_strdup_printf(_("Scanning folder %s%c%s ..."),
749                                               rootpath, G_DIR_SEPARATOR,
750                                               item->path);
751                 else
752                         str = g_strdup_printf(_("Scanning folder %s ..."),
753                                               rootpath);
754
755                 STATUSBAR_PUSH(mainwin, str);
756                 STATUSBAR_POP(mainwin);
757                 g_free(str);
758         }
759 }
760
761 static GtkWidget *label_window_create(const gchar *str)
762 {
763         GtkWidget *window;
764         GtkWidget *label;
765
766         window = gtk_window_new(GTK_WINDOW_DIALOG);
767         gtk_widget_set_usize(window, 380, 60);
768         gtk_container_set_border_width(GTK_CONTAINER(window), 8);
769         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
770         gtk_window_set_title(GTK_WINDOW(window), str);
771         gtk_window_set_modal(GTK_WINDOW(window), TRUE);
772         gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
773         manage_window_set_transient(GTK_WINDOW(window));
774
775         label = gtk_label_new(str);
776         gtk_container_add(GTK_CONTAINER(window), label);
777         gtk_widget_show(label);
778
779         gtk_widget_show_now(window);
780
781         return window;
782 }
783
784 void folderview_update_tree(Folder *folder)
785 {
786         GtkWidget *window;
787
788         g_return_if_fail(folder != NULL);
789
790         if (!folder->scan_tree) return;
791
792         inc_lock();
793         window = label_window_create(_("Rescanning folder tree..."));
794
795         folder_set_ui_func(folder, folderview_scan_tree_func, NULL);
796         folder->scan_tree(folder);
797         folder_set_ui_func(folder, NULL, NULL);
798
799         folder_write_list();
800         folderview_set_all();
801
802         gtk_widget_destroy(window);
803         inc_unlock();
804 }
805
806 void folderview_update_all(void)
807 {
808         GList *list;
809         GtkWidget *window;
810
811         inc_lock();
812         window = label_window_create(_("Rescanning all folder trees..."));
813
814         list = folder_get_list();
815         for (; list != NULL; list = list->next) {
816                 Folder *folder = list->data;
817
818                 if (!folder->scan_tree) continue;
819                 folder_set_ui_func(folder, folderview_scan_tree_func, NULL);
820                 folder->scan_tree(folder);
821                 folder_set_ui_func(folder, NULL, NULL);
822         }
823
824         folder_write_list();
825         folderview_set_all();
826         gtk_widget_destroy(window);
827         inc_unlock();
828 }
829
830 void folderview_update_all_node(void)
831 {
832         GList *list;
833         FolderItem *item;
834         FolderView *folderview;
835         GtkCTree *ctree;
836         GtkCTreeNode *node;
837
838         for (list = folderview_list; list != NULL; list = list->next) {
839                 folderview = (FolderView *)list->data;
840                 ctree = GTK_CTREE(folderview->ctree);
841
842                 inc_lock();
843                 main_window_lock(folderview->mainwin);
844                 gtk_widget_set_sensitive(folderview->ctree, FALSE);
845
846                 for (node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
847                      node != NULL; node = gtkut_ctree_node_next(ctree, node)) {
848                         item = gtk_ctree_node_get_row_data(ctree, node);
849                         if (!item || !FOLDER_IS_LOCAL(item->folder) ||
850                             !item->path)
851                                 continue;
852                         folderview_scan_tree_func(item->folder, item, NULL);
853                         folder_item_scan(item);
854                         folderview_update_node(folderview, node);
855                 }
856
857                 gtk_widget_set_sensitive(folderview->ctree, TRUE);
858                 main_window_unlock(folderview->mainwin);
859                 inc_unlock();
860         }
861
862         folder_write_list();
863 }
864
865 static gboolean folderview_search_new_recursive(GtkCTree *ctree,
866                                                 GtkCTreeNode *node)
867 {
868         FolderItem *item;
869
870         if (node) {
871                 item = gtk_ctree_node_get_row_data(ctree, node);
872                 if (item) {
873                         if (item->new > 0 ||
874                             (item->stype == F_QUEUE && item->total > 0))
875                                 return TRUE;
876                 }
877                 node = GTK_CTREE_ROW(node)->children;
878         } else
879                 node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
880
881         while (node) {
882                 if (folderview_search_new_recursive(ctree, node) == TRUE)
883                         return TRUE;
884                 node = GTK_CTREE_ROW(node)->sibling;
885         }
886
887         return FALSE;
888 }
889
890 static gboolean folderview_have_new_children(FolderView *folderview,
891                                              GtkCTreeNode *node)
892 {
893         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
894
895         if (!node)
896                 node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
897         if (!node)
898                 return FALSE;
899
900         node = GTK_CTREE_ROW(node)->children;
901
902         while (node) {
903                 if (folderview_search_new_recursive(ctree, node) == TRUE)
904                         return TRUE;
905                 node = GTK_CTREE_ROW(node)->sibling;
906         }
907
908         return FALSE;
909 }
910
911 static gboolean folderview_search_unread_recursive(GtkCTree *ctree,
912                                                    GtkCTreeNode *node)
913 {
914         FolderItem *item;
915
916         if (node) {
917                 item = gtk_ctree_node_get_row_data(ctree, node);
918                 if (item) {
919                         if (item->unread > 0 ||
920                             (item->stype == F_QUEUE && item->total > 0))
921                                 return TRUE;
922                 }
923                 node = GTK_CTREE_ROW(node)->children;
924         } else
925                 node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
926
927         while (node) {
928                 if (folderview_search_unread_recursive(ctree, node) == TRUE)
929                         return TRUE;
930                 node = GTK_CTREE_ROW(node)->sibling;
931         }
932
933         return FALSE;
934 }
935
936 static gboolean folderview_have_unread_children(FolderView *folderview,
937                                                 GtkCTreeNode *node)
938 {
939         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
940
941         if (!node)
942                 node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
943         if (!node)
944                 return FALSE;
945
946         node = GTK_CTREE_ROW(node)->children;
947
948         while (node) {
949                 if (folderview_search_unread_recursive(ctree, node) == TRUE)
950                         return TRUE;
951                 node = GTK_CTREE_ROW(node)->sibling;
952         }
953
954         return FALSE;
955 }
956
957 static void folderview_update_node(FolderView *folderview, GtkCTreeNode *node)
958 {
959         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
960         GtkStyle *style = NULL;
961         FolderItem *item;
962         GdkPixmap *xpm, *openxpm;
963         GdkBitmap *mask, *openmask;
964         gchar *name;
965         gchar *str;
966         gboolean add_unread_mark;
967         gboolean use_bold, use_color;
968
969         item = gtk_ctree_node_get_row_data(ctree, node);
970         g_return_if_fail(item != NULL);
971
972         switch (item->stype) {
973         case F_INBOX:
974                 if (item->hide_read_msgs) {
975                         xpm = inboxhrmxpm;
976                         mask = inboxhrmxpmmask;
977                         openxpm = inboxopenhrmxpm;
978                         openmask = inboxopenhrmxpmmask;
979                 } else {
980                         xpm = inboxxpm;
981                         mask = inboxxpmmask;
982                         openxpm = inboxopenxpm;
983                         openmask = inboxopenxpmmask;
984                 }
985                 name = g_strdup(_("Inbox"));
986                 break;
987         case F_OUTBOX:
988                 if (item->hide_read_msgs) {
989                         xpm = outboxhrmxpm;
990                         mask = outboxhrmxpmmask;
991                         openxpm = outboxopenhrmxpm;
992                         openmask = outboxopenhrmxpmmask;
993                 } else {
994                         xpm = outboxxpm;
995                         mask = outboxxpmmask;
996                         openxpm = outboxopenxpm;
997                         openmask = outboxopenxpmmask;
998                 }
999                 name = g_strdup(_("Outbox"));
1000                 break;
1001         case F_QUEUE:
1002                 if (item->hide_read_msgs) {
1003                         xpm = queuehrmxpm;
1004                         mask = queuehrmxpmmask;
1005                         openxpm = queueopenhrmxpm;
1006                         openmask = queueopenhrmxpmmask;
1007                 } else {
1008                         xpm = queuexpm;
1009                         mask = queuexpmmask;
1010                         openxpm = queueopenxpm;
1011                         openmask = queueopenxpmmask;
1012                 }
1013                 name = g_strdup(_("Queue"));
1014                 break;
1015         case F_TRASH:
1016                 if (item->hide_read_msgs) {
1017                         xpm = trashhrmxpm;
1018                         mask = trashhrmxpmmask;
1019                         openxpm = trashopenhrmxpm;
1020                         openmask = trashopenhrmxpmmask;
1021                 } else {
1022                         xpm = trashxpm;
1023                         mask = trashxpmmask;
1024                         openxpm = trashopenxpm;
1025                         openmask = trashopenxpmmask;
1026                 }
1027                 name = g_strdup(_("Trash"));
1028                 break;
1029         case F_DRAFT:
1030                 xpm = folderxpm;
1031                 mask = folderxpmmask;
1032                 if (item->hide_read_msgs) {
1033                         openxpm = folderopenhrmxpm;
1034                         openmask = folderopenhrmxpmmask;
1035                 } else {
1036                         openxpm = folderopenxpm;
1037                         openmask = folderopenxpmmask;
1038                 }
1039                 name = g_strdup(_("Draft"));
1040                 break;
1041         default:
1042                 if (item->hide_read_msgs) {
1043                         xpm = folderhrmxpm;
1044                         mask = folderhrmxpmmask;
1045                         openxpm = folderopenhrmxpm;
1046                         openmask = folderopenhrmxpmmask;
1047                 } else {
1048                         xpm = folderxpm;
1049                         mask = folderxpmmask;
1050                         openxpm = folderopenxpm;
1051                         openmask = folderopenxpmmask;
1052                 }
1053                 if (!item->parent) {
1054                         switch (item->folder->type) {
1055                         case F_MH:
1056                                 name = " (MH)"; break;
1057                         case F_MBOX:
1058                                 name = " (mbox)"; break;
1059                         case F_IMAP:
1060                                 name = " (IMAP4)"; break;
1061                         case F_NEWS:
1062                                 name = " (News)"; break;
1063                         default:
1064                                 name = "";
1065                         }
1066                         name = g_strconcat(item->name, name, NULL);
1067                 } else
1068                         name = g_strdup(item->name);
1069         }
1070
1071         if (!GTK_CTREE_ROW(node)->expanded &&
1072             folderview_have_unread_children(folderview, node))
1073                 add_unread_mark = TRUE;
1074         else
1075                 add_unread_mark = FALSE;
1076
1077         if (item->stype == F_QUEUE && item->total > 0 &&
1078             prefs_common.display_folder_unread) {
1079                 str = g_strdup_printf("%s (%d%s)", name, item->total,
1080                                       add_unread_mark ? "+" : "");
1081                 gtk_ctree_set_node_info(ctree, node, str, FOLDER_SPACING,
1082                                         xpm, mask, openxpm, openmask,
1083                                         FALSE, GTK_CTREE_ROW(node)->expanded);
1084                 g_free(str);
1085         } else if ((item->unread > 0 || add_unread_mark) &&
1086                  prefs_common.display_folder_unread) {
1087
1088                 if (item->unread > 0)
1089                         str = g_strdup_printf("%s (%d%s)", name, item->unread,
1090                                               add_unread_mark ? "+" : "");
1091                 else
1092                         str = g_strdup_printf("%s (+)", name);
1093                 gtk_ctree_set_node_info(ctree, node, str, FOLDER_SPACING,
1094                                         xpm, mask, openxpm, openmask,
1095                                         FALSE, GTK_CTREE_ROW(node)->expanded);
1096                 g_free(str);
1097         } else
1098                 gtk_ctree_set_node_info(ctree, node, name, FOLDER_SPACING,
1099                                         xpm, mask, openxpm, openmask,
1100                                         FALSE, GTK_CTREE_ROW(node)->expanded);
1101         g_free(name);
1102
1103         if (!item->parent) {
1104                 gtk_ctree_node_set_text(ctree, node, COL_NEW,    "-");
1105                 gtk_ctree_node_set_text(ctree, node, COL_UNREAD, "-");
1106                 gtk_ctree_node_set_text(ctree, node, COL_TOTAL,  "-");
1107         } else {
1108                 gtk_ctree_node_set_text(ctree, node, COL_NEW,    itos(item->new));
1109                 gtk_ctree_node_set_text(ctree, node, COL_UNREAD, itos(item->unread));
1110                 gtk_ctree_node_set_text(ctree, node, COL_TOTAL,  itos(item->total));
1111         }
1112
1113         if (item->stype == F_TRASH)
1114                 use_bold = use_color = FALSE;
1115         if (item->stype == F_QUEUE) {
1116                 /* highlight queue folder if there are any messages */
1117                 use_bold = use_color = (item->total > 0);
1118         } else {
1119                 /* if unread messages exist, print with bold font */
1120                 use_bold = (item->unread > 0) || add_unread_mark;
1121                 /* if new messages exist, print with colored letter */
1122                 use_color =
1123                         (item->new > 0) ||
1124                         (add_unread_mark &&
1125                          folderview_have_new_children(folderview, node));
1126         }
1127
1128         gtk_ctree_node_set_foreground(ctree, node, NULL);
1129
1130         if (use_bold && use_color)
1131                 style = bold_color_style;
1132         else if (use_bold) {
1133                 style = bold_style;
1134                 if (item->op_count > 0) {
1135                         style = bold_tgtfold_style;
1136                 }
1137         }
1138         else if (use_color) {
1139                 style = normal_color_style;
1140                 gtk_ctree_node_set_foreground(ctree, node,
1141                                               &folderview->color_new);
1142         }
1143         else if (item->op_count > 0) {
1144                 style = bold_tgtfold_style;
1145         } else {
1146                 style = normal_style;
1147         }
1148
1149         gtk_ctree_node_set_row_style(ctree, node, style);
1150
1151         if ((node = gtkut_ctree_find_collapsed_parent(ctree, node)) != NULL)
1152                 folderview_update_node(folderview, node);
1153 }
1154
1155 void folderview_update_item(FolderItem *item, gboolean update_summary)
1156 {
1157         GList *list;
1158         FolderView *folderview;
1159         GtkCTree *ctree;
1160         GtkCTreeNode *node;
1161
1162         g_return_if_fail(item != NULL);
1163
1164         for (list = folderview_list; list != NULL; list = list->next) {
1165                 folderview = (FolderView *)list->data;
1166                 ctree = GTK_CTREE(folderview->ctree);
1167
1168                 node = gtk_ctree_find_by_row_data(ctree, NULL, item);
1169                 if (node) {
1170                         folderview_update_node(folderview, node);
1171                         if (update_summary && folderview->opened == node)
1172                                 summary_show(folderview->summaryview,
1173                                              item, FALSE);
1174                 }
1175         }
1176 }
1177
1178 static void folderview_update_item_foreach_func(gpointer key, gpointer val,
1179                                                 gpointer data)
1180 {
1181         folderview_update_item((FolderItem *)key, FALSE);
1182 }
1183
1184 void folderview_update_item_foreach(GHashTable *table)
1185 {
1186         g_hash_table_foreach(table, folderview_update_item_foreach_func, NULL);
1187 }
1188
1189 static gboolean folderview_gnode_func(GtkCTree *ctree, guint depth,
1190                                       GNode *gnode, GtkCTreeNode *cnode,
1191                                       gpointer data)
1192 {
1193         FolderView *folderview = (FolderView *)data;
1194         FolderItem *item = FOLDER_ITEM(gnode->data);
1195
1196         g_return_val_if_fail(item != NULL, FALSE);
1197
1198         gtk_ctree_node_set_row_data(ctree, cnode, item);
1199         folderview_update_node(folderview, cnode);
1200
1201         return TRUE;
1202 }
1203
1204 static void folderview_expand_func(GtkCTree *ctree, GtkCTreeNode *node,
1205                                    gpointer data)
1206 {
1207         FolderView *folderview = (FolderView *)data;
1208         FolderItem *item;
1209
1210         if (GTK_CTREE_ROW(node)->children) {
1211                 item = gtk_ctree_node_get_row_data(ctree, node);
1212                 g_return_if_fail(item != NULL);
1213
1214                 if (!item->collapsed)
1215                         gtk_ctree_expand(ctree, node);
1216                 else
1217                         folderview_update_node(folderview, node);
1218         }
1219 }
1220
1221 #define SET_SPECIAL_FOLDER(ctree, item) \
1222 { \
1223         if (item) { \
1224                 GtkCTreeNode *node, *sibling; \
1225  \
1226                 node = gtk_ctree_find_by_row_data(ctree, root, item); \
1227                 if (!node) \
1228                         g_warning("%s not found.\n", item->path); \
1229                 else { \
1230                         if (!prev) \
1231                                 sibling = GTK_CTREE_ROW(root)->children; \
1232                         else \
1233                                 sibling = GTK_CTREE_ROW(prev)->sibling; \
1234                         if (node != sibling) \
1235                                 gtk_ctree_move(ctree, node, root, sibling); \
1236                 } \
1237  \
1238                 prev = node; \
1239         } \
1240 }
1241
1242 static void folderview_sort_folders(FolderView *folderview, GtkCTreeNode *root,
1243                                     Folder *folder)
1244 {
1245         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1246         GtkCTreeNode *prev = NULL;
1247
1248         gtk_ctree_sort_recursive(ctree, root);
1249
1250         if (GTK_CTREE_ROW(root)->parent) return;
1251
1252         SET_SPECIAL_FOLDER(ctree, folder->inbox);
1253         SET_SPECIAL_FOLDER(ctree, folder->outbox);
1254         SET_SPECIAL_FOLDER(ctree, folder->draft);
1255         SET_SPECIAL_FOLDER(ctree, folder->queue);
1256         SET_SPECIAL_FOLDER(ctree, folder->trash);
1257 }
1258
1259 static void folderview_append_folder(FolderView *folderview, Folder *folder)
1260 {
1261         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1262         GtkCTreeNode *root;
1263
1264         g_return_if_fail(folder != NULL);
1265
1266         root = gtk_ctree_insert_gnode(ctree, NULL, NULL, folder->node,
1267                                       folderview_gnode_func, folderview);
1268         gtk_ctree_pre_recursive(ctree, root, folderview_expand_func,
1269                                 folderview);
1270         folderview_sort_folders(folderview, root, folder);
1271 }
1272
1273 void folderview_new_folder(FolderView *folderview)
1274 {
1275         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1276         FolderItem *item;
1277
1278         if (!folderview->selected) return;
1279
1280         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1281         g_return_if_fail(item != NULL);
1282         g_return_if_fail(item->folder != NULL);
1283
1284         switch (item->folder->type) {
1285         case F_MBOX:
1286                 folderview_new_mbox_folder_cb(folderview, 0, NULL);
1287                 break;
1288         case F_MH:
1289         case F_MAILDIR:
1290                 folderview_new_folder_cb(folderview, 0, NULL);
1291                 break;
1292         case F_IMAP:
1293                 folderview_new_imap_folder_cb(folderview, 0, NULL);
1294                 break;
1295         case F_NEWS:
1296         default:
1297                 break;
1298         }
1299 }
1300
1301 void folderview_rename_folder(FolderView *folderview)
1302 {
1303         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1304         FolderItem *item;
1305
1306         if (!folderview->selected) return;
1307
1308         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1309         g_return_if_fail(item != NULL);
1310         g_return_if_fail(item->folder != NULL);
1311         if (!item->path) return;
1312         if (item->stype != F_NORMAL) return;
1313
1314         switch (item->folder->type) {
1315         case F_MBOX:
1316                 folderview_rename_mbox_folder_cb(folderview, 0, NULL);
1317         case F_MH:
1318         case F_MAILDIR:
1319                 folderview_rename_folder_cb(folderview, 0, NULL);
1320                 break;
1321         case F_IMAP:
1322         case F_NEWS:
1323         default:
1324                 break;
1325         }
1326 }
1327
1328 void folderview_delete_folder(FolderView *folderview)
1329 {
1330         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1331         FolderItem *item;
1332
1333         if (!folderview->selected) return;
1334
1335         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1336         g_return_if_fail(item != NULL);
1337         g_return_if_fail(item->folder != NULL);
1338         if (!item->path) return;
1339         if (item->stype != F_NORMAL) return;
1340
1341         switch (item->folder->type) {
1342         case F_MH:
1343         case F_MBOX:
1344         case F_MAILDIR:
1345                 folderview_delete_folder_cb(folderview, 0, NULL);
1346                 break;
1347         case F_IMAP:
1348                 folderview_rm_imap_folder_cb(folderview, 0, NULL);
1349         case F_NEWS:
1350         default:
1351                 break;
1352         }
1353 }
1354
1355
1356 /* callback functions */
1357
1358 static void folderview_button_pressed(GtkWidget *ctree, GdkEventButton *event,
1359                                       FolderView *folderview)
1360 {
1361         GtkCList *clist = GTK_CLIST(ctree);
1362         gint prev_row = -1, row = -1, column = -1;
1363         FolderItem *item;
1364         Folder *folder;
1365         GtkWidget *popup;
1366         gboolean mark_all_read   = FALSE;
1367         gboolean new_folder      = FALSE;
1368         gboolean rename_folder   = FALSE;
1369         gboolean delete_folder   = FALSE;
1370         gboolean update_tree     = FALSE;
1371         gboolean rescan_tree     = FALSE;
1372         gboolean remove_tree     = FALSE;
1373         gboolean folder_property = FALSE;
1374         gboolean folder_processing  = FALSE;
1375         gboolean folder_scoring  = FALSE;
1376         gboolean search_folder = FALSE;
1377
1378         if (!event) return;
1379
1380         if (event->button == 1) {
1381                 folderview->open_folder = TRUE;
1382                 return;
1383         }
1384
1385         if (event->button == 2 || event->button == 3) {
1386                 /* right clicked */
1387                 if (clist->selection) {
1388                         GtkCTreeNode *node;
1389
1390                         node = GTK_CTREE_NODE(clist->selection->data);
1391                         if (node)
1392                                 prev_row = gtkut_ctree_get_nth_from_node
1393                                         (GTK_CTREE(ctree), node);
1394                 }
1395
1396                 if (!gtk_clist_get_selection_info(clist, event->x, event->y,
1397                                                   &row, &column))
1398                         return;
1399                 if (prev_row != row) {
1400                         gtk_clist_unselect_all(clist);
1401                         if (event->button == 2)
1402                                 folderview_select_node
1403                                         (folderview,
1404                                          gtk_ctree_node_nth(GTK_CTREE(ctree),
1405                                                             row));
1406                         else
1407                                 gtk_clist_select_row(clist, row, column);
1408                 }
1409         }
1410
1411         if (event->button != 3) return;
1412
1413         item = gtk_clist_get_row_data(clist, row);
1414         g_return_if_fail(item != NULL);
1415         g_return_if_fail(item->folder != NULL);
1416         folder = item->folder;
1417
1418         if (folderview->mainwin->lock_count == 0) {
1419                 new_folder = TRUE;
1420                 if (item->parent == NULL)
1421                         update_tree = remove_tree = TRUE;
1422                 else
1423                         mark_all_read = search_folder = TRUE;
1424                 if (FOLDER_IS_LOCAL(folder) || FOLDER_TYPE(folder) == F_IMAP || FOLDER_TYPE(folder) == F_MBOX) {
1425                         if (item->parent == NULL)
1426                                 update_tree = rescan_tree = TRUE;
1427                         else if (item->stype == F_NORMAL)
1428                                 rename_folder = delete_folder = folder_property = folder_scoring = folder_processing = TRUE;
1429                         else if (item->stype == F_INBOX)
1430                                 folder_property = folder_scoring = folder_processing = TRUE;
1431                         else if (item->stype == F_TRASH)
1432                                 folder_processing = TRUE;
1433                         else if (item->stype == F_OUTBOX)
1434                                 folder_processing = TRUE;
1435                 } else if (FOLDER_TYPE(folder) == F_NEWS) {
1436                         if (item->parent != NULL)
1437                                 delete_folder = folder_scoring = folder_processing = TRUE;
1438                 }
1439                 if (item->unread < 1) 
1440                         mark_all_read = FALSE;
1441         }
1442
1443 #define SET_SENS(factory, name, sens) \
1444         menu_set_sensitive(folderview->factory, name, sens)
1445         
1446         mark_all_read = mark_all_read && 
1447                         (item == folderview->summaryview->folder_item);
1448
1449         if (FOLDER_IS_LOCAL(folder)) {
1450                 popup = folderview->mail_popup;
1451                 menu_set_insensitive_all(GTK_MENU_SHELL(popup));
1452                 SET_SENS(mail_factory, "/Mark all read", mark_all_read);
1453                 SET_SENS(mail_factory, "/Create new folder...", new_folder);
1454                 SET_SENS(mail_factory, "/Rename folder...", rename_folder);
1455                 SET_SENS(mail_factory, "/Delete folder", delete_folder);
1456                 SET_SENS(mail_factory, "/Check for new messages", update_tree);
1457                 SET_SENS(mail_factory, "/Rescan folder tree", rescan_tree);
1458                 SET_SENS(mail_factory, "/Remove mailbox", remove_tree);
1459                 SET_SENS(mail_factory, "/Property...", folder_property);
1460                 SET_SENS(mail_factory, "/Processing...", folder_processing);
1461                 SET_SENS(mail_factory, "/Scoring...", folder_scoring);
1462                 SET_SENS(mail_factory, "/Search folder...", search_folder);
1463         } else if (FOLDER_TYPE(folder) == F_IMAP) {
1464                 popup = folderview->imap_popup;
1465                 menu_set_insensitive_all(GTK_MENU_SHELL(popup));
1466                 SET_SENS(imap_factory, "/Mark all read", mark_all_read);
1467                 SET_SENS(imap_factory, "/Create new folder...", new_folder);
1468                 SET_SENS(imap_factory, "/Rename folder...", rename_folder);
1469                 SET_SENS(imap_factory, "/Delete folder", delete_folder);
1470                 SET_SENS(imap_factory, "/Check for new messages", update_tree);
1471                 SET_SENS(imap_factory, "/Rescan folder tree", rescan_tree);
1472                 SET_SENS(imap_factory, "/Remove IMAP4 account", remove_tree);
1473                 SET_SENS(imap_factory, "/Processing...", folder_processing);
1474                 SET_SENS(imap_factory, "/Scoring...", folder_scoring);
1475                 SET_SENS(imap_factory, "/Search folder...", search_folder);
1476         } else if (FOLDER_TYPE(folder) == F_NEWS) {
1477                 popup = folderview->news_popup;
1478                 menu_set_insensitive_all(GTK_MENU_SHELL(popup));
1479                 SET_SENS(news_factory, "/Mark all read", mark_all_read);
1480                 SET_SENS(news_factory, "/Subscribe to newsgroup...", new_folder);
1481                 SET_SENS(news_factory, "/Remove newsgroup", delete_folder);
1482 #if 0
1483                 SET_SENS(news_factory, "/Check for new messages", update_tree);
1484 #endif
1485                 SET_SENS(news_factory, "/Remove news account", remove_tree);
1486                 SET_SENS(news_factory, "/Search folder...", search_folder);
1487                 SET_SENS(news_factory, "/Processing...", folder_processing);
1488                 SET_SENS(news_factory, "/Scoring...", folder_scoring);
1489         } else if (FOLDER_TYPE(folder) == F_MBOX) {
1490                 popup = folderview->mbox_popup;
1491                 menu_set_insensitive_all(GTK_MENU_SHELL(popup));
1492                 SET_SENS(mbox_factory, "/Create new folder...", new_folder);
1493                 SET_SENS(mbox_factory, "/Rename folder...", rename_folder);
1494                 SET_SENS(mbox_factory, "/Delete folder", delete_folder);
1495                 SET_SENS(mbox_factory, "/Processing...", folder_processing);
1496                 SET_SENS(mbox_factory, "/Scoring...", folder_scoring);
1497         } else
1498                 return;
1499
1500 #undef SET_SENS
1501
1502         gtk_menu_popup(GTK_MENU(popup), NULL, NULL, NULL, NULL,
1503                        event->button, event->time);
1504 }
1505
1506 static void folderview_button_released(GtkWidget *ctree, GdkEventButton *event,
1507                                        FolderView *folderview)
1508 {
1509         if (!event) return;
1510
1511         if (event->button == 1 && folderview->open_folder == FALSE &&
1512             folderview->opened != NULL) {
1513                 gtkut_ctree_set_focus_row(GTK_CTREE(ctree),
1514                                           folderview->opened);
1515                 gtk_ctree_select(GTK_CTREE(ctree), folderview->opened);
1516         }
1517 }
1518
1519 static void folderview_key_pressed(GtkWidget *widget, GdkEventKey *event,
1520                                    FolderView *folderview)
1521 {
1522         if (!event) return;
1523
1524         switch (event->keyval) {
1525         case GDK_Return:
1526                 if (folderview->selected) {
1527                         folderview_select_node(folderview,
1528                                                folderview->selected);
1529                 }
1530                 break;
1531         case GDK_space:
1532                 if (folderview->selected) {
1533                         if (folderview->opened == folderview->selected &&
1534                             folderview->summaryview->messages == 0)
1535                                 folderview_select_next_unread(folderview);
1536                         else
1537                                 folderview_select_node(folderview,
1538                                                        folderview->selected);
1539                 }
1540                 break;
1541         default:
1542                 break;
1543         }
1544 }
1545
1546 static void folderview_selected(GtkCTree *ctree, GtkCTreeNode *row,
1547                                 gint column, FolderView *folderview)
1548 {
1549         static gboolean can_select = TRUE;      /* exclusive lock */
1550         gboolean opened;
1551         FolderItem *item;
1552
1553         folderview->selected = row;
1554
1555         if (folderview->opened == row) {
1556                 folderview->open_folder = FALSE;
1557                 return;
1558         }
1559
1560         if (!can_select) {
1561                 gtkut_ctree_set_focus_row(ctree, folderview->opened);
1562                 gtk_ctree_select(ctree, folderview->opened);
1563                 return;
1564         }
1565
1566         if (!folderview->open_folder) return;
1567
1568         item = gtk_ctree_node_get_row_data(ctree, row);
1569         if (!item) return;
1570
1571         can_select = FALSE;
1572
1573         /* CLAWS: set compose button type: news folder items 
1574          * always have a news folder as parent */
1575         if (item->folder) 
1576                 main_window_toolbar_set_compose_button
1577                         (folderview->mainwin,
1578                          item->folder->type == F_NEWS ? 
1579                          COMPOSEBUTTON_NEWS : COMPOSEBUTTON_MAIL);
1580          
1581         if (item->path)
1582                 debug_print(_("Folder %s is selected\n"), item->path);
1583
1584         if (!GTK_CTREE_ROW(row)->children)
1585                 gtk_ctree_expand(ctree, row);
1586         if (folderview->opened &&
1587             !GTK_CTREE_ROW(folderview->opened)->children)
1588                 gtk_ctree_collapse(ctree, folderview->opened);
1589
1590         /* ungrab the mouse event */
1591         if (GTK_WIDGET_HAS_GRAB(ctree)) {
1592                 gtk_grab_remove(GTK_WIDGET(ctree));
1593                 if (gdk_pointer_is_grabbed())
1594                         gdk_pointer_ungrab(GDK_CURRENT_TIME);
1595         }
1596
1597         opened = summary_show(folderview->summaryview, item, FALSE);
1598
1599         if (!opened) {
1600                 gtkut_ctree_set_focus_row(ctree, folderview->opened);
1601                 gtk_ctree_select(ctree, folderview->opened);
1602         } else
1603                 folderview->opened = row;
1604
1605         folderview->open_folder = FALSE;
1606         can_select = TRUE;
1607 }
1608
1609 static void folderview_tree_expanded(GtkCTree *ctree, GtkCTreeNode *node,
1610                                      FolderView *folderview)
1611 {
1612         FolderItem *item;
1613
1614         item = gtk_ctree_node_get_row_data(ctree, node);
1615         g_return_if_fail(item != NULL);
1616         item->collapsed = FALSE;
1617         folderview_update_node(folderview, node);
1618 }
1619
1620 static void folderview_tree_collapsed(GtkCTree *ctree, GtkCTreeNode *node,
1621                                       FolderView *folderview)
1622 {
1623         FolderItem *item;
1624
1625         item = gtk_ctree_node_get_row_data(ctree, node);
1626         g_return_if_fail(item != NULL);
1627         item->collapsed= TRUE;
1628         folderview_update_node(folderview, node);
1629 }
1630
1631 static void folderview_popup_close(GtkMenuShell *menu_shell,
1632                                    FolderView *folderview)
1633 {
1634         if (!folderview->opened) return;
1635
1636         gtkut_ctree_set_focus_row(GTK_CTREE(folderview->ctree),
1637                                   folderview->opened);
1638         gtk_ctree_select(GTK_CTREE(folderview->ctree), folderview->opened);
1639 }
1640
1641 static void folderview_col_resized(GtkCList *clist, gint column, gint width,
1642                                    FolderView *folderview)
1643 {
1644         switch (column) {
1645         case COL_FOLDER:
1646                 prefs_common.folder_col_folder = width;
1647                 break;
1648         case COL_NEW:
1649                 prefs_common.folder_col_new = width;
1650                 break;
1651         case COL_UNREAD:
1652                 prefs_common.folder_col_unread = width;
1653                 break;
1654         case COL_TOTAL:
1655                 prefs_common.folder_col_total = width;
1656                 break;
1657         default:
1658         }
1659 }
1660
1661 static GtkCTreeNode *folderview_find_by_name(GtkCTree *ctree,
1662                                              GtkCTreeNode *node,
1663                                              const gchar *name)
1664 {
1665         FolderItem *item;
1666
1667         if (!node)
1668                 node = GTK_CTREE_NODE(GTK_CLIST(ctree)->row_list);
1669         if (!node)
1670                 return NULL;
1671
1672         node = GTK_CTREE_ROW(node)->children;
1673
1674         while (node) {
1675                 item = gtk_ctree_node_get_row_data(ctree, node);
1676                 if (!folderview_compare_name(item, name))
1677                         return node;
1678                 node = GTK_CTREE_ROW(node)->sibling;
1679         }
1680
1681         return NULL;
1682 }
1683
1684 static void folderview_update_tree_cb(FolderView *folderview, guint action,
1685                                       GtkWidget *widget)
1686 {
1687         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1688         FolderItem *item;
1689
1690         if (!folderview->selected) return;
1691
1692         summary_show(folderview->summaryview, NULL, FALSE);
1693
1694         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1695         g_return_if_fail(item != NULL);
1696         g_return_if_fail(item->folder != NULL);
1697
1698         if (action == 0)
1699                 folderview_update_all_node();
1700         else
1701                 folderview_update_tree(item->folder);
1702 }
1703
1704 static void folderview_new_folder_cb(FolderView *folderview, guint action,
1705                                      GtkWidget *widget)
1706 {
1707         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1708         gchar *text[N_FOLDER_COLS] = {NULL, "0", "0", "0"};
1709         FolderItem *item;
1710         FolderItem *new_item;
1711         gchar *new_folder;
1712         GtkCTreeNode *node;
1713
1714         if (!folderview->selected) return;
1715
1716         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1717         g_return_if_fail(item != NULL);
1718         g_return_if_fail(item->folder != NULL);
1719
1720         new_folder = input_dialog(_("New folder"),
1721                                   _("Input the name of new folder:"),
1722                                   _("NewFolder"));
1723         if (!new_folder) return;
1724
1725         if (item->folder->type != F_MBOX) {
1726                 if (strchr(new_folder, G_DIR_SEPARATOR) != NULL) {
1727                         alertpanel_error(_("`%c' can't be included in folder name."),
1728                                          G_DIR_SEPARATOR);
1729                         g_free(new_folder);
1730                         return;
1731                 }
1732         }
1733
1734         /* find whether the directory already exists */
1735         if (folderview_find_by_name(ctree, folderview->selected, new_folder)) {
1736                 alertpanel_error(_("The folder `%s' already exists."),
1737                                  new_folder);
1738                 g_free(new_folder);
1739                 return;
1740         }
1741
1742         new_item = item->folder->create_folder(item->folder, item, new_folder);
1743         if (!new_item) {
1744                 alertpanel_error(_("The folder `%s' could not be created."), 
1745                                  new_folder);
1746                 g_free(new_folder);
1747                 return;
1748         } 
1749         g_free(new_folder);
1750
1751         gtk_clist_freeze(GTK_CLIST(ctree));
1752
1753         text[COL_FOLDER] = new_item->name;
1754         node = gtk_ctree_insert_node(ctree, folderview->selected, NULL, text,
1755                                      FOLDER_SPACING,
1756                                      folderxpm, folderxpmmask,
1757                                      folderopenxpm, folderopenxpmmask,
1758                                      FALSE, FALSE);
1759         gtk_ctree_expand(ctree, folderview->selected);
1760         gtk_ctree_node_set_row_data(ctree, node, new_item);
1761         folderview_sort_folders(folderview, folderview->selected, item->folder);
1762
1763         gtk_clist_thaw(GTK_CLIST(ctree));
1764
1765         folder_write_list();
1766 }
1767
1768 static void folderview_new_mbox_folder_cb(FolderView *folderview, guint action,
1769                                           GtkWidget *widget)
1770 {
1771         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1772         gchar *text[N_FOLDER_COLS] = {NULL, "0", "0", "0"};
1773         FolderItem *item;
1774         FolderItem *new_item;
1775         gchar *new_folder;
1776         GtkCTreeNode *node;
1777
1778         if (!folderview->selected) return;
1779
1780         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1781         g_return_if_fail(item != NULL);
1782         g_return_if_fail(item->folder != NULL);
1783
1784         new_folder = input_dialog(_("New folder"),
1785                                   _("Input the name of new folder:"),
1786                                   _("NewFolder"));
1787         if (!new_folder) return;
1788
1789         /* find whether the directory already exists */
1790         if (folderview_find_by_name(ctree, folderview->selected, new_folder)) {
1791                 alertpanel_error(_("The folder `%s' already exists."),
1792                                  new_folder);
1793                 g_free(new_folder);
1794                 return;
1795         }
1796
1797         new_item = item->folder->create_folder(item->folder, item, new_folder);
1798         g_free(new_folder);
1799         if (!new_item) return;
1800
1801         gtk_clist_freeze(GTK_CLIST(ctree));
1802
1803         text[COL_FOLDER] = new_item->name;
1804         node = gtk_ctree_insert_node(ctree, folderview->selected, NULL, text,
1805                                      FOLDER_SPACING,
1806                                      folderxpm, folderxpmmask,
1807                                      folderopenxpm, folderopenxpmmask,
1808                                      FALSE, FALSE);
1809         gtk_ctree_expand(ctree, folderview->selected);
1810         gtk_ctree_node_set_row_data(ctree, node, new_item);
1811         folderview_sort_folders(folderview, folderview->selected, item->folder);
1812
1813         gtk_clist_thaw(GTK_CLIST(ctree));
1814
1815         folder_write_list();
1816 }
1817
1818 static void folderview_rename_folder_cb(FolderView *folderview, guint action,
1819                                         GtkWidget *widget)
1820 {
1821         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1822         FolderItem *item;
1823         gchar *new_folder;
1824         gchar *message;
1825
1826         if (!folderview->selected) return;
1827
1828         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1829         g_return_if_fail(item != NULL);
1830         g_return_if_fail(item->path != NULL);
1831         g_return_if_fail(item->folder != NULL);
1832
1833         message = g_strdup_printf(_("Input new name for `%s':"),
1834                                   g_basename(item->path));
1835         new_folder = input_dialog(_("Rename folder"), message,
1836                                   g_basename(item->path));
1837         g_free(message);
1838         if (!new_folder) return;
1839
1840         if (strchr(new_folder, G_DIR_SEPARATOR) != NULL) {
1841                 alertpanel_error(_("`%c' can't be included in folder name."),
1842                                  G_DIR_SEPARATOR);
1843                 g_free(new_folder);
1844                 return;
1845         }
1846
1847         if (folderview_find_by_name
1848                 (ctree, GTK_CTREE_ROW(folderview->selected)->parent,
1849                  new_folder)) {
1850                 alertpanel_error(_("The folder `%s' already exists."),
1851                                  new_folder);
1852                 g_free(new_folder);
1853                 return;
1854         }
1855
1856         if (item->folder->rename_folder(item->folder, item, new_folder) < 0) {
1857                 g_free(new_folder);
1858                 return;
1859         }
1860         g_free(new_folder);
1861
1862         gtk_clist_freeze(GTK_CLIST(ctree));
1863
1864         folderview_update_node(folderview, folderview->selected);
1865         folderview_sort_folders(folderview,
1866                                 GTK_CTREE_ROW(folderview->selected)->parent,
1867                                 item->folder);
1868         if (folderview->opened == folderview->selected) {
1869                 if (!GTK_CTREE_ROW(folderview->opened)->children)
1870                         gtk_ctree_expand(ctree, folderview->opened);
1871                 summary_show(folderview->summaryview, item, FALSE);
1872         }
1873
1874         gtk_clist_thaw(GTK_CLIST(ctree));
1875
1876         folder_write_list();
1877 }
1878
1879 static void folderview_rename_mbox_folder_cb(FolderView *folderview,
1880                                              guint action,
1881                                              GtkWidget *widget)
1882 {
1883         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1884         FolderItem *item;
1885         gchar *new_folder;
1886         gchar *message;
1887
1888         if (!folderview->selected) return;
1889
1890         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1891         g_return_if_fail(item != NULL);
1892         g_return_if_fail(item->path != NULL);
1893         g_return_if_fail(item->folder != NULL);
1894
1895         message = g_strdup_printf(_("Input new name for `%s':"),
1896                                   g_basename(item->path));
1897         new_folder = input_dialog(_("Rename folder"), message,
1898                                   g_basename(item->path));
1899         g_free(message);
1900         if (!new_folder) return;
1901
1902         if (folderview_find_by_name
1903                 (ctree, GTK_CTREE_ROW(folderview->selected)->parent,
1904                  new_folder)) {
1905                 alertpanel_error(_("The folder `%s' already exists."),
1906                                  new_folder);
1907                 g_free(new_folder);
1908                 return;
1909         }
1910
1911         if (item->folder->rename_folder(item->folder, item, new_folder) < 0) {
1912                 g_free(new_folder);
1913                 return;
1914         }
1915         g_free(new_folder);
1916
1917         gtk_clist_freeze(GTK_CLIST(ctree));
1918
1919         folderview_update_node(folderview, folderview->selected);
1920         folderview_sort_folders(folderview,
1921                                 GTK_CTREE_ROW(folderview->selected)->parent,
1922                                 item->folder);
1923         if (folderview->opened == folderview->selected) {
1924                 if (!GTK_CTREE_ROW(folderview->opened)->children)
1925                         gtk_ctree_expand(ctree, folderview->opened);
1926                 summary_show(folderview->summaryview, item, FALSE);
1927         }
1928
1929         gtk_clist_thaw(GTK_CLIST(ctree));
1930
1931         folder_write_list();
1932 }
1933
1934 static void folderview_delete_folder_cb(FolderView *folderview, guint action,
1935                                         GtkWidget *widget)
1936 {
1937         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1938         FolderItem *item;
1939         gchar *message;
1940         AlertValue avalue;
1941
1942         if (!folderview->selected) return;
1943
1944         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
1945         g_return_if_fail(item != NULL);
1946         g_return_if_fail(item->path != NULL);
1947         g_return_if_fail(item->folder != NULL);
1948
1949         message = g_strdup_printf
1950                 (_("All folder(s) and message(s) under `%s' will be deleted.\n"
1951                    "Do you really want to delete?"),
1952                  g_basename(item->path));
1953         avalue = alertpanel(_("Delete folder"), message,
1954                             _("Yes"), _("+No"), NULL);
1955         g_free(message);
1956         if (avalue != G_ALERTDEFAULT) return;
1957
1958         if (item->folder->remove_folder(item->folder, item) < 0) {
1959                 alertpanel_error(_("Can't remove the folder `%s'."),
1960                                  item->path);
1961                 return;
1962         }
1963
1964         if (folderview->opened == folderview->selected ||
1965             gtk_ctree_is_ancestor(ctree,
1966                                   folderview->selected,
1967                                   folderview->opened)) {
1968                 summary_clear_all(folderview->summaryview);
1969                 folderview->opened = NULL;
1970         }
1971
1972         gtk_ctree_remove_node(ctree, folderview->selected);
1973         folder_write_list();
1974 }
1975
1976 static void folderview_remove_mailbox_cb(FolderView *folderview, guint action,
1977                                          GtkWidget *widget)
1978 {
1979         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
1980         GtkCTreeNode *node;
1981         FolderItem *item;
1982         gchar *message;
1983         AlertValue avalue;
1984
1985         if (!folderview->selected) return;
1986         node = folderview->selected;
1987         item = gtk_ctree_node_get_row_data(ctree, node);
1988         g_return_if_fail(item != NULL);
1989         g_return_if_fail(item->folder != NULL);
1990         if (item->parent) return;
1991
1992         message = g_strdup_printf
1993                 (_("Really remove the mailbox `%s' ?\n"
1994                    "(The messages are NOT deleted from disk)"),
1995                  item->folder->name);
1996         avalue = alertpanel(_("Remove folder"), message,
1997                             _("Yes"), _("+No"), NULL);
1998         g_free(message);
1999         if (avalue != G_ALERTDEFAULT) return;
2000
2001         folder_destroy(item->folder);
2002         summary_clear_all(folderview->summaryview);
2003         folderview_unselect(folderview);
2004         gtk_ctree_remove_node(ctree, node);
2005         folder_write_list();
2006 }
2007
2008 static void folderview_new_imap_folder_cb(FolderView *folderview, guint action,
2009                                           GtkWidget *widget)
2010 {
2011         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2012         gchar *text[N_FOLDER_COLS] = {NULL, "0", "0", "0"};
2013         GtkCTreeNode *node;
2014         FolderItem *item;
2015         FolderItem *new_item;
2016         gchar *new_folder;
2017         gchar *p;
2018
2019         if (!folderview->selected) return;
2020
2021         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2022         g_return_if_fail(item != NULL);
2023         g_return_if_fail(item->folder != NULL);
2024         g_return_if_fail(item->folder->type == F_IMAP);
2025         g_return_if_fail(item->folder->account != NULL);
2026
2027         new_folder = input_dialog
2028                 (_("New folder"),
2029                  _("Input the name of new folder:\n"
2030                    "(if you want to create a folder to store subfolders,\n"
2031                    " append `/' at the end of the name)"),
2032                  _("NewFolder"));
2033         if (!new_folder) return;
2034
2035         if ((p = strchr(new_folder, G_DIR_SEPARATOR)) != NULL &&
2036             *(p + 1) != '\0') {
2037                 alertpanel_error(_("`%c' can't be included in folder name."),
2038                                  G_DIR_SEPARATOR);
2039                 g_free(new_folder);
2040                 return;
2041         }
2042
2043         /* find whether the directory already exists */
2044         if (folderview_find_by_name(ctree, folderview->selected, new_folder)) {
2045                 alertpanel_error(_("The folder `%s' already exists."),
2046                                  new_folder);
2047                 g_free(new_folder);
2048                 return;
2049         }
2050
2051         new_item = item->folder->create_folder(item->folder, item, new_folder);
2052         if (!new_item) {
2053                 alertpanel_error(_("Can't create the folder `%s'."),
2054                                  new_folder);
2055                 g_free(new_folder);
2056                 return;
2057         }
2058         g_free(new_folder);
2059
2060         gtk_clist_freeze(GTK_CLIST(ctree));
2061
2062         text[COL_FOLDER] = new_item->name;
2063         node = gtk_ctree_insert_node(ctree, folderview->selected, NULL, text,
2064                                      FOLDER_SPACING,
2065                                      folderxpm, folderxpmmask,
2066                                      folderopenxpm, folderopenxpmmask,
2067                                      FALSE, FALSE);
2068         gtk_ctree_expand(ctree, folderview->selected);
2069         gtk_ctree_node_set_row_data(ctree, node, new_item);
2070         folderview_sort_folders(folderview, folderview->selected, item->folder);
2071
2072         gtk_clist_thaw(GTK_CLIST(ctree));
2073
2074         folder_write_list();
2075 }
2076
2077 static void folderview_rm_imap_folder_cb(FolderView *folderview, guint action,
2078                                          GtkWidget *widget)
2079 {
2080         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2081         FolderItem *item;
2082         gchar *message;
2083         AlertValue avalue;
2084
2085         if (!folderview->selected) return;
2086
2087         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2088         g_return_if_fail(item != NULL);
2089         g_return_if_fail(item->folder != NULL);
2090         g_return_if_fail(item->folder->type == F_IMAP);
2091         g_return_if_fail(item->folder->account != NULL);
2092
2093         message = g_strdup_printf(_("Really delete folder `%s'?"),
2094                                   g_basename(item->path));
2095         avalue = alertpanel(_("Delete folder"), message,
2096                             _("Yes"), _("+No"), NULL);
2097         g_free(message);
2098         if (avalue != G_ALERTDEFAULT) return;
2099
2100         if (item->folder->remove_folder(item->folder, item) < 0) {
2101                 alertpanel_error(_("Can't remove the folder `%s'."),
2102                                  item->path);
2103                 if (folderview->opened == folderview->selected)
2104                         summary_show(folderview->summaryview,
2105                                      folderview->summaryview->folder_item,
2106                                      FALSE);
2107                 return;
2108         }
2109
2110         if (folderview->opened == folderview->selected ||
2111             gtk_ctree_is_ancestor(ctree,
2112                                   folderview->selected,
2113                                   folderview->opened)) {
2114                 summary_clear_all(folderview->summaryview);
2115                 folderview->opened = NULL;
2116         }
2117
2118         gtk_ctree_remove_node(ctree, folderview->selected);
2119         folder_write_list();
2120 }
2121
2122 static void folderview_rm_imap_server_cb(FolderView *folderview, guint action,
2123                                          GtkWidget *widget)
2124 {
2125         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2126         FolderItem *item;
2127         gchar *message;
2128         AlertValue avalue;
2129
2130         if (!folderview->selected) return;
2131
2132         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2133         g_return_if_fail(item != NULL);
2134         g_return_if_fail(item->folder != NULL);
2135         g_return_if_fail(item->folder->type == F_IMAP);
2136         g_return_if_fail(item->folder->account != NULL);
2137
2138         message = g_strdup_printf(_("Really delete IMAP4 account `%s'?"),
2139                                   item->folder->name);
2140         avalue = alertpanel(_("Delete IMAP4 account"), message,
2141                             _("Yes"), _("+No"), NULL);
2142         g_free(message);
2143
2144         if (avalue != G_ALERTDEFAULT) return;
2145
2146         if (folderview->opened == folderview->selected ||
2147             gtk_ctree_is_ancestor(ctree,
2148                                   folderview->selected,
2149                                   folderview->opened)) {
2150                 summary_clear_all(folderview->summaryview);
2151                 folderview->opened = NULL;
2152         }
2153
2154         account_destroy(item->folder->account);
2155         folder_destroy(item->folder);
2156         gtk_ctree_remove_node(ctree, folderview->selected);
2157         account_set_menu();
2158         main_window_reflect_prefs_all();
2159         folder_write_list();
2160 }
2161
2162 static void folderview_new_news_group_cb(FolderView *folderview, guint action,
2163                                          GtkWidget *widget)
2164 {
2165         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2166         gchar *text[N_FOLDER_COLS] = {NULL, "0", "0", "0"};
2167         GtkCTreeNode *servernode, *node;
2168         Folder *folder;
2169         FolderItem *item;
2170         FolderItem *rootitem;
2171         FolderItem *newitem;
2172         GSList *new_subscr;
2173         GSList *cur;
2174         GNode *gnode;
2175
2176         if (!folderview->selected) return;
2177
2178         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2179         g_return_if_fail(item != NULL);
2180         folder = item->folder;
2181         g_return_if_fail(folder != NULL);
2182         g_return_if_fail(folder->type == F_NEWS);
2183         g_return_if_fail(folder->account != NULL);
2184
2185         if (GTK_CTREE_ROW(folderview->selected)->parent != NULL)
2186                 servernode = GTK_CTREE_ROW(folderview->selected)->parent;
2187         else
2188                 servernode = folderview->selected;
2189
2190         rootitem = gtk_ctree_node_get_row_data(ctree, servernode);
2191
2192         new_subscr = grouplist_dialog(folder);
2193
2194         /* remove unsubscribed newsgroups */
2195         for (gnode = folder->node->children; gnode != NULL; ) {
2196                 GNode *next = gnode->next;
2197
2198                 item = FOLDER_ITEM(gnode->data);
2199                 if (g_slist_find_custom(new_subscr, item->path,
2200                                         (GCompareFunc)g_strcasecmp) != NULL) {
2201                         gnode = next;
2202                         continue;
2203                 }
2204
2205                 node = gtk_ctree_find_by_row_data(ctree, servernode, item);
2206                 if (!node) {
2207                         gnode = next;
2208                         continue;
2209                 }
2210
2211                 if (folderview->opened == node) {
2212                         summary_clear_all(folderview->summaryview);
2213                         folderview->opened = NULL;
2214                 }
2215
2216                 folder_item_remove(item);
2217                 gtk_ctree_remove_node(ctree, node);
2218
2219                 gnode = next;
2220         }
2221
2222         gtk_clist_freeze(GTK_CLIST(ctree));
2223
2224         /* add subscribed newsgroups */
2225         for (cur = new_subscr; cur != NULL; cur = cur->next) {
2226                 gchar *name = (gchar *)cur->data;
2227
2228                 if (folderview_find_by_name(ctree, servernode, name) != NULL)
2229                         continue;
2230
2231                 text[COL_FOLDER] = name;
2232                 node = gtk_ctree_insert_node(ctree, servernode, NULL, text,
2233                                              FOLDER_SPACING,
2234                                              folderxpm, folderxpmmask,
2235                                              folderopenxpm, folderopenxpmmask,
2236                                              FALSE, FALSE);
2237                 gtk_ctree_expand(ctree, servernode);
2238
2239                 newitem = folder_item_new(name, name);
2240                 folder_item_append(rootitem, newitem);
2241                 gtk_ctree_node_set_row_data(ctree, node, newitem);
2242         }
2243
2244         gtk_ctree_sort_node(ctree, servernode);
2245         gtk_clist_thaw(GTK_CLIST(ctree));
2246
2247         slist_free_strings(new_subscr);
2248         g_slist_free(new_subscr);
2249
2250         folder_write_list();
2251 }
2252
2253 static void folderview_rm_news_group_cb(FolderView *folderview, guint action,
2254                                         GtkWidget *widget)
2255 {
2256         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2257         FolderItem *item;
2258         gchar *message;
2259         AlertValue avalue;
2260
2261         if (!folderview->selected) return;
2262
2263         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2264         g_return_if_fail(item != NULL);
2265         g_return_if_fail(item->folder != NULL);
2266         g_return_if_fail(item->folder->type == F_NEWS);
2267         g_return_if_fail(item->folder->account != NULL);
2268
2269         message = g_strdup_printf(_("Really delete newsgroup `%s'?"),
2270                                   g_basename(item->path));
2271         avalue = alertpanel(_("Delete newsgroup"), message,
2272                             _("Yes"), _("+No"), NULL);
2273         g_free(message);
2274         if (avalue != G_ALERTDEFAULT) return;
2275
2276         if (folderview->opened == folderview->selected) {
2277                 summary_clear_all(folderview->summaryview);
2278                 folderview->opened = NULL;
2279         }
2280
2281         folder_item_remove(item);
2282         gtk_ctree_remove_node(ctree, folderview->selected);
2283         folder_write_list();
2284 }
2285
2286 static void folderview_rm_news_server_cb(FolderView *folderview, guint action,
2287                                          GtkWidget *widget)
2288 {
2289         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2290         FolderItem *item;
2291         gchar *message;
2292         AlertValue avalue;
2293
2294         if (!folderview->selected) return;
2295
2296         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2297         g_return_if_fail(item != NULL);
2298         g_return_if_fail(item->folder != NULL);
2299         g_return_if_fail(item->folder->type == F_NEWS);
2300         g_return_if_fail(item->folder->account != NULL);
2301
2302         message = g_strdup_printf(_("Really delete news account `%s'?"),
2303                                   item->folder->name);
2304         avalue = alertpanel(_("Delete news account"), message,
2305                             _("Yes"), _("+No"), NULL);
2306         g_free(message);
2307
2308         if (avalue != G_ALERTDEFAULT) return;
2309
2310         if (folderview->opened == folderview->selected ||
2311             gtk_ctree_is_ancestor(ctree,
2312                                   folderview->selected,
2313                                   folderview->opened)) {
2314                 summary_clear_all(folderview->summaryview);
2315                 folderview->opened = NULL;
2316         }
2317
2318         account_destroy(item->folder->account);
2319         folder_destroy(item->folder);
2320         gtk_ctree_remove_node(ctree, folderview->selected);
2321         account_set_menu();
2322         main_window_reflect_prefs_all();
2323         folder_write_list();
2324 }
2325
2326 static void folderview_search_cb(FolderView *folderview, guint action,
2327                                  GtkWidget *widget)
2328 {
2329         summary_search(folderview->summaryview);
2330 }
2331
2332 static gboolean folderview_drag_motion_cb(GtkWidget      *widget,
2333                                           GdkDragContext *context,
2334                                           gint            x,
2335                                           gint            y,
2336                                           guint           time,
2337                                           FolderView     *folderview)
2338 {
2339         gint row, column;
2340         FolderItem *item, *src_item;
2341         GtkCTreeNode *node = NULL;
2342         gboolean acceptable = FALSE;
2343
2344         if (gtk_clist_get_selection_info
2345                 (GTK_CLIST(widget), x - 24, y - 24, &row, &column)) {
2346                 node = gtk_ctree_node_nth(GTK_CTREE(widget), row);
2347                 item = gtk_ctree_node_get_row_data(GTK_CTREE(widget), node);
2348                 src_item = folderview->summaryview->folder_item;
2349                 if (item && item->folder && item->path &&
2350                     src_item && src_item != item) {
2351                         switch (item->folder->type) {
2352                         case F_MH:
2353                         case F_IMAP:
2354                                 acceptable = TRUE;
2355                                 break;
2356                         default:
2357                                 break;
2358                         }
2359                 }
2360         }
2361
2362         if (acceptable) {
2363                 gtk_signal_handler_block_by_func
2364                         (GTK_OBJECT(widget),
2365                          GTK_SIGNAL_FUNC(folderview_selected), folderview);
2366                 gtk_ctree_select(GTK_CTREE(widget), node);
2367                 gtk_signal_handler_unblock_by_func
2368                         (GTK_OBJECT(widget),
2369                          GTK_SIGNAL_FUNC(folderview_selected), folderview);
2370                 gdk_drag_status(context, 
2371                                         (context->actions == GDK_ACTION_COPY ?
2372                                         GDK_ACTION_COPY : GDK_ACTION_MOVE) , time);
2373         } else {
2374                 gtk_ctree_select(GTK_CTREE(widget), folderview->opened);
2375                 gdk_drag_status(context, 0, time);
2376         }
2377
2378         return acceptable;
2379 }
2380
2381 static void folderview_drag_leave_cb(GtkWidget      *widget,
2382                                      GdkDragContext *context,
2383                                      guint           time,
2384                                      FolderView     *folderview)
2385 {
2386         gtk_ctree_select(GTK_CTREE(widget), folderview->opened);
2387 }
2388
2389 static void folderview_drag_received_cb(GtkWidget        *widget,
2390                                         GdkDragContext   *drag_context,
2391                                         gint              x,
2392                                         gint              y,
2393                                         GtkSelectionData *data,
2394                                         guint             info,
2395                                         guint             time,
2396                                         FolderView       *folderview)
2397 {
2398         gint row, column;
2399         FolderItem *item, *src_item;
2400         GtkCTreeNode *node;
2401
2402         if (gtk_clist_get_selection_info
2403                 (GTK_CLIST(widget), x - 24, y - 24, &row, &column) == 0)
2404                 return;
2405
2406         node = gtk_ctree_node_nth(GTK_CTREE(widget), row);
2407         item = gtk_ctree_node_get_row_data(GTK_CTREE(widget), node);
2408         src_item = folderview->summaryview->folder_item;
2409         if (item && src_item) {
2410                 switch (drag_context->action) {
2411                         case GDK_ACTION_COPY:
2412                                 summary_copy_selected_to(folderview->summaryview, item);
2413                                 gtk_drag_finish(drag_context, TRUE, FALSE, time);
2414                                 break;
2415                         case GDK_ACTION_MOVE:
2416                         case GDK_ACTION_DEFAULT:
2417                         default:
2418                 if (src_item->folder->type != item->folder->type ||
2419                     (item->folder->type == F_IMAP &&
2420                      src_item->folder != item->folder))
2421                         summary_copy_selected_to(folderview->summaryview, item);
2422                 else
2423                         summary_move_selected_to(folderview->summaryview, item);
2424                 gtk_drag_finish(drag_context, TRUE, TRUE, time);
2425                 }
2426         } else
2427                 gtk_drag_finish(drag_context, FALSE, FALSE, time);
2428 }
2429
2430 static gint folderview_compare_name(gconstpointer a, gconstpointer b)
2431 {
2432         const FolderItem *item = a;
2433         const gchar *name = b;
2434
2435         if (!item->path) return -1;
2436         return strcmp2(g_basename(item->path), name);
2437 }
2438
2439 static void folderview_scoring_cb(FolderView *folderview, guint action,
2440                                    GtkWidget *widget)
2441 {
2442         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2443         FolderItem *item;
2444
2445         if (!folderview->selected) return;
2446
2447         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2448         g_return_if_fail(item != NULL);
2449         g_return_if_fail(item->folder != NULL);
2450
2451         prefs_scoring_open(item);
2452 }
2453
2454 static void folderview_processing_cb(FolderView *folderview, guint action,
2455                                      GtkWidget *widget)
2456 {
2457         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2458         FolderItem *item;
2459
2460         if (!folderview->selected) return;
2461
2462         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2463         g_return_if_fail(item != NULL);
2464         g_return_if_fail(item->folder != NULL);
2465
2466         prefs_filtering_open(item);
2467 }
2468
2469 static void folderview_property_cb(FolderView *folderview, guint action, 
2470                                    GtkWidget *widget) 
2471 {
2472         GtkCTree *ctree = GTK_CTREE(folderview->ctree);
2473         FolderItem *item;
2474
2475         if (!folderview->selected) return;
2476
2477         item = gtk_ctree_node_get_row_data(ctree, folderview->selected);
2478         g_return_if_fail(item != NULL);
2479         g_return_if_fail(item->folder != NULL);
2480
2481         prefs_folder_item_create(folderview, item);
2482 }
2483
2484 void folderview_set_target_folder_color(gint color_op) 
2485 {
2486         gint firstone = 1;
2487         GList *list;
2488         FolderView *folderview;
2489
2490         for (list = folderview_list; list != NULL; list = list->next) {
2491                 folderview = (FolderView *)list->data;
2492                 gtkut_convert_int_to_gdk_color(color_op, &folderview->color_op);
2493                 if (firstone) {
2494                         bold_tgtfold_style->fg[GTK_STATE_NORMAL] =
2495                                 folderview->color_op;
2496                         firstone = 0;
2497                 }
2498         }
2499 }
2500
2501 void folderview_reflect_prefs_pixmap_theme(FolderView *folderview)
2502 {
2503         folderview_init(folderview);
2504         folderview_set_all();
2505         folderview_select(folderview, folderview->summaryview->folder_item);
2506 }