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