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