Fix access beyond array bounds
[claws.git] / src / toolbar.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2001-2013 Hiroyuki Yamamoto and the Claws Mail team
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 3 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, see <http://www.gnu.org/licenses/>.
17  * 
18  */
19
20 /*
21  * General functions for accessing address book files.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #include "claws-features.h"
27 #endif
28
29 #include "defs.h"
30
31 #include <glib.h>
32 #include <glib/gi18n.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <dirent.h>
36 #include <sys/stat.h>
37 #include <math.h>
38 #include <setjmp.h>
39
40 #include "main.h"
41 #include "mainwindow.h"
42 #include "summaryview.h"
43 #include "compose.h"
44 #include "utils.h"
45 #include "xml.h"
46 #include "mgutils.h"
47 #include "prefs_gtk.h"
48 #include "codeconv.h"
49 #include "stock_pixmap.h"
50 #include "manage_window.h"
51 #include "gtkutils.h"
52 #include "toolbar.h"
53 #include "menu.h"
54 #include "inc.h"
55 #include "action.h"
56 #include "prefs_actions.h"
57 #include "prefs_common.h"
58 #include "prefs_toolbar.h"
59 #include "alertpanel.h"
60 #include "imap.h"
61 #include "account.h"
62 #include "send_message.h"
63 #ifndef USE_NEW_ADDRBOOK
64         #include "addressbook.h"
65 #else
66         #include "addressbook-dbus.h"
67 #endif
68
69 /* elements */
70 #define TOOLBAR_TAG_INDEX        "toolbar"
71 #define TOOLBAR_TAG_ITEM         "item"
72 #define TOOLBAR_TAG_SEPARATOR    "separator"
73
74 #define TOOLBAR_ICON_FILE   "file"    
75 #define TOOLBAR_ICON_TEXT   "text"     
76 #define TOOLBAR_ICON_ACTION "action"    
77
78 static void toolbar_init(Toolbar * toolbar);
79 static gboolean      toolbar_is_duplicate               (gint           action,
80                                                  ToolbarType    source);
81 static void   toolbar_parse_item                (XMLFile        *file,
82                                                  ToolbarType    source);
83
84 static gint   toolbar_ret_val_from_text         (const gchar    *text);
85 static gchar *toolbar_ret_text_from_val         (gint           val);
86
87 static void   toolbar_set_default_main          (void);
88 static void   toolbar_set_default_compose       (void);
89 static void   toolbar_set_default_msgview       (void);
90
91 static void     toolbar_style                   (ToolbarType     type, 
92                                                  guint           action, 
93                                                  gpointer        data);
94
95 static MainWindow *get_mainwin                  (gpointer data);
96 static void activate_compose_button             (Toolbar        *toolbar,
97                                                  ToolbarStyle    style,
98                                                  ComposeButtonType type);
99
100 /* toolbar callbacks */
101 static void toolbar_reply                       (gpointer        data, 
102                                                  guint           action);
103 static void toolbar_learn                       (gpointer        data, 
104                                                  guint           action);
105 static void toolbar_delete_cb                   (GtkWidget      *widget,
106                                                  gpointer        data);
107 static void toolbar_trash_cb                    (GtkWidget      *widget,
108                                                  gpointer        data);
109
110 static void toolbar_compose_cb                  (GtkWidget      *widget,
111                                                  gpointer        data);
112
113 static void toolbar_learn_cb                    (GtkWidget      *widget,
114                                                  gpointer        data);
115
116 static void toolbar_reply_cb                    (GtkWidget      *widget,
117                                                  gpointer        data);
118
119 static void toolbar_reply_to_all_cb             (GtkWidget      *widget,
120                                                  gpointer        data);
121
122 static void toolbar_reply_to_list_cb            (GtkWidget      *widget,
123                                                  gpointer        data);
124
125 static void toolbar_reply_to_sender_cb          (GtkWidget      *widget,
126                                                  gpointer        data);
127
128 static void toolbar_forward_cb                  (GtkWidget      *widget,
129                                                  gpointer        data);
130
131 static void toolbar_prev_unread_cb              (GtkWidget      *widget,
132                                                  gpointer        data);
133 static void toolbar_next_unread_cb              (GtkWidget      *widget,
134                                                  gpointer        data);
135
136 static void toolbar_ignore_thread_cb            (GtkWidget      *widget,
137                                                  gpointer        data);
138
139 static void toolbar_watch_thread_cb             (GtkWidget      *widget,
140                                                  gpointer        data);
141
142 static void toolbar_print_cb                    (GtkWidget      *widget,
143                                                  gpointer        data);
144
145 static void toolbar_actions_execute_cb          (GtkWidget      *widget,
146                                                  gpointer        data);
147 static void toolbar_plugins_execute_cb      (GtkWidget      *widget,
148                              gpointer        data);
149
150
151 static void toolbar_send_cb                     (GtkWidget      *widget,
152                                                  gpointer        data);
153 static void toolbar_send_later_cb               (GtkWidget      *widget,
154                                                  gpointer        data);
155 static void toolbar_draft_cb                    (GtkWidget      *widget,
156                                                  gpointer        data);
157 static void toolbar_close_cb                    (GtkWidget      *widget,
158                                                  gpointer        data);
159 static void toolbar_preferences_cb              (GtkWidget      *widget,
160                                                  gpointer        data);
161 static void toolbar_open_mail_cb                (GtkWidget      *widget,
162                                                  gpointer        data);
163 static void toolbar_insert_cb                   (GtkWidget      *widget,
164                                                  gpointer        data);
165 static void toolbar_attach_cb                   (GtkWidget      *widget,
166                                                  gpointer        data);
167 static void toolbar_sig_cb                      (GtkWidget      *widget,
168                                                  gpointer        data);
169 static void toolbar_ext_editor_cb               (GtkWidget      *widget,
170                                                  gpointer        data);
171 static void toolbar_linewrap_current_cb         (GtkWidget      *widget,
172                                                  gpointer        data);
173 static void toolbar_linewrap_all_cb             (GtkWidget      *widget,
174                                                  gpointer        data);
175 static void toolbar_addrbook_cb                 (GtkWidget      *widget, 
176                                                  gpointer        data);
177 #ifdef USE_ENCHANT
178 static void toolbar_check_spelling_cb           (GtkWidget      *widget, 
179                                                  gpointer        data);
180 #endif
181 static void toolbar_cancel_inc_cb               (GtkWidget      *widget,
182                                                  gpointer        data);
183 static void toolbar_cancel_send_cb              (GtkWidget      *widget,
184                                                  gpointer        data);
185 static void toolbar_cancel_all_cb               (GtkWidget      *widget,
186                                                  gpointer        data);
187
188 struct {
189         gchar *index_str;
190         const gchar *descr;
191 } toolbar_text [] = {
192         { "A_RECEIVE_ALL",      N_("Receive Mail from all Accounts")       },
193         { "A_RECEIVE_CUR",      N_("Receive Mail from current Account")    },
194         { "A_SEND_QUEUED",      N_("Send Queued Messages")                 },
195         { "A_COMPOSE_EMAIL",    N_("Compose Email")                        },
196         { "A_COMPOSE_NEWS",     N_("Compose News")                         },
197         { "A_REPLY_MESSAGE",    N_("Reply to Message")                     },
198         { "A_REPLY_SENDER",     N_("Reply to Sender")                      },
199         { "A_REPLY_ALL",        N_("Reply to All")                         },
200         { "A_REPLY_ML",         N_("Reply to Mailing-list")                },
201         { "A_OPEN_MAIL",        N_("Open email")                           },
202         { "A_FORWARD",          N_("Forward Message")                      }, 
203         { "A_TRASH",            N_("Trash Message")                        },
204         { "A_DELETE_REAL",      N_("Delete Message")                       },
205         { "A_EXECUTE",          N_("Execute")                              },
206         { "A_GOTO_PREV",        N_("Go to Previous Unread Message")        },
207         { "A_GOTO_NEXT",        N_("Go to Next Unread Message")            },
208         { "A_IGNORE_THREAD",    N_("Ignore thread")                        },
209         { "A_WATCH_THREAD",     N_("Watch thread")                         },
210         { "A_PRINT",            N_("Print")                                },
211         { "A_LEARN_SPAM",       N_("Learn Spam or Ham")                    },
212         { "A_GO_FOLDERS",       N_("Open folder/Go to folder list")        },
213         { "A_PREFERENCES",      N_("Preferences")                          },
214
215         { "A_SEND",             N_("Send Message")                         },
216         { "A_SENDL",            N_("Put into queue folder and send later") },
217         { "A_DRAFT",            N_("Save to draft folder")                 },
218         { "A_INSERT",           N_("Insert file")                          },   
219         { "A_ATTACH",           N_("Attach file")                          },
220         { "A_SIG",              N_("Insert signature")                     },
221         { "A_EXTEDITOR",        N_("Edit with external editor")            },
222         { "A_LINEWRAP_CURRENT", N_("Wrap long lines of current paragraph") }, 
223         { "A_LINEWRAP_ALL",     N_("Wrap all long lines")                  }, 
224         { "A_ADDRBOOK",         N_("Address book")                         },
225 #ifdef USE_ENCHANT
226         { "A_CHECK_SPELLING",   N_("Check spelling")                       },
227 #endif
228         { "A_CLAWS_ACTIONS",    N_("Claws Mail Actions Feature")           }, 
229         { "A_CANCEL_INC",       N_("Cancel receiving")                     },
230         { "A_CANCEL_SEND",      N_("Cancel sending")                       },
231         { "A_CANCEL_ALL",       N_("Cancel receiving/sending")             },
232         { "A_CLOSE",            N_("Close window")                         },
233         { "A_SEPARATOR",        N_("Separator")                            },
234         { "A_CLAWS_PLUGINS",    N_("Claws Mail Plugins")                   },
235 };
236
237 /* struct holds configuration files and a list of
238  * currently active toolbar items 
239  * TOOLBAR_MAIN, TOOLBAR_COMPOSE and TOOLBAR_MSGVIEW
240  * give us an index
241  */
242 struct {
243         const gchar  *conf_file;
244         GSList       *item_list;
245 } toolbar_config[NUM_TOOLBARS] = {
246         { "toolbar_main.xml",    NULL},
247         { "toolbar_compose.xml", NULL}, 
248         { "toolbar_msgview.xml", NULL}
249 };
250
251 gint toolbar_ret_val_from_descr(const gchar *descr)
252 {
253         gint i;
254
255         for (i = 0; i < N_ACTION_VAL; i++) {
256                 if (g_utf8_collate(gettext(toolbar_text[i].descr), descr) == 0)
257                                 return i;
258         }
259         
260         return -1;
261 }
262
263 gchar *toolbar_ret_descr_from_val(gint val)
264 {
265         cm_return_val_if_fail(val >=0 && val < N_ACTION_VAL, NULL);
266
267         return gettext(toolbar_text[val].descr);
268 }
269
270 static gint toolbar_ret_val_from_text(const gchar *text)
271 {
272         gint i;
273         
274         for (i = 0; i < N_ACTION_VAL; i++) {
275                 if (g_utf8_collate(toolbar_text[i].index_str, text) == 0)
276                                 return i;
277         }
278
279         return -1;
280 }
281
282 static gchar *toolbar_ret_text_from_val(gint val)
283 {
284         cm_return_val_if_fail(val >=0 && val < N_ACTION_VAL, NULL);
285
286         return toolbar_text[val].index_str;
287 }
288
289 static gboolean toolbar_is_duplicate(gint action, ToolbarType source)
290 {
291         GSList *cur;
292
293         if ((action == A_SEPARATOR) || (action == A_CLAWS_ACTIONS) || (action == A_CLAWS_PLUGINS))
294                 return FALSE;
295
296         for (cur = toolbar_config[source].item_list; cur != NULL; cur = cur->next) {
297                 ToolbarItem *item = (ToolbarItem*) cur->data;
298                 
299                 if (item->index == action)
300                         return TRUE;
301         }
302         return FALSE;
303 }
304
305 /* depending on toolbar type this function 
306    returns a list of available toolbar events being 
307    displayed by prefs_toolbar
308 */
309 GList *toolbar_get_action_items(ToolbarType source)
310 {
311         GList *items = NULL;
312         gint i = 0;
313         
314         if (source == TOOLBAR_MAIN) {
315                 gint main_items[] = { A_RECEIVE_ALL,   A_RECEIVE_CUR,   A_SEND_QUEUED,
316                                         A_COMPOSE_EMAIL, A_REPLY_MESSAGE, A_REPLY_SENDER, 
317                                         A_REPLY_ALL,     A_REPLY_ML,      A_OPEN_MAIL,     A_FORWARD, 
318                                         A_TRASH,         A_DELETE_REAL,   A_EXECUTE,       A_GOTO_PREV, 
319                                         A_GOTO_NEXT,     A_IGNORE_THREAD, A_WATCH_THREAD,  A_PRINT,
320                                         A_ADDRBOOK,      A_LEARN_SPAM,    A_GO_FOLDERS, 
321                                         A_CANCEL_INC,    A_CANCEL_SEND,   A_CANCEL_ALL,    A_PREFERENCES };
322
323                 for (i = 0; i < sizeof main_items / sizeof main_items[0]; i++)  {
324                         items = g_list_append(items, gettext(toolbar_text[main_items[i]].descr));
325                 }       
326         }
327         else if (source == TOOLBAR_COMPOSE) {
328                 gint comp_items[] =   { A_SEND,          A_SENDL,        A_DRAFT,
329                                         A_INSERT,        A_ATTACH,       A_SIG,
330                                         A_EXTEDITOR,     A_LINEWRAP_CURRENT,     
331                                         A_LINEWRAP_ALL,  A_ADDRBOOK,
332 #ifdef USE_ENCHANT
333                                         A_CHECK_SPELLING, 
334 #endif
335                                         A_CLOSE };      
336
337                 for (i = 0; i < sizeof comp_items / sizeof comp_items[0]; i++) 
338                         items = g_list_append(items, gettext(toolbar_text[comp_items[i]].descr));
339         }
340         else if (source == TOOLBAR_MSGVIEW) {
341                 gint msgv_items[] =   { A_COMPOSE_EMAIL, A_REPLY_MESSAGE, A_REPLY_SENDER,
342                                         A_REPLY_ALL,     A_REPLY_ML,      A_FORWARD,
343                                         A_TRASH, A_DELETE_REAL,       A_GOTO_PREV,        A_GOTO_NEXT,
344                                         A_ADDRBOOK,      A_LEARN_SPAM, A_CLOSE };       
345
346                 for (i = 0; i < sizeof msgv_items / sizeof msgv_items[0]; i++) 
347                         items = g_list_append(items, gettext(toolbar_text[msgv_items[i]].descr));
348         }
349
350         return items;
351 }
352
353 static void toolbar_parse_item(XMLFile *file, ToolbarType source)
354 {
355         GList *attr;
356         gchar *name, *value;
357         ToolbarItem *item = NULL;
358         gboolean rewrite = FALSE;
359
360         attr = xml_get_current_tag_attr(file);
361         item = g_new0(ToolbarItem, 1);
362         while( attr ) {
363                 name = ((XMLAttr *)attr->data)->name;
364                 value = ((XMLAttr *)attr->data)->value;
365                 
366                 if (g_utf8_collate(name, TOOLBAR_ICON_FILE) == 0) 
367                         item->file = g_strdup (value);
368                 else if (g_utf8_collate(name, TOOLBAR_ICON_TEXT) == 0)
369                         item->text = g_strdup (*value ? gettext(value):"");
370                 else if (g_utf8_collate(name, TOOLBAR_ICON_ACTION) == 0)
371                         item->index = toolbar_ret_val_from_text(value);
372                 if (item->index == -1 && !strcmp(value, "A_DELETE")) {
373                         /* switch button */
374                         item->index = A_TRASH;
375                         g_free(item->file);
376                         item->file = g_strdup("trash_btn");
377                         g_free(item->text);
378                         item->text = g_strdup(C_("Toolbar", "Trash"));
379                         rewrite = TRUE;
380                 }
381                 if (item->index == -1 && !strcmp(value, "A_SYL_ACTIONS")) {
382                         /* switch button */
383                         item->index = A_CLAWS_ACTIONS;
384                         rewrite = TRUE;
385                 }
386                 attr = g_list_next(attr);
387         }
388         if (item->index != -1) {
389                 
390                 if (!toolbar_is_duplicate(item->index, source)) 
391                         toolbar_config[source].item_list = g_slist_append(toolbar_config[source].item_list,
392                                                                          item);
393         }
394         if (rewrite) {
395                 toolbar_save_config_file(source);
396         }
397 }
398
399 const gchar *toolbar_get_short_text(int action) {
400         switch(action) {
401         case A_GO_FOLDERS:      return _("Folders");
402         case A_OPEN_MAIL:       return _("Open");
403         case A_RECEIVE_ALL:     return _("Get Mail");
404         case A_RECEIVE_CUR:     return _("Get");
405         case A_SEND_QUEUED:     return _("Send");
406         case A_COMPOSE_EMAIL:   return C_("Toolbar", "Compose");
407         case A_COMPOSE_NEWS:    return C_("Toolbar", "Compose");
408         case A_REPLY_MESSAGE:   return _("Reply");
409         case A_REPLY_ALL:       return _("All");
410         case A_REPLY_SENDER:    return C_("Toolbar", "Sender");
411         case A_REPLY_ML:        return _("List");
412         case A_FORWARD:         return _("Forward");
413         case A_TRASH:           return C_("Toolbar", "Trash");
414         case A_DELETE_REAL:     return _("Delete");
415         case A_LEARN_SPAM:      return _("Spam");
416         case A_GOTO_PREV:       return _("Prev");
417         case A_GOTO_NEXT:       return _("Next");
418         case A_IGNORE_THREAD:   return _("Ignore thread");
419         case A_WATCH_THREAD:    return _("Watch thread");
420         case A_PRINT:           return _("Print");
421         case A_CLOSE:           return _("Close");
422         case A_PREFERENCES:     return _("Preferences");
423         case A_SEND:            return _("Send");
424         case A_SENDL:           return _("Send later");
425         case A_DRAFT:           return _("Draft");
426         case A_INSERT:          return _("Insert");
427         case A_ATTACH:          return _("Attach");
428         case A_SIG:             return _("Insert sig.");
429         case A_EXTEDITOR:       return _("Edit");
430         case A_LINEWRAP_CURRENT:return _("Wrap para.");
431         case A_LINEWRAP_ALL:    return _("Wrap all");
432         case A_ADDRBOOK:        return _("Address");
433         case A_CANCEL_INC:      return _("Stop");
434         case A_CANCEL_SEND:     return _("Stop");
435         case A_CANCEL_ALL:      return _("Stop all");
436         case A_EXECUTE:         return _("Execute");
437         #ifdef USE_ENCHANT
438         case A_CHECK_SPELLING:  return _("Check spelling");
439         #endif
440         default:                return "";
441         }
442 }
443
444 gint toolbar_get_icon(int action) {
445         switch(action) {
446         case A_GO_FOLDERS:      return STOCK_PIXMAP_GO_FOLDERS;
447         case A_OPEN_MAIL:       return STOCK_PIXMAP_OPEN_MAIL;
448         case A_RECEIVE_ALL:     return STOCK_PIXMAP_MAIL_RECEIVE_ALL;
449         case A_RECEIVE_CUR:     return STOCK_PIXMAP_MAIL_RECEIVE;
450         case A_SEND_QUEUED:     return STOCK_PIXMAP_MAIL_SEND_QUEUE;
451         case A_COMPOSE_EMAIL:   return STOCK_PIXMAP_MAIL_COMPOSE;
452         case A_COMPOSE_NEWS:    return STOCK_PIXMAP_NEWS_COMPOSE;
453         case A_REPLY_MESSAGE:   return STOCK_PIXMAP_MAIL_REPLY;
454         case A_REPLY_ALL:       return STOCK_PIXMAP_MAIL_REPLY_TO_ALL;
455         case A_REPLY_SENDER:    return STOCK_PIXMAP_MAIL_REPLY_TO_AUTHOR;
456         case A_REPLY_ML:        return STOCK_PIXMAP_MAIL_REPLY_TO_LIST;
457         case A_FORWARD:         return STOCK_PIXMAP_MAIL_FORWARD;
458         case A_TRASH:           return STOCK_PIXMAP_TRASH;
459         case A_DELETE_REAL:     return STOCK_PIXMAP_DELETE;
460         case A_LEARN_SPAM:      return STOCK_PIXMAP_SPAM_BTN;
461         case A_GOTO_PREV:       return STOCK_PIXMAP_UP_ARROW;
462         case A_GOTO_NEXT:       return STOCK_PIXMAP_DOWN_ARROW;
463         case A_IGNORE_THREAD:   return STOCK_PIXMAP_IGNORETHREAD;
464         case A_WATCH_THREAD:    return STOCK_PIXMAP_WATCHTHREAD;
465         case A_PRINT:           return STOCK_PIXMAP_PRINTER;
466         case A_CLOSE:           return STOCK_PIXMAP_CLOSE;
467         case A_PREFERENCES:     return STOCK_PIXMAP_PREFERENCES;
468         case A_SEND:            return STOCK_PIXMAP_MAIL_SEND;
469         case A_SENDL:           return STOCK_PIXMAP_MAIL_SEND_QUEUE;
470         case A_DRAFT:           return STOCK_PIXMAP_MAIL;
471         case A_INSERT:          return STOCK_PIXMAP_INSERT_FILE;
472         case A_ATTACH:          return STOCK_PIXMAP_MAIL_ATTACH;
473         case A_SIG:             return STOCK_PIXMAP_MAIL_SIGN;
474         case A_EXTEDITOR:       return STOCK_PIXMAP_EDIT_EXTERN;
475         case A_LINEWRAP_CURRENT:return STOCK_PIXMAP_LINEWRAP_CURRENT;
476         case A_LINEWRAP_ALL:    return STOCK_PIXMAP_LINEWRAP_ALL;
477         case A_ADDRBOOK:        return STOCK_PIXMAP_ADDRESS_BOOK;
478         case A_CANCEL_INC:      return STOCK_PIXMAP_CANCEL;
479         case A_CANCEL_SEND:     return STOCK_PIXMAP_CANCEL;
480         case A_CANCEL_ALL:      return STOCK_PIXMAP_CANCEL;
481         case A_EXECUTE:         return STOCK_PIXMAP_EXEC;
482         #ifdef USE_ENCHANT
483         case A_CHECK_SPELLING:  return STOCK_PIXMAP_CHECK_SPELLING;
484         #endif
485         default:                return -1;
486         }
487 }
488
489 static void toolbar_set_default_main(void) 
490 {
491         struct {
492                 gint action;
493         } default_toolbar[] = {
494 #ifdef GENERIC_UMPC
495                 { A_GO_FOLDERS},
496                 { A_OPEN_MAIL},         
497                 { A_SEPARATOR}, 
498 #endif
499                 { A_RECEIVE_ALL},
500                 { A_SEPARATOR}, 
501                 { A_SEND_QUEUED},
502                 { A_COMPOSE_EMAIL},
503                 { A_SEPARATOR},
504                 { A_REPLY_MESSAGE}, 
505 #ifndef GENERIC_UMPC
506                 { A_REPLY_ALL},
507                 { A_REPLY_SENDER},
508 #endif
509                 { A_FORWARD},
510                 { A_SEPARATOR},
511                 { A_TRASH},
512 #ifndef GENERIC_UMPC
513                 { A_LEARN_SPAM},
514 #endif
515                 { A_SEPARATOR},
516                 { A_GOTO_NEXT}
517         };
518         
519         gint i;
520         
521         for (i = 0; i < sizeof(default_toolbar) / sizeof(default_toolbar[0]); i++) {
522                 
523                 ToolbarItem *toolbar_item = g_new0(ToolbarItem, 1);
524                 
525                 if (default_toolbar[i].action != A_SEPARATOR) {
526                         
527                         gchar *file = NULL;
528                         if (toolbar_get_icon(default_toolbar[i].action) > -1) {
529                                 file = stock_pixmap_get_name((StockPixmap)toolbar_get_icon(default_toolbar[i].action));
530                         }
531                         
532                         toolbar_item->file  = g_strdup(file);
533                         toolbar_item->index = default_toolbar[i].action;
534                         toolbar_item->text  = g_strdup(toolbar_get_short_text(default_toolbar[i].action));
535                 } else {
536
537                         toolbar_item->file  = g_strdup(TOOLBAR_TAG_SEPARATOR);
538                         toolbar_item->index = A_SEPARATOR;
539                 }
540                 
541                 if (toolbar_item->index != -1) {
542                         if ( !toolbar_is_duplicate(toolbar_item->index, TOOLBAR_MAIN)) 
543                                 toolbar_config[TOOLBAR_MAIN].item_list = 
544                                         g_slist_append(toolbar_config[TOOLBAR_MAIN].item_list, toolbar_item);
545                 }       
546         }
547 }
548
549 static void toolbar_set_default_compose(void)
550 {
551         struct {
552                 gint action;
553         } default_toolbar[] = {
554 #ifdef GENERIC_UMPC
555                 { A_CLOSE},
556                 { A_SEPARATOR}, 
557 #endif
558                 { A_SEND},
559                 { A_SENDL},
560                 { A_DRAFT},
561                 { A_SEPARATOR}, 
562 #ifndef GENERIC_UMPC
563                 { A_INSERT},
564 #endif
565                 { A_ATTACH},
566                 { A_SEPARATOR},
567                 { A_ADDRBOOK}
568         };
569         
570         gint i;
571
572         for (i = 0; i < sizeof(default_toolbar) / sizeof(default_toolbar[0]); i++) {
573                 
574                 ToolbarItem *toolbar_item = g_new0(ToolbarItem, 1);
575                 
576                 if (default_toolbar[i].action != A_SEPARATOR) {
577                         
578                         gchar *file = NULL;
579                         if (toolbar_get_icon(default_toolbar[i].action) > -1) {
580                                 file = stock_pixmap_get_name((StockPixmap)toolbar_get_icon(default_toolbar[i].action));
581                         }
582                         toolbar_item->file  = g_strdup(file);
583                         toolbar_item->index = default_toolbar[i].action;
584                         toolbar_item->text  = g_strdup(toolbar_get_short_text(default_toolbar[i].action));
585                 } else {
586
587                         toolbar_item->file  = g_strdup(TOOLBAR_TAG_SEPARATOR);
588                         toolbar_item->index = A_SEPARATOR;
589                 }
590                 
591                 if (toolbar_item->index != -1) {
592                         if ( !toolbar_is_duplicate(toolbar_item->index, TOOLBAR_COMPOSE)) 
593                                 toolbar_config[TOOLBAR_COMPOSE].item_list = 
594                                         g_slist_append(toolbar_config[TOOLBAR_COMPOSE].item_list, toolbar_item);
595                 }       
596         }
597 }
598
599 static void toolbar_set_default_msgview(void)
600 {
601         struct {
602                 gint action;
603         } default_toolbar[] = {
604 #ifdef GENERIC_UMPC
605                 { A_CLOSE},
606                 { A_SEPARATOR}, 
607 #endif
608                 { A_REPLY_MESSAGE}, 
609                 { A_REPLY_ALL},
610                 { A_REPLY_SENDER},
611                 { A_FORWARD},
612                 { A_SEPARATOR},
613                 { A_TRASH},
614 #ifndef GENERIC_UMPC
615                 { A_LEARN_SPAM},
616 #endif
617                 { A_GOTO_NEXT}
618         };
619         
620         gint i;
621
622         for (i = 0; i < sizeof(default_toolbar) / sizeof(default_toolbar[0]); i++) {
623                 
624                 ToolbarItem *toolbar_item = g_new0(ToolbarItem, 1);
625                 
626                 if (default_toolbar[i].action != A_SEPARATOR) {
627                         gchar *file = NULL;
628                         if (toolbar_get_icon(default_toolbar[i].action) > -1) {
629                                 file = stock_pixmap_get_name((StockPixmap)toolbar_get_icon(default_toolbar[i].action));
630                         }
631                         
632                         toolbar_item->file  = g_strdup(file);
633                         toolbar_item->index = default_toolbar[i].action;
634                         toolbar_item->text  = g_strdup(toolbar_get_short_text(default_toolbar[i].action));
635                 } else {
636
637                         toolbar_item->file  = g_strdup(TOOLBAR_TAG_SEPARATOR);
638                         toolbar_item->index = A_SEPARATOR;
639                 }
640                 
641                 if (toolbar_item->index != -1) {
642                         if ( !toolbar_is_duplicate(toolbar_item->index, TOOLBAR_MSGVIEW)) 
643                                 toolbar_config[TOOLBAR_MSGVIEW].item_list = 
644                                         g_slist_append(toolbar_config[TOOLBAR_MSGVIEW].item_list, toolbar_item);
645                 }       
646         }
647 }
648
649 void toolbar_set_default(ToolbarType source)
650 {
651         if (source == TOOLBAR_MAIN)
652                 toolbar_set_default_main();
653         else if  (source == TOOLBAR_COMPOSE)
654                 toolbar_set_default_compose();
655         else if  (source == TOOLBAR_MSGVIEW)
656                 toolbar_set_default_msgview();
657 }
658
659 void toolbar_save_config_file(ToolbarType source)
660 {
661         GSList *cur;
662         FILE *fp;
663         PrefFile *pfile;
664         gchar *fileSpec = NULL;
665
666         debug_print("save Toolbar Configuration to %s\n", toolbar_config[source].conf_file);
667
668         fileSpec = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, toolbar_config[source].conf_file, NULL );
669         pfile = prefs_write_open(fileSpec);
670         if( pfile ) {
671                 fp = pfile->fp;
672                 if (fprintf(fp, "<?xml version=\"1.0\" encoding=\"%s\" ?>\n", CS_INTERNAL) < 0)
673                         goto fail;
674
675                 if (fprintf(fp, "<%s>\n", TOOLBAR_TAG_INDEX) < 0)
676                         goto fail;
677
678                 for (cur = toolbar_config[source].item_list; cur != NULL; cur = cur->next) {
679                         ToolbarItem *toolbar_item = (ToolbarItem*) cur->data;
680                         
681                         if (toolbar_item->index != A_SEPARATOR) {
682                                 if (fprintf(fp, "\t<%s %s=\"%s\" %s=\"",
683                                         TOOLBAR_TAG_ITEM, 
684                                         TOOLBAR_ICON_FILE, toolbar_item->file,
685                                         TOOLBAR_ICON_TEXT) < 0)
686                                         goto fail;
687                                 if (xml_file_put_escape_str(fp, toolbar_item->text) < 0)
688                                         goto fail;
689                                 if (fprintf(fp, "\" %s=\"%s\"/>\n",
690                                         TOOLBAR_ICON_ACTION, 
691                                         toolbar_ret_text_from_val(toolbar_item->index)) < 0)
692                                         goto fail;
693                         } else {
694                                 if (fprintf(fp, "\t<%s/>\n", TOOLBAR_TAG_SEPARATOR) < 0)
695                                         goto fail;
696                         }
697                 }
698
699                 if (fprintf(fp, "</%s>\n", TOOLBAR_TAG_INDEX) < 0)
700                         goto fail;
701         
702                 g_free( fileSpec );
703                 if (prefs_file_close (pfile) < 0 ) 
704                         g_warning("failed to write toolbar configuration to file\n");
705                 return;
706                 
707 fail:
708                 FILE_OP_ERROR(fileSpec, "fprintf");
709                 g_free( fileSpec );
710                 prefs_file_close_revert (pfile);
711         } else
712                 g_warning("failed to open toolbar configuration file for writing\n");
713 }
714
715 void toolbar_read_config_file(ToolbarType source)
716 {
717         XMLFile *file   = NULL;
718         gchar *fileSpec = NULL;
719         jmp_buf    jumper;
720
721         debug_print("read Toolbar Configuration from %s\n", toolbar_config[source].conf_file);
722
723         fileSpec = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, toolbar_config[source].conf_file, NULL );
724         file = xml_open_file(fileSpec);
725         g_free(fileSpec);
726
727         toolbar_clear_list(source);
728
729         if (file) {
730                 if ((setjmp(jumper))
731                 || (xml_get_dtd(file))
732                 || (xml_parse_next_tag(file))
733                 || (!xml_compare_tag(file, TOOLBAR_TAG_INDEX))) {
734                         xml_close_file(file);
735                         return;
736                 }
737
738                 for (;;) {
739                         if (!file->level) 
740                                 break;
741                         /* Get item tag */
742                         if (xml_parse_next_tag(file)) 
743                                 longjmp(jumper, 1);
744
745                         /* Get next tag (icon, icon_text or icon_action) */
746                         if (xml_compare_tag(file, TOOLBAR_TAG_ITEM)) {
747                                 toolbar_parse_item(file, source);
748                         } else if (xml_compare_tag(file, TOOLBAR_TAG_SEPARATOR)) {
749                                 ToolbarItem *item = g_new0(ToolbarItem, 1);
750                         
751                                 item->file   = g_strdup(TOOLBAR_TAG_SEPARATOR);
752                                 item->index  = A_SEPARATOR;
753                                 toolbar_config[source].item_list = 
754                                         g_slist_append(toolbar_config[source].item_list, item);
755                         }
756
757                 }
758                 xml_close_file(file);
759         }
760
761         if ((!file) || (g_slist_length(toolbar_config[source].item_list) == 0)) {
762
763                 if (source == TOOLBAR_MAIN) 
764                         toolbar_set_default(TOOLBAR_MAIN);
765                 else if (source == TOOLBAR_COMPOSE) 
766                         toolbar_set_default(TOOLBAR_COMPOSE);
767                 else if (source == TOOLBAR_MSGVIEW) 
768                         toolbar_set_default(TOOLBAR_MSGVIEW);
769                 else {          
770                         g_warning("refusing to write unknown Toolbar Configuration number %d\n", source);
771                         return;
772                 }
773
774                 toolbar_save_config_file(source);
775         }
776 }
777
778 /*
779  * clears list of toolbar items read from configuration files
780  */
781 void toolbar_clear_list(ToolbarType source)
782 {
783         while (toolbar_config[source].item_list != NULL) {
784                 ToolbarItem *item = (ToolbarItem*) toolbar_config[source].item_list->data;
785                 
786                 toolbar_config[source].item_list = 
787                         g_slist_remove(toolbar_config[source].item_list, item);
788
789                 g_free(item->file);
790                 g_free(item->text);
791                 g_free(item);   
792         }
793         g_slist_free(toolbar_config[source].item_list);
794 }
795
796
797 /* 
798  * return list of Toolbar items
799  */
800 GSList *toolbar_get_list(ToolbarType source)
801 {
802         GSList *list = NULL;
803
804         if ((source == TOOLBAR_MAIN) || (source == TOOLBAR_COMPOSE) || (source == TOOLBAR_MSGVIEW))
805                 list = toolbar_config[source].item_list;
806
807         return list;
808 }
809
810 void toolbar_set_list_item(ToolbarItem *t_item, ToolbarType source)
811 {
812         ToolbarItem *toolbar_item = g_new0(ToolbarItem, 1);
813
814         toolbar_item->file  = g_strdup(t_item->file);
815         toolbar_item->text  = g_strdup(t_item->text);
816         toolbar_item->index = t_item->index;
817         
818         toolbar_config[source].item_list = 
819                 g_slist_append(toolbar_config[source].item_list,
820                                toolbar_item);
821 }
822
823 static void toolbar_action_execute(GtkWidget    *widget,
824                             GSList       *action_list, 
825                             gpointer     data,
826                             gint         source) 
827 {
828         GSList *cur;
829         gint i = 0;
830
831         for (cur = action_list; cur != NULL;  cur = cur->next) {
832                 ToolbarClawsActions *act = (ToolbarClawsActions*)cur->data;
833
834                 if (widget == act->widget) {
835                         i = prefs_actions_find_by_name(act->name);
836
837                         if (i != -1) 
838                                 break;
839                 }
840         }
841
842         if (i != -1) 
843                 actions_execute(data, i, widget, source);
844         else
845                 g_warning ("Error: did not find Claws Action to execute");
846 }
847
848 gboolean toolbar_check_action_btns(ToolbarType type)
849 {
850         GSList *temp, *curr, *list = toolbar_config[type].item_list;
851         gboolean modified = FALSE;
852         
853         curr = list;
854         while (curr != NULL) {
855                 ToolbarItem *toolbar_item = (ToolbarItem *) curr->data;
856                 temp = curr;
857                 curr = curr->next;
858                 
859                 if (toolbar_item->index != A_CLAWS_ACTIONS)
860                         continue;
861
862                 if (prefs_actions_find_by_name(toolbar_item->text) == -1) {
863                         list = g_slist_delete_link(list, temp);
864                         g_free(toolbar_item->file);
865                         g_free(toolbar_item->text);
866                         g_free(toolbar_item);
867                         modified = TRUE;
868                 }
869         }
870         
871         return modified;
872 }
873
874 #if !(GTK_CHECK_VERSION(2,12,0))
875 #define CLAWS_SET_TOOL_ITEM_TIP(widget,tip) { \
876         gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(widget), GTK_TOOLTIPS(toolbar_tips),    \
877                         tip, NULL);                                                             \
878 }
879 #else
880 #define CLAWS_SET_TOOL_ITEM_TIP(widget,tip) { \
881         gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(widget), tip);                             \
882 }
883 #endif  
884
885 #if !(GTK_CHECK_VERSION(2,12,0))
886 #define CLAWS_SET_ARROW_TIP(widget,tip) { \
887         gtk_menu_tool_button_set_arrow_tooltip(GTK_MENU_TOOL_BUTTON(widget), GTK_TOOLTIPS(toolbar_tips),        \
888                         tip, NULL);                                                             \
889 }
890 #else
891 #define CLAWS_SET_ARROW_TIP(widget,tip) { \
892         gtk_menu_tool_button_set_arrow_tooltip_text(GTK_MENU_TOOL_BUTTON(widget), tip);                         \
893 }
894 #endif  
895
896 static void activate_compose_button (Toolbar           *toolbar,
897                                      ToolbarStyle      style,
898                                      ComposeButtonType type)
899 {
900 #if !(GTK_CHECK_VERSION(2,12,0))
901         GtkTooltips *toolbar_tips = toolbar->tooltips;
902 #endif
903         if ((!toolbar->compose_mail_btn))
904                 return;
905
906         if (type == COMPOSEBUTTON_NEWS) {
907                 gtk_tool_button_set_icon_widget(
908                         GTK_TOOL_BUTTON(toolbar->compose_mail_btn),
909                         toolbar->compose_news_icon);
910 #ifndef GENERIC_UMPC
911                 CLAWS_SET_TOOL_ITEM_TIP(GTK_TOOL_ITEM(toolbar->compose_mail_btn), _("Compose News message"));
912 #endif  
913                 gtk_widget_show(toolbar->compose_news_icon);
914         } else {
915                 gtk_tool_button_set_icon_widget(
916                         GTK_TOOL_BUTTON(toolbar->compose_mail_btn),
917                         toolbar->compose_mail_icon);
918 #ifndef GENERIC_UMPC
919                 CLAWS_SET_TOOL_ITEM_TIP(GTK_TOOL_ITEM(toolbar->compose_mail_btn), _("Compose Email"));
920 #endif  
921                 gtk_widget_show(toolbar->compose_mail_icon);
922         }
923         toolbar->compose_btn_type = type;
924 }
925
926 void toolbar_set_compose_button(Toolbar            *toolbar, 
927                                 ComposeButtonType  compose_btn_type)
928 {
929         if (toolbar->compose_btn_type != compose_btn_type)
930                 activate_compose_button(toolbar, 
931                                         prefs_common.toolbar_style,
932                                         compose_btn_type);
933 }
934
935 static void activate_learn_button (Toolbar           *toolbar,
936                                      ToolbarStyle      style,
937                                      LearnButtonType type)
938 {
939 #if !(GTK_CHECK_VERSION(2,12,0))
940         GtkTooltips *toolbar_tips = toolbar->tooltips;
941 #endif
942         if ((!toolbar->learn_spam_btn))
943                 return;
944
945         if (type == LEARN_SPAM) {
946                 gtk_tool_button_set_icon_widget(
947                         GTK_TOOL_BUTTON(toolbar->learn_spam_btn),
948                         toolbar->learn_spam_icon);
949                 gtk_tool_button_set_label(
950                         GTK_TOOL_BUTTON(toolbar->learn_spam_btn),
951                         _("Spam"));
952 #ifndef GENERIC_UMPC
953                 CLAWS_SET_TOOL_ITEM_TIP(GTK_TOOL_ITEM(toolbar->learn_spam_btn), _("Learn spam"));       
954 #endif
955                 gtk_widget_show(toolbar->learn_spam_icon);
956         } else {
957                 gtk_tool_button_set_icon_widget(
958                         GTK_TOOL_BUTTON(toolbar->learn_spam_btn),
959                         toolbar->learn_ham_icon);
960                 gtk_tool_button_set_label(
961                         GTK_TOOL_BUTTON(toolbar->learn_spam_btn),
962                         _("Ham"));
963 #ifndef GENERIC_UMPC
964                 CLAWS_SET_TOOL_ITEM_TIP(GTK_TOOL_ITEM(toolbar->learn_spam_btn), _("Learn ham"));
965 #endif  
966                 gtk_widget_show(toolbar->learn_ham_icon);
967         }
968         toolbar->learn_btn_type = type; 
969 }
970
971 void toolbar_set_learn_button(Toolbar            *toolbar, 
972                                 LearnButtonType  learn_btn_type)
973 {
974         if (toolbar->learn_btn_type != learn_btn_type)
975                 activate_learn_button(toolbar, 
976                                         prefs_common.toolbar_style,
977                                         learn_btn_type);
978 }
979
980 void toolbar_toggle(guint action, gpointer data)
981 {
982         MainWindow *mainwin = (MainWindow*)data;
983         GList *list;
984         GList *cur;
985
986         cm_return_if_fail(mainwin != NULL);
987
988         toolbar_style(TOOLBAR_MAIN, action, mainwin);
989
990         list = compose_get_compose_list();
991         for (cur = list; cur != NULL; cur = cur->next) {
992                 toolbar_style(TOOLBAR_COMPOSE, action, cur->data);
993         }
994         list = messageview_get_msgview_list();
995         for (cur = list; cur != NULL; cur = cur->next) {
996                 toolbar_style(TOOLBAR_MSGVIEW, action, cur->data);
997         }
998         
999 }
1000
1001 void toolbar_set_style(GtkWidget *toolbar_wid, GtkWidget *handlebox_wid, guint action)
1002 {
1003         switch ((ToolbarStyle)action) {
1004         case TOOLBAR_NONE:
1005                 gtk_widget_hide(handlebox_wid);
1006                 break;
1007         case TOOLBAR_ICON:
1008                 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar_wid),
1009                                       GTK_TOOLBAR_ICONS);
1010                 break;
1011         case TOOLBAR_TEXT:
1012                 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar_wid),
1013                                       GTK_TOOLBAR_TEXT);
1014                 break;
1015         case TOOLBAR_BOTH:
1016                 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar_wid),
1017                                       GTK_TOOLBAR_BOTH);
1018                 break;
1019         case TOOLBAR_BOTH_HORIZ:
1020                 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar_wid),
1021                                       GTK_TOOLBAR_BOTH_HORIZ);
1022                 break;
1023         default:
1024                 return;
1025         }
1026
1027         prefs_common.toolbar_style = (ToolbarStyle)action;
1028         gtk_widget_set_size_request(handlebox_wid, 1, -1);
1029         
1030         if (prefs_common.toolbar_style != TOOLBAR_NONE) {
1031                 gtk_widget_show(handlebox_wid);
1032                 gtk_widget_queue_resize(handlebox_wid);
1033         }
1034 }
1035 /*
1036  * Change the style of toolbar
1037  */
1038 static void toolbar_style(ToolbarType type, guint action, gpointer data)
1039 {
1040         GtkWidget  *handlebox_wid;
1041         GtkWidget  *toolbar_wid;
1042         MainWindow *mainwin = (MainWindow*)data;
1043         Compose    *compose = (Compose*)data;
1044         MessageView *msgview = (MessageView*)data;
1045         
1046         cm_return_if_fail(data != NULL);
1047         
1048         switch (type) {
1049         case TOOLBAR_MAIN:
1050                 handlebox_wid = mainwin->handlebox;
1051                 toolbar_wid = mainwin->toolbar->toolbar;
1052                 break;
1053         case TOOLBAR_COMPOSE:
1054                 handlebox_wid = compose->handlebox;
1055                 toolbar_wid = compose->toolbar->toolbar;
1056                 break;
1057         case TOOLBAR_MSGVIEW: 
1058                 handlebox_wid = msgview->handlebox;
1059                 toolbar_wid = msgview->toolbar->toolbar;
1060                 break;
1061         default:
1062
1063                 return;
1064         }
1065         toolbar_set_style(toolbar_wid, handlebox_wid, action);
1066 }
1067
1068 /* Toolbar handling */
1069 static void toolbar_inc_cb(GtkWidget    *widget,
1070                            gpointer      data)
1071 {
1072         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1073         MainWindow *mainwin;
1074
1075         cm_return_if_fail(toolbar_item != NULL);
1076
1077         switch (toolbar_item->type) {
1078         case TOOLBAR_MAIN:
1079                 mainwin = (MainWindow*)toolbar_item->parent;    
1080                 inc_mail_cb(mainwin, 0, NULL);
1081                 break;
1082         default:
1083                 break;
1084         }
1085 }
1086
1087 static void toolbar_inc_all_cb(GtkWidget        *widget,
1088                                gpointer          data)
1089 {
1090         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1091         MainWindow *mainwin;
1092
1093         cm_return_if_fail(toolbar_item != NULL);
1094
1095         switch (toolbar_item->type) {
1096         case TOOLBAR_MAIN:
1097                 mainwin = (MainWindow*)toolbar_item->parent;
1098                 inc_all_account_mail_cb(mainwin, 0, NULL);
1099                 break;
1100         default:
1101                 break;
1102         }
1103 }
1104
1105 static void toolbar_send_queued_cb(GtkWidget *widget,gpointer data)
1106 {
1107         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1108         MainWindow *mainwin;
1109
1110         cm_return_if_fail(toolbar_item != NULL);
1111
1112         switch (toolbar_item->type) {
1113         case TOOLBAR_MAIN:
1114                 mainwin = (MainWindow*)toolbar_item->parent;
1115                 send_queue_cb(mainwin, 0, NULL);
1116                 break;
1117         default:
1118                 break;
1119         }
1120 }
1121
1122 static void toolbar_exec_cb(GtkWidget   *widget,
1123                             gpointer     data)
1124 {
1125         MainWindow *mainwin = get_mainwin(data);
1126
1127         cm_return_if_fail(mainwin != NULL);
1128         summary_execute(mainwin->summaryview);
1129 }
1130
1131 /*
1132  * Delete current/selected(s) message(s)
1133  */
1134 static void toolbar_trash_cb(GtkWidget *widget, gpointer data)
1135 {
1136         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1137         MainWindow *mainwin;
1138
1139         cm_return_if_fail(toolbar_item != NULL);
1140         cm_return_if_fail(toolbar_item->parent);
1141         
1142         switch (toolbar_item->type) {
1143         case TOOLBAR_MSGVIEW:
1144                 messageview_delete((MessageView *)toolbar_item->parent);
1145                 break;
1146         case TOOLBAR_MAIN:
1147                 mainwin = (MainWindow *)toolbar_item->parent;
1148                 summary_delete_trash(mainwin->summaryview);
1149                 break;
1150         default: 
1151                 debug_print("toolbar event not supported\n");
1152                 break;
1153         }
1154 }
1155
1156 /*
1157  * Delete current/selected(s) message(s)
1158  */
1159 static void toolbar_delete_cb(GtkWidget *widget, gpointer data)
1160 {
1161         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1162         MainWindow *mainwin;
1163
1164         cm_return_if_fail(toolbar_item != NULL);
1165         cm_return_if_fail(toolbar_item->parent);
1166         
1167         switch (toolbar_item->type) {
1168         case TOOLBAR_MSGVIEW:
1169                 messageview_delete((MessageView *)toolbar_item->parent);
1170                 break;
1171         case TOOLBAR_MAIN:
1172                 mainwin = (MainWindow *)toolbar_item->parent;
1173                 summary_delete(mainwin->summaryview);
1174                 break;
1175         default: 
1176                 debug_print("toolbar event not supported\n");
1177                 break;
1178         }
1179 }
1180
1181
1182 /*
1183  * Compose new message
1184  */
1185 static void toolbar_compose_cb(GtkWidget *widget, gpointer data)
1186 {
1187         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1188         MainWindow *mainwin;
1189         MessageView *msgview;
1190
1191         cm_return_if_fail(toolbar_item != NULL);
1192
1193         switch (toolbar_item->type) {
1194         case TOOLBAR_MAIN:
1195                 mainwin = (MainWindow*)toolbar_item->parent;
1196                 if (mainwin->toolbar->compose_btn_type == COMPOSEBUTTON_NEWS) 
1197                         compose_news_cb(mainwin, 0, NULL);
1198                 else
1199                         compose_mail_cb(mainwin, 0, NULL);
1200                 break;
1201         case TOOLBAR_MSGVIEW:
1202                 msgview = (MessageView*)toolbar_item->parent;
1203                 compose_new_with_folderitem(NULL, 
1204                                             msgview->msginfo->folder, NULL);
1205                 break;  
1206         default:
1207                 debug_print("toolbar event not supported\n");
1208         }
1209 }
1210
1211 static void toolbar_learn(gpointer data, guint as_spam)
1212 {
1213         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1214         MainWindow *mainwin;
1215         MessageView *msgview;
1216
1217         cm_return_if_fail(toolbar_item != NULL);
1218
1219         switch (toolbar_item->type) {
1220         case TOOLBAR_MAIN:
1221                 mainwin = (MainWindow*)toolbar_item->parent;
1222                 if (as_spam) 
1223                         mainwindow_learn(mainwin, TRUE);
1224                 else
1225                         mainwindow_learn(mainwin, FALSE);
1226                 break;
1227         case TOOLBAR_MSGVIEW:
1228                 msgview = (MessageView*)toolbar_item->parent;
1229                 if (as_spam) 
1230                         messageview_learn(msgview, TRUE);
1231                 else
1232                         messageview_learn(msgview, FALSE);
1233                 break;
1234         default:
1235                 debug_print("toolbar event not supported\n");
1236         }
1237 }
1238
1239 static void toolbar_learn_cb(GtkWidget *widget, gpointer data)
1240 {
1241         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1242         MainWindow *mainwin;
1243         MessageView *msgview;
1244
1245         cm_return_if_fail(toolbar_item != NULL);
1246
1247         switch (toolbar_item->type) {
1248         case TOOLBAR_MAIN:
1249                 mainwin = (MainWindow*)toolbar_item->parent;
1250                 if (mainwin->toolbar->learn_btn_type == LEARN_SPAM) 
1251                         mainwindow_learn(mainwin, TRUE);
1252                 else
1253                         mainwindow_learn(mainwin, FALSE);
1254                 break;
1255         case TOOLBAR_MSGVIEW:
1256                 msgview = (MessageView*)toolbar_item->parent;
1257                 if (msgview->toolbar->learn_btn_type == LEARN_SPAM) 
1258                         messageview_learn(msgview, TRUE);
1259                 else
1260                         messageview_learn(msgview, FALSE);
1261                 break;
1262         default:
1263                 debug_print("toolbar event not supported\n");
1264         }
1265 }
1266
1267
1268 /*
1269  * Reply Message
1270  */
1271 static void toolbar_reply_cb(GtkWidget *widget, gpointer data)
1272 {
1273         toolbar_reply(data, (prefs_common.reply_with_quote ? 
1274                       COMPOSE_REPLY_WITH_QUOTE : COMPOSE_REPLY_WITHOUT_QUOTE));
1275 }
1276
1277
1278 /*
1279  * Reply message to Sender and All recipients
1280  */
1281 static void toolbar_reply_to_all_cb(GtkWidget *widget, gpointer data)
1282 {
1283         toolbar_reply(data,
1284                       (prefs_common.reply_with_quote ? COMPOSE_REPLY_TO_ALL_WITH_QUOTE 
1285                       : COMPOSE_REPLY_TO_ALL_WITHOUT_QUOTE));
1286 }
1287
1288
1289 /*
1290  * Reply to Mailing List
1291  */
1292 static void toolbar_reply_to_list_cb(GtkWidget *widget, gpointer data)
1293 {
1294         toolbar_reply(data, 
1295                       (prefs_common.reply_with_quote ? COMPOSE_REPLY_TO_LIST_WITH_QUOTE 
1296                       : COMPOSE_REPLY_TO_LIST_WITHOUT_QUOTE));
1297 }
1298
1299
1300 /*
1301  * Reply to sender of message
1302  */ 
1303 static void toolbar_reply_to_sender_cb(GtkWidget *widget, gpointer data)
1304 {
1305         toolbar_reply(data, 
1306                       (prefs_common.reply_with_quote ? COMPOSE_REPLY_TO_SENDER_WITH_QUOTE 
1307                       : COMPOSE_REPLY_TO_SENDER_WITHOUT_QUOTE));
1308 }
1309
1310 /*
1311  * Open addressbook
1312  */ 
1313 static void toolbar_addrbook_cb(GtkWidget *widget, gpointer data)
1314 {
1315         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1316         Compose *compose;
1317
1318         cm_return_if_fail(toolbar_item != NULL);
1319
1320         switch (toolbar_item->type) {
1321         case TOOLBAR_MAIN:
1322         case TOOLBAR_MSGVIEW:
1323                 compose = NULL;
1324                 break;
1325         case TOOLBAR_COMPOSE:
1326                 compose = (Compose *)toolbar_item->parent;
1327                 break;
1328         default:
1329                 return;
1330         }
1331 #ifndef USE_NEW_ADDRBOOK
1332         addressbook_open(compose);
1333 #else
1334         GError* error = NULL;
1335         addressbook_connect_signals(compose);
1336         addressbook_dbus_open(TRUE, &error);
1337         if (error) {
1338                 g_warning("%s", error->message);
1339                 g_error_free(error);
1340         }
1341 #endif
1342 }
1343
1344
1345 /*
1346  * Forward current/selected(s) message(s)
1347  */
1348 static void toolbar_forward_cb(GtkWidget *widget, gpointer data)
1349 {
1350         toolbar_reply(data, (COMPOSE_FORWARD));
1351 }
1352
1353 /*
1354  * Goto Prev Unread Message
1355  */
1356 static void toolbar_prev_unread_cb(GtkWidget *widget, gpointer data)
1357 {
1358         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1359         MainWindow *mainwin;
1360         MessageView *msgview;
1361
1362         cm_return_if_fail(toolbar_item != NULL);
1363
1364         switch (toolbar_item->type) {
1365         case TOOLBAR_MAIN:
1366                 mainwin = (MainWindow*)toolbar_item->parent;
1367                 summary_select_prev_unread(mainwin->summaryview);
1368                 break;
1369                 
1370         case TOOLBAR_MSGVIEW:
1371                 msgview = (MessageView*)toolbar_item->parent;
1372                 msgview->updating = TRUE;
1373                 summary_select_prev_unread(msgview->mainwin->summaryview);
1374                 msgview->updating = FALSE;
1375
1376                 if (msgview->deferred_destroy) {
1377                         debug_print("messageview got away!\n");
1378                         messageview_destroy(msgview);
1379                         return;
1380                 }
1381                 
1382                 /* Now we need to update the messageview window */
1383                 if (msgview->mainwin->summaryview->selected) {
1384 #ifndef GENERIC_UMPC
1385                         MsgInfo * msginfo = summary_get_selected_msg(msgview->mainwin->summaryview);
1386                        
1387                         if (msginfo)
1388                                 messageview_show(msgview, msginfo, 
1389                                          msgview->all_headers);
1390 #endif
1391                 } else {
1392                         gtk_widget_destroy(msgview->window);
1393                 }
1394                 break;
1395         default:
1396                 debug_print("toolbar event not supported\n");
1397         }
1398 }
1399
1400 /*
1401  * Goto Next Unread Message
1402  */
1403 static void toolbar_next_unread_cb(GtkWidget *widget, gpointer data)
1404 {
1405         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1406         MainWindow *mainwin;
1407         MessageView *msgview;
1408
1409         cm_return_if_fail(toolbar_item != NULL);
1410
1411         switch (toolbar_item->type) {
1412         case TOOLBAR_MAIN:
1413                 mainwin = (MainWindow*)toolbar_item->parent;
1414                 summary_select_next_unread(mainwin->summaryview);
1415                 break;
1416                 
1417         case TOOLBAR_MSGVIEW:
1418                 msgview = (MessageView*)toolbar_item->parent;
1419                 msgview->updating = TRUE;
1420                 summary_select_next_unread(msgview->mainwin->summaryview);
1421                 msgview->updating = FALSE;
1422
1423                 if (msgview->deferred_destroy) {
1424                         debug_print("messageview got away!\n");
1425                         messageview_destroy(msgview);
1426                         return;
1427                 }
1428
1429                 /* Now we need to update the messageview window */
1430                 if (msgview->mainwin->summaryview->selected) {
1431 #ifndef GENERIC_UMPC
1432                         MsgInfo * msginfo = summary_get_selected_msg(msgview->mainwin->summaryview);
1433                         
1434                         if (msginfo)
1435                                 messageview_show(msgview, msginfo, 
1436                                          msgview->all_headers);
1437 #endif
1438                 } else {
1439                         gtk_widget_destroy(msgview->window);
1440                 }
1441                 break;
1442         default:
1443                 debug_print("toolbar event not supported\n");
1444         }
1445 }
1446
1447 static void toolbar_ignore_thread_cb(GtkWidget *widget, gpointer data)
1448 {
1449         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1450         MainWindow *mainwin;
1451
1452         cm_return_if_fail(toolbar_item != NULL);
1453
1454         switch (toolbar_item->type) {
1455         case TOOLBAR_MAIN:
1456                 mainwin = (MainWindow *) toolbar_item->parent;
1457                 summary_toggle_ignore_thread(mainwin->summaryview);
1458                 break;
1459         case TOOLBAR_MSGVIEW:
1460                 /* TODO: see toolbar_next_unread_cb() if you need
1461                  * this in the message view */
1462                 break;
1463         default:
1464                 debug_print("toolbar event not supported\n");
1465                 break;
1466         }
1467 }
1468
1469 static void toolbar_watch_thread_cb(GtkWidget *widget, gpointer data)
1470 {
1471         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1472         MainWindow *mainwin;
1473
1474         cm_return_if_fail(toolbar_item != NULL);
1475
1476         switch (toolbar_item->type) {
1477         case TOOLBAR_MAIN:
1478                 mainwin = (MainWindow *) toolbar_item->parent;
1479                 summary_toggle_watch_thread(mainwin->summaryview);
1480                 break;
1481         case TOOLBAR_MSGVIEW:
1482                 /* TODO: see toolbar_next_unread_cb() if you need
1483                  * this in the message view */
1484                 break;
1485         default:
1486                 debug_print("toolbar event not supported\n");
1487                 break;
1488         }
1489 }
1490
1491 static void toolbar_cancel_inc_cb(GtkWidget *widget, gpointer data)
1492 {
1493         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1494
1495         cm_return_if_fail(toolbar_item != NULL);
1496         inc_cancel_all();
1497         imap_cancel_all();
1498 }
1499
1500 static void toolbar_cancel_send_cb(GtkWidget *widget, gpointer data)
1501 {
1502         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1503
1504         cm_return_if_fail(toolbar_item != NULL);
1505         send_cancel();
1506 }
1507
1508 static void toolbar_cancel_all_cb(GtkWidget *widget, gpointer data)
1509 {
1510         toolbar_cancel_inc_cb(widget, data);
1511         toolbar_cancel_send_cb(widget, data);
1512 }
1513
1514 static void toolbar_print_cb(GtkWidget *widget, gpointer data)
1515 {
1516         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1517         MainWindow *mainwin;
1518
1519         cm_return_if_fail(toolbar_item != NULL);
1520
1521         switch (toolbar_item->type) {
1522         case TOOLBAR_MAIN:
1523                 mainwin = (MainWindow *) toolbar_item->parent;
1524                 summary_print(mainwin->summaryview);
1525                 break;
1526         case TOOLBAR_MSGVIEW:
1527                 /* TODO: see toolbar_next_unread_cb() if you need
1528                  * this in the message view */
1529                 break;
1530         default:
1531                 debug_print("toolbar event not supported\n");
1532                 break;
1533         }
1534 }
1535
1536 static void toolbar_send_cb(GtkWidget *widget, gpointer data)
1537 {
1538         compose_toolbar_cb(A_SEND, data);
1539 }
1540
1541 static void toolbar_send_later_cb(GtkWidget *widget, gpointer data)
1542 {
1543         compose_toolbar_cb(A_SENDL, data);
1544 }
1545
1546 static void toolbar_draft_cb(GtkWidget *widget, gpointer data)
1547 {
1548         compose_toolbar_cb(A_DRAFT, data);
1549 }
1550
1551 static void toolbar_close_cb(GtkWidget *widget, gpointer data)
1552 {
1553         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1554         MainWindow *mainwin;
1555         MessageView *messageview;
1556         Compose *compose;
1557
1558         cm_return_if_fail(toolbar_item != NULL);
1559
1560         switch (toolbar_item->type) {
1561         case TOOLBAR_MAIN:
1562                 mainwin = (MainWindow *) toolbar_item->parent;
1563                 app_will_exit(NULL, mainwin);
1564                 break;
1565         case TOOLBAR_MSGVIEW:
1566                 messageview = (MessageView *)toolbar_item->parent;
1567                 messageview_destroy(messageview);
1568                 break;
1569         case TOOLBAR_COMPOSE:
1570                 compose = (Compose *)toolbar_item->parent;
1571                 compose_close_toolbar(compose);
1572                 break;
1573         }
1574 }
1575
1576 static void toolbar_preferences_cb(GtkWidget *widget, gpointer data)
1577 {
1578         prefs_gtk_open();
1579 }
1580
1581 static void toolbar_open_mail_cb(GtkWidget *widget, gpointer data)
1582 {
1583         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1584         MainWindow *mainwin;
1585
1586         cm_return_if_fail(toolbar_item != NULL);
1587
1588         switch (toolbar_item->type) {
1589         case TOOLBAR_MAIN:
1590                 mainwin = (MainWindow *) toolbar_item->parent;
1591                 summary_open_row(NULL, mainwin->summaryview);
1592                 break;
1593         case TOOLBAR_MSGVIEW:
1594                 debug_print("toolbar event not supported\n");
1595                 break;
1596         case TOOLBAR_COMPOSE:
1597                 debug_print("toolbar event not supported\n");
1598                 break;
1599         }
1600 }
1601
1602 static void toolbar_insert_cb(GtkWidget *widget, gpointer data)
1603 {
1604         compose_toolbar_cb(A_INSERT, data);
1605 }
1606
1607 static void toolbar_attach_cb(GtkWidget *widget, gpointer data)
1608 {
1609         compose_toolbar_cb(A_ATTACH, data);
1610 }
1611
1612 static void toolbar_sig_cb(GtkWidget *widget, gpointer data)
1613 {
1614         compose_toolbar_cb(A_SIG, data);
1615 }
1616
1617 static void toolbar_ext_editor_cb(GtkWidget *widget, gpointer data)
1618 {
1619         compose_toolbar_cb(A_EXTEDITOR, data);
1620 }
1621
1622 static void toolbar_linewrap_current_cb(GtkWidget *widget, gpointer data)
1623 {
1624         compose_toolbar_cb(A_LINEWRAP_CURRENT, data);
1625 }
1626
1627 static void toolbar_linewrap_all_cb(GtkWidget *widget, gpointer data)
1628 {
1629         compose_toolbar_cb(A_LINEWRAP_ALL, data);
1630 }
1631
1632 #ifdef USE_ENCHANT
1633 static void toolbar_check_spelling_cb(GtkWidget *widget, gpointer data)
1634 {
1635         compose_toolbar_cb(A_CHECK_SPELLING, data);
1636 }
1637 #endif
1638 /*
1639  * Execute actions from toolbar
1640  */
1641 static void toolbar_actions_execute_cb(GtkWidget *widget, gpointer data)
1642 {
1643         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1644         GSList *action_list;
1645         MainWindow *mainwin;
1646         Compose *compose;
1647         MessageView *msgview;
1648         gpointer parent = toolbar_item->parent;
1649
1650         cm_return_if_fail(toolbar_item != NULL);
1651
1652         switch (toolbar_item->type) {
1653         case TOOLBAR_MAIN:
1654                 mainwin = (MainWindow*)parent;
1655                 action_list = mainwin->toolbar->action_list;
1656                 break;
1657         case TOOLBAR_COMPOSE:
1658                 compose = (Compose*)parent;
1659                 action_list = compose->toolbar->action_list;
1660                 break;
1661         case TOOLBAR_MSGVIEW:
1662                 msgview = (MessageView*)parent;
1663                 action_list = msgview->toolbar->action_list;
1664                 break;
1665         default:
1666                 debug_print("toolbar event not supported\n");
1667                 return;
1668         }
1669         toolbar_action_execute(widget, action_list, parent, toolbar_item->type);        
1670 }
1671
1672 static void toolbar_plugins_execute_cb(GtkWidget *widget, gpointer data)
1673 {
1674         ToolbarItem *toolbar_item = data;
1675         prefs_toolbar_execute_plugin_item(toolbar_item->parent, toolbar_item->type, toolbar_item->text);
1676 }
1677
1678 static MainWindow *get_mainwin(gpointer data)
1679 {
1680         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1681         MainWindow *mainwin = NULL;
1682         MessageView *msgview;
1683
1684         cm_return_val_if_fail(toolbar_item != NULL, NULL);
1685
1686         switch(toolbar_item->type) {
1687         case TOOLBAR_MAIN:
1688                 mainwin = (MainWindow*)toolbar_item->parent;
1689                 break;
1690         case TOOLBAR_MSGVIEW:
1691                 msgview = (MessageView*)toolbar_item->parent;
1692                 mainwin = (MainWindow*)msgview->mainwin;
1693                 break;
1694         default:
1695                 break;
1696         }
1697
1698         return mainwin;
1699 }
1700
1701 static void toolbar_go_folders_cb(GtkWidget *widget, gpointer data)
1702 {
1703         ToolbarItem *toolbar_item = (ToolbarItem*)data;
1704         MainWindow *mainwin = NULL;
1705         switch(toolbar_item->type) {
1706         case TOOLBAR_MAIN:
1707                 mainwin = (MainWindow*)toolbar_item->parent;
1708                 break;
1709         default:
1710                 g_warning("wrong toolbar type\n");
1711                 return;
1712         }
1713
1714         if (!mainwin->in_folder) {
1715                 FolderItem *item = folderview_get_selected_item(mainwin->folderview);
1716                 if (item) {
1717                         folderview_select(mainwin->folderview, item);
1718                 }
1719         } else {
1720                 gtk_widget_grab_focus(mainwin->folderview->ctree);
1721                 mainwindow_exit_folder(mainwin);
1722         }
1723 }
1724
1725 static void toolbar_buttons_cb(GtkWidget   *widget, 
1726                                ToolbarItem *item)
1727 {
1728         gint num_items;
1729         gint i;
1730         struct {
1731                 gint   index;
1732                 void (*func)(GtkWidget *widget, gpointer data);
1733         } callbacks[] = {
1734                 { A_RECEIVE_ALL,        toolbar_inc_all_cb              },
1735                 { A_RECEIVE_CUR,        toolbar_inc_cb                  },
1736                 { A_SEND_QUEUED,        toolbar_send_queued_cb          },
1737                 { A_COMPOSE_EMAIL,      toolbar_compose_cb              },
1738                 { A_COMPOSE_NEWS,       toolbar_compose_cb              },
1739                 { A_REPLY_MESSAGE,      toolbar_reply_cb                },
1740                 { A_REPLY_SENDER,       toolbar_reply_to_sender_cb      },
1741                 { A_REPLY_ALL,          toolbar_reply_to_all_cb         },
1742                 { A_REPLY_ML,           toolbar_reply_to_list_cb        },
1743                 { A_FORWARD,            toolbar_forward_cb              },
1744                 { A_TRASH,              toolbar_trash_cb                },
1745                 { A_DELETE_REAL,        toolbar_delete_cb               },
1746                 { A_EXECUTE,            toolbar_exec_cb                 },
1747                 { A_GOTO_PREV,          toolbar_prev_unread_cb          },
1748                 { A_GOTO_NEXT,          toolbar_next_unread_cb          },
1749                 { A_IGNORE_THREAD,      toolbar_ignore_thread_cb        },
1750                 { A_WATCH_THREAD,       toolbar_watch_thread_cb         },
1751                 { A_PRINT,              toolbar_print_cb                },
1752                 { A_LEARN_SPAM,         toolbar_learn_cb                },
1753                 { A_GO_FOLDERS,         toolbar_go_folders_cb           },
1754
1755                 { A_SEND,               toolbar_send_cb                 },
1756                 { A_SENDL,              toolbar_send_later_cb           },
1757                 { A_DRAFT,              toolbar_draft_cb                },
1758                 { A_OPEN_MAIL,          toolbar_open_mail_cb            },
1759                 { A_CLOSE,              toolbar_close_cb                },
1760                 { A_PREFERENCES,        toolbar_preferences_cb          },
1761                 { A_INSERT,             toolbar_insert_cb               },
1762                 { A_ATTACH,             toolbar_attach_cb               },
1763                 { A_SIG,                toolbar_sig_cb                  },
1764                 { A_EXTEDITOR,          toolbar_ext_editor_cb           },
1765                 { A_LINEWRAP_CURRENT,   toolbar_linewrap_current_cb     },
1766                 { A_LINEWRAP_ALL,       toolbar_linewrap_all_cb         },
1767                 { A_ADDRBOOK,           toolbar_addrbook_cb             },
1768 #ifdef USE_ENCHANT
1769                 { A_CHECK_SPELLING,     toolbar_check_spelling_cb       },
1770 #endif
1771                 { A_CLAWS_ACTIONS,      toolbar_actions_execute_cb      },
1772                 { A_CANCEL_INC,         toolbar_cancel_inc_cb           },
1773                 { A_CANCEL_SEND,        toolbar_cancel_send_cb          },
1774                 { A_CANCEL_ALL,         toolbar_cancel_all_cb           },
1775                 { A_CLAWS_PLUGINS,  toolbar_plugins_execute_cb  },
1776         };
1777
1778         num_items = sizeof(callbacks)/sizeof(callbacks[0]);
1779
1780         for (i = 0; i < num_items; i++) {
1781                 if (callbacks[i].index == item->index) {
1782                         callbacks[i].func(widget, item);
1783                         return;
1784                 }
1785         }
1786 }
1787 #ifndef GENERIC_UMPC
1788 #define TOOLBAR_ITEM(item,icon,text,tooltip) {                                                          \
1789         item = GTK_WIDGET(gtk_tool_button_new(icon, text));                                             \
1790         gtkut_widget_set_can_focus(gtk_bin_get_child(GTK_BIN(item)), FALSE);                            \
1791         gtk_tool_item_set_homogeneous(GTK_TOOL_ITEM(item), FALSE);                                      \
1792         gtk_tool_item_set_is_important(GTK_TOOL_ITEM(item), TRUE);                                      \
1793         g_signal_connect (G_OBJECT(item), "clicked", G_CALLBACK(toolbar_buttons_cb), toolbar_item);     \
1794         gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), -1);                              \
1795         CLAWS_SET_TOOL_ITEM_TIP(GTK_TOOL_ITEM(item),                                                    \
1796                         tooltip);                                                                       \
1797 }
1798
1799 #define TOOLBAR_MENUITEM(item,icon,text,tooltip,menutip) {                                              \
1800         GtkWidget *child = NULL, *btn = NULL, *arr = NULL;                                              \
1801         GList *gchild = NULL;                                                                           \
1802         item = GTK_WIDGET(gtk_menu_tool_button_new(icon, text));                                        \
1803         gtk_tool_item_set_homogeneous(GTK_TOOL_ITEM(item), FALSE);                              \
1804         gtk_tool_item_set_is_important(GTK_TOOL_ITEM(item), TRUE);                                      \
1805         g_signal_connect (G_OBJECT(item), "clicked", G_CALLBACK(toolbar_buttons_cb), toolbar_item);     \
1806         gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), -1);                              \
1807         CLAWS_SET_TOOL_ITEM_TIP(GTK_TOOL_ITEM(item),                                                    \
1808                         tooltip);                                                                       \
1809         CLAWS_SET_ARROW_TIP(GTK_MENU_TOOL_BUTTON(item), menutip);                                       \
1810         child = gtk_bin_get_child(GTK_BIN(item));                                                       \
1811         gchild = gtk_container_get_children(                                                            \
1812                         GTK_CONTAINER(child));                                                          \
1813         btn = (GtkWidget *)gchild->data;                                                                \
1814         gtkut_widget_set_can_focus(btn, FALSE);                                                         \
1815         arr = (GtkWidget *)(gchild->next?gchild->next->data:NULL);                                      \
1816         gtkut_widget_set_can_focus(arr, FALSE);                                                         \
1817         g_list_free(gchild);                                                                            \
1818         gchild = gtk_container_get_children(GTK_CONTAINER(arr));                                        \
1819         gtk_widget_set_size_request(GTK_WIDGET(gchild->data), 9, -1);                                   \
1820         g_list_free(gchild);                                                                            \
1821 }
1822 #else
1823 #define TOOLBAR_ITEM(item,icon,text,tooltip) {                                                          \
1824         item = GTK_WIDGET(gtk_tool_button_new(icon, text));                                             \
1825         gtkut_widget_set_can_focus(gtk_bin_get_child(GTK_BIN(item)), FALSE);                            \
1826         gtk_tool_item_set_homogeneous(GTK_TOOL_ITEM(item), FALSE);                                      \
1827         gtk_tool_item_set_is_important(GTK_TOOL_ITEM(item), TRUE);                                      \
1828         g_signal_connect (G_OBJECT(item), "clicked", G_CALLBACK(toolbar_buttons_cb), toolbar_item);     \
1829         gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), -1);                              \
1830 }
1831
1832 #define TOOLBAR_MENUITEM(item,icon,text,tooltip,menutip) {                                              \
1833         GtkWidget *child = NULL, *btn = NULL, *arr = NULL;                                              \
1834         GList *gchild = NULL;                                                                           \
1835         item = GTK_WIDGET(gtk_menu_tool_button_new(icon, text));                                        \
1836         gtk_tool_item_set_homogeneous(GTK_TOOL_ITEM(item), FALSE);                              \
1837         gtk_tool_item_set_is_important(GTK_TOOL_ITEM(item), TRUE);                                      \
1838         g_signal_connect (G_OBJECT(item), "clicked", G_CALLBACK(toolbar_buttons_cb), toolbar_item);     \
1839         gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), -1);                              \
1840         child = gtk_bin_get_child(GTK_BIN(item));                                                       \
1841         gchild = gtk_container_get_children(                                                            \
1842                         GTK_CONTAINER(child));                                                          \
1843         btn = (GtkWidget *)gchild->data;                                                                \
1844         gtkut_widget_set_can_focus(btn, FALSE);                                                         \
1845         arr = (GtkWidget *)(gchild->next?gchild->next->data:NULL);                                      \
1846         gtkut_widget_set_can_focus(arr, FALSE);                                                         \
1847         g_list_free(gchild);                                                                            \
1848         gchild = gtk_container_get_children(GTK_CONTAINER(arr));                                        \
1849         gtk_widget_set_size_request(GTK_WIDGET(gchild->data), 9, -1);                                   \
1850         g_list_free(gchild);                                                                            \
1851 }
1852 #endif
1853
1854 #define ADD_MENU_ITEM(name,cb,data) {                                                   \
1855         item = gtk_menu_item_new_with_mnemonic(name);                                   \
1856         gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);                              \
1857         g_signal_connect(G_OBJECT(item), "activate",                                    \
1858                          G_CALLBACK(cb),                                                \
1859                            toolbar_item);                                               \
1860         g_object_set_data(G_OBJECT(item), "int-value", GINT_TO_POINTER(data));          \
1861         gtk_widget_show(item);                                                          \
1862 }
1863
1864 static void toolbar_reply_menu_cb(GtkWidget *widget, gpointer data)
1865 {
1866         gpointer int_value = g_object_get_data(G_OBJECT(widget), "int-value");
1867         ToolbarItem *toolbar_item = (ToolbarItem *)data;
1868         
1869         toolbar_reply(toolbar_item, GPOINTER_TO_INT(int_value));
1870 }
1871
1872 static void toolbar_learn_menu_cb(GtkWidget *widget, gpointer data)
1873 {
1874         gpointer int_value = g_object_get_data(G_OBJECT(widget), "int-value");
1875         ToolbarItem *toolbar_item = (ToolbarItem *)data;
1876         
1877         toolbar_learn(toolbar_item, GPOINTER_TO_INT(int_value));
1878 }
1879
1880 /**
1881  * Create a new toolbar with specified type
1882  * if a callback list is passed it will be used before the 
1883  * common callback list
1884  **/
1885 Toolbar *toolbar_create(ToolbarType      type, 
1886                         GtkWidget       *container,
1887                         gpointer         data)
1888 {
1889         ToolbarItem *toolbar_item;
1890
1891         GtkWidget *toolbar;
1892         GtkWidget *icon_wid = NULL;
1893         GtkWidget *icon_news;
1894         GtkWidget *icon_ham;
1895         GtkWidget *item;
1896         ToolbarClawsActions *action_item;
1897         GSList *cur;
1898         GSList *toolbar_list;
1899         Toolbar *toolbar_data;
1900         GtkWidget *menu;
1901 #ifndef GENERIC_UMPC
1902 #if !(GTK_CHECK_VERSION(2,12,0))
1903         GtkTooltips *toolbar_tips = gtk_tooltips_new();
1904 #endif
1905 #endif  
1906         toolbar_read_config_file(type);
1907         toolbar_list = toolbar_get_list(type);
1908
1909         toolbar_data = g_new0(Toolbar, 1); 
1910
1911         toolbar = gtk_toolbar_new();
1912
1913 #if (GTK_CHECK_VERSION(2,16,0))
1914         gtk_orientable_set_orientation(GTK_ORIENTABLE(toolbar), GTK_ORIENTATION_HORIZONTAL);
1915 #else
1916         gtk_toolbar_set_orientation(GTK_TOOLBAR(toolbar), GTK_ORIENTATION_HORIZONTAL);
1917 #endif
1918         gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH);
1919         gtk_toolbar_set_show_arrow(GTK_TOOLBAR(toolbar), TRUE);
1920         
1921         for (cur = toolbar_list; cur != NULL; cur = cur->next) {
1922
1923                 if (g_ascii_strcasecmp(((ToolbarItem*)cur->data)->file, TOOLBAR_TAG_SEPARATOR) == 0) {
1924                         gtk_toolbar_insert(GTK_TOOLBAR(toolbar), gtk_separator_tool_item_new(), -1);
1925                         continue;
1926                 }
1927                 
1928                 toolbar_item = g_new0(ToolbarItem, 1); 
1929                 toolbar_item->index = ((ToolbarItem*)cur->data)->index;
1930                 toolbar_item->file = g_strdup(((ToolbarItem*)cur->data)->file);
1931                 toolbar_item->text = g_strdup(((ToolbarItem*)cur->data)->text);
1932                 toolbar_item->parent = data;
1933                 toolbar_item->type = type;
1934
1935                 /* collect toolbar items in list to keep track */
1936                 toolbar_data->item_list = 
1937                         g_slist_append(toolbar_data->item_list, 
1938                                        toolbar_item);
1939                 icon_wid = stock_pixmap_widget(container, stock_pixmap_get_icon(toolbar_item->file));
1940                         
1941                 switch (toolbar_item->index) {
1942
1943                 case A_GO_FOLDERS:
1944                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Go to folder list"));
1945                         toolbar_data->folders_btn = item;
1946                         break;
1947                 case A_RECEIVE_ALL:
1948                         TOOLBAR_MENUITEM(item,icon_wid,toolbar_item->text,
1949                                 _("Receive Mail from all Accounts"),
1950                                 _("Receive Mail from selected Account"));
1951                         toolbar_data->getall_btn = item;
1952                         break;
1953                 case A_RECEIVE_CUR:
1954                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text, _("Receive Mail from current Account"));
1955                         toolbar_data->get_btn = item;
1956                         break;
1957                 case A_SEND_QUEUED:
1958                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Send Queued Messages"));
1959                         toolbar_data->send_btn = item; 
1960                         break;
1961                 case A_CLOSE:
1962                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Close window"));
1963                         toolbar_data->close_window_btn = item; 
1964                         break;
1965                 case A_PREFERENCES:
1966                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Open preferences"));
1967                         toolbar_data->preferences_btn = item; 
1968                         break;
1969                 case A_OPEN_MAIL:
1970                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Open email"));
1971                         toolbar_data->open_mail_btn = item; 
1972                         break;
1973                 case A_COMPOSE_EMAIL:
1974 #ifndef GENERIC_UMPC
1975                         TOOLBAR_MENUITEM(item,icon_wid,toolbar_item->text,
1976                                 _("Compose Email"),
1977                                 _("Compose with selected Account"));
1978                         toolbar_data->compose_mail_btn = item; 
1979                         toolbar_data->compose_mail_icon = icon_wid; 
1980                         g_object_ref(toolbar_data->compose_mail_icon);
1981
1982                         icon_news = stock_pixmap_widget(container, STOCK_PIXMAP_NEWS_COMPOSE);
1983                         toolbar_data->compose_news_icon = icon_news; 
1984                         g_object_ref(toolbar_data->compose_news_icon);
1985 #else
1986                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,
1987                                 _("Compose Email"));
1988                         toolbar_data->compose_mail_btn = item; 
1989                         toolbar_data->compose_mail_icon = icon_wid; 
1990
1991                         icon_news = stock_pixmap_widget(container, STOCK_PIXMAP_NEWS_COMPOSE);
1992                         toolbar_data->compose_news_icon = icon_news; 
1993 #endif
1994                         break;
1995                 case A_LEARN_SPAM:
1996                         TOOLBAR_MENUITEM(item,icon_wid,toolbar_item->text,
1997                                 _("Spam"),
1998                                 _("Learn as..."));
1999                         toolbar_data->learn_spam_btn = item; 
2000                         toolbar_data->learn_spam_icon = icon_wid; 
2001                         g_object_ref(toolbar_data->learn_spam_icon);
2002
2003                         icon_ham = stock_pixmap_widget(container, STOCK_PIXMAP_HAM_BTN);
2004                         toolbar_data->learn_ham_icon = icon_ham; 
2005                         g_object_ref(toolbar_data->learn_ham_icon);
2006
2007                         menu = gtk_menu_new();
2008                         ADD_MENU_ITEM(_("Learn as _Spam"), toolbar_learn_menu_cb, TRUE);
2009                         ADD_MENU_ITEM(_("Learn as _Ham"), toolbar_learn_menu_cb, FALSE);
2010                         gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_data->learn_spam_btn), menu);
2011                         break;
2012                 case A_REPLY_MESSAGE:
2013 #ifndef GENERIC_UMPC
2014                         TOOLBAR_MENUITEM(item,icon_wid,toolbar_item->text,
2015                                 _("Reply to Message"),
2016                                 _("Reply to Message options"));
2017                         toolbar_data->reply_btn = item;
2018
2019                         menu = gtk_menu_new();
2020                         ADD_MENU_ITEM(_("_Reply with quote"), toolbar_reply_menu_cb, COMPOSE_REPLY_WITH_QUOTE);
2021                         ADD_MENU_ITEM(_("Reply without _quote"), toolbar_reply_menu_cb, COMPOSE_REPLY_WITHOUT_QUOTE);
2022                         gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_data->reply_btn), menu);
2023 #else
2024                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,
2025                                 _("Reply to Message"));
2026                         toolbar_data->reply_btn = item;
2027 #endif
2028                         break;
2029                 case A_REPLY_SENDER:
2030 #ifndef GENERIC_UMPC
2031                         TOOLBAR_MENUITEM(item,icon_wid,toolbar_item->text,
2032                                 _("Reply to Sender"),
2033                                 _("Reply to Sender options"));
2034                         toolbar_data->replysender_btn = item;
2035
2036                         menu = gtk_menu_new();
2037                         ADD_MENU_ITEM(_("_Reply with quote"), toolbar_reply_menu_cb, COMPOSE_REPLY_TO_SENDER_WITH_QUOTE);
2038                         ADD_MENU_ITEM(_("Reply without _quote"), toolbar_reply_menu_cb, COMPOSE_REPLY_TO_SENDER_WITHOUT_QUOTE);
2039                         gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_data->replysender_btn), menu);
2040 #else
2041                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,
2042                                 _("Reply to Sender"));
2043                         toolbar_data->replysender_btn = item;
2044 #endif
2045                         break;
2046                 case A_REPLY_ALL:
2047 #ifndef GENERIC_UMPC
2048                         TOOLBAR_MENUITEM(item,icon_wid,toolbar_item->text,
2049                                 _("Reply to All"),
2050                                 _("Reply to All options"));
2051                         toolbar_data->replyall_btn = item;
2052
2053                         menu = gtk_menu_new();
2054                         ADD_MENU_ITEM(_("_Reply with quote"), toolbar_reply_menu_cb, COMPOSE_REPLY_TO_ALL_WITH_QUOTE);
2055                         ADD_MENU_ITEM(_("Reply without _quote"), toolbar_reply_menu_cb, COMPOSE_REPLY_TO_ALL_WITHOUT_QUOTE);
2056                         gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_data->replyall_btn), menu);
2057 #else
2058                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,
2059                                 _("Reply to All"));
2060                         toolbar_data->replyall_btn = item;
2061 #endif
2062                         break;
2063                 case A_REPLY_ML:
2064 #ifndef GENERIC_UMPC
2065                         TOOLBAR_MENUITEM(item,icon_wid,toolbar_item->text,
2066                                 _("Reply to Mailing-list"),
2067                                 _("Reply to Mailing-list options"));
2068                         toolbar_data->replylist_btn = item;
2069
2070                         menu = gtk_menu_new();
2071                         ADD_MENU_ITEM(_("_Reply with quote"), toolbar_reply_menu_cb, COMPOSE_REPLY_TO_LIST_WITH_QUOTE);
2072                         ADD_MENU_ITEM(_("Reply without _quote"), toolbar_reply_menu_cb, COMPOSE_REPLY_TO_LIST_WITHOUT_QUOTE);
2073                         gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_data->replylist_btn), menu);
2074 #else
2075                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,
2076                                 _("Reply to Mailing-list"));
2077                         toolbar_data->replylist_btn = item;
2078 #endif
2079                         break;
2080                 case A_FORWARD:
2081 #ifndef GENERIC_UMPC
2082                         TOOLBAR_MENUITEM(item,icon_wid,toolbar_item->text,
2083                                 _("Forward Message"),
2084                                 _("Forward Message options"));
2085                         toolbar_data->fwd_btn = item;
2086
2087                         menu = gtk_menu_new();
2088                         ADD_MENU_ITEM(_("_Forward"), toolbar_reply_menu_cb, COMPOSE_FORWARD_INLINE);
2089                         ADD_MENU_ITEM(_("For_ward as attachment"), toolbar_reply_menu_cb, COMPOSE_FORWARD_AS_ATTACH);
2090                         ADD_MENU_ITEM(_("Redirec_t"), toolbar_reply_menu_cb, COMPOSE_REDIRECT);
2091                         gtk_menu_tool_button_set_menu(GTK_MENU_TOOL_BUTTON(toolbar_data->fwd_btn), menu);
2092 #else
2093                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,
2094                                 _("Forward Message"));
2095                         toolbar_data->fwd_btn = item;
2096 #endif
2097                         break;
2098                 case A_TRASH:
2099                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Trash Message"));
2100                         toolbar_data->trash_btn = item;
2101                         break;
2102                 case A_DELETE_REAL:
2103                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Delete Message"));
2104                         toolbar_data->delete_btn = item;
2105                         break;
2106                 case A_EXECUTE:
2107                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Execute"));
2108                         toolbar_data->exec_btn = item;
2109                         break;
2110                 case A_GOTO_PREV:
2111                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Go to Previous Unread Message"));
2112                         toolbar_data->prev_btn = item;
2113                         break;
2114                 case A_GOTO_NEXT:
2115                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Go to Next Unread Message"));
2116                         toolbar_data->next_btn = item;
2117                         break;
2118                 
2119                 /* Compose Toolbar */
2120                 case A_SEND:
2121                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Send Message"));
2122                         toolbar_data->send_btn = item;
2123                         break;
2124                 case A_SENDL:
2125                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Put into queue folder and send later"));
2126                         toolbar_data->sendl_btn = item;
2127                         break;
2128                 case A_DRAFT:
2129                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Save to draft folder"));
2130                         toolbar_data->draft_btn = item; 
2131                         break;
2132                 case A_INSERT:
2133                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Insert file"));
2134                         toolbar_data->insert_btn = item; 
2135                         break;
2136                 case A_ATTACH:
2137                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Attach file"));
2138                         toolbar_data->attach_btn = item;
2139                         break;
2140                 case A_SIG:
2141                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Insert signature"));
2142                         toolbar_data->sig_btn = item;
2143                         break;
2144                 case A_EXTEDITOR:
2145                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Edit with external editor"));
2146                         toolbar_data->exteditor_btn = item;
2147                         break;
2148                 case A_LINEWRAP_CURRENT:
2149                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Wrap long lines of current paragraph"));
2150                         toolbar_data->linewrap_current_btn = item;
2151                         break;
2152                 case A_LINEWRAP_ALL:
2153                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Wrap all long lines"));
2154                         toolbar_data->linewrap_all_btn = item;
2155                         break;
2156                 case A_ADDRBOOK:
2157                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Address book"));
2158                         toolbar_data->addrbook_btn = item;
2159                         break;
2160 #ifdef USE_ENCHANT
2161                 case A_CHECK_SPELLING:
2162                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Check spelling"));
2163                         toolbar_data->spellcheck_btn = item;
2164                         break;
2165 #endif
2166
2167                 case A_CLAWS_ACTIONS:
2168                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,toolbar_item->text);
2169                         action_item = g_new0(ToolbarClawsActions, 1);
2170                         action_item->widget = item;
2171                         action_item->name   = g_strdup(toolbar_item->text);
2172
2173                         toolbar_data->action_list = 
2174                                 g_slist_append(toolbar_data->action_list,
2175                                                action_item);
2176                         break;
2177                 case A_CANCEL_INC:
2178                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Cancel receiving"));
2179                         toolbar_data->cancel_inc_btn = item;
2180                         break;
2181                 case A_CANCEL_SEND:
2182                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Cancel sending"));
2183                         toolbar_data->cancel_send_btn = item;
2184                         break;
2185                 case A_CANCEL_ALL:
2186                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,_("Cancel receiving/sending"));
2187                         toolbar_data->cancel_all_btn = item;
2188                         break;
2189                 case A_CLAWS_PLUGINS:
2190                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text, toolbar_item->text);
2191                         break;
2192                 default:
2193                         TOOLBAR_ITEM(item,icon_wid,toolbar_item->text,
2194                                 toolbar_ret_descr_from_val(toolbar_item->index));
2195                         /* find and set the tool tip text */
2196                         break;
2197                 }
2198
2199         }
2200         toolbar_data->toolbar = toolbar;
2201 #ifndef GENERIC_UMPC
2202 #if !(GTK_CHECK_VERSION(2,12,0))
2203         toolbar_data->tooltips = toolbar_tips;
2204 #endif
2205 #endif
2206         gtk_widget_show_all(toolbar);
2207
2208         if (type == TOOLBAR_MAIN) {
2209 #ifdef GENERIC_UMPC
2210                 MainWindow *mainwin = mainwindow_get_mainwindow();
2211                 GtkWidget *progressbar = gtk_progress_bar_new();
2212                 item = GTK_WIDGET(gtk_tool_item_new());
2213                 gtk_container_add (GTK_CONTAINER (item), progressbar);
2214                 gtk_widget_show(item);
2215                 gtk_widget_set_size_request(progressbar, 84, -1);
2216                 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), GTK_TOOL_ITEM(item), -1);
2217                 mainwin->progressbar = progressbar;
2218 #endif
2219                 activate_compose_button(toolbar_data, 
2220                                         prefs_common.toolbar_style, 
2221                                         toolbar_data->compose_btn_type);
2222         }
2223         if (type != TOOLBAR_COMPOSE)
2224                 activate_learn_button(toolbar_data, prefs_common.toolbar_style,
2225                                 LEARN_SPAM);
2226         
2227         gtk_container_add(GTK_CONTAINER(container), toolbar);
2228         gtk_container_set_border_width(GTK_CONTAINER(container), 0);
2229
2230         return toolbar_data; 
2231 }
2232
2233 /**
2234  * Free toolbar structures
2235  */ 
2236 void toolbar_destroy(Toolbar * toolbar) {
2237
2238         TOOLBAR_DESTROY_ITEMS(toolbar->item_list);      
2239         TOOLBAR_DESTROY_ACTIONS(toolbar->action_list);
2240 }
2241
2242 void toolbar_update(ToolbarType type, gpointer data)
2243 {
2244         Toolbar *toolbar_data;
2245         GtkWidget *handlebox;
2246         MainWindow *mainwin = (MainWindow*)data;
2247         Compose    *compose = (Compose*)data;
2248         MessageView *msgview = (MessageView*)data;
2249
2250 #ifndef GENERIC_UMPC
2251         switch(type) {
2252         case TOOLBAR_MAIN:
2253                 toolbar_data = mainwin->toolbar;
2254                 handlebox    = mainwin->handlebox;
2255                 break;
2256         case TOOLBAR_COMPOSE:
2257                 toolbar_data = compose->toolbar;
2258                 handlebox    = compose->handlebox;
2259                 break;
2260         case TOOLBAR_MSGVIEW:
2261                 toolbar_data = msgview->toolbar;
2262                 handlebox    = msgview->handlebox;
2263                 break;
2264         default:
2265                 return;
2266         }
2267
2268         gtk_container_remove(GTK_CONTAINER(handlebox), 
2269                              GTK_WIDGET(toolbar_data->toolbar));
2270
2271         toolbar_init(toolbar_data);
2272         toolbar_data = toolbar_create(type, handlebox, data);
2273 #else
2274         switch(type) {
2275         case TOOLBAR_MAIN:
2276                 toolbar_data = mainwin->toolbar;
2277                 handlebox    = mainwin->window;
2278                 break;
2279         case TOOLBAR_COMPOSE:
2280                 toolbar_data = compose->toolbar;
2281                 handlebox    = compose->window;
2282                 break;
2283         case TOOLBAR_MSGVIEW:
2284                 toolbar_data = msgview->toolbar;
2285                 handlebox    = msgview->window;
2286                 break;
2287         default:
2288                 return;
2289         }
2290         toolbar_init(toolbar_data);
2291         toolbar_data = toolbar_create(type, handlebox, data);
2292 #endif
2293
2294         switch(type) {
2295         case TOOLBAR_MAIN:
2296                 mainwin->toolbar = toolbar_data;
2297                 break;
2298         case TOOLBAR_COMPOSE:
2299                 compose->toolbar = toolbar_data;
2300                 break;
2301         case TOOLBAR_MSGVIEW:
2302                 msgview->toolbar = toolbar_data;
2303                 break;
2304         }
2305
2306         toolbar_style(type, prefs_common.toolbar_style, data);
2307
2308         if (type == TOOLBAR_MAIN) {
2309                 toolbar_main_set_sensitive((MainWindow*)data);
2310                 account_set_menu_only_toolbar();
2311         }
2312 }
2313
2314 #if !GTK_CHECK_VERSION(2,14,0)
2315 /* Work around http://bugzilla.gnome.org/show_bug.cgi?id=56070 */
2316 #define GTK_BUTTON_SET_SENSITIVE(widget,sensitive) {            \
2317         gboolean in_btn1 = FALSE, in_btn2 = FALSE;              \
2318         if (GTK_IS_BUTTON(widget))                              \
2319                 in_btn1 = GTK_BUTTON(widget)->in_button;        \
2320         else if (GTK_IS_MENU_TOOL_BUTTON(widget)) {             \
2321                 GtkWidget *child = gtk_bin_get_child(           \
2322                         GTK_BIN(widget));                       \
2323                 GList *gchild = gtk_container_get_children(     \
2324                         GTK_CONTAINER(child));                  \
2325                 GtkWidget *btn = (GtkWidget *)gchild->data;     \
2326                 GtkWidget *arr = (GtkWidget *)                  \
2327                         (gchild->next?gchild->next->data:NULL); \
2328                 g_list_free(gchild);                            \
2329                 if (GTK_IS_BUTTON(btn))                         \
2330                         in_btn1 = GTK_BUTTON(btn)->in_button;   \
2331                 if (GTK_IS_BUTTON(arr))                         \
2332                         in_btn2 = GTK_BUTTON(arr)->in_button;   \
2333         }                                                       \
2334         else if (GTK_IS_TOOL_ITEM(widget)) {                    \
2335                 GtkWidget *child = gtk_bin_get_child(           \
2336                         GTK_BIN(widget));                       \
2337                 if (GTK_IS_BUTTON(child))                       \
2338                         in_btn1 = GTK_BUTTON(child)->in_button; \
2339         }                                                       \
2340         gtk_widget_set_sensitive(widget, sensitive);            \
2341         if (GTK_IS_BUTTON(widget))                              \
2342                 GTK_BUTTON(widget)->in_button = in_btn1;        \
2343         else if (GTK_IS_MENU_TOOL_BUTTON(widget)) {             \
2344                 GtkWidget *child = gtk_bin_get_child(           \
2345                         GTK_BIN(widget));                       \
2346                 GList *gchild = gtk_container_get_children(     \
2347                         GTK_CONTAINER(child));                  \
2348                 GtkWidget *btn = (GtkWidget *)gchild->data;     \
2349                 GtkWidget *arr = (GtkWidget *)                  \
2350                         (gchild->next?gchild->next->data:NULL); \
2351                 g_list_free(gchild);                            \
2352                 if (GTK_IS_BUTTON(btn))                         \
2353                         GTK_BUTTON(btn)->in_button = in_btn1;   \
2354                 if (GTK_IS_BUTTON(arr))                         \
2355                         GTK_BUTTON(arr)->in_button = in_btn2;   \
2356         }                                                       \
2357         else if (GTK_IS_TOOL_ITEM(widget)) {                    \
2358                 GtkWidget *child = gtk_bin_get_child(           \
2359                         GTK_BIN(widget));                       \
2360                 if (GTK_IS_BUTTON(child))                       \
2361                         GTK_BUTTON(child)->in_button = in_btn1; \
2362         }                                                       \
2363 }
2364 #else
2365 #define GTK_BUTTON_SET_SENSITIVE(widget,sensitive) {            \
2366         gtk_widget_set_sensitive(widget, sensitive);            \
2367 }
2368 #endif
2369
2370 void toolbar_main_set_sensitive(gpointer data)
2371 {
2372         SensitiveCondMask state;
2373         gboolean sensitive;
2374         MainWindow *mainwin = (MainWindow*)data;
2375         Toolbar *toolbar = mainwin->toolbar;
2376         GSList *cur;
2377         GSList *entry_list = NULL;
2378         
2379         typedef struct _Entry Entry;
2380         struct _Entry {
2381                 GtkWidget *widget;
2382                 SensitiveCondMask cond;
2383                 gboolean empty;
2384         };
2385
2386 #define SET_WIDGET_COND(w, ...)     \
2387 do { \
2388         Entry *e = g_new0(Entry, 1); \
2389         e->widget = w; \
2390         e->cond = main_window_get_mask(__VA_ARGS__, -1); \
2391         entry_list = g_slist_append(entry_list, e); \
2392 } while (0)
2393         
2394         /* match all bit flags */
2395
2396         if (toolbar->get_btn)
2397                 SET_WIDGET_COND(toolbar->get_btn, 
2398                         M_HAVE_ACCOUNT, M_UNLOCKED, M_HAVE_RETRIEVABLE_ACCOUNT);
2399
2400         if (toolbar->getall_btn) {
2401                 SET_WIDGET_COND(toolbar->getall_btn, 
2402                         M_HAVE_ACCOUNT, M_UNLOCKED, M_HAVE_ANY_RETRIEVABLE_ACCOUNT);
2403         }
2404         if (toolbar->send_btn) {
2405                 SET_WIDGET_COND(toolbar->send_btn,
2406                         M_HAVE_QUEUED_MAILS);
2407         }
2408         if (toolbar->compose_mail_btn) {
2409                 SET_WIDGET_COND(toolbar->compose_mail_btn, 
2410                         M_HAVE_ACCOUNT);
2411         }
2412         if (toolbar->close_window_btn) {
2413                 SET_WIDGET_COND(toolbar->close_window_btn, 
2414                         M_UNLOCKED);
2415         }
2416         if (toolbar->open_mail_btn) {
2417                 SET_WIDGET_COND(toolbar->open_mail_btn, 
2418                         M_TARGET_EXIST, M_SUMMARY_ISLIST);
2419         }
2420         if (toolbar->reply_btn) {
2421                 SET_WIDGET_COND(toolbar->reply_btn,
2422                         M_HAVE_ACCOUNT, M_TARGET_EXIST, M_SUMMARY_ISLIST);
2423         }
2424         if (toolbar->replyall_btn) {
2425                 SET_WIDGET_COND(toolbar->replyall_btn,
2426                         M_HAVE_ACCOUNT, M_TARGET_EXIST, M_SUMMARY_ISLIST);
2427         }
2428         if (toolbar->replylist_btn) {
2429                 SET_WIDGET_COND(toolbar->replylist_btn,
2430                         M_HAVE_ACCOUNT, M_TARGET_EXIST, M_SUMMARY_ISLIST);
2431         }
2432         if (toolbar->replysender_btn) {
2433                 SET_WIDGET_COND(toolbar->replysender_btn,
2434                         M_HAVE_ACCOUNT, M_TARGET_EXIST, M_SUMMARY_ISLIST);
2435         }
2436         if (toolbar->fwd_btn) {
2437                 SET_WIDGET_COND(toolbar->fwd_btn, 
2438                         M_HAVE_ACCOUNT, M_TARGET_EXIST, M_SUMMARY_ISLIST);
2439         }
2440
2441         if (prefs_common.next_unread_msg_dialog == NEXTUNREADMSGDIALOG_ASSUME_NO) {
2442                 SET_WIDGET_COND(toolbar->next_btn, M_MSG_EXIST, M_SUMMARY_ISLIST);
2443         } else {
2444                 SET_WIDGET_COND(toolbar->next_btn, -1);
2445         }
2446         
2447         if (toolbar->trash_btn)
2448                 SET_WIDGET_COND(toolbar->trash_btn,
2449                         M_TARGET_EXIST, M_ALLOW_DELETE, M_NOT_NEWS);
2450
2451         if (toolbar->delete_btn)
2452                 SET_WIDGET_COND(toolbar->delete_btn,
2453                         M_TARGET_EXIST, M_ALLOW_DELETE);
2454
2455         if (toolbar->exec_btn)
2456                 SET_WIDGET_COND(toolbar->exec_btn, 
2457                         M_DELAY_EXEC);
2458         
2459         if (toolbar->learn_spam_btn)
2460                 SET_WIDGET_COND(toolbar->learn_spam_btn, 
2461                         M_TARGET_EXIST, M_CAN_LEARN_SPAM, M_SUMMARY_ISLIST);
2462
2463         if (toolbar->cancel_inc_btn)
2464                 SET_WIDGET_COND(toolbar->cancel_inc_btn,
2465                                 M_INC_ACTIVE);
2466
2467         if (toolbar->cancel_send_btn)
2468                 SET_WIDGET_COND(toolbar->cancel_send_btn,
2469                                 M_SEND_ACTIVE);
2470
2471         for (cur = toolbar->action_list; cur != NULL;  cur = cur->next) {
2472                 ToolbarClawsActions *act = (ToolbarClawsActions*)cur->data;
2473                 
2474                 SET_WIDGET_COND(act->widget, M_TARGET_EXIST, M_UNLOCKED);
2475         }
2476
2477         state = main_window_get_current_state(mainwin);
2478
2479         for (cur = entry_list; cur != NULL; cur = cur->next) {
2480                 Entry *e = (Entry*) cur->data;
2481
2482                 if (e->widget != NULL) {
2483                         sensitive = ((e->cond & state) == e->cond);
2484                         GTK_BUTTON_SET_SENSITIVE(e->widget, sensitive); 
2485                 }
2486         }
2487         
2488         while (entry_list != NULL) {
2489                 Entry *e = (Entry*) entry_list->data;
2490
2491                 g_free(e);
2492                 entry_list = g_slist_remove(entry_list, e);
2493         }
2494
2495         /* match any bit flags */
2496
2497         if (toolbar->cancel_all_btn)
2498                 SET_WIDGET_COND(toolbar->cancel_all_btn,
2499                                 M_INC_ACTIVE, M_SEND_ACTIVE);
2500
2501         for (cur = entry_list; cur != NULL; cur = cur->next) {
2502                 Entry *e = (Entry*) cur->data;
2503
2504                 if (e->widget != NULL) {
2505                         sensitive = ((e->cond & state) != 0);
2506                         GTK_BUTTON_SET_SENSITIVE(e->widget, sensitive); 
2507                 }
2508         }
2509
2510         while (entry_list != NULL) {
2511                 Entry *e = (Entry*) entry_list->data;
2512
2513                 g_free(e);
2514                 entry_list = g_slist_remove(entry_list, e);
2515         }
2516
2517         g_slist_free(entry_list);
2518
2519         activate_compose_button(toolbar, 
2520                                 prefs_common.toolbar_style,
2521                                 toolbar->compose_btn_type);
2522         
2523 #undef SET_WIDGET_COND
2524 }
2525
2526 void toolbar_comp_set_sensitive(gpointer data, gboolean sensitive)
2527 {
2528         Compose *compose = (Compose*)data;
2529         GSList *items = compose->toolbar->action_list;
2530
2531         if (compose->toolbar->send_btn)
2532                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->send_btn, sensitive);
2533         if (compose->toolbar->sendl_btn)
2534                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->sendl_btn, sensitive);
2535         if (compose->toolbar->draft_btn )
2536                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->draft_btn , sensitive);
2537         if (compose->toolbar->insert_btn )
2538                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->insert_btn , sensitive);
2539         if (compose->toolbar->attach_btn)
2540                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->attach_btn, sensitive);
2541         if (compose->toolbar->sig_btn)
2542                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->sig_btn, sensitive);
2543         if (compose->toolbar->exteditor_btn)
2544                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->exteditor_btn, sensitive);
2545         if (compose->toolbar->linewrap_current_btn)
2546                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->linewrap_current_btn, sensitive);
2547         if (compose->toolbar->linewrap_all_btn)
2548                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->linewrap_all_btn, sensitive);
2549         if (compose->toolbar->addrbook_btn)
2550                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->addrbook_btn, sensitive);
2551 #ifdef USE_ENCHANT
2552         if (compose->toolbar->spellcheck_btn)
2553                 GTK_BUTTON_SET_SENSITIVE(compose->toolbar->spellcheck_btn, sensitive);
2554 #endif
2555         for (; items != NULL; items = g_slist_next(items)) {
2556                 ToolbarClawsActions *item = (ToolbarClawsActions *)items->data;
2557                 GTK_BUTTON_SET_SENSITIVE(item->widget, sensitive);
2558         }
2559 }
2560
2561 /**
2562  * Initialize toolbar structure
2563  **/
2564 static void toolbar_init(Toolbar * toolbar)
2565 {
2566
2567         toolbar->toolbar           = NULL;
2568         toolbar->folders_btn       = NULL;
2569         toolbar->get_btn           = NULL;
2570         toolbar->getall_btn        = NULL;
2571         toolbar->send_btn          = NULL;
2572         toolbar->compose_mail_btn  = NULL;
2573         toolbar->compose_mail_icon = NULL;
2574         toolbar->compose_news_icon = NULL;
2575         toolbar->reply_btn         = NULL;
2576         toolbar->replysender_btn   = NULL;
2577         toolbar->replyall_btn      = NULL;
2578         toolbar->replylist_btn     = NULL;
2579         toolbar->fwd_btn           = NULL;
2580         toolbar->trash_btn         = NULL;
2581         toolbar->delete_btn        = NULL;
2582         toolbar->prev_btn          = NULL;
2583         toolbar->next_btn          = NULL;
2584         toolbar->exec_btn          = NULL;
2585         toolbar->separator         = NULL;
2586         toolbar->learn_spam_btn    = NULL;
2587         toolbar->learn_spam_icon   = NULL;
2588         toolbar->learn_ham_icon    = NULL;
2589         toolbar->cancel_inc_btn    = NULL;
2590         toolbar->cancel_send_btn   = NULL;
2591         toolbar->cancel_all_btn    = NULL;
2592
2593         /* compose buttons */ 
2594         toolbar->sendl_btn         = NULL;
2595         toolbar->draft_btn         = NULL;
2596         toolbar->insert_btn        = NULL;
2597         toolbar->attach_btn        = NULL;
2598         toolbar->sig_btn           = NULL; 
2599         toolbar->exteditor_btn     = NULL; 
2600         toolbar->linewrap_current_btn = NULL;   
2601         toolbar->linewrap_all_btn  = NULL;      
2602         toolbar->addrbook_btn      = NULL; 
2603
2604         toolbar->open_mail_btn     = NULL;
2605         toolbar->close_window_btn  = NULL;
2606         toolbar->preferences_btn   = NULL;
2607         toolbar->action_list       = NULL;
2608         toolbar->item_list         = NULL;
2609 #ifdef USE_ENCHANT
2610         toolbar->spellcheck_btn    = NULL;
2611 #endif
2612 #if !GTK_CHECK_VERSION(2,12,0)
2613         toolbar->tooltips          = NULL;
2614 #endif
2615
2616         toolbar_destroy(toolbar);
2617 }
2618
2619 /*
2620  */
2621 static void toolbar_reply(gpointer data, guint action)
2622 {
2623         ToolbarItem *toolbar_item = (ToolbarItem*)data;
2624         MainWindow *mainwin;
2625         MessageView *msgview;
2626         GSList *msginfo_list = NULL;
2627
2628         cm_return_if_fail(toolbar_item != NULL);
2629
2630         switch (toolbar_item->type) {
2631         case TOOLBAR_MAIN:
2632                 mainwin = (MainWindow*)toolbar_item->parent;
2633                 msginfo_list = summary_get_selection(mainwin->summaryview);
2634                 msgview = (MessageView*)mainwin->messageview;
2635                 break;
2636         case TOOLBAR_MSGVIEW:
2637                 msgview = (MessageView*)toolbar_item->parent;
2638                 cm_return_if_fail(msgview != NULL);     
2639                 msginfo_list = g_slist_append(msginfo_list, msgview->msginfo);
2640                 break;
2641         default:
2642                 return;
2643         }
2644
2645         cm_return_if_fail(msgview != NULL);
2646         cm_return_if_fail(msginfo_list != NULL);
2647         compose_reply_from_messageview(msgview, msginfo_list, action);
2648         g_slist_free(msginfo_list);
2649
2650         /* TODO: update reply state ion summaryview */
2651 }
2652
2653
2654 /* exported functions */
2655
2656 void inc_mail_cb(gpointer data, guint action, GtkWidget *widget)
2657 {
2658         MainWindow *mainwin = (MainWindow*)data;
2659
2660         inc_mail(mainwin, prefs_common.newmail_notify_manu);
2661 }
2662
2663 void inc_all_account_mail_cb(gpointer data, guint action, GtkWidget *widget)
2664 {
2665         MainWindow *mainwin = (MainWindow*)data;
2666
2667         inc_all_account_mail(mainwin, FALSE, prefs_common.newmail_notify_manu);
2668 }
2669
2670 void send_queue_cb(gpointer data, guint action, GtkWidget *widget)
2671 {
2672         GList *list;
2673         gboolean found;
2674         gboolean got_error = FALSE;
2675         gchar *errstr = NULL;
2676
2677         if (prefs_common.work_offline)
2678                 if (alertpanel(_("Offline warning"), 
2679                                _("You're working offline. Override?"),
2680                                GTK_STOCK_NO, GTK_STOCK_YES,
2681                                NULL) != G_ALERTALTERNATE)
2682                 return;
2683
2684         /* ask for confirmation before sending queued messages only
2685            in online mode and if there is at least one message queued
2686            in any of the folder queue
2687         */
2688         if (prefs_common.confirm_send_queued_messages) {
2689                 found = FALSE;
2690                 /* check if there's a queued message */
2691                 for (list = folder_get_list(); !found && list != NULL; list = list->next) {
2692                         Folder *folder = list->data;
2693
2694                         found = !procmsg_queue_is_empty(folder->queue);
2695                 }
2696                 /* if necessary, ask for confirmation before sending */
2697                 if (found && !prefs_common.work_offline) {
2698                         if (alertpanel(_("Send queued messages"), 
2699                                    _("Send all queued messages?"),
2700                                    GTK_STOCK_CANCEL, _("_Send"),
2701                                    NULL) != G_ALERTALTERNATE)
2702                                 return;
2703                 }
2704         }
2705
2706         for (list = folder_get_list(); list != NULL; list = list->next) {
2707                 Folder *folder = list->data;
2708
2709                 if (folder->queue) {
2710                         if (procmsg_send_queue(folder->queue, 
2711                                                prefs_common.savemsg,
2712                                                &errstr) < 0)
2713                                 got_error = TRUE;
2714                 }
2715         }
2716         if (got_error) {
2717                 if (!errstr)
2718                         alertpanel_error_log(_("Some errors occurred while "
2719                                            "sending queued messages."));
2720                 else {
2721                         alertpanel_error_log(_("Some errors occurred "
2722                                         "while sending queued messages:\n%s"), errstr);
2723                         g_free(errstr);
2724                 }
2725         }
2726 }
2727
2728 void compose_mail_cb(gpointer data, guint action, GtkWidget *widget)
2729 {
2730         MainWindow *mainwin = (MainWindow*)data;
2731         PrefsAccount *ac = NULL;
2732         FolderItem *item = mainwin->summaryview->folder_item;   
2733         GList * list;
2734         GList * cur;
2735         
2736         if (item) {
2737                 ac = account_find_from_item(item);
2738                 if (ac && ac->protocol != A_NNTP) {
2739                         compose_new_with_folderitem(ac, item, NULL);            /* CLAWS */
2740                         return;
2741                 }
2742         }
2743
2744         /*
2745          * CLAWS - use current account
2746          */
2747         if (cur_account && (cur_account->protocol != A_NNTP)) {
2748                 compose_new_with_folderitem(cur_account, item, NULL);
2749                 return;
2750         }
2751
2752         /*
2753          * CLAWS - just get the first one
2754          */
2755         list = account_get_list();
2756         for (cur = list ; cur != NULL ; cur = g_list_next(cur)) {
2757                 ac = (PrefsAccount *) cur->data;
2758                 if (ac->protocol != A_NNTP) {
2759                         compose_new_with_folderitem(ac, item, NULL);
2760                         return;
2761                 }
2762         }
2763 }
2764
2765 void compose_news_cb(gpointer data, guint action, GtkWidget *widget)
2766 {
2767         MainWindow *mainwin = (MainWindow*)data;
2768         PrefsAccount * ac = NULL;
2769         GList * list;
2770         GList * cur;
2771
2772         if (mainwin->summaryview->folder_item) {
2773                 ac = mainwin->summaryview->folder_item->folder->account;
2774                 if (ac && ac->protocol == A_NNTP) {
2775                         compose_new_with_folderitem(ac,
2776                                     mainwin->summaryview->folder_item, NULL);
2777                         return;
2778                 }
2779         }
2780
2781         list = account_get_list();
2782         for(cur = list ; cur != NULL ; cur = g_list_next(cur)) {
2783                 ac = (PrefsAccount *) cur->data;
2784                 if (ac->protocol == A_NNTP) {
2785                         compose_new_with_folderitem(ac,
2786                                     mainwin->summaryview->folder_item, NULL);
2787                         return;
2788                 }
2789         }
2790 }