2007-05-03 [wwp] 2.9.1cvs41
authorTristan Chabredier <wwp@claws-mail.org>
Thu, 3 May 2007 12:44:01 +0000 (12:44 +0000)
committerTristan Chabredier <wwp@claws-mail.org>
Thu, 3 May 2007 12:44:01 +0000 (12:44 +0000)
* src/prefs_common.c
* src/prefs_filtering.c
* src/prefs_template.c
* src/common/template.c
* src/common/template.h
* src/gtk/gtkutils.c
* src/gtk/gtkutils.h
Templates are no longer automatically sorted
by name, but can be sorted manually using
|< < > >| buttons as well as drag'n'drop.

ChangeLog
PATCHSETS
configure.ac
src/common/template.c
src/common/template.h
src/gtk/gtkutils.c
src/gtk/gtkutils.h
src/prefs_common.c
src/prefs_filtering.c
src/prefs_template.c

index 8c425cb..f47d747 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2007-05-03 [wwp]       2.9.1cvs41
+
+       * src/prefs_common.c
+       * src/prefs_filtering.c
+       * src/prefs_template.c
+       * src/common/template.c
+       * src/common/template.h
+       * src/gtk/gtkutils.c
+       * src/gtk/gtkutils.h
+               Templates are no longer automatically sorted
+               by name, but can be sorted manually using
+               |< < > >| buttons as well as drag'n'drop.
+
 2007-05-03 [wwp]       2.9.1cvs40
 
        * src/plugins/spamassassin/spamassassin.c
 2007-05-03 [wwp]       2.9.1cvs40
 
        * src/plugins/spamassassin/spamassassin.c
index 1aa853e..0b4608c 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.96.2.171 -r 1.96.2.172 src/textview.c;  ) > 2.9.1cvs38.patchset
 ( cvs diff -u -r 1.149.2.72 -r 1.149.2.73 src/inc.c;  ) > 2.9.1cvs39.patchset
 ( cvs diff -u -r 1.18.2.51 -r 1.18.2.52 src/plugins/spamassassin/spamassassin.c;  cvs diff -u -r 1.4.2.14 -r 1.4.2.15 src/plugins/spamassassin/spamassassin.h;  cvs diff -u -r 1.23.2.37 -r 1.23.2.38 src/plugins/spamassassin/spamassassin_gtk.c;  cvs diff -u -r 1.1.2.29 -r 1.1.2.30 src/plugins/bogofilter/bogofilter.c;  cvs diff -u -r 1.1.2.11 -r 1.1.2.12 src/plugins/bogofilter/bogofilter.h;  cvs diff -u -r 1.1.2.23 -r 1.1.2.24 src/plugins/bogofilter/bogofilter_gtk.c;  ) > 2.9.1cvs40.patchset
 ( cvs diff -u -r 1.96.2.171 -r 1.96.2.172 src/textview.c;  ) > 2.9.1cvs38.patchset
 ( cvs diff -u -r 1.149.2.72 -r 1.149.2.73 src/inc.c;  ) > 2.9.1cvs39.patchset
 ( cvs diff -u -r 1.18.2.51 -r 1.18.2.52 src/plugins/spamassassin/spamassassin.c;  cvs diff -u -r 1.4.2.14 -r 1.4.2.15 src/plugins/spamassassin/spamassassin.h;  cvs diff -u -r 1.23.2.37 -r 1.23.2.38 src/plugins/spamassassin/spamassassin_gtk.c;  cvs diff -u -r 1.1.2.29 -r 1.1.2.30 src/plugins/bogofilter/bogofilter.c;  cvs diff -u -r 1.1.2.11 -r 1.1.2.12 src/plugins/bogofilter/bogofilter.h;  cvs diff -u -r 1.1.2.23 -r 1.1.2.24 src/plugins/bogofilter/bogofilter_gtk.c;  ) > 2.9.1cvs40.patchset
+( cvs diff -u -r 1.204.2.132 -r 1.204.2.133 src/prefs_common.c;  cvs diff -u -r 1.59.2.55 -r 1.59.2.56 src/prefs_filtering.c;  cvs diff -u -r 1.12.2.40 -r 1.12.2.41 src/prefs_template.c;  cvs diff -u -r 1.2.4.18 -r 1.2.4.19 src/common/template.c;  cvs diff -u -r 1.1.4.4 -r 1.1.4.5 src/common/template.h;  cvs diff -u -r 1.5.2.57 -r 1.5.2.58 src/gtk/gtkutils.c;  cvs diff -u -r 1.4.2.34 -r 1.4.2.35 src/gtk/gtkutils.h;  ) > 2.9.1cvs41.patchset
index 1a82bc5..fb3188e 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=9
 MICRO_VERSION=1
 INTERFACE_AGE=0
 BINARY_AGE=0
 MICRO_VERSION=1
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=40
+EXTRA_VERSION=41
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index 2594458..225c1d8 100644 (file)
@@ -45,6 +45,7 @@ static Template *template_load(gchar *filename)
        }
 
        tmpl = g_new(Template, 1);
        }
 
        tmpl = g_new(Template, 1);
+       tmpl->load_filename = g_strdup(filename);;
        tmpl->name = NULL;
        tmpl->subject = NULL;
        tmpl->to = NULL;
        tmpl->name = NULL;
        tmpl->subject = NULL;
        tmpl->to = NULL;
@@ -88,6 +89,7 @@ static Template *template_load(gchar *filename)
 
 void template_free(Template *tmpl)
 {
 
 void template_free(Template *tmpl)
 {
+       g_free(tmpl->load_filename);
        g_free(tmpl->name);
        g_free(tmpl->subject);
        g_free(tmpl->to);
        g_free(tmpl->name);
        g_free(tmpl->subject);
        g_free(tmpl->to);
@@ -111,14 +113,33 @@ void template_clear_config(GSList *tmpl_list)
 
 static gint tmpl_compare(gconstpointer tmpl1, gconstpointer tmpl2)
 {
 
 static gint tmpl_compare(gconstpointer tmpl1, gconstpointer tmpl2)
 {
+       gchar *basename1, *basename2;
+       long filenum1, filenum2;
+       gint ret = 0;
+
        if ((Template *)tmpl1 == NULL || (Template *)tmpl2 == NULL)
                return 0;
 
        if ((Template *)tmpl1 == NULL || (Template *)tmpl2 == NULL)
                return 0;
 
-       if (((Template *)tmpl1)->name == NULL || ((Template *)tmpl2)->name == NULL)
+       if (((Template *)tmpl1)->load_filename == NULL || ((Template *)tmpl2)->load_filename == NULL)
+               return 0;
+
+       basename1 = g_path_get_basename(((Template *)tmpl1)->load_filename);
+       basename2 = g_path_get_basename(((Template *)tmpl2)->load_filename);
+       filenum1 = atol(basename1);
+       filenum2 = atol(basename2);
+       g_free(basename1);
+       g_free(basename2);
+
+       if (filenum1 == 0 || filenum2 == 0)
                return 0;
 
                return 0;
 
-       return (gint) strcmp((char *)((Template *)tmpl1)->name, 
-                            (char *)((Template *)tmpl2)->name);
+       if (filenum1 < filenum2)
+               ret = -1;
+       else
+               if (filenum1 > filenum2)
+                       ret = 1;
+                       
+       return ret;
 }
 
 GSList *template_read_config(void)
 }
 
 GSList *template_read_config(void)
index ba19a61..618e1e4 100644 (file)
@@ -26,6 +26,7 @@
 typedef struct _Template       Template;
 
 struct _Template {
 typedef struct _Template       Template;
 
 struct _Template {
+       gchar *load_filename;
        gchar *name;
        gchar *subject;
        gchar *to;
        gchar *name;
        gchar *subject;
        gchar *to;
index 1af30db..600904a 100644 (file)
@@ -1630,3 +1630,74 @@ GtkWidget *gtkut_window_new              (GtkWindowType   type,
        return window;
 }
 #endif
        return window;
 }
 #endif
+
+gboolean gtkut_tree_iter_comp(GtkTreeModel *model, 
+                                    GtkTreeIter *iter1, 
+                                    GtkTreeIter *iter2)
+{
+       GtkTreePath *path1 = gtk_tree_model_get_path(model, iter1);
+       GtkTreePath *path2 = gtk_tree_model_get_path(model, iter2);
+       gboolean result;
+
+       result = gtk_tree_path_compare(path1, path2) == 0;
+
+       gtk_tree_path_free(path1);
+       gtk_tree_path_free(path2);
+       
+       return result;
+}
+
+/*!
+ *\brief       Get selected row number.
+ */
+gint gtkut_list_view_get_selected_row(GtkWidget *list_view)
+{
+       GtkTreeView *view = GTK_TREE_VIEW(list_view);
+       GtkTreeModel *model = gtk_tree_view_get_model(view);
+       int n_rows = gtk_tree_model_iter_n_children(model, NULL);
+       GtkTreeSelection *selection;
+       GtkTreeIter iter;
+       int row;
+
+       if (n_rows == 0) 
+               return -1;
+       
+       selection = gtk_tree_view_get_selection(view);
+       if (!gtk_tree_selection_get_selected(selection, &model, &iter))
+               return -1;
+       
+       /* get all iterators and compare them... */
+       for (row = 0; row < n_rows; row++) {
+               GtkTreeIter itern;
+
+               gtk_tree_model_iter_nth_child(model, &itern, NULL, row);
+               if (gtkut_tree_iter_comp(model, &iter, &itern))
+                       return row;
+       }
+       
+       return -1;
+}
+
+/*!
+ *\brief       Select a row by its number.
+ */
+gboolean gtkut_list_view_select_row(GtkWidget *list, gint row)
+{
+       GtkTreeView *list_view = GTK_TREE_VIEW(list);
+       GtkTreeSelection *selection = gtk_tree_view_get_selection(list_view);
+       GtkTreeModel *model = gtk_tree_view_get_model(list_view);
+       GtkTreeIter iter;
+       GtkTreePath *path;
+
+       if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row))
+               return FALSE;
+       
+       gtk_tree_selection_select_iter(selection, &iter);
+
+       path = gtk_tree_model_get_path(model, &iter);
+       gtk_tree_view_set_cursor(list_view, path, NULL, FALSE);
+       gtk_tree_path_free(path);
+       
+       return TRUE;
+}
+
index 255ef7a..52cff00 100644 (file)
@@ -247,4 +247,11 @@ gboolean gtkut_tree_model_text_iter_prev(GtkTreeModel *model,
 gboolean gtkut_tree_model_get_iter_last(GtkTreeModel *model,
                                 GtkTreeIter *iter);
 
 gboolean gtkut_tree_model_get_iter_last(GtkTreeModel *model,
                                 GtkTreeIter *iter);
 
+gboolean gtkut_tree_iter_comp(GtkTreeModel *model, 
+                                    GtkTreeIter *iter1, 
+                                    GtkTreeIter *iter2);
+
+gint gtkut_list_view_get_selected_row(GtkWidget *list_view);
+gboolean gtkut_list_view_select_row(GtkWidget *list, gint row);
+
 #endif /* __GTKUTILS_H__ */
 #endif /* __GTKUTILS_H__ */
index 79b6ff9..3b86b94 100644 (file)
@@ -846,7 +846,7 @@ static PrefParam param[] = {
        {"matcherwin_height", "-1", &prefs_common.matcherwin_height, P_INT,
         NULL, NULL, NULL},
 
        {"matcherwin_height", "-1", &prefs_common.matcherwin_height, P_INT,
         NULL, NULL, NULL},
 
-       {"templateswin_width", "440", &prefs_common.templateswin_width, P_INT,
+       {"templateswin_width", "480", &prefs_common.templateswin_width, P_INT,
         NULL, NULL, NULL},
        {"templateswin_height", "-1", &prefs_common.templateswin_height, P_INT,
         NULL, NULL, NULL},
         NULL, NULL, NULL},
        {"templateswin_height", "-1", &prefs_common.templateswin_height, P_INT,
         NULL, NULL, NULL},
index ad594b6..2ad626b 100644 (file)
@@ -142,8 +142,6 @@ static void prefs_filtering_list_view_get_rule_info (GtkWidget *list,
 
 static GtkWidget *prefs_filtering_list_view_create     (void);
 static void prefs_filtering_create_list_view_columns   (GtkWidget *list_view);
 
 static GtkWidget *prefs_filtering_list_view_create     (void);
 static void prefs_filtering_create_list_view_columns   (GtkWidget *list_view);
-static gint prefs_filtering_get_selected_row           (GtkWidget *list_view);
-static gboolean prefs_filtering_list_view_select_row   (GtkWidget *list, gint row);
 
 static gboolean prefs_filtering_selected               (GtkTreeSelection *selector,
                                                         GtkTreeModel *model, 
 
 static gboolean prefs_filtering_selected               (GtkTreeSelection *selector,
                                                         GtkTreeModel *model, 
@@ -1047,7 +1045,7 @@ static void prefs_filtering_register_cb(void)
 
 static void prefs_filtering_substitute_cb(void)
 {
 
 static void prefs_filtering_substitute_cb(void)
 {
-       gint selected_row = prefs_filtering_get_selected_row
+       gint selected_row = gtkut_list_view_get_selected_row
                (filtering.cond_list_view);
        FilteringProp *prop;
        gboolean enabled;
                (filtering.cond_list_view);
        FilteringProp *prop;
        gboolean enabled;
@@ -1083,7 +1081,7 @@ static void prefs_filtering_delete_cb(void)
        GtkTreeIter iter;
        gint row;
        
        GtkTreeIter iter;
        gint row;
        
-       row = prefs_filtering_get_selected_row(filtering.cond_list_view);
+       row = gtkut_list_view_get_selected_row(filtering.cond_list_view);
        if (row <= 0) 
                return; 
 
        if (row <= 0) 
                return; 
 
@@ -1107,7 +1105,7 @@ static void prefs_filtering_top(void)
        GtkTreeIter top, sel;
        GtkTreeModel *model;
 
        GtkTreeIter top, sel;
        GtkTreeModel *model;
 
-       row = prefs_filtering_get_selected_row(filtering.cond_list_view);
+       row = gtkut_list_view_get_selected_row(filtering.cond_list_view);
        if (row <= 1) 
                return;
 
        if (row <= 1) 
                return;
 
@@ -1118,7 +1116,7 @@ static void prefs_filtering_top(void)
                return;
 
        gtk_list_store_move_after(GTK_LIST_STORE(model), &sel, &top);
                return;
 
        gtk_list_store_move_after(GTK_LIST_STORE(model), &sel, &top);
-       prefs_filtering_list_view_select_row(filtering.cond_list_view, 1);
+       gtkut_list_view_select_row(filtering.cond_list_view, 1);
 }
 
 static void prefs_filtering_up(void)
 }
 
 static void prefs_filtering_up(void)
@@ -1127,7 +1125,7 @@ static void prefs_filtering_up(void)
        GtkTreeIter top, sel;
        GtkTreeModel *model;
 
        GtkTreeIter top, sel;
        GtkTreeModel *model;
 
-       row = prefs_filtering_get_selected_row(filtering.cond_list_view);
+       row = gtkut_list_view_get_selected_row(filtering.cond_list_view);
        if (row <= 1) 
                return;
                
        if (row <= 1) 
                return;
                
@@ -1138,7 +1136,7 @@ static void prefs_filtering_up(void)
                return;
 
        gtk_list_store_swap(GTK_LIST_STORE(model), &top, &sel);
                return;
 
        gtk_list_store_swap(GTK_LIST_STORE(model), &top, &sel);
-       prefs_filtering_list_view_select_row(filtering.cond_list_view, row - 1);
+       gtkut_list_view_select_row(filtering.cond_list_view, row - 1);
 }
 
 static void prefs_filtering_down(void)
 }
 
 static void prefs_filtering_down(void)
@@ -1149,7 +1147,7 @@ static void prefs_filtering_down(void)
 
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(filtering.cond_list_view));       
        n_rows = gtk_tree_model_iter_n_children(model, NULL);
 
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(filtering.cond_list_view));       
        n_rows = gtk_tree_model_iter_n_children(model, NULL);
-       row = prefs_filtering_get_selected_row(filtering.cond_list_view);
+       row = gtkut_list_view_get_selected_row(filtering.cond_list_view);
        if (row < 1 || row >= n_rows - 1)
                return;
 
        if (row < 1 || row >= n_rows - 1)
                return;
 
@@ -1158,7 +1156,7 @@ static void prefs_filtering_down(void)
                return;
                        
        gtk_list_store_swap(GTK_LIST_STORE(model), &top, &sel);
                return;
                        
        gtk_list_store_swap(GTK_LIST_STORE(model), &top, &sel);
-       prefs_filtering_list_view_select_row(filtering.cond_list_view, row + 1);
+       gtkut_list_view_select_row(filtering.cond_list_view, row + 1);
 }
 
 static void prefs_filtering_bottom(void)
 }
 
 static void prefs_filtering_bottom(void)
@@ -1169,7 +1167,7 @@ static void prefs_filtering_bottom(void)
 
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(filtering.cond_list_view));       
        n_rows = gtk_tree_model_iter_n_children(model, NULL);
 
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(filtering.cond_list_view));       
        n_rows = gtk_tree_model_iter_n_children(model, NULL);
-       row = prefs_filtering_get_selected_row(filtering.cond_list_view);
+       row = gtkut_list_view_get_selected_row(filtering.cond_list_view);
        if (row < 1 || row >= n_rows - 1)
                return;
 
        if (row < 1 || row >= n_rows - 1)
                return;
 
@@ -1178,7 +1176,7 @@ static void prefs_filtering_bottom(void)
                return;
 
        gtk_list_store_move_after(GTK_LIST_STORE(model), &top, &sel);           
                return;
 
        gtk_list_store_move_after(GTK_LIST_STORE(model), &top, &sel);           
-       prefs_filtering_list_view_select_row(filtering.cond_list_view, n_rows - 1);
+       gtkut_list_view_select_row(filtering.cond_list_view, n_rows - 1);
 }
 
 static void prefs_filtering_select_set(FilteringProp *prop)
 }
 
 static void prefs_filtering_select_set(FilteringProp *prop)
@@ -1504,73 +1502,6 @@ static void prefs_filtering_create_list_view_columns(GtkWidget *list_view)
        gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
 }
 
        gtk_tree_view_append_column(GTK_TREE_VIEW(list_view), column);          
 }
 
-static gboolean gtkut_tree_iter_comp(GtkTreeModel *model, 
-                                    GtkTreeIter *iter1, 
-                                    GtkTreeIter *iter2)
-{
-       GtkTreePath *path1 = gtk_tree_model_get_path(model, iter1);
-       GtkTreePath *path2 = gtk_tree_model_get_path(model, iter2);
-       gboolean result;
-
-       result = gtk_tree_path_compare(path1, path2) == 0;
-
-       gtk_tree_path_free(path1);
-       gtk_tree_path_free(path2);
-       
-       return result;
-}
-
-/*!
- *\brief       Get selected row number.
- */
-static gint prefs_filtering_get_selected_row(GtkWidget *list_view)
-{
-       GtkTreeView *view = GTK_TREE_VIEW(list_view);
-       GtkTreeModel *model = gtk_tree_view_get_model(view);
-       int n_rows = gtk_tree_model_iter_n_children(model, NULL);
-       GtkTreeSelection *selection;
-       GtkTreeIter iter;
-       int row;
-
-       if (n_rows == 0) 
-               return -1;
-       
-       selection = gtk_tree_view_get_selection(view);
-       if (!gtk_tree_selection_get_selected(selection, &model, &iter))
-               return -1;
-       
-       /* get all iterators and compare them... */
-       for (row = 0; row < n_rows; row++) {
-               GtkTreeIter itern;
-
-               gtk_tree_model_iter_nth_child(model, &itern, NULL, row);
-               if (gtkut_tree_iter_comp(model, &iter, &itern))
-                       return row;
-       }
-       
-       return -1;
-}
-
-static gboolean prefs_filtering_list_view_select_row(GtkWidget *list, gint row)
-{
-       GtkTreeView *list_view = GTK_TREE_VIEW(list);
-       GtkTreeSelection *selection = gtk_tree_view_get_selection(list_view);
-       GtkTreeModel *model = gtk_tree_view_get_model(list_view);
-       GtkTreeIter iter;
-       GtkTreePath *path;
-
-       if (!gtk_tree_model_iter_nth_child(model, &iter, NULL, row))
-               return FALSE;
-       
-       gtk_tree_selection_select_iter(selection, &iter);
-
-       path = gtk_tree_model_get_path(model, &iter);
-       gtk_tree_view_set_cursor(list_view, path, NULL, FALSE);
-       gtk_tree_path_free(path);
-       
-       return TRUE;
-}
-
 /*!
  *\brief       Triggered when a row is selected
  */
 /*!
  *\brief       Triggered when a row is selected
  */
index f750b9e..0f2fa3a 100644 (file)
@@ -41,6 +41,7 @@
 #include "quote_fmt.h"
 #include "prefs_common.h"
 #include "manual.h"
 #include "quote_fmt.h"
 #include "prefs_common.h"
 #include "manual.h"
+#include "gtkutils.h"
 
 enum {
        TEMPL_TEXT,
 
 enum {
        TEMPL_TEXT,
@@ -82,13 +83,16 @@ static void prefs_template_ok_cb            (void);
 static void prefs_template_register_cb         (void);
 static void prefs_template_substitute_cb       (void);
 static void prefs_template_delete_cb           (void);
 static void prefs_template_register_cb         (void);
 static void prefs_template_substitute_cb       (void);
 static void prefs_template_delete_cb           (void);
+static void prefs_template_top_cb              (void);
+static void prefs_template_up_cb               (void);
+static void prefs_template_down_cb     (void);
+static void prefs_template_bottom_cb   (void);
 
 static GtkListStore* prefs_template_create_data_store  (void);
 static void prefs_template_list_view_insert_template   (GtkWidget *list_view,
                                                         GtkTreeIter *row_iter,
                                                         const gchar *template,
 
 static GtkListStore* prefs_template_create_data_store  (void);
 static void prefs_template_list_view_insert_template   (GtkWidget *list_view,
                                                         GtkTreeIter *row_iter,
                                                         const gchar *template,
-                                                        Template *data,
-                                                        gboolean sorted);
+                                                        Template *data);
 static GtkWidget *prefs_template_list_view_create      (void);
 static void prefs_template_create_list_view_columns    (GtkWidget *list_view);
 static gboolean prefs_template_selected                        (GtkTreeSelection *selector,
 static GtkWidget *prefs_template_list_view_create      (void);
 static void prefs_template_create_list_view_columns    (GtkWidget *list_view);
 static gboolean prefs_template_selected                        (GtkTreeSelection *selector,
@@ -138,8 +142,15 @@ static void prefs_template_window_create(void)
        GtkWidget           *subst_btn;
        GtkWidget           *del_btn;
        GtkWidget         *desc_btn;
        GtkWidget           *subst_btn;
        GtkWidget           *del_btn;
        GtkWidget         *desc_btn;
-       GtkWidget       *scroll1;
-       GtkWidget         *list_view;
+       GtkWidget       *hbox4;
+       GtkWidget         *scroll1;
+       GtkWidget           *list_view;
+       GtkWidget         *vbox3;
+       GtkWidget           *spc_vbox;
+       GtkWidget           *top_btn;
+       GtkWidget           *up_btn;
+       GtkWidget           *down_btn;
+       GtkWidget           *bottom_btn;
        GtkWidget       *confirm_area;
        GtkWidget         *help_btn;
        GtkWidget         *cancel_btn;
        GtkWidget       *confirm_area;
        GtkWidget         *help_btn;
        GtkWidget         *cancel_btn;
@@ -291,13 +302,49 @@ static void prefs_template_window_create(void)
                         G_CALLBACK(quote_fmt_quote_description), NULL);
 
        /* templates list */
                         G_CALLBACK(quote_fmt_quote_description), NULL);
 
        /* templates list */
+       hbox4 = gtk_hbox_new(FALSE, 8);
+       gtk_widget_show(hbox4);
+       gtk_box_pack_start(GTK_BOX(vbox2), hbox4, TRUE, TRUE, 0);
+
        scroll1 = gtk_scrolled_window_new(NULL, NULL);
        gtk_widget_show(scroll1);
        scroll1 = gtk_scrolled_window_new(NULL, NULL);
        gtk_widget_show(scroll1);
-       gtk_box_pack_start(GTK_BOX(vbox2), scroll1, TRUE, TRUE, 0);
+       gtk_box_pack_start(GTK_BOX(hbox4), scroll1, TRUE, TRUE, 0);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll1),
                                       GTK_POLICY_AUTOMATIC,
                                       GTK_POLICY_AUTOMATIC);
                                       
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll1),
                                       GTK_POLICY_AUTOMATIC,
                                       GTK_POLICY_AUTOMATIC);
                                       
+       vbox3 = gtk_vbox_new(FALSE, 8);
+       gtk_widget_show(vbox3);
+       gtk_box_pack_start(GTK_BOX(hbox4), vbox3, FALSE, FALSE, 0);
+
+       top_btn = gtk_button_new_from_stock(GTK_STOCK_GOTO_TOP);
+       gtk_widget_show(top_btn);
+       gtk_box_pack_start(GTK_BOX(vbox3), top_btn, FALSE, FALSE, 0);
+       g_signal_connect(G_OBJECT(top_btn), "clicked",
+                        G_CALLBACK(prefs_template_top_cb), NULL);
+
+       PACK_VSPACER(vbox3, spc_vbox, VSPACING_NARROW_2);
+
+       up_btn = gtk_button_new_from_stock(GTK_STOCK_GO_UP);
+       gtk_widget_show(up_btn);
+       gtk_box_pack_start (GTK_BOX(vbox3), up_btn, FALSE, FALSE, 0);
+       g_signal_connect(G_OBJECT(up_btn), "clicked",
+                        G_CALLBACK(prefs_template_up_cb), NULL);
+
+       down_btn = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
+       gtk_widget_show (down_btn);
+       gtk_box_pack_start(GTK_BOX (vbox3), down_btn, FALSE, FALSE, 0);
+       g_signal_connect(G_OBJECT (down_btn), "clicked",
+                        G_CALLBACK(prefs_template_down_cb), NULL);
+
+       PACK_VSPACER(vbox3, spc_vbox, VSPACING_NARROW_2);
+
+       bottom_btn = gtk_button_new_from_stock(GTK_STOCK_GOTO_BOTTOM);
+       gtk_widget_show(bottom_btn);
+       gtk_box_pack_start(GTK_BOX(vbox3), bottom_btn, FALSE, FALSE, 0);
+       g_signal_connect(G_OBJECT(bottom_btn), "clicked",
+                        G_CALLBACK(prefs_template_bottom_cb), NULL);
+
        list_view = prefs_template_list_view_create();
        gtk_widget_show(list_view);
        gtk_widget_set_size_request(scroll1, -1, 140);
        list_view = prefs_template_list_view_create();
        gtk_widget_show(list_view);
        gtk_widget_set_size_request(scroll1, -1, 140);
@@ -332,8 +379,8 @@ static void prefs_template_window_create(void)
        address_completion_start(window);
 
        if (!geometry.min_height) {
        address_completion_start(window);
 
        if (!geometry.min_height) {
-               geometry.min_width = 440;
-               geometry.min_height = 500;
+               geometry.min_width = 480;
+               geometry.min_height = 540;
        }
 
        gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
        }
 
        gtk_window_set_geometry_hints(GTK_WINDOW(window), NULL, &geometry,
@@ -365,7 +412,7 @@ static void prefs_template_window_setup(void)
 
        prefs_template_list_view_insert_template(templates.list_view,
                                                 NULL, _("(New)"),
 
        prefs_template_list_view_insert_template(templates.list_view,
                                                 NULL, _("(New)"),
-                                                NULL, FALSE);
+                                                NULL);
        
        tmpl_list = template_read_config();
 
        
        tmpl_list = template_read_config();
 
@@ -373,7 +420,7 @@ static void prefs_template_window_setup(void)
                tmpl = (Template *)cur->data;
                prefs_template_list_view_insert_template(templates.list_view,
                                                         NULL, tmpl->name, 
                tmpl = (Template *)cur->data;
                prefs_template_list_view_insert_template(templates.list_view,
                                                         NULL, tmpl->name, 
-                                                        tmpl, FALSE);
+                                                        tmpl);
        }
 
        gtk_entry_set_text(GTK_ENTRY(templates.entry_name), "");
        }
 
        gtk_entry_set_text(GTK_ENTRY(templates.entry_name), "");
@@ -476,6 +523,7 @@ static GSList *prefs_template_get_list(void)
                        Template *ntmpl;
                        
                        ntmpl = g_new(Template, 1);
                        Template *ntmpl;
                        
                        ntmpl = g_new(Template, 1);
+                       ntmpl->load_filename = NULL;
                        ntmpl->name    = tmpl->name && *(tmpl->name) 
                                         ? g_strdup(tmpl->name) 
                                         : NULL;
                        ntmpl->name    = tmpl->name && *(tmpl->name) 
                                         ? g_strdup(tmpl->name) 
                                         : NULL;
@@ -605,6 +653,7 @@ static gboolean prefs_template_list_view_set_row(GtkTreeIter *row)
        }
        
        tmpl = g_new(Template, 1);
        }
        
        tmpl = g_new(Template, 1);
+       tmpl->load_filename = NULL;
        tmpl->name = name;
        tmpl->subject = subject;
        tmpl->to = to;
        tmpl->name = name;
        tmpl->subject = subject;
        tmpl->to = to;
@@ -613,7 +662,7 @@ static gboolean prefs_template_list_view_set_row(GtkTreeIter *row)
        tmpl->value = value;
 
        prefs_template_list_view_insert_template(templates.list_view,
        tmpl->value = value;
 
        prefs_template_list_view_insert_template(templates.list_view,
-                                                row, tmpl->name, tmpl, TRUE);
+                                                row, tmpl->name, tmpl);
        return TRUE;
 }
 
        return TRUE;
 }
 
@@ -673,6 +722,86 @@ static void prefs_template_delete_cb(void)
        gtk_list_store_remove(GTK_LIST_STORE(model), &row);             
 }
 
        gtk_list_store_remove(GTK_LIST_STORE(model), &row);             
 }
 
+static void prefs_template_top_cb(void)
+{
+       gint row;
+       GtkTreeIter top, sel;
+       GtkTreeModel *model;
+
+       row = gtkut_list_view_get_selected_row(templates.list_view);
+       if (row <= 1) 
+               return;
+
+       model = gtk_tree_view_get_model(GTK_TREE_VIEW(templates.list_view));            
+       
+       if (!gtk_tree_model_iter_nth_child(model, &top, NULL, 0)
+       ||  !gtk_tree_model_iter_nth_child(model, &sel, NULL, row))
+               return;
+
+       gtk_list_store_move_after(GTK_LIST_STORE(model), &sel, &top);
+       gtkut_list_view_select_row(templates.list_view, 1);
+}
+
+static void prefs_template_up_cb(void)
+{
+       gint row;
+       GtkTreeIter top, sel;
+       GtkTreeModel *model;
+
+       row = gtkut_list_view_get_selected_row(templates.list_view);
+       if (row <= 1) 
+               return;
+               
+       model = gtk_tree_view_get_model(GTK_TREE_VIEW(templates.list_view));    
+
+       if (!gtk_tree_model_iter_nth_child(model, &top, NULL, row - 1)
+       ||  !gtk_tree_model_iter_nth_child(model, &sel, NULL, row))
+               return;
+
+       gtk_list_store_swap(GTK_LIST_STORE(model), &top, &sel);
+       gtkut_list_view_select_row(templates.list_view, row - 1);
+}
+
+static void prefs_template_down_cb(void)
+{
+       gint row, n_rows;
+       GtkTreeIter top, sel;
+       GtkTreeModel *model;
+
+       model = gtk_tree_view_get_model(GTK_TREE_VIEW(templates.list_view));    
+       n_rows = gtk_tree_model_iter_n_children(model, NULL);
+       row = gtkut_list_view_get_selected_row(templates.list_view);
+       if (row < 1 || row >= n_rows - 1)
+               return;
+
+       if (!gtk_tree_model_iter_nth_child(model, &top, NULL, row)
+       ||  !gtk_tree_model_iter_nth_child(model, &sel, NULL, row + 1))
+               return;
+                       
+       gtk_list_store_swap(GTK_LIST_STORE(model), &top, &sel);
+       gtkut_list_view_select_row(templates.list_view, row + 1);
+}
+
+static void prefs_template_bottom_cb(void)
+{
+       gint row, n_rows;
+       GtkTreeIter top, sel;
+       GtkTreeModel *model;
+
+       model = gtk_tree_view_get_model(GTK_TREE_VIEW(templates.list_view));    
+       n_rows = gtk_tree_model_iter_n_children(model, NULL);
+       row = gtkut_list_view_get_selected_row(templates.list_view);
+       if (row < 1 || row >= n_rows - 1)
+               return;
+
+       if (!gtk_tree_model_iter_nth_child(model, &top, NULL, row)
+       ||  !gtk_tree_model_iter_nth_child(model, &sel, NULL, n_rows - 1))
+               return;
+
+       gtk_list_store_move_after(GTK_LIST_STORE(model), &top, &sel);           
+       gtkut_list_view_select_row(templates.list_view, n_rows - 1);
+}
+
 static GtkListStore* prefs_template_create_data_store(void)
 {
        return gtk_list_store_new(N_TEMPL_COLUMNS,
 static GtkListStore* prefs_template_create_data_store(void)
 {
        return gtk_list_store_new(N_TEMPL_COLUMNS,
@@ -682,33 +811,10 @@ static GtkListStore* prefs_template_create_data_store(void)
                                  -1);
 }
 
                                  -1);
 }
 
-static gboolean prefs_template_list_view_find_insertion_point(GtkTreeModel* model,
-                                                       const gchar* template,
-                                                       GtkTreeIter* iter)
-{
-       GtkTreeIter i;
-       gchar *text = NULL;
-
-       if ((gtk_tree_model_get_iter_first(model, &i))) {
-               for ( ; gtk_tree_model_iter_next(model, &i); ) {
-                       gtk_tree_model_get(model, &i, TEMPL_TEXT, &text, -1);
-                       if (strcmp(text, template) >= 0) {
-                               g_free(text);
-                               *iter = i;
-                               return TRUE;
-                       }
-                       g_free(text);
-               }
-       }
-       /* cannot add before (need to append) */
-       return FALSE;
-}
-
 static void prefs_template_list_view_insert_template(GtkWidget *list_view,
                                                     GtkTreeIter *row_iter,
                                                     const gchar *template,
 static void prefs_template_list_view_insert_template(GtkWidget *list_view,
                                                     GtkTreeIter *row_iter,
                                                     const gchar *template,
-                                                    Template *data,
-                                                        gboolean sorted)
+                                                    Template *data)
 {
        GtkTreeIter iter;
        GtkTreeModel *model = gtk_tree_view_get_model
 {
        GtkTreeIter iter;
        GtkTreeModel *model = gtk_tree_view_get_model
@@ -717,46 +823,11 @@ static void prefs_template_list_view_insert_template(GtkWidget *list_view,
        GAuto *auto_data;                                       
 
        if (row_iter == NULL) {
        GAuto *auto_data;                                       
 
        if (row_iter == NULL) {
-               if (sorted) {
-                       GtkTreeIter insertion_point;
-
-                       /* insert sorted */
-                       if (prefs_template_list_view_find_insertion_point(model,
-                                       template, &insertion_point)) {
-                               gtk_list_store_insert_before(list_store, &iter,
-                                               &insertion_point);
-                       } else {
-                               gtk_list_store_append(list_store, &iter);
-                       }
-               } else {
-                       /* append new */
-                       gtk_list_store_append(list_store, &iter);
-               }
+               /* append new */
+               gtk_list_store_append(list_store, &iter);
        } else {
                /* modify the existing */
                iter = *row_iter;
        } else {
                /* modify the existing */
                iter = *row_iter;
-
-               if (sorted) {
-                       GtkTreeIter insertion_point;
-                       gchar *text = NULL;
-
-                       /* force re-sorting if template's name changed */
-                       gtk_tree_model_get(model, row_iter, TEMPL_TEXT, &text, -1);
-                       if (strcmp(text, template) != 0) {
-
-                               /* move the modified template */
-                               if (prefs_template_list_view_find_insertion_point(model,
-                                               template, &insertion_point)) {
-                                       gtk_list_store_move_before(list_store, row_iter,
-                                                       &insertion_point);
-                               } else {
-                                       /* move to the end */
-                                       gtk_list_store_move_before(list_store, row_iter,
-                                                       NULL);
-                               }
-                       }
-                       g_free(text);
-               }
        }
                
        auto_data = g_auto_pointer_new_with_free(data, (GFreeFunc) template_free);  
        }
                
        auto_data = g_auto_pointer_new_with_free(data, (GFreeFunc) template_free);  
@@ -783,7 +854,8 @@ static GtkWidget *prefs_template_list_view_create(void)
        g_object_unref(model);  
        
        gtk_tree_view_set_rules_hint(list_view, prefs_common.use_stripes_everywhere);
        g_object_unref(model);  
        
        gtk_tree_view_set_rules_hint(list_view, prefs_common.use_stripes_everywhere);
-       
+       gtk_tree_view_set_reorderable(list_view, TRUE);
+
        selector = gtk_tree_view_get_selection(list_view);
        gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
        gtk_tree_selection_set_select_function(selector, prefs_template_selected,
        selector = gtk_tree_view_get_selection(list_view);
        gtk_tree_selection_set_mode(selector, GTK_SELECTION_BROWSE);
        gtk_tree_selection_set_select_function(selector, prefs_template_selected,