2005-05-31 [paul] 1.9.11cvs26
[claws.git] / src / prefs_summaries.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2004 Hiroyuki Yamamoto & The Sylpheed-Claws 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 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 <stdio.h>
27 #include <stdlib.h>
28
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 #include <gtk/gtk.h>
32 #include <gdk/gdkkeysyms.h>
33
34 #include "prefs_common.h"
35 #include "prefs_gtk.h"
36 #include "prefs_summary_column.h"
37
38 #include "gtk/gtkutils.h"
39 #include "gtk/prefswindow.h"
40
41 #include "manage_window.h"
42
43 typedef struct _SummariesPage
44 {
45         PrefsPage page;
46
47         GtkWidget *window;
48
49         GtkWidget *chkbtn_transhdr;
50         GtkWidget *chkbtn_folder_unread;
51         GtkWidget *spinbtn_ng_abbrev_len;
52         GtkWidget *chkbtn_swapfrom;
53         GtkWidget *chkbtn_useaddrbook;
54         GtkWidget *chkbtn_threadsubj;
55         GtkWidget *button_datefmt;
56         GtkWidget *entry_datefmt;
57 } SummariesPage;
58
59 enum {
60         DATEFMT_FMT,
61         DATEFMT_TXT,
62         N_DATEFMT_COLUMNS
63 };
64
65 static void date_format_ok_btn_clicked          (GtkButton      *button,
66                                                  GtkWidget     **widget);
67 static void date_format_cancel_btn_clicked      (GtkButton      *button,
68                                                  GtkWidget     **widget);
69 static gboolean date_format_key_pressed         (GtkWidget      *keywidget,
70                                                  GdkEventKey    *event,
71                                                  GtkWidget     **widget);
72 static gboolean date_format_on_delete           (GtkWidget      *dialogwidget,
73                                                  GdkEventAny    *event,
74                                                  GtkWidget     **widget);
75 static void date_format_entry_on_change         (GtkEditable    *editable,
76                                                  GtkLabel       *example);
77 static void date_format_select_row              (GtkTreeView *list_view,
78                                                  GtkTreePath *path,
79                                                  GtkTreeViewColumn *column,
80                                                  GtkWidget *date_format);
81
82 static GtkWidget *date_format_create(GtkButton *button, void *data)
83 {
84         static GtkWidget *datefmt_win = NULL;
85
86         GtkWidget *vbox1;
87         GtkWidget *scrolledwindow1;
88         GtkWidget *datefmt_list_view;
89         GtkWidget *table;
90         GtkWidget *label1;
91         GtkWidget *label2;
92         GtkWidget *label3;
93         GtkWidget *confirm_area;
94         GtkWidget *ok_btn;
95         GtkWidget *cancel_btn;
96         GtkWidget *datefmt_entry;
97         GtkListStore *store;
98
99         struct {
100                 gchar *fmt;
101                 gchar *txt;
102         } time_format[] = {
103                 { "%a", NULL },
104                 { "%A", NULL },
105                 { "%b", NULL },
106                 { "%B", NULL },
107                 { "%c", NULL },
108                 { "%C", NULL },
109                 { "%d", NULL },
110                 { "%H", NULL },
111                 { "%I", NULL },
112                 { "%j", NULL },
113                 { "%m", NULL },
114                 { "%M", NULL },
115                 { "%p", NULL },
116                 { "%S", NULL },
117                 { "%w", NULL },
118                 { "%x", NULL },
119                 { "%y", NULL },
120                 { "%Y", NULL },
121                 { "%Z", NULL }
122         };
123
124         gchar *titles[2];
125         gint i;
126         const gint TIME_FORMAT_ELEMS =
127                 sizeof time_format / sizeof time_format[0];
128
129         GtkCellRenderer *renderer;
130         GtkTreeViewColumn *column;
131         GtkTreeSelection *selection;
132
133         time_format[0].txt  = _("the full abbreviated weekday name");
134         time_format[1].txt  = _("the full weekday name");
135         time_format[2].txt  = _("the abbreviated month name");
136         time_format[3].txt  = _("the full month name");
137         time_format[4].txt  = _("the preferred date and time for the current locale");
138         time_format[5].txt  = _("the century number (year/100)");
139         time_format[6].txt  = _("the day of the month as a decimal number");
140         time_format[7].txt  = _("the hour as a decimal number using a 24-hour clock");
141         time_format[8].txt  = _("the hour as a decimal number using a 12-hour clock");
142         time_format[9].txt  = _("the day of the year as a decimal number");
143         time_format[10].txt = _("the month as a decimal number");
144         time_format[11].txt = _("the minute as a decimal number");
145         time_format[12].txt = _("either AM or PM");
146         time_format[13].txt = _("the second as a decimal number");
147         time_format[14].txt = _("the day of the week as a decimal number");
148         time_format[15].txt = _("the preferred date for the current locale");
149         time_format[16].txt = _("the last two digits of a year");
150         time_format[17].txt = _("the year as a decimal number");
151         time_format[18].txt = _("the time zone or name or abbreviation");
152
153         if (datefmt_win) return datefmt_win;
154
155         store = gtk_list_store_new(N_DATEFMT_COLUMNS,
156                                    G_TYPE_STRING,
157                                    G_TYPE_STRING,
158                                    -1);
159
160         for (i = 0; i < TIME_FORMAT_ELEMS; i++) {
161                 GtkTreeIter iter;
162
163                 gtk_list_store_append(store, &iter);
164                 gtk_list_store_set(store, &iter,
165                                    DATEFMT_FMT, time_format[i].fmt,
166                                    DATEFMT_TXT, time_format[i].txt,
167                                    -1);
168         }
169
170         datefmt_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
171         gtk_container_set_border_width(GTK_CONTAINER(datefmt_win), 8);
172         gtk_window_set_title(GTK_WINDOW(datefmt_win), _("Date format"));
173         gtk_window_set_position(GTK_WINDOW(datefmt_win), GTK_WIN_POS_CENTER);
174         gtk_widget_set_size_request(datefmt_win, 440, 280);
175
176         vbox1 = gtk_vbox_new(FALSE, 10);
177         gtk_widget_show(vbox1);
178         gtk_container_add(GTK_CONTAINER(datefmt_win), vbox1);
179
180         scrolledwindow1 = gtk_scrolled_window_new(NULL, NULL);
181         gtk_scrolled_window_set_policy
182                 (GTK_SCROLLED_WINDOW(scrolledwindow1),
183                  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
184         gtk_widget_show(scrolledwindow1);
185         gtk_box_pack_start(GTK_BOX(vbox1), scrolledwindow1, TRUE, TRUE, 0);
186
187         datefmt_list_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
188         g_object_unref(G_OBJECT(store));
189         gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(datefmt_list_view),
190                                      prefs_common.enable_rules_hint);
191         gtk_widget_show(datefmt_list_view);
192         gtk_container_add(GTK_CONTAINER(scrolledwindow1), datefmt_list_view);
193
194         renderer = gtk_cell_renderer_text_new();
195         column = gtk_tree_view_column_new_with_attributes
196                         (_("Specifier"), renderer, "text", DATEFMT_FMT,
197                          NULL);
198         gtk_tree_view_append_column(GTK_TREE_VIEW(datefmt_list_view), column);
199         
200         renderer = gtk_cell_renderer_text_new();
201         column = gtk_tree_view_column_new_with_attributes
202                         (_("Description"), renderer, "text", DATEFMT_TXT,
203                          NULL);
204         gtk_tree_view_append_column(GTK_TREE_VIEW(datefmt_list_view), column);
205         
206         /* gtk_clist_set_column_width(GTK_CLIST(datefmt_clist), 0, 80); */
207         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(datefmt_list_view));
208         gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
209
210         g_signal_connect(G_OBJECT(datefmt_list_view), "row_activated", 
211                          G_CALLBACK(date_format_select_row),
212                          datefmt_win);
213         
214         table = gtk_table_new(2, 2, FALSE);
215         gtk_widget_show(table);
216         gtk_box_pack_start(GTK_BOX(vbox1), table, FALSE, FALSE, 0);
217         gtk_table_set_row_spacings(GTK_TABLE(table), 4);
218         gtk_table_set_col_spacings(GTK_TABLE(table), 8);
219
220         label1 = gtk_label_new(_("Date format"));
221         gtk_widget_show(label1);
222         gtk_table_attach(GTK_TABLE(table), label1, 0, 1, 0, 1,
223                          GTK_FILL, 0, 0, 0);
224         gtk_label_set_justify(GTK_LABEL(label1), GTK_JUSTIFY_LEFT);
225         gtk_misc_set_alignment(GTK_MISC(label1), 0, 0.5);
226
227         datefmt_entry = gtk_entry_new();
228         gtk_entry_set_max_length(GTK_ENTRY(datefmt_entry), 256);
229         gtk_widget_show(datefmt_entry);
230         gtk_table_attach(GTK_TABLE(table), datefmt_entry, 1, 2, 0, 1,
231                          (GTK_EXPAND | GTK_FILL), 0, 0, 0);
232
233         /* we need the "sample" entry box; add it as data so callbacks can
234          * get the entry box */
235         g_object_set_data(G_OBJECT(datefmt_win), "datefmt_sample",
236                           datefmt_entry);
237
238         label2 = gtk_label_new(_("Example"));
239         gtk_widget_show(label2);
240         gtk_table_attach(GTK_TABLE(table), label2, 0, 1, 1, 2,
241                          GTK_FILL, 0, 0, 0);
242         gtk_label_set_justify(GTK_LABEL(label2), GTK_JUSTIFY_LEFT);
243         gtk_misc_set_alignment(GTK_MISC(label2), 0, 0.5);
244
245         label3 = gtk_label_new("");
246         gtk_widget_show(label3);
247         gtk_table_attach(GTK_TABLE(table), label3, 1, 2, 1, 2,
248                          (GTK_EXPAND | GTK_FILL), 0, 0, 0);
249         gtk_label_set_justify(GTK_LABEL(label3), GTK_JUSTIFY_LEFT);
250         gtk_misc_set_alignment(GTK_MISC(label3), 0, 0.5);
251
252         gtkut_stock_button_set_create(&confirm_area, &ok_btn, GTK_STOCK_OK,
253                                 &cancel_btn, GTK_STOCK_CANCEL, NULL, NULL);
254
255         gtk_box_pack_start(GTK_BOX(vbox1), confirm_area, FALSE, FALSE, 0);
256         gtk_widget_show(confirm_area);
257         gtk_widget_grab_default(ok_btn);
258
259         /* set the current format */
260         gtk_entry_set_text(GTK_ENTRY(datefmt_entry), prefs_common.date_format);
261         date_format_entry_on_change(GTK_EDITABLE(datefmt_entry),
262                                     GTK_LABEL(label3));
263
264         g_signal_connect(G_OBJECT(ok_btn), "clicked",
265                          G_CALLBACK(date_format_ok_btn_clicked),
266                          &datefmt_win);
267         g_signal_connect(G_OBJECT(cancel_btn), "clicked",
268                          G_CALLBACK(date_format_cancel_btn_clicked),
269                          &datefmt_win);
270         g_signal_connect(G_OBJECT(datefmt_win), "key_press_event",
271                          G_CALLBACK(date_format_key_pressed),
272                          &datefmt_win);
273         g_signal_connect(G_OBJECT(datefmt_win), "delete_event",
274                          G_CALLBACK(date_format_on_delete),
275                          &datefmt_win);
276         g_signal_connect(G_OBJECT(datefmt_entry), "changed",
277                          G_CALLBACK(date_format_entry_on_change),
278                          label3);
279
280         gtk_window_set_position(GTK_WINDOW(datefmt_win), GTK_WIN_POS_CENTER);
281         gtk_window_set_modal(GTK_WINDOW(datefmt_win), TRUE);
282
283         gtk_widget_show(datefmt_win);
284         manage_window_set_transient(GTK_WINDOW(datefmt_win));
285
286         gtk_widget_grab_focus(ok_btn);
287
288         return datefmt_win;
289 }
290
291 void prefs_summaries_create_widget(PrefsPage *_page, GtkWindow *window, 
292                                   gpointer data)
293 {
294         SummariesPage *prefs_summaries = (SummariesPage *) _page;
295         
296         GtkWidget *vbox1;
297         GtkWidget *chkbtn_transhdr;
298         GtkWidget *chkbtn_folder_unread;
299         GtkWidget *hbox1;
300         GtkWidget *label_ng_abbrev;
301         GtkWidget *spinbtn_ng_abbrev_len;
302         GtkObject *spinbtn_ng_abbrev_len_adj;
303         GtkWidget *frame_summary;
304         GtkWidget *vbox2;
305         GtkWidget *chkbtn_swapfrom;
306         GtkWidget *chkbtn_useaddrbook;
307         GtkWidget *chkbtn_threadsubj;
308         GtkWidget *vbox3;
309         GtkWidget *label_datefmt;
310         GtkWidget *button_datefmt;
311         GtkWidget *entry_datefmt;
312         GtkWidget *button_dispitem;
313
314         vbox1 = gtk_vbox_new (FALSE, VSPACING);
315         gtk_widget_show (vbox1);
316         gtk_container_set_border_width (GTK_CONTAINER (vbox1), VBOX_BORDER);
317
318         vbox2 = gtk_vbox_new (FALSE, 0);
319         gtk_widget_show (vbox2);
320         gtk_box_pack_start (GTK_BOX (vbox1), vbox2, FALSE, TRUE, 0);
321
322         PACK_CHECK_BUTTON
323                 (vbox2, chkbtn_transhdr,
324                  _("Translate header name (such as `From:', `Subject:')"));
325
326         PACK_CHECK_BUTTON (vbox2, chkbtn_folder_unread,
327                            _("Display unread number next to folder name"));
328
329         PACK_VSPACER(vbox2, vbox3, VSPACING_NARROW_2);
330
331         hbox1 = gtk_hbox_new (FALSE, 8);
332         gtk_widget_show (hbox1);
333         gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, TRUE, 0);
334
335         label_ng_abbrev = gtk_label_new
336                 (_("Abbreviate newsgroup names longer than"));
337         gtk_widget_show (label_ng_abbrev);
338         gtk_box_pack_start (GTK_BOX (hbox1), label_ng_abbrev, FALSE, FALSE, 0);
339
340         spinbtn_ng_abbrev_len_adj = gtk_adjustment_new (16, 0, 999, 1, 10, 10);
341         spinbtn_ng_abbrev_len = gtk_spin_button_new
342                 (GTK_ADJUSTMENT (spinbtn_ng_abbrev_len_adj), 1, 0);
343         gtk_widget_show (spinbtn_ng_abbrev_len);
344         gtk_box_pack_start (GTK_BOX (hbox1), spinbtn_ng_abbrev_len,
345                             FALSE, FALSE, 0);
346         gtk_widget_set_size_request (spinbtn_ng_abbrev_len, 56, -1);
347         gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (spinbtn_ng_abbrev_len),
348                                      TRUE);
349
350         label_ng_abbrev = gtk_label_new
351                 (_("letters"));
352         gtk_widget_show (label_ng_abbrev);
353         gtk_box_pack_start (GTK_BOX (hbox1), label_ng_abbrev, FALSE, FALSE, 0);
354
355         /* ---- Summary ---- */
356
357         PACK_FRAME(vbox1, frame_summary, _("Summary View"));
358
359         vbox2 = gtk_vbox_new (FALSE, 0);
360         gtk_widget_show (vbox2);
361         gtk_container_add (GTK_CONTAINER (frame_summary), vbox2);
362         gtk_container_set_border_width (GTK_CONTAINER (vbox2), 8);
363
364         PACK_CHECK_BUTTON
365                 (vbox2, chkbtn_swapfrom,
366                  _("Display recipient in `From' column if sender is yourself"));
367         PACK_CHECK_BUTTON
368                 (vbox2, chkbtn_useaddrbook,
369                  _("Display sender using address book"));
370         PACK_CHECK_BUTTON
371                 (vbox2, chkbtn_threadsubj,
372                  _("Thread using subject in addition to standard headers"));
373
374         PACK_VSPACER(vbox2, vbox3, VSPACING_NARROW_2);
375
376         hbox1 = gtk_hbox_new (FALSE, 8);
377         gtk_widget_show (hbox1);
378         gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, TRUE, 0);
379
380         label_datefmt = gtk_label_new (_("Date format"));
381         gtk_widget_show (label_datefmt);
382         gtk_box_pack_start (GTK_BOX (hbox1), label_datefmt, FALSE, FALSE, 0);
383
384         entry_datefmt = gtk_entry_new ();
385         gtk_widget_show (entry_datefmt);
386         gtk_box_pack_start (GTK_BOX (hbox1), entry_datefmt, TRUE, TRUE, 0);
387
388         button_datefmt = gtk_button_new_with_label (" ... ");
389
390         gtk_widget_show (button_datefmt);
391         gtk_box_pack_start (GTK_BOX (hbox1), button_datefmt, FALSE, FALSE, 0);
392         g_signal_connect (G_OBJECT (button_datefmt), "clicked",
393                           G_CALLBACK (date_format_create), NULL);
394
395         PACK_VSPACER(vbox2, vbox3, VSPACING_NARROW);
396
397         hbox1 = gtk_hbox_new (FALSE, 8);
398         gtk_widget_show (hbox1);
399         gtk_box_pack_start (GTK_BOX (vbox2), hbox1, FALSE, TRUE, 0);
400
401         button_dispitem = gtk_button_new_with_label
402                 (_(" Set displayed items in summary... "));
403         gtk_widget_show (button_dispitem);
404         gtk_box_pack_start (GTK_BOX (hbox1), button_dispitem, FALSE, TRUE, 0);
405         g_signal_connect (G_OBJECT (button_dispitem), "clicked",
406                           G_CALLBACK (prefs_summary_column_open),
407                           NULL);
408
409         prefs_summaries->window                 = GTK_WIDGET(window);
410         
411         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chkbtn_transhdr),
412                         prefs_common.trans_hdr);
413         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chkbtn_folder_unread),
414                         prefs_common.display_folder_unread);
415         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chkbtn_swapfrom),
416                         prefs_common.swap_from);
417         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chkbtn_useaddrbook),
418                         prefs_common.use_addr_book);
419         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(chkbtn_threadsubj),
420                         prefs_common.thread_by_subject);
421         gtk_spin_button_set_value(GTK_SPIN_BUTTON(spinbtn_ng_abbrev_len),
422                         prefs_common.ng_abbrev_len);
423         gtk_entry_set_text(GTK_ENTRY(entry_datefmt), 
424                         prefs_common.date_format?prefs_common.date_format:"");  
425
426         prefs_summaries->chkbtn_transhdr = chkbtn_transhdr;
427         prefs_summaries->chkbtn_folder_unread = chkbtn_folder_unread;
428         prefs_summaries->spinbtn_ng_abbrev_len = spinbtn_ng_abbrev_len;
429         prefs_summaries->chkbtn_swapfrom = chkbtn_swapfrom;
430         prefs_summaries->chkbtn_useaddrbook = chkbtn_useaddrbook;
431         prefs_summaries->chkbtn_threadsubj = chkbtn_threadsubj;
432         prefs_summaries->entry_datefmt = entry_datefmt;
433
434         prefs_summaries->page.widget = vbox1;
435 }
436
437 void prefs_summaries_save(PrefsPage *_page)
438 {
439         SummariesPage *page = (SummariesPage *) _page;
440
441         prefs_common.trans_hdr = gtk_toggle_button_get_active(
442                         GTK_TOGGLE_BUTTON(page->chkbtn_transhdr));
443         prefs_common.display_folder_unread = gtk_toggle_button_get_active(
444                         GTK_TOGGLE_BUTTON(page->chkbtn_folder_unread));
445         prefs_common.swap_from = gtk_toggle_button_get_active(
446                         GTK_TOGGLE_BUTTON(page->chkbtn_swapfrom));
447         prefs_common.use_addr_book = gtk_toggle_button_get_active(
448                         GTK_TOGGLE_BUTTON(page->chkbtn_useaddrbook));
449         prefs_common.thread_by_subject = gtk_toggle_button_get_active(
450                         GTK_TOGGLE_BUTTON(page->chkbtn_threadsubj));
451         prefs_common.ng_abbrev_len = gtk_spin_button_get_value_as_int(
452                         GTK_SPIN_BUTTON(page->spinbtn_ng_abbrev_len));
453         
454         g_free(prefs_common.date_format); 
455         prefs_common.date_format = gtk_editable_get_chars(
456                         GTK_EDITABLE(page->entry_datefmt), 0, -1);      
457 }
458
459 static void prefs_summaries_destroy_widget(PrefsPage *_page)
460 {
461 }
462
463 SummariesPage *prefs_summaries;
464
465 void prefs_summaries_init(void)
466 {
467         SummariesPage *page;
468         static gchar *path[3];
469
470         path[0] = _("Display");
471         path[1] = _("Summaries");
472         path[2] = NULL;
473
474         page = g_new0(SummariesPage, 1);
475         page->page.path = path;
476         page->page.create_widget = prefs_summaries_create_widget;
477         page->page.destroy_widget = prefs_summaries_destroy_widget;
478         page->page.save_page = prefs_summaries_save;
479         page->page.weight = 60.0;
480         prefs_gtk_register_page((PrefsPage *) page);
481         prefs_summaries = page;
482 }
483
484 void prefs_summaries_done(void)
485 {
486         prefs_gtk_unregister_page((PrefsPage *) prefs_summaries);
487         g_free(prefs_summaries);
488 }
489
490 static void date_format_ok_btn_clicked(GtkButton *button, GtkWidget **widget)
491 {
492         GtkWidget *datefmt_sample = NULL;
493         gchar *text;
494
495         g_return_if_fail(widget != NULL);
496         g_return_if_fail(*widget != NULL);
497         g_return_if_fail(prefs_summaries->entry_datefmt != NULL);
498
499         datefmt_sample = GTK_WIDGET(g_object_get_data
500                                     (G_OBJECT(*widget), "datefmt_sample"));
501         g_return_if_fail(datefmt_sample != NULL);
502
503         text = gtk_editable_get_chars(GTK_EDITABLE(datefmt_sample), 0, -1);
504         g_free(prefs_common.date_format);
505         prefs_common.date_format = text;
506         gtk_entry_set_text(GTK_ENTRY(prefs_summaries->entry_datefmt), text);
507
508         gtk_widget_destroy(*widget);
509         *widget = NULL;
510 }
511
512 static void date_format_cancel_btn_clicked(GtkButton *button,
513                                            GtkWidget **widget)
514 {
515         g_return_if_fail(widget != NULL);
516         g_return_if_fail(*widget != NULL);
517
518         gtk_widget_destroy(*widget);
519         *widget = NULL;
520 }
521
522 static gboolean date_format_key_pressed(GtkWidget *keywidget, GdkEventKey *event,
523                                         GtkWidget **widget)
524 {
525         if (event && event->keyval == GDK_Escape)
526                 date_format_cancel_btn_clicked(NULL, widget);
527         return FALSE;
528 }
529
530 static gboolean date_format_on_delete(GtkWidget *dialogwidget,
531                                       GdkEventAny *event, GtkWidget **widget)
532 {
533         g_return_val_if_fail(widget != NULL, FALSE);
534         g_return_val_if_fail(*widget != NULL, FALSE);
535
536         *widget = NULL;
537         return FALSE;
538 }
539
540 static void date_format_entry_on_change(GtkEditable *editable,
541                                         GtkLabel *example)
542 {
543         time_t cur_time;
544         struct tm *cal_time;
545         gchar buffer[100];
546         gchar *text;
547
548         cur_time = time(NULL);
549         cal_time = localtime(&cur_time);
550         buffer[0] = 0;
551         text = gtk_editable_get_chars(editable, 0, -1);
552         if (text)
553                 strftime(buffer, sizeof buffer, text, cal_time); 
554         g_free(text);
555
556         text = conv_codeset_strdup(buffer,
557                                    conv_get_locale_charset_str(),
558                                    CS_UTF_8);
559         if (!text)
560                 text = g_strdup(buffer);
561
562         gtk_label_set_text(example, text);
563
564         g_free(text);
565 }
566
567 static void date_format_select_row(GtkTreeView *list_view,
568                                    GtkTreePath *path,
569                                    GtkTreeViewColumn *column,
570                                    GtkWidget *date_format)
571 {
572         gint cur_pos;
573         gchar *format;
574         const gchar *old_format;
575         gchar *new_format;
576         GtkWidget *datefmt_sample;
577         GtkTreeIter iter;
578         GtkTreeModel *model;
579         
580         g_return_if_fail(date_format != NULL);
581
582         /* only on double click */
583         datefmt_sample = GTK_WIDGET(g_object_get_data(G_OBJECT(date_format), 
584                                                       "datefmt_sample"));
585
586         g_return_if_fail(datefmt_sample != NULL);
587
588         model = gtk_tree_view_get_model(list_view);
589
590         /* get format from list */
591         if (!gtk_tree_model_get_iter(model, &iter, path))
592                 return;
593
594         gtk_tree_model_get(model, &iter, DATEFMT_FMT, &format, -1);             
595         
596         cur_pos = gtk_editable_get_position(GTK_EDITABLE(datefmt_sample));
597         old_format = gtk_entry_get_text(GTK_ENTRY(datefmt_sample));
598
599         /* insert the format into the text entry */
600         new_format = g_malloc(strlen(old_format) + 3);
601
602         strncpy(new_format, old_format, cur_pos);
603         new_format[cur_pos] = '\0';
604         strcat(new_format, format);
605         strcat(new_format, &old_format[cur_pos]);
606
607         gtk_entry_set_text(GTK_ENTRY(datefmt_sample), new_format);
608         gtk_editable_set_position(GTK_EDITABLE(datefmt_sample), cur_pos + 2);
609
610         g_free(new_format);
611 }