sync account.c with sylpheed 0.5.3 plus button
[claws.git] / src / prefs_display_header.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999-2001 Hiroyuki Yamamoto
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <gtk/gtk.h>
28 #include <gdk/gdkkeysyms.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33
34 #include "intl.h"
35 #include "prefs.h"
36 #include "prefs_display_header.h"
37 #include "prefs_common.h"
38 #include "manage_window.h"
39 #include "alertpanel.h"
40 #include "displayheader.h"
41 #include "utils.h"
42 #include "gtkutils.h"
43
44 static struct DisplayHeader {
45         GtkWidget *window;
46
47         GtkWidget *ok_btn;
48         GtkWidget *cancel_btn;
49
50         GtkWidget *hdr_combo;
51         GtkWidget *hdr_entry;
52         GtkWidget *key_check;
53         GtkWidget *headers_clist;
54         GtkWidget *hidden_headers_clist;
55
56         GtkWidget *other_headers;
57 } dispheader;
58
59 /*
60    parameter name, default value, pointer to the prefs variable, data type,
61    pointer to the widget pointer,
62    pointer to the function for data setting,
63    pointer to the function for widget setting
64  */
65
66 #define VSPACING                12
67 #define VSPACING_NARROW         4
68 #define DEFAULT_ENTRY_WIDTH     80
69 #define PREFSBUFSIZE            1024
70
71 /* widget creating functions */
72 static void prefs_display_header_create (void);
73
74 static void prefs_display_header_set_dialog     (void);
75 static void prefs_display_header_set_list       (void);
76 static gint prefs_display_header_clist_set_row  (gboolean hidden);
77
78 /* callback functions */
79 static void prefs_display_header_register_cb    (GtkButton      *btn,
80                                                  gpointer        hidden_data);
81 static void prefs_display_header_delete_cb      (GtkButton      *btn,
82                                                  gpointer        clist_data);
83 static void prefs_display_header_up             (void);
84 static void prefs_display_header_down           (void);
85
86 static void prefs_display_header_row_moved      (GtkCList       *clist,
87                                                  gint            source_row,
88                                                  gint            dest_row,
89                                                  gpointer        data);
90
91 static void prefs_display_header_key_pressed    (GtkWidget      *widget,
92                                                  GdkEventKey    *event,
93                                                  gpointer        data);
94 static void prefs_display_header_ok             (void);
95 static void prefs_display_header_cancel         (void);
96 static gint prefs_display_header_deleted        (GtkWidget      *widget,
97                                                  GdkEventAny    *event,
98                                                  gpointer        data);
99
100 static gchar *defaults[] =
101 {
102         "From",
103         "To",
104         "Cc",
105         "Reply-To",
106         "Newsgroups",
107         "Followup-To",
108         "Subject",
109         "Date",
110         "Sender",
111         "Organization",
112         "X-Mailer",
113         "X-Newsreader",
114         "User-Agent",
115         "-Received",
116         "-Message-Id",
117         "-In-Reply-To",
118         "-References",
119         "-Mime-Version",
120         "-Content-Type",
121         "-Content-Transfer-Encoding",
122         "-X-UIDL",
123         "-Precedence",
124         "-Status",
125         "-Priority",
126         "-X-Face"
127 };
128
129 static void prefs_display_header_set_default(void)
130 {
131         gint i;
132         DisplayHeaderProp *dp;
133
134         for(i = 0; i < sizeof(defaults) / sizeof(defaults[0]); i++) {
135                 dp = display_header_prop_read_str(defaults[i]);
136                 prefs_common.disphdr_list =
137                         g_slist_append(prefs_common.disphdr_list, dp);
138         }
139 }
140
141 void prefs_display_header_open(void)
142 {
143         if (prefs_rc_is_readonly(DISPLAY_HEADER_RC))
144                 return;
145
146         if (!dispheader.window) {
147                 prefs_display_header_create();
148         }
149
150         manage_window_set_transient(GTK_WINDOW(dispheader.window));
151         gtk_widget_grab_focus(dispheader.ok_btn);
152
153         prefs_display_header_set_dialog();
154
155         gtk_widget_show(dispheader.window);
156 }
157
158 static void prefs_display_header_create(void)
159 {
160         GtkWidget *window;
161         GtkWidget *vbox;
162         GtkWidget *btn_hbox;
163         GtkWidget *ok_btn;
164         GtkWidget *cancel_btn;
165         GtkWidget *confirm_area;
166
167         GtkWidget *vbox1;
168
169         GtkWidget *hbox1;
170         GtkWidget *hdr_label;
171         GtkWidget *hdr_combo;
172
173         GtkWidget *btn_vbox;
174         GtkWidget *reg_btn;
175         GtkWidget *del_btn;
176         GtkWidget *up_btn;
177         GtkWidget *down_btn;
178
179         GtkWidget *clist_hbox;
180         GtkWidget *clist_hbox1;
181         GtkWidget *clist_hbox2;
182         GtkWidget *clist_scrolledwin;
183         GtkWidget *headers_clist;
184         GtkWidget *hidden_headers_clist;
185
186         GtkWidget *checkbtn_other_headers;
187
188         gchar *title[1];
189
190         debug_print(_("Creating display header setting window...\n"));
191
192         window = gtk_window_new (GTK_WINDOW_DIALOG);
193         gtk_container_set_border_width (GTK_CONTAINER (window), 8);
194         gtk_window_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
195         gtk_window_set_modal (GTK_WINDOW (window), TRUE);
196         gtk_window_set_policy (GTK_WINDOW (window), FALSE, TRUE, FALSE);
197
198         vbox = gtk_vbox_new (FALSE, 6);
199         gtk_widget_show (vbox);
200         gtk_container_add (GTK_CONTAINER (window), vbox);
201
202         btn_hbox = gtk_hbox_new (FALSE, 8);
203         gtk_widget_show (btn_hbox);
204         gtk_box_pack_end (GTK_BOX (vbox), btn_hbox, FALSE, FALSE, 0);
205
206         gtkut_button_set_create(&confirm_area, &ok_btn, _("OK"),
207                                 &cancel_btn, _("Cancel"), NULL, NULL);
208         gtk_widget_show (confirm_area);
209         gtk_box_pack_end (GTK_BOX(btn_hbox), confirm_area, FALSE, FALSE, 0);
210         gtk_widget_grab_default (ok_btn);
211
212         gtk_window_set_title (GTK_WINDOW(window),
213                               _("Display header setting"));
214         gtk_signal_connect (GTK_OBJECT(window), "focus_in_event",
215                             GTK_SIGNAL_FUNC(manage_window_focus_in), NULL);
216         gtk_signal_connect (GTK_OBJECT(window), "focus_out_event",
217                             GTK_SIGNAL_FUNC(manage_window_focus_out), NULL);
218         gtk_signal_connect (GTK_OBJECT(window), "delete_event",
219                             GTK_SIGNAL_FUNC(prefs_display_header_deleted),
220                             NULL);
221         gtk_signal_connect (GTK_OBJECT(window), "key_press_event",
222                             GTK_SIGNAL_FUNC(prefs_display_header_key_pressed),
223                             NULL);
224         gtk_signal_connect (GTK_OBJECT(ok_btn), "clicked",
225                             GTK_SIGNAL_FUNC(prefs_display_header_ok),
226                             NULL);
227         gtk_signal_connect (GTK_OBJECT(cancel_btn), "clicked",
228                             GTK_SIGNAL_FUNC(prefs_display_header_cancel),
229                             NULL);
230
231         vbox1 = gtk_vbox_new (FALSE, VSPACING);
232         gtk_widget_show (vbox1);
233         gtk_box_pack_start (GTK_BOX (vbox), vbox1, TRUE, TRUE, 0);
234         gtk_container_set_border_width (GTK_CONTAINER (vbox1), 2);
235
236         hbox1 = gtk_hbox_new (FALSE, 8);
237         gtk_widget_show (hbox1);
238         gtk_box_pack_start (GTK_BOX (vbox1), hbox1, FALSE, TRUE, 0);
239
240         hdr_label = gtk_label_new (_("Header name"));
241         gtk_widget_show (hdr_label);
242         gtk_box_pack_start (GTK_BOX (hbox1), hdr_label, FALSE, FALSE, 0);
243
244         hdr_combo = gtk_combo_new ();
245         gtk_widget_show (hdr_combo);
246         gtk_box_pack_start (GTK_BOX (hbox1), hdr_combo, TRUE, TRUE, 0);
247         gtk_widget_set_usize (hdr_combo, 150, -1);
248         gtkut_combo_set_items (GTK_COMBO (hdr_combo),
249                                "From", "To", "Cc", "Subject", "Date",
250                                "Reply-To", "Sender", "User-Agent", "X-Mailer",
251                                NULL);
252
253         clist_hbox = gtk_hbox_new (FALSE, 10);
254         gtk_widget_show (clist_hbox);
255         gtk_box_pack_start (GTK_BOX (vbox1), clist_hbox, TRUE, TRUE, 0);
256
257         /* display headers list */
258
259         clist_hbox1 = gtk_hbox_new (FALSE, 8);
260         gtk_widget_show (clist_hbox1);
261         gtk_box_pack_start (GTK_BOX (clist_hbox), clist_hbox1, TRUE, TRUE, 0);
262
263         clist_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
264         gtk_widget_set_usize (clist_scrolledwin, 200, 210);
265         gtk_widget_show (clist_scrolledwin);
266         gtk_box_pack_start (GTK_BOX (clist_hbox1), clist_scrolledwin,
267                             TRUE, TRUE, 0);
268         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (clist_scrolledwin),
269                                         GTK_POLICY_AUTOMATIC,
270                                         GTK_POLICY_AUTOMATIC);
271
272         title[0] = _("Displayed Headers");
273         headers_clist = gtk_clist_new_with_titles(1, title);
274         gtk_widget_show (headers_clist);
275         gtk_container_add (GTK_CONTAINER (clist_scrolledwin), headers_clist);
276         gtk_clist_set_selection_mode (GTK_CLIST (headers_clist),
277                                       GTK_SELECTION_BROWSE);
278         gtk_clist_set_reorderable (GTK_CLIST (headers_clist), TRUE);
279         gtk_clist_set_use_drag_icons (GTK_CLIST (headers_clist), FALSE);
280         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (headers_clist)->column[0].button,
281                                 GTK_CAN_FOCUS);
282         gtk_signal_connect_after
283                 (GTK_OBJECT (headers_clist), "row_move",
284                  GTK_SIGNAL_FUNC (prefs_display_header_row_moved), NULL);
285
286         btn_vbox = gtk_vbox_new (FALSE, 8);
287         gtk_widget_show (btn_vbox);
288         gtk_box_pack_start (GTK_BOX (clist_hbox1), btn_vbox, FALSE, FALSE, 0);
289
290         reg_btn = gtk_button_new_with_label (_("Add"));
291         gtk_widget_show (reg_btn);
292         gtk_box_pack_start (GTK_BOX (btn_vbox), reg_btn, FALSE, TRUE, 0);
293         gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
294                             GTK_SIGNAL_FUNC (prefs_display_header_register_cb),
295                             FALSE);
296         del_btn = gtk_button_new_with_label (_("Delete"));
297         gtk_widget_show (del_btn);
298         gtk_box_pack_start (GTK_BOX (btn_vbox), del_btn, FALSE, TRUE, 0);
299         gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
300                             GTK_SIGNAL_FUNC (prefs_display_header_delete_cb),
301                             headers_clist);
302
303         up_btn = gtk_button_new_with_label (_("Up"));
304         gtk_widget_show (up_btn);
305         gtk_box_pack_start (GTK_BOX (btn_vbox), up_btn, FALSE, FALSE, 0);
306         gtk_signal_connect (GTK_OBJECT (up_btn), "clicked",
307                             GTK_SIGNAL_FUNC (prefs_display_header_up), NULL);
308
309         down_btn = gtk_button_new_with_label (_("Down"));
310         gtk_widget_show (down_btn);
311         gtk_box_pack_start (GTK_BOX (btn_vbox), down_btn, FALSE, FALSE, 0);
312         gtk_signal_connect (GTK_OBJECT (down_btn), "clicked",
313                             GTK_SIGNAL_FUNC (prefs_display_header_down), NULL);
314
315         /* hidden headers list */
316
317         clist_hbox2 = gtk_hbox_new (FALSE, 8);
318         gtk_widget_show (clist_hbox2);
319         gtk_box_pack_start (GTK_BOX (clist_hbox), clist_hbox2, TRUE, TRUE, 0);
320
321         clist_scrolledwin = gtk_scrolled_window_new (NULL, NULL);
322         gtk_widget_set_usize (clist_scrolledwin, 200, 210);
323         gtk_widget_show (clist_scrolledwin);
324         gtk_box_pack_start (GTK_BOX (clist_hbox2), clist_scrolledwin,
325                             TRUE, TRUE, 0);
326         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (clist_scrolledwin),
327                                         GTK_POLICY_AUTOMATIC,
328                                         GTK_POLICY_AUTOMATIC);
329
330         title[0] = _("Hidden headers");
331         hidden_headers_clist = gtk_clist_new_with_titles(1, title);
332         gtk_widget_show (hidden_headers_clist);
333         gtk_container_add (GTK_CONTAINER (clist_scrolledwin),
334                            hidden_headers_clist);
335         gtk_clist_set_selection_mode (GTK_CLIST (hidden_headers_clist),
336                                       GTK_SELECTION_BROWSE);
337         gtk_clist_set_auto_sort(GTK_CLIST (hidden_headers_clist), TRUE);
338         GTK_WIDGET_UNSET_FLAGS (GTK_CLIST (hidden_headers_clist)->
339                                 column[0].button, GTK_CAN_FOCUS);
340
341         btn_vbox = gtk_vbox_new (FALSE, 8);
342         gtk_widget_show (btn_vbox);
343         gtk_box_pack_start (GTK_BOX (clist_hbox2), btn_vbox, FALSE, FALSE, 0);
344
345         reg_btn = gtk_button_new_with_label (_("Add"));
346         gtk_widget_show (reg_btn);
347         gtk_box_pack_start (GTK_BOX (btn_vbox), reg_btn, FALSE, TRUE, 0);
348         gtk_signal_connect (GTK_OBJECT (reg_btn), "clicked",
349                             GTK_SIGNAL_FUNC
350                             (prefs_display_header_register_cb),
351                             (void *) TRUE);
352         del_btn = gtk_button_new_with_label (_("Delete"));
353         gtk_widget_show (del_btn);
354         gtk_box_pack_start (GTK_BOX (btn_vbox), del_btn, FALSE, TRUE, 0);
355         gtk_signal_connect (GTK_OBJECT (del_btn), "clicked",
356                             GTK_SIGNAL_FUNC (prefs_display_header_delete_cb),
357                             (void *) hidden_headers_clist);
358
359         PACK_CHECK_BUTTON (btn_hbox, checkbtn_other_headers,
360                            _("Show all unspecified headers"));
361         SET_TOGGLE_SENSITIVITY (checkbtn_other_headers, clist_hbox2);
362
363         gtk_widget_show_all(window);
364
365         dispheader.window        = window;
366         dispheader.ok_btn        = ok_btn;
367         dispheader.cancel_btn    = cancel_btn;
368
369         dispheader.hdr_combo     = hdr_combo;
370         dispheader.hdr_entry     = GTK_COMBO (hdr_combo)->entry;
371
372         dispheader.headers_clist        = headers_clist;
373         dispheader.hidden_headers_clist = hidden_headers_clist;
374
375         dispheader.other_headers = checkbtn_other_headers;
376 }
377
378 void prefs_display_header_read_config(void)
379 {
380         gchar *rcpath;
381         FILE *fp;
382         gchar buf[PREFSBUFSIZE];
383         DisplayHeaderProp *dp;
384
385         debug_print(_("Reading configuration for displaying headers...\n"));
386
387         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
388                              DISPLAY_HEADER_RC, NULL);
389         if ((fp = fopen(rcpath, "r")) == NULL) {
390                 if (ENOENT != errno) FILE_OP_ERROR(rcpath, "fopen");
391                 g_free(rcpath);
392                 prefs_common.disphdr_list = NULL;
393                 prefs_display_header_set_default();
394                 return;
395         }
396         g_free(rcpath);
397
398         /* remove all previous headers list */
399         while (prefs_common.disphdr_list != NULL) {
400                 dp = (DisplayHeaderProp *)prefs_common.disphdr_list->data;
401                 display_header_prop_free(dp);
402                 prefs_common.disphdr_list =
403                         g_slist_remove(prefs_common.disphdr_list, dp);
404         }
405
406         while (fgets(buf, sizeof(buf), fp) != NULL) {
407                 g_strdelimit(buf, "\r\n", '\0');
408                 dp = display_header_prop_read_str(buf);
409                 if (dp)
410                         prefs_common.disphdr_list =
411                                 g_slist_append(prefs_common.disphdr_list, dp);
412         }
413
414         fclose(fp);
415 }
416
417 void prefs_display_header_write_config(void)
418 {
419         gchar *rcpath;
420         PrefFile *pfile;
421         GSList *cur;
422
423         debug_print(_("Writing configuration for displaying headers...\n"));
424
425         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
426                              DISPLAY_HEADER_RC, NULL);
427
428         if ((pfile = prefs_write_open(rcpath)) == NULL) {
429                 g_warning(_("failed to write configuration to file\n"));
430                 g_free(rcpath);
431                 return;
432         }
433
434         for (cur = prefs_common.disphdr_list; cur != NULL;
435              cur = cur->next) {
436                 DisplayHeaderProp *dp = (DisplayHeaderProp *)cur->data;
437                 gchar *dpstr;
438
439                 dpstr = display_header_prop_get_str(dp);
440                 if (fputs(dpstr, pfile->fp) == EOF ||
441                     fputc('\n', pfile->fp) == EOF) {
442                         FILE_OP_ERROR(rcpath, "fputs || fputc");
443                         prefs_write_close_revert(pfile);
444                         g_free(rcpath);
445                         g_free(dpstr);
446                         return;
447                 }
448                 g_free(dpstr);
449         }
450
451         g_free(rcpath);
452
453         if (prefs_write_close(pfile) < 0) {
454                 g_warning(_("failed to write configuration to file\n"));
455                 return;
456         }
457 }
458
459 static void prefs_display_header_set_dialog(void)
460 {
461         GtkCList *clist = GTK_CLIST(dispheader.headers_clist);
462         GtkCList *hidden_clist = GTK_CLIST(dispheader.hidden_headers_clist);
463         GSList *cur;
464         gchar *dp_str[1];
465         gint row;
466
467         gtk_clist_freeze(clist);
468         gtk_clist_freeze(hidden_clist);
469
470         gtk_clist_clear(clist);
471         gtk_clist_clear(hidden_clist);
472
473         for (cur = prefs_common.disphdr_list; cur != NULL;
474              cur = cur->next) {
475                 DisplayHeaderProp *dp = (DisplayHeaderProp *)cur->data;
476
477                 dp_str[0] = dp->name;
478
479                 if (dp->hidden) {
480                         row = gtk_clist_append(hidden_clist, dp_str);
481                         gtk_clist_set_row_data(hidden_clist, row, dp);
482                 } else {
483                         row = gtk_clist_append(clist, dp_str);
484                         gtk_clist_set_row_data(clist, row, dp);
485                 }
486         }
487
488         gtk_clist_thaw(hidden_clist);
489         gtk_clist_thaw(clist);
490
491         gtk_toggle_button_set_active
492                 (GTK_TOGGLE_BUTTON(dispheader.other_headers),
493                  prefs_common.show_other_header);
494 }
495
496 static void prefs_display_header_set_list()
497 {
498         gint row = 0;
499         DisplayHeaderProp *dp;
500
501         g_slist_free(prefs_common.disphdr_list);
502         prefs_common.disphdr_list = NULL;
503
504         while ((dp = gtk_clist_get_row_data
505                 (GTK_CLIST(dispheader.headers_clist), row)) != NULL) {
506                 prefs_common.disphdr_list =
507                         g_slist_append(prefs_common.disphdr_list, dp);
508                 row++;
509         }
510
511         row = 0;
512         while ((dp = gtk_clist_get_row_data
513                 (GTK_CLIST(dispheader.hidden_headers_clist), row)) != NULL) {
514                 prefs_common.disphdr_list =
515                         g_slist_append(prefs_common.disphdr_list, dp);
516                 row++;
517         }
518 }
519
520 static gint prefs_display_header_find_header(GtkCList *clist,
521                                              const gchar *header)
522 {
523         gint row = 0;
524         DisplayHeaderProp *dp;
525
526         while ((dp = gtk_clist_get_row_data(clist, row)) != NULL) {
527                 if (g_strcasecmp(dp->name, header) == 0)
528                         return row;
529                 row++;
530         }
531
532         return -1;
533 }
534
535 static gint prefs_display_header_clist_set_row(gboolean hidden)
536 {
537         GtkCList *clist;
538         DisplayHeaderProp *dp;
539         gchar *entry_text;
540         gchar *dp_str[1];
541         gint row;
542
543         entry_text = gtk_entry_get_text(GTK_ENTRY(dispheader.hdr_entry));
544         if (entry_text[0] == '\0') {
545                 alertpanel_error(_("Header name is not set."));
546                 return -1;
547         }
548
549         if (hidden)
550                 clist = GTK_CLIST(dispheader.hidden_headers_clist);
551         else
552                 clist = GTK_CLIST(dispheader.headers_clist);
553
554         if (prefs_display_header_find_header(clist, entry_text) != -1) {
555                 alertpanel_error(_("This header is already in the list."));
556                 return -1;
557         }
558
559         dp = g_new0(DisplayHeaderProp, 1);
560
561         dp->name = g_strdup(entry_text);
562         dp->hidden = hidden;
563
564         dp_str[0] = dp->name;
565         row = gtk_clist_append(clist, dp_str);
566         gtk_clist_set_row_data(clist, row, dp);
567
568         prefs_display_header_set_list();
569
570         return row;
571 }
572
573 static void prefs_display_header_register_cb(GtkButton *btn,
574                                              gpointer hidden_data)
575 {
576         gboolean hidden = (gboolean)hidden_data;
577
578         prefs_display_header_clist_set_row(hidden);
579 }
580
581 static void prefs_display_header_delete_cb(GtkButton *btn, gpointer clist_data)
582 {
583         GtkCList *clist = GTK_CLIST(clist_data);
584         DisplayHeaderProp *dp;
585         gint row;
586
587         if (!clist->selection) return;
588         row = GPOINTER_TO_INT(clist->selection->data);
589
590         dp = gtk_clist_get_row_data(clist, row);
591         display_header_prop_free(dp);
592         gtk_clist_remove(clist, row);
593         prefs_common.disphdr_list =
594                 g_slist_remove(prefs_common.disphdr_list, dp);
595 }
596
597 static void prefs_display_header_up(void)
598 {
599         GtkCList *clist = GTK_CLIST(dispheader.headers_clist);
600         gint row;
601
602         if (!clist->selection) return;
603
604         row = GPOINTER_TO_INT(clist->selection->data);
605         if (row > 0)
606                 gtk_clist_row_move(clist, row, row - 1);
607 }
608
609 static void prefs_display_header_down(void)
610 {
611         GtkCList *clist = GTK_CLIST(dispheader.headers_clist);
612         gint row;
613
614         if (!clist->selection) return;
615
616         row = GPOINTER_TO_INT(clist->selection->data);
617         if (row >= 0 && row < clist->rows - 1)
618                 gtk_clist_row_move(clist, row, row + 1);
619 }
620
621 static void prefs_display_header_row_moved(GtkCList *clist, gint source_row,
622                                            gint dest_row, gpointer data)
623 {
624         prefs_display_header_set_list();
625 }
626
627 static void prefs_display_header_key_pressed(GtkWidget *widget,
628                                              GdkEventKey *event,
629                                              gpointer data)
630 {
631         if (event && event->keyval == GDK_Escape)
632                 prefs_display_header_cancel();
633 }
634
635 static void prefs_display_header_ok(void)
636 {
637         prefs_common.show_other_header =
638                 gtk_toggle_button_get_active
639                         (GTK_TOGGLE_BUTTON(dispheader.other_headers));
640         prefs_display_header_write_config();
641         gtk_widget_hide(dispheader.window);
642 }
643
644 static void prefs_display_header_cancel(void)
645 {
646         prefs_display_header_read_config();
647         gtk_widget_hide(dispheader.window);
648 }
649
650 static gint prefs_display_header_deleted(GtkWidget *widget, GdkEventAny *event,
651                                          gpointer data)
652 {
653         prefs_display_header_cancel();
654         return TRUE;
655 }