Gazpacho support, added the following properties:
[hildon] / hildon-widgets / hildon-font-selection-dialog.c
1 /*
2  * This file is part of hildon-libs
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  *
6  * Contact: Luc Pionchon <luc.pionchon@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include <gtk/gtkstock.h>
29 #include <gtk/gtkcombobox.h>
30 #include <gtk/gtktogglebutton.h>
31 #include <gtk/gtkcheckbutton.h>
32 #include <gtk/gtklabel.h>
33 #include <gtk/gtkvbox.h>
34 #include <gtk/gtkliststore.h>
35 #include <gtk/gtknotebook.h>
36 #include <gtk/gtk.h>
37 #include <glib.h>
38 #include <gdk/gdkkeysyms.h>
39
40 #include "hildon-font-selection-dialog.h"
41 #include <hildon-widgets/hildon-caption.h>
42 #include <hildon-widgets/hildon-color-selector.h>
43 #include <hildon-widgets/hildon-color-button.h>
44
45 #ifdef HAVE_CONFIG_H
46 #include <config.h>
47 #endif
48
49 #include <libintl.h>
50 #define _(String) dgettext(PACKAGE, String)
51
52 #define SUPERSCRIPT_RISE 3333
53 #define SUBSCRIPT_LOW -3333
54 #define ON_BIT 0x01
55 #define OFF_BIT 0x02
56 #define REFERENCE_LINE "Reference: " /*localized string?*/
57
58 /*
59  * These are what we use as the standard font sizes, for the size list.
60  */
61 static const guint16 font_sizes[] = 
62 {
63   6, 8, 10, 12, 16, 24, 32
64 };
65
66 #define HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(obj) \
67 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
68                               HILDON_TYPE_FONT_SELECTION_DIALOG, \
69                               HildonFontSelectionDialogPrivate))
70
71 /*None of designed api function works, so now it all comes down to 
72  *use properties to achieve what we are supposed to achieve*/
73 enum
74 {
75   PROP_FAMILY = 1,
76   PROP_FAMILY_SET,
77   PROP_SIZE,
78   PROP_SIZE_SET,
79   PROP_COLOR,
80   PROP_COLOR_SET,
81   PROP_BOLD,
82   PROP_BOLD_SET,
83   PROP_ITALIC,
84   PROP_ITALIC_SET,
85   PROP_UNDERLINE,
86   PROP_UNDERLINE_SET,
87   PROP_STRIKETHROUGH,
88   PROP_STRIKETHROUGH_SET,
89   PROP_POSITION,
90   PROP_POSITION_SET,
91   PROP_PREVIEW_TEXT
92 };
93
94 typedef struct
95 _HildonFontSelectionDialogPrivate HildonFontSelectionDialogPrivate;
96
97 struct _HildonFontSelectionDialogPrivate 
98 {  
99   GtkNotebook *notebook;
100
101   gchar *preview_text;
102
103   /*Tab one*/
104   GtkWidget *cbx_font_type;
105   GtkWidget *cbx_font_size;
106   GtkWidget *font_color_button;
107
108   /*Tab two*/
109   GtkWidget *chk_bold;
110   GtkWidget *chk_italic;
111   GtkWidget *chk_underline;
112
113   /*Tab three*/
114   GtkWidget *chk_strikethrough;
115   GtkWidget *cbx_positioning;
116
117   /*Every family*/
118   PangoFontFamily **families;
119   gint n_families;
120
121   /*color_set is used to show whether the color is inconsistent
122    * The handler id is used to block the signal emission
123    * when we change the color setting*/
124   
125   gboolean color_set;
126   gulong color_modified_signal_handler;
127 };
128
129 /*combo box active row indicator -2--inconsistent, -1--undefined 
130  * please make sure that you use settings_init settings_apply
131  * and settings_destroy, dont even try to touch this structure 
132  * without using the three above interface functions, of course
133  * if you know what you are doing, do as you please ;-)*/
134 typedef struct
135 {
136   HildonFontSelectionDialog
137                *fsd; /*pointer to our font selection dialog*/
138   
139   gint         family; /*combo box indicator*/
140   gint         size; /*combo box indicator*/
141   GdkColor     *color; /*free after read the setting*/
142   gboolean     color_inconsist;
143   gint         weight; /*bit mask*/
144   gint         style;  /*bit mask*/
145   gint         underline; /*bit mask*/
146   gint         strikethrough; /*bit mask*/
147   gint         position; /*combo box indicator*/
148
149 }HildonFontSelectionDialogSettings;
150
151 static gboolean
152               hildon_font_selection_dialog_preview_key_press
153                                              (GtkWidget * widget,
154                                               GdkEventKey * event,
155                                               gpointer data);
156
157 /*Some tools from gtk_font_selection*/
158 static int    cmp_families                   (const void *a, const void *b);
159
160 static void   hildon_font_selection_dialog_show_preview
161                                              (HildonFontSelectionDialog 
162                                               *fontsel);
163                                              
164 static PangoAttrList*
165               hildon_font_selection_dialog_create_attrlist
166                                              (HildonFontSelectionDialog 
167                                               *fontsel, guint start_index,
168                                               guint len);
169
170 static void   hildon_font_selection_dialog_show_available_positionings
171                                              (HildonFontSelectionDialogPrivate
172                                               *priv);
173                                                  
174 static void   hildon_font_selection_dialog_show_available_fonts
175                                              (HildonFontSelectionDialog
176                                               *fontsel);
177                                                  
178 static void   hildon_font_selection_dialog_show_available_sizes
179                                              (HildonFontSelectionDialogPrivate
180                                               *priv);
181
182 static void   hildon_font_selection_dialog_class_init
183                                              (HildonFontSelectionDialogClass 
184                                               *klass);
185                                                  
186 static void   hildon_font_selection_dialog_init
187                                              (HildonFontSelectionDialog 
188                                               *fontseldiag);
189
190 static void   hildon_font_selection_dialog_finalize
191                                              (GObject * object);
192
193 static void   hildon_font_selection_dialog_construct_notebook  
194                                              (HildonFontSelectionDialog
195                                               *fontsel);
196                                              
197 static void   color_modified_cb              (HildonColorButton *button,
198                                               GParamSpec *pspec,
199                                               gpointer data);
200
201 static void   check_tags                     (gpointer data,
202                                               gpointer user_data);
203
204 static void   settings_init                  (HildonFontSelectionDialogSettings
205                                               *setttings,
206                                               HildonFontSelectionDialog
207                                               *fsd);
208
209 static void   settings_apply                 (HildonFontSelectionDialogSettings
210                                               *setttings);
211
212 static void   settings_destroy               (HildonFontSelectionDialogSettings
213                                               *setttings);
214
215 static void   bit_mask_toggle                (gint mask, GtkToggleButton*
216                                               button, GObject *object, 
217                                               const gchar *prop, 
218                                               const gchar *prop_set);
219
220 static void   combo_active                   (gint active, GtkComboBox *box,
221                                               GObject *object, 
222                                               const gchar *prop,
223                                               const gchar *prop_set);
224
225 static void   add_preview_text_attr          (PangoAttrList *list, 
226                                               PangoAttribute *attr, 
227                                               guint start, 
228                                               guint len);
229
230 static void   toggle_clicked                 (GtkButton *button, 
231                                               gpointer data);
232         
233                                              
234                                              
235 static GtkDialogClass *font_selection_dialog_parent_class = NULL;
236
237 GType hildon_font_selection_dialog_get_type(void)
238 {
239   static GType font_selection_dialog_type = 0;
240
241   if (!font_selection_dialog_type) {
242     static const GTypeInfo fontsel_diag_info = {
243       sizeof(HildonFontSelectionDialogClass),
244       NULL,       /* base_init */
245       NULL,       /* base_finalize */
246       (GClassInitFunc) hildon_font_selection_dialog_class_init,
247       NULL,       /* class_finalize */
248       NULL,       /* class_data */
249       sizeof(HildonFontSelectionDialog),
250       0,  /* n_preallocs */
251       (GInstanceInitFunc) hildon_font_selection_dialog_init,
252     };
253
254     font_selection_dialog_type =
255       g_type_register_static(GTK_TYPE_DIALOG,
256                              "HildonFontSelectionDialog",
257                              &fontsel_diag_info, 0);
258   }
259
260   return font_selection_dialog_type;
261 }
262
263 static void
264 hildon_font_selection_dialog_get_property (GObject      *object,
265                                            guint         prop_id,
266                                            GValue       *value,
267                                            GParamSpec   *pspec)
268 {
269   gint i;
270   GdkColor *color = NULL;
271   
272   HildonFontSelectionDialogPrivate *priv =
273     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(
274         HILDON_FONT_SELECTION_DIALOG(object));
275   
276   
277   switch (prop_id)
278     {
279     case PROP_FAMILY:
280       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_type));
281       if(i >= 0 && i < priv->n_families)
282         g_value_set_string(value, 
283                            pango_font_family_get_name(priv->families[i]));
284       else
285         g_value_set_string(value, "Nokia Sans");
286       break;
287       
288     case PROP_FAMILY_SET:
289       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_type));
290       if(i >= 0 && i < priv->n_families)
291         g_value_set_boolean(value, TRUE);
292       else
293         g_value_set_boolean(value, FALSE);
294       break;
295       
296     case PROP_SIZE:
297       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_size));
298       if(i >= 0 && i < G_N_ELEMENTS(font_sizes))
299         g_value_set_int(value, font_sizes[i]);
300       else
301         g_value_set_int(value, 16);
302       break;
303       
304     case PROP_SIZE_SET:
305       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_font_size));
306       if(i >= 0 && i < G_N_ELEMENTS(font_sizes))
307         g_value_set_boolean(value, TRUE);
308       else
309         g_value_set_boolean(value, FALSE);
310       break;
311
312     case PROP_COLOR:
313       color = hildon_color_button_get_color
314         (HILDON_COLOR_BUTTON(priv->font_color_button));
315       g_value_set_boxed(value, (gconstpointer) color);
316       if(color != NULL)
317         gdk_color_free(color);
318       break;
319       
320     case PROP_COLOR_SET:
321       g_value_set_boolean(value, priv->color_set);
322       break;
323
324     case PROP_BOLD:
325       g_value_set_boolean(value, 
326         gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(priv->chk_bold)));
327       break;
328
329     case PROP_BOLD_SET:
330       g_value_set_boolean(value,
331         !gtk_toggle_button_get_inconsistent
332         (GTK_TOGGLE_BUTTON(priv->chk_bold)));
333       break;
334       
335     case PROP_ITALIC:
336       g_value_set_boolean(value, 
337         gtk_toggle_button_get_active
338         (GTK_TOGGLE_BUTTON(priv->chk_italic)));
339       break;
340
341     case PROP_ITALIC_SET:
342       g_value_set_boolean(value,
343         !gtk_toggle_button_get_inconsistent
344         (GTK_TOGGLE_BUTTON(priv->chk_italic)));
345       break;
346       
347     case PROP_UNDERLINE:
348       g_value_set_boolean(value, 
349         gtk_toggle_button_get_active
350         (GTK_TOGGLE_BUTTON(priv->chk_underline)));
351       break;
352
353     case PROP_UNDERLINE_SET:
354       g_value_set_boolean(value,
355         !gtk_toggle_button_get_inconsistent
356         (GTK_TOGGLE_BUTTON(priv->chk_underline)));
357       break;
358       
359     case PROP_STRIKETHROUGH:
360       g_value_set_boolean(value, 
361         gtk_toggle_button_get_active
362         (GTK_TOGGLE_BUTTON(priv->chk_strikethrough)));
363       break;
364
365     case PROP_STRIKETHROUGH_SET:
366       g_value_set_boolean(value,
367         !gtk_toggle_button_get_inconsistent
368         (GTK_TOGGLE_BUTTON(priv->chk_strikethrough)));
369       break;
370
371     case PROP_POSITION:
372       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_positioning));
373       if(i == 1)/*super*/
374         g_value_set_int(value, 1);
375       else if(i == 2)/*sub*/
376         g_value_set_int(value, -1);
377       else
378         g_value_set_int(value, 0);
379       break;
380       
381     case PROP_POSITION_SET:
382       i = gtk_combo_box_get_active(GTK_COMBO_BOX(priv->cbx_positioning));
383       if(i >= 0 && i < 3)
384         g_value_set_boolean(value, TRUE);
385       else
386         g_value_set_boolean(value, FALSE);
387       break;
388     
389     case PROP_PREVIEW_TEXT:
390         g_value_set_string(value,
391                 hildon_font_selection_dialog_get_preview_text(
392                     HILDON_FONT_SELECTION_DIALOG(object)));
393       break;
394     
395     default:
396       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
397       break;
398     }
399 }
400
401 static void 
402 hildon_font_selection_dialog_set_property (GObject         *object,
403                                            guint            prop_id,
404                                            const GValue    *value,
405                                            GParamSpec      *pspec)
406 {
407   gint i, size;
408   const gchar *str;
409   gboolean b;
410   GdkColor *color = NULL;
411   GdkColor black;
412   
413   HildonFontSelectionDialogPrivate *priv =
414     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(
415         HILDON_FONT_SELECTION_DIALOG(object));
416   black.red = black.green = black.blue = 0;
417   
418   switch (prop_id)
419     {
420     case PROP_FAMILY:
421       str = g_value_get_string(value);
422       for(i = 0; i < priv->n_families; i++)
423         {
424           if(strcmp(str, pango_font_family_get_name(priv->families[i]))
425              == 0)
426             {
427               gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_type), i);
428               break;
429             }
430         }
431       break;
432       
433     case PROP_FAMILY_SET:
434       b = g_value_get_boolean(value);
435       if(!b)
436         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_type), -1);
437       break;
438     
439     case PROP_SIZE:
440       size = g_value_get_int(value);
441       for(i = 0; i < G_N_ELEMENTS(font_sizes); i++)
442         {
443           if(size == font_sizes[i])
444             {
445               gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_size), i);
446               break;
447             }
448         }
449       break;
450       
451     case PROP_SIZE_SET:
452       b = g_value_get_boolean(value);
453       if(!b)
454         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_font_size), -1);
455       break;
456
457     case PROP_COLOR:
458       color = (GdkColor *) g_value_get_boxed(value);
459       if(color != NULL)
460         hildon_color_button_set_color(HILDON_COLOR_BUTTON
461                                       (priv->font_color_button),
462                                       color);
463       else
464         hildon_color_button_set_color(HILDON_COLOR_BUTTON
465                                       (priv->font_color_button),
466                                       &black);
467       break;
468
469     case PROP_COLOR_SET:
470       priv->color_set = g_value_get_boolean(value);
471       if(!priv->color_set)
472         {
473           /*set color to black, but block our signal handler*/
474           g_signal_handler_block((gpointer) priv->font_color_button,
475                                  priv->color_modified_signal_handler);
476           
477           hildon_color_button_set_color(HILDON_COLOR_BUTTON
478                                         (priv->font_color_button), 
479                                         &black);
480           
481           g_signal_handler_unblock((gpointer) priv->font_color_button,
482                                  priv->color_modified_signal_handler);
483         }
484       break;
485
486     case PROP_BOLD:
487       /*this call will make sure that we dont get extra clicked signal*/
488       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_bold),
489                                          FALSE);
490       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_bold),
491                                    g_value_get_boolean(value));
492       break;
493
494     case PROP_BOLD_SET:
495       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_bold),
496                                          !g_value_get_boolean(value));
497       break;
498       
499     case PROP_ITALIC:
500       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_italic),
501                                          FALSE);
502       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_italic),
503                                    g_value_get_boolean(value));
504       break;
505
506     case PROP_ITALIC_SET:
507       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_italic),
508                                          !g_value_get_boolean(value));
509       break;
510       
511     case PROP_UNDERLINE:
512       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON
513                                          (priv->chk_underline),
514                                          FALSE);
515       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_underline),
516                                    g_value_get_boolean(value));
517       break;
518
519     case PROP_UNDERLINE_SET:
520       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON(priv->chk_underline),
521                                          !g_value_get_boolean(value));
522       break;
523   
524     case PROP_STRIKETHROUGH:
525       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON
526                                          (priv->chk_strikethrough),
527                                          FALSE);
528       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->chk_strikethrough),
529                                    g_value_get_boolean(value));
530       break;
531
532     case PROP_STRIKETHROUGH_SET:
533       gtk_toggle_button_set_inconsistent(GTK_TOGGLE_BUTTON
534                                          (priv->chk_strikethrough),
535                                          !g_value_get_boolean(value));
536       break;
537
538     case PROP_POSITION:
539       i = g_value_get_int(value);
540       if( i == 1 )
541         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 1);
542       else if(i == -1)
543         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 2);
544       else
545         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), 0);
546       break;
547       
548     case PROP_POSITION_SET:
549       b = g_value_get_boolean(value);
550       if(!b)
551         gtk_combo_box_set_active(GTK_COMBO_BOX(priv->cbx_positioning), -1);
552       break;
553
554     case PROP_PREVIEW_TEXT:
555       hildon_font_selection_dialog_set_preview_text(
556               HILDON_FONT_SELECTION_DIALOG(object),
557               g_value_get_string(value));
558       break;
559     
560     default:
561       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
562       break;
563     }
564 }
565
566 static void
567 hildon_font_selection_dialog_class_init(HildonFontSelectionDialogClass *
568                                         klass)
569 {
570   GObjectClass *gobject_class;
571
572   font_selection_dialog_parent_class = g_type_class_peek_parent(klass);
573   gobject_class = G_OBJECT_CLASS(klass);
574   gobject_class->finalize = hildon_font_selection_dialog_finalize;
575   gobject_class->get_property = hildon_font_selection_dialog_get_property;
576   gobject_class->set_property = hildon_font_selection_dialog_set_property;
577
578   g_object_class_install_property(gobject_class, PROP_FAMILY,
579                                   g_param_spec_string("family",
580                                   "Font family", "String defines"
581                                   " the font family", "Nokia Sans",
582                                   G_PARAM_READWRITE));
583   
584   g_object_class_install_property(gobject_class, PROP_FAMILY_SET,
585                                   g_param_spec_boolean ("family-set",
586                                   "family inconsistent state",
587                                   "Whether the family property"
588                                   " is inconsistent", FALSE,
589                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
590   
591   g_object_class_install_property(gobject_class, PROP_SIZE,
592                                    g_param_spec_int ("size",
593                                    "Font size",
594                                    "Font size in Pt",
595                                    6, 32, 16,
596                                    G_PARAM_READWRITE));
597   
598   g_object_class_install_property(gobject_class, PROP_SIZE_SET,
599                                   g_param_spec_boolean ("size-set",
600                                   "size inconsistent state",
601                                   "Whether the size property"
602                                   " is inconsistent", FALSE,
603                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
604   
605   g_object_class_install_property(gobject_class, PROP_COLOR,
606                                   g_param_spec_boxed ("color",
607                                   "text color",
608                                   "gdk color for the text",
609                                   GDK_TYPE_COLOR,
610                                   G_PARAM_READWRITE));
611
612   g_object_class_install_property(gobject_class, PROP_COLOR_SET,
613                                   g_param_spec_boolean ("color-set",
614                                   "color inconsistent state",
615                                   "Whether the color property"
616                                   " is inconsistent", FALSE,
617                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
618
619   g_object_class_install_property(gobject_class, PROP_BOLD,
620                                   g_param_spec_boolean ("bold",
621                                   "text weight",
622                                   "Whether the text is bold",
623                                   FALSE,
624                                   G_PARAM_READWRITE));
625   
626   g_object_class_install_property(gobject_class, PROP_BOLD_SET,
627                                   g_param_spec_boolean ("bold-set",
628                                   "bold inconsistent state",
629                                   "Whether the bold"
630                                   " is inconsistent", FALSE,
631                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
632   
633   g_object_class_install_property(gobject_class, PROP_ITALIC,
634                                   g_param_spec_boolean ("italic",
635                                   "text style",
636                                   "Whether the text is italic",
637                                   FALSE,
638                                   G_PARAM_READWRITE));
639   
640   g_object_class_install_property(gobject_class, PROP_ITALIC_SET,
641                                   g_param_spec_boolean ("italic-set",
642                                   "italic inconsistent state",
643                                   "Whether the italic"
644                                   " is inconsistent", FALSE,
645                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
646   
647   g_object_class_install_property(gobject_class, PROP_UNDERLINE,
648                                   g_param_spec_boolean ("underline",
649                                   "text underline",
650                                   "Whether the text is underlined",
651                                   FALSE,
652                                   G_PARAM_READWRITE));
653   
654   g_object_class_install_property(gobject_class, PROP_UNDERLINE_SET,
655                                   g_param_spec_boolean ("underline-set",
656                                   "underline inconsistent state",
657                                   "Whether the underline"
658                                   " is inconsistent", FALSE,
659                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
660   
661   g_object_class_install_property(gobject_class, PROP_STRIKETHROUGH,
662                                   g_param_spec_boolean ("strikethrough",
663                                   "strikethroughed text",
664                                   "Whether the text is strikethroughed",
665                                   FALSE,
666                                   G_PARAM_READWRITE));
667   
668   g_object_class_install_property(gobject_class, PROP_STRIKETHROUGH_SET,
669                                   g_param_spec_boolean ("strikethrough-set",
670                                   "strikethrough inconsistent state",
671                                   "Whether the strikethrough"
672                                   " is inconsistent", FALSE,
673                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
674   
675   g_object_class_install_property(gobject_class, PROP_POSITION,
676                                    g_param_spec_int ("position",
677                                    "Font position",
678                                    "Font position super or subscript",
679                                    -1, 1, 0,
680                                    G_PARAM_READWRITE));
681   
682   g_object_class_install_property(gobject_class, PROP_POSITION_SET,
683                                   g_param_spec_boolean ("position-set",
684                                   "position inconsistent state",
685                                   "Whether the position"
686                                   " is inconsistent", FALSE,
687                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
688   
689   g_object_class_install_property(gobject_class, PROP_PREVIEW_TEXT,
690                                   g_param_spec_string("preview-text",
691                                   "Preview Text", 
692                                   "the text in preview dialog, which does" 
693                                   "not include the reference text",
694                                   "",
695                                   G_PARAM_READWRITE));
696   
697
698   g_type_class_add_private(klass,
699                            sizeof(struct _HildonFontSelectionDialogPrivate));
700 }
701
702
703 static void 
704 hildon_font_selection_dialog_init(HildonFontSelectionDialog *fontseldiag)
705 {
706   HildonFontSelectionDialogPrivate *priv =
707     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontseldiag);
708   GtkWidget *preview_button;
709   
710   priv->notebook = GTK_NOTEBOOK(gtk_notebook_new());
711
712   hildon_font_selection_dialog_construct_notebook(fontseldiag);
713   
714   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fontseldiag)->vbox),
715                      GTK_WIDGET(priv->notebook), TRUE, TRUE, 0);
716   
717   /* Add dialog buttons */
718   gtk_dialog_add_button(GTK_DIALOG(fontseldiag),
719                         _("ecdg_bd_font_dialog_ok"),
720                         GTK_RESPONSE_OK);
721   
722   preview_button = gtk_button_new_with_label(_("ecdg_bd_font_dialog_preview"));
723   gtk_box_pack_start(GTK_BOX(GTK_DIALOG(fontseldiag)->action_area), 
724                      preview_button, FALSE, TRUE, 0);
725   g_signal_connect_swapped(preview_button, "clicked",
726                            G_CALLBACK
727                            (hildon_font_selection_dialog_show_preview),
728                            fontseldiag);
729   gtk_widget_show(preview_button);
730
731   gtk_dialog_add_button(GTK_DIALOG(fontseldiag),
732                         _("ecdg_bd_font_dialog_cancel"),
733                         GTK_RESPONSE_CANCEL);
734
735   /*Set default preview text*/
736   priv->preview_text = g_strdup(_("ecdg_fi_preview_font_preview_text"));
737
738   gtk_window_set_title(GTK_WINDOW(fontseldiag), _("ecdg_ti_font"));
739   /*here is the line to make sure that notebook has the default focus*/
740   gtk_container_set_focus_child(GTK_CONTAINER(GTK_DIALOG(fontseldiag)->vbox),
741                                 GTK_WIDGET(priv->notebook));
742 }
743
744 static void 
745 hildon_font_selection_dialog_construct_notebook (HildonFontSelectionDialog
746                                                  *fontsel)
747 {
748   gint i;
749   GtkWidget *vbox_tab[3];
750   GtkWidget *font_color_box;
751   GtkWidget *caption_control;
752   GtkSizeGroup *group;
753   
754   HildonFontSelectionDialogPrivate *priv =
755     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel);
756
757   for (i = 0; i < 3; i++)
758     vbox_tab[i] = gtk_vbox_new(TRUE, 0);
759
760   group =
761     GTK_SIZE_GROUP(gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL));
762   
763   /*Tab one*/
764   priv->cbx_font_type = gtk_combo_box_new_text();
765   hildon_font_selection_dialog_show_available_fonts(fontsel);
766   caption_control = hildon_caption_new(group,
767                                        _("ecdg_fi_font_font"),
768                                        priv->cbx_font_type,
769                                        NULL,
770                                        HILDON_CAPTION_OPTIONAL);
771   gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control,
772                      FALSE, FALSE, 0);
773
774   priv->cbx_font_size = gtk_combo_box_new_text();
775   hildon_font_selection_dialog_show_available_sizes(priv);
776   caption_control = hildon_caption_new(group,
777                                        _("ecdg_fi_font_size"),
778                                        priv->cbx_font_size,
779                                        NULL,
780                                        HILDON_CAPTION_OPTIONAL);
781   gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control,
782                      FALSE, FALSE, 0);
783
784   font_color_box = gtk_hbox_new(FALSE, 0);
785   priv->font_color_button = hildon_color_button_new();
786   priv->color_set = FALSE;
787   priv->color_modified_signal_handler = 
788     g_signal_connect(G_OBJECT(priv->font_color_button), "notify::color",
789                      G_CALLBACK(color_modified_cb), (gpointer) priv);
790   gtk_box_pack_start(GTK_BOX(font_color_box),
791                      priv->font_color_button, FALSE, FALSE, 0);
792   
793   /*dummy widget for packing purpose only*/
794   gtk_box_pack_start(GTK_BOX(font_color_box), gtk_label_new(""),
795                      TRUE, TRUE, 0);
796   
797   caption_control =
798     hildon_caption_new(group, _("ecdg_fi_font_color_selector"),
799                        font_color_box,
800                        NULL, HILDON_CAPTION_OPTIONAL);
801   
802   gtk_box_pack_start(GTK_BOX(vbox_tab[0]), caption_control,
803                      FALSE, FALSE, 0);
804
805   /*Tab two*/
806   priv->chk_bold = gtk_check_button_new();
807   caption_control = hildon_caption_new(group,
808                                        _("ecdg_fi_font_bold"),
809                                        priv->chk_bold,
810                                        NULL,
811                                        HILDON_CAPTION_OPTIONAL);
812   gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control,
813                      FALSE, FALSE, 0);
814   g_signal_connect(G_OBJECT(priv->chk_bold), "clicked", 
815                    G_CALLBACK(toggle_clicked), NULL);
816
817   priv->chk_italic = gtk_check_button_new();
818   caption_control =
819     hildon_caption_new(group, _("ecdg_fi_font_italic"),
820                        priv->chk_italic,
821                        NULL, HILDON_CAPTION_OPTIONAL);
822   gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control,
823                      FALSE, FALSE, 0);
824   g_signal_connect(G_OBJECT(priv->chk_italic), "clicked", 
825                    G_CALLBACK(toggle_clicked), NULL);
826
827   priv->chk_underline = gtk_check_button_new();
828   caption_control =
829     hildon_caption_new(group, _("ecdg_fi_font_underline"),
830                        priv->chk_underline, NULL,
831                        HILDON_CAPTION_OPTIONAL);
832   gtk_box_pack_start(GTK_BOX(vbox_tab[1]), caption_control,
833                      FALSE, FALSE, 0);
834   g_signal_connect(G_OBJECT(priv->chk_underline), "clicked", 
835                    G_CALLBACK(toggle_clicked), NULL);
836
837   /*Tab three*/
838   priv->chk_strikethrough = gtk_check_button_new();
839   caption_control =
840     hildon_caption_new(group, _("ecdg_fi_font_strikethrough"),
841                        priv->chk_strikethrough, NULL,
842                        HILDON_CAPTION_OPTIONAL);
843   gtk_box_pack_start(GTK_BOX(vbox_tab[2]), caption_control,
844                      FALSE, FALSE, 0);
845   g_signal_connect(G_OBJECT(priv->chk_strikethrough), "clicked", 
846                    G_CALLBACK(toggle_clicked), NULL);
847
848   priv->cbx_positioning = gtk_combo_box_new_text();
849   hildon_font_selection_dialog_show_available_positionings(priv);
850   caption_control =
851     hildon_caption_new(group, _("ecdg_fi_font_special"),
852                        priv->cbx_positioning, NULL,
853                        HILDON_CAPTION_OPTIONAL);
854   gtk_box_pack_start(GTK_BOX(vbox_tab[2]), caption_control,
855                      FALSE, FALSE, 0);
856   
857   /* Populate notebook */
858   gtk_notebook_insert_page(priv->notebook, vbox_tab[0], NULL, 0);
859   gtk_notebook_insert_page(priv->notebook, vbox_tab[1], NULL, 1);
860   gtk_notebook_insert_page(priv->notebook, vbox_tab[2], NULL, 2);
861   gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[0],
862                                   _("ecdg_ti_font_dialog_style"));
863   gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[1],
864                                   _("ecdg_ti_font_dialog_format"));
865   gtk_notebook_set_tab_label_text(priv->notebook, vbox_tab[2],
866                                   _("ecdg_ti_font_dialog_other"));
867   
868   gtk_widget_show_all(GTK_WIDGET(priv->notebook));
869 }
870
871 static void 
872 color_modified_cb(HildonColorButton *button, GParamSpec *pspec, gpointer data)
873 {
874   HildonFontSelectionDialogPrivate *priv = 
875     (HildonFontSelectionDialogPrivate *) data;
876
877   priv->color_set = TRUE;
878 }
879
880 static void 
881 hildon_font_selection_dialog_finalize(GObject * object)
882 {
883   HildonFontSelectionDialogPrivate *priv;
884   HildonFontSelectionDialog *fontsel;
885
886   g_return_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(object));
887   fontsel = HILDON_FONT_SELECTION_DIALOG(object);
888
889   priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel);
890   
891   g_free(priv->preview_text);
892   g_free(priv->families);
893
894   if (G_OBJECT_CLASS(font_selection_dialog_parent_class)->finalize)
895     G_OBJECT_CLASS(font_selection_dialog_parent_class)->finalize(object);
896 }
897
898 static int 
899 cmp_families(const void *a, const void *b)
900 {
901   const char *a_name =
902     pango_font_family_get_name(*(PangoFontFamily **) a);
903   const char *b_name =
904     pango_font_family_get_name(*(PangoFontFamily **) b);
905
906   return g_utf8_collate(a_name, b_name);
907 }
908
909 static gboolean
910 hildon_font_selection_dialog_preview_key_press(GtkWidget * widget,
911                                                GdkEventKey * event,
912                                                gpointer data)
913 {
914   g_return_val_if_fail(widget, FALSE);
915   g_return_val_if_fail(event, FALSE);
916
917   if (event->keyval == GDK_Escape) 
918     {
919       gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_CANCEL);
920       return TRUE;
921     }
922
923   return FALSE;
924 }
925
926 static void
927 add_preview_text_attr(PangoAttrList *list, PangoAttribute *attr, 
928                       guint start, guint len)
929 {
930   attr->start_index = start;
931   attr->end_index = start + len;
932   pango_attr_list_insert(list, attr);
933 }
934
935 static PangoAttrList*
936 hildon_font_selection_dialog_create_attrlist(HildonFontSelectionDialog *
937                                          fontsel, guint start_index, guint len)
938 {
939   PangoAttrList *list;
940   PangoAttribute *attr;
941   gint size, position;
942   gboolean family_set, size_set, color_set, bold, bold_set,
943            italic, italic_set, underline, underline_set,
944            strikethrough, strikethrough_set, position_set;
945   GdkColor *color = NULL;
946   gchar *family = NULL;
947
948   list = pango_attr_list_new();
949  
950   g_object_get(G_OBJECT(fontsel),
951                "family", &family, "family-set", &family_set,
952                "size", &size, "size-set", &size_set,
953                "color", &color, "color-set", &color_set,
954                "bold", &bold, "bold-set", &bold_set,
955                "italic", &italic, "italic-set", &italic_set,
956                "underline", &underline, "underline-set", &underline_set,
957                "strikethrough", &strikethrough, "strikethrough-set", 
958                &strikethrough_set, "position", &position, 
959                "position-set", &position_set, NULL);
960
961   /*family*/
962   if(family_set)
963     {
964       attr = pango_attr_family_new(family);
965       add_preview_text_attr(list, attr, start_index, len);
966     }
967   g_free(family);
968   
969   /*size*/
970   if(size_set)
971     {
972       attr = pango_attr_size_new(size * PANGO_SCALE);
973       add_preview_text_attr(list, attr, start_index, len);
974     }
975   
976   /*color*/
977   if(color_set)
978     {
979       attr = pango_attr_foreground_new(color->red, color->green, color->blue);
980       add_preview_text_attr(list, attr, start_index, len);
981     }
982   
983   if(color != NULL)
984     gdk_color_free(color);
985   
986   /*weight*/
987   if(bold_set)
988     {
989       if(bold)
990         attr = pango_attr_weight_new(PANGO_WEIGHT_BOLD);
991       else
992         attr = pango_attr_weight_new(PANGO_WEIGHT_NORMAL);
993
994       add_preview_text_attr(list, attr, start_index, len);
995     }
996   
997   /*style*/
998   if(italic_set)
999     {
1000       if(italic)
1001         attr = pango_attr_style_new(PANGO_STYLE_ITALIC);
1002       else
1003         attr = pango_attr_style_new(PANGO_STYLE_NORMAL);
1004
1005       add_preview_text_attr(list, attr, start_index, len);
1006     }
1007   
1008   /*underline*/
1009   if(underline_set)
1010     {
1011       if(underline)
1012         attr = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
1013       else
1014         attr = pango_attr_underline_new(PANGO_UNDERLINE_NONE);
1015
1016       add_preview_text_attr(list, attr, start_index, len);
1017     }
1018   
1019   /*strikethrough*/
1020   if(strikethrough_set)
1021     {
1022       if(strikethrough)
1023         attr = pango_attr_strikethrough_new(TRUE);
1024       else
1025         attr = pango_attr_strikethrough_new(FALSE);
1026
1027       add_preview_text_attr(list, attr, start_index, len);
1028     }
1029   
1030   /*position*/
1031   if(position_set)
1032     {
1033       switch(position)
1034         {
1035         case 1: /*super*/
1036           attr = pango_attr_rise_new(SUPERSCRIPT_RISE);
1037           break;
1038         case -1: /*sub*/
1039           attr = pango_attr_rise_new(SUBSCRIPT_LOW);
1040           break;
1041         default: /*normal*/
1042           attr = pango_attr_rise_new(0);
1043           break;
1044         }
1045
1046       add_preview_text_attr(list, attr, start_index, len);
1047     }
1048   
1049   return list;
1050 }
1051
1052 static void
1053 hildon_font_selection_dialog_show_preview(HildonFontSelectionDialog *
1054                                           fontsel)
1055 {
1056   HildonFontSelectionDialogPrivate *priv =
1057     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel);
1058   gint size;
1059   gboolean family_set, size_set;
1060   PangoAttribute *attr;
1061   PangoAttrList *list;
1062   GtkWidget *preview_dialog;
1063   GtkWidget *preview_label;
1064   gchar *str = NULL;
1065   
1066   /*Preview dialog init*/
1067   preview_dialog=
1068     gtk_dialog_new_with_buttons(_("ecdg_ti_preview_font"), NULL,
1069                                 GTK_DIALOG_MODAL |
1070                                 GTK_DIALOG_DESTROY_WITH_PARENT |
1071                                 GTK_DIALOG_NO_SEPARATOR,
1072                                 _("ecdg_bd_font_dialog_ok"),
1073                                 GTK_RESPONSE_ACCEPT,
1074                                 NULL);
1075
1076   str = g_strconcat(REFERENCE_LINE, priv->preview_text, 0);
1077   preview_label = gtk_label_new(str);
1078   g_free(str);
1079   str = NULL;
1080
1081   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(preview_dialog)->vbox),
1082                     preview_label);
1083
1084   /* set keypress handler (ESC hardkey) */
1085   g_signal_connect(G_OBJECT(preview_dialog), "key-press-event",
1086                    G_CALLBACK
1087                    (hildon_font_selection_dialog_preview_key_press),
1088                    NULL);
1089
1090   /*Set the font*/
1091   list = hildon_font_selection_dialog_create_attrlist(fontsel, 
1092                                 strlen(REFERENCE_LINE),
1093                                 strlen(priv->preview_text));
1094
1095   g_object_get(G_OBJECT(fontsel), "family", &str, "family-set",
1096                &family_set, "size", &size, "size-set", &size_set,
1097                NULL);
1098   /*make reference text to have the same fontface and size*/
1099   if(family_set)
1100     {
1101       attr = pango_attr_family_new(str);
1102       add_preview_text_attr(list, attr, 0, strlen(REFERENCE_LINE));
1103     }
1104   g_free(str);
1105   
1106   /*size*/
1107   if(size_set)
1108     {
1109       attr = pango_attr_size_new(size * PANGO_SCALE);
1110       add_preview_text_attr(list, attr, 0, strlen(REFERENCE_LINE));
1111     }
1112   
1113   gtk_label_set_attributes(GTK_LABEL(preview_label), list);
1114   pango_attr_list_unref(list);
1115   
1116   /*And show the dialog*/
1117   gtk_window_set_transient_for(GTK_WINDOW(preview_dialog), 
1118                                GTK_WINDOW(fontsel));
1119   gtk_widget_show_all(preview_dialog);
1120   gtk_dialog_run(GTK_DIALOG(preview_dialog));
1121   gtk_widget_destroy(preview_dialog);
1122 }
1123
1124 static void
1125 hildon_font_selection_dialog_show_available_fonts(HildonFontSelectionDialog 
1126                                                   *fontsel)
1127
1128 {
1129   gint i;
1130   
1131   HildonFontSelectionDialogPrivate *priv =
1132     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fontsel);
1133
1134   pango_context_list_families(gtk_widget_get_pango_context
1135                               (GTK_WIDGET(fontsel)), &priv->families,
1136                               &priv->n_families);
1137
1138   qsort(priv->families, priv->n_families, sizeof(PangoFontFamily *),
1139         cmp_families);
1140
1141
1142   for (i = 0; i < priv->n_families; i++) 
1143     {
1144       const gchar *name = pango_font_family_get_name(priv->families[i]);
1145
1146       gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_font_type),
1147                                 name);
1148     }
1149 }
1150
1151
1152 static void
1153 hildon_font_selection_dialog_show_available_positionings
1154                                              (HildonFontSelectionDialogPrivate
1155                                               *priv)
1156 {
1157   gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning),
1158                             _("ecdg_va_font_printpos_1"));
1159   gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning),
1160                             _("ecdg_va_font_printpos_2"));
1161   gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_positioning),
1162                             _("ecdg_va_font_printpos_3"));
1163 }
1164
1165 /*Loads the sizes from a pre-allocated table*/
1166 static void
1167 hildon_font_selection_dialog_show_available_sizes
1168                                              (HildonFontSelectionDialogPrivate
1169                                               *priv)
1170 {
1171   gchar *size_str;
1172   gint i;
1173
1174   for (i = 0; i < G_N_ELEMENTS(font_sizes); i++) 
1175     {
1176       size_str = g_strdup_printf ("%i %s",
1177                                   font_sizes[i],
1178                                   _("ecdg_va_font_size_trailer"));
1179
1180       gtk_combo_box_append_text(GTK_COMBO_BOX(priv->cbx_font_size),
1181                                 size_str);
1182       g_free (size_str);
1183     }
1184 }
1185
1186 static
1187 void check_tags(gpointer data, gpointer user_data)
1188 {
1189   gchar *font_family;
1190   GdkColor *fore_color =  NULL;
1191   gint p_size, p_weight, p_style, p_underline, p_rise;
1192   gboolean b_st, ff_s, size_s, fgc_s, w_s, ss_s, u_s, sth_s, r_s;
1193   
1194   GtkTextTag *tag = (GtkTextTag*) data;
1195   HildonFontSelectionDialogSettings *settings = 
1196     (HildonFontSelectionDialogSettings *) user_data;
1197   HildonFontSelectionDialogPrivate *priv = 
1198     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd);
1199   
1200   /*get all the properties*/
1201   g_object_get(G_OBJECT(tag),
1202                "family", &font_family, "family-set", &ff_s,
1203                "size", &p_size, "size-set", &size_s,
1204                "foreground-gdk", &fore_color, "foreground-set", &fgc_s,
1205                "weight", &p_weight, "weight-set", &w_s,
1206                "style", &p_style, "style-set", &ss_s,
1207                "underline", &p_underline, "underline-set", &u_s,
1208                "strikethrough", &b_st, "strikethrough-set", &sth_s, 
1209                "rise", &p_rise, "rise-set", & r_s,
1210                NULL);
1211   
1212   /*settings*/
1213   if(ff_s)
1214     {
1215       gint new_f = -1;
1216       gint i;
1217       
1218       for(i = 0; i < priv->n_families; i++)
1219         {
1220           if(strcmp(font_family, 
1221                     pango_font_family_get_name(priv->families[i])) == 0)
1222             {
1223               new_f = i;
1224               break;
1225             }
1226         }
1227       
1228       if(settings->family == -1)
1229         settings->family = new_f;
1230       else if(settings->family != -2 && 
1231               settings->family != new_f)
1232         settings->family = -2;/*inconsist*/
1233
1234       g_free(font_family);
1235     }
1236   
1237   if(size_s)
1238     {
1239       gint new_size = -1;
1240       gint i;
1241       
1242       for(i = 0; i < G_N_ELEMENTS(font_sizes); i++)
1243         {
1244           if(p_size == font_sizes[i] * PANGO_SCALE)
1245             {
1246               new_size = i;
1247               break;
1248             }
1249         }
1250       
1251       if(settings->size == -1)
1252         settings->size = new_size;
1253       else if(settings->size != -2 && 
1254               settings->size != new_size)
1255         settings->size = -2;/*inconsist*/
1256     }
1257   
1258   if(fgc_s && settings->color == NULL 
1259      && !settings->color_inconsist)
1260         settings->color = fore_color;
1261   else if(fore_color != NULL)
1262     {
1263       if(!gdk_color_equal(fore_color, settings->color) 
1264          && fgc_s)
1265         settings->color_inconsist = TRUE;
1266       
1267       gdk_color_free(fore_color);
1268     }
1269
1270   if(w_s)
1271     settings->weight |= p_weight == PANGO_WEIGHT_NORMAL ? OFF_BIT : ON_BIT;
1272   
1273   if(ss_s)
1274     settings->style |= p_style == PANGO_STYLE_NORMAL ? OFF_BIT : ON_BIT;
1275   
1276   if(u_s)
1277     settings->underline |= 
1278       p_underline == PANGO_UNDERLINE_NONE ? OFF_BIT : ON_BIT;
1279   
1280   if(sth_s)
1281     settings->strikethrough |= b_st ? ON_BIT : OFF_BIT;
1282
1283   if(r_s)
1284     {
1285       gint new_rs = -1;
1286       
1287       if(p_rise == 0)
1288         new_rs = 0;/*normal*/
1289       else if (p_rise > 0)
1290         new_rs = 1;/*super*/
1291       else
1292         new_rs = 2;/*sub*/
1293
1294       if(settings->position == -1)
1295         settings->position = new_rs;
1296       else if(settings->position != -2 && 
1297               settings->position != new_rs)
1298         settings->position = -2;/*inconsist*/
1299     }
1300 }
1301
1302 static
1303 void check_attrs(gpointer data, gpointer user_data)
1304 {
1305   PangoAttribute *attr = (PangoAttribute *) data;
1306   HildonFontSelectionDialogSettings *settings = 
1307     (HildonFontSelectionDialogSettings *) user_data;
1308   HildonFontSelectionDialogPrivate *priv = 
1309     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd);
1310   
1311   gchar *family;
1312   GdkColor color;
1313   gint i;
1314   gint size, weight, style, underline, strikethrough, rise;
1315   gint new_f = -1, new_size = -1, new_rise = -1;
1316
1317   switch(attr->klass->type)
1318     {
1319     case PANGO_ATTR_FAMILY:
1320       family = ((PangoAttrString *) attr)->value;
1321
1322       for(i = 0; i < priv->n_families; i++)
1323         {
1324           if(strcmp(family, 
1325                     pango_font_family_get_name(priv->families[i])) == 0)
1326             {
1327               new_f = i;
1328               break;
1329             }
1330         }
1331
1332       if(settings->family == -1)
1333         settings->family = new_f;
1334       else if(settings->family != -2 && 
1335               settings->family != new_f)
1336         settings->family = -2;/*inconsist*/
1337       
1338       break;
1339     case PANGO_ATTR_SIZE:
1340       size = ((PangoAttrInt *) attr)->value;
1341       
1342       for(i = 0; i < G_N_ELEMENTS(font_sizes); i++)
1343         {
1344           if(size == font_sizes[i] * PANGO_SCALE)
1345             {
1346               new_size = i;
1347               break;
1348             }
1349         }
1350       
1351       if(settings->size == -1)
1352         settings->size = new_size;
1353       else if(settings->size != -2 && 
1354               settings->size != new_size)
1355         settings->size = -2;/*inconsist*/
1356
1357       break;
1358     case PANGO_ATTR_FOREGROUND:
1359       color.red = ((PangoAttrColor *) attr)->color.red;
1360       color.green = ((PangoAttrColor *) attr)->color.green;
1361       color.blue = ((PangoAttrColor *) attr)->color.blue;
1362
1363       if(!settings->color_inconsist &&  settings->color == NULL)
1364         settings->color = gdk_color_copy(&color);
1365       else if(settings->color != NULL && 
1366               !gdk_color_equal(&color, settings->color))
1367         settings->color_inconsist = TRUE;
1368
1369       break;
1370     case PANGO_ATTR_WEIGHT:
1371       weight = ((PangoAttrInt *) attr)->value;
1372
1373       settings->weight |= weight == PANGO_WEIGHT_NORMAL ? OFF_BIT : ON_BIT;
1374       
1375       break;
1376     case PANGO_ATTR_STYLE:
1377       style = ((PangoAttrInt *) attr)->value;
1378
1379       settings->style |= style == PANGO_STYLE_NORMAL ? OFF_BIT : ON_BIT; 
1380       
1381       break;
1382     case PANGO_ATTR_UNDERLINE:
1383       underline = ((PangoAttrInt *) attr)->value;
1384
1385       settings->underline |= 
1386         underline == PANGO_UNDERLINE_NONE ? OFF_BIT : ON_BIT;
1387   
1388       break;
1389     case PANGO_ATTR_STRIKETHROUGH:
1390       strikethrough = ((PangoAttrInt *) attr)->value;
1391       
1392       settings->strikethrough |= strikethrough ? ON_BIT : OFF_BIT;
1393
1394       break;
1395     case PANGO_ATTR_RISE:
1396       rise = ((PangoAttrInt *) attr)->value;
1397       
1398       if(rise == 0)
1399         new_rise = 0;/*normal*/
1400       else if (rise > 0)
1401         new_rise = 1;/*super*/
1402       else
1403         new_rise = 2;/*sub*/
1404
1405       if(settings->position == -1)
1406         settings->position = new_rise;
1407       else if(settings->position != -2 && 
1408               settings->position != new_rise)
1409         settings->position = -2;/*inconsist*/
1410
1411       break;
1412     default:
1413       break;
1414     }
1415
1416   pango_attribute_destroy(attr);
1417 }
1418
1419 static void
1420 settings_init(HildonFontSelectionDialogSettings *settings,
1421               HildonFontSelectionDialog  *fsd)
1422 {
1423   settings->fsd = fsd;
1424   settings->family = -1;
1425   settings->size = -1;
1426   settings->color = NULL;
1427   settings->color_inconsist = FALSE;
1428   settings->weight = 0;
1429   settings->style = 0;
1430   settings->underline = 0;
1431   settings->strikethrough = 0;
1432   settings->position = -1;
1433 }
1434
1435 static void
1436 bit_mask_toggle(gint mask, GtkToggleButton *button,
1437                 GObject *object, const gchar *prop,
1438                 const gchar *prop_set)
1439 {
1440   
1441   if(mask == 3)
1442     gtk_toggle_button_set_inconsistent(button, TRUE);
1443   else
1444     {
1445       gtk_toggle_button_set_inconsistent(button, FALSE);
1446
1447       if(mask == 1)
1448         gtk_toggle_button_set_active(button, TRUE);
1449       else
1450         gtk_toggle_button_set_active(button, FALSE);
1451
1452       g_object_notify(object, prop);
1453     }
1454
1455   g_object_notify(object, prop_set);
1456 }
1457
1458 static void
1459 combo_active(gint active, GtkComboBox *box, 
1460              GObject *object, const gchar *prop, const gchar *prop_set)
1461 {
1462   /*probaly not the best function, but we need all these
1463    * parameters to keep things together*/
1464  
1465   
1466   if(active >= 0)
1467     {
1468       gtk_combo_box_set_active(box, active);
1469       g_object_notify(object, prop);
1470     }
1471   else
1472     gtk_combo_box_set_active(box, -1);
1473
1474   g_object_notify(object, prop_set);
1475 }
1476
1477 static void
1478 settings_apply(HildonFontSelectionDialogSettings *settings)
1479 {
1480
1481   HildonFontSelectionDialogPrivate *priv = 
1482     HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(settings->fsd);
1483   
1484   /*family*/
1485   combo_active(settings->family, GTK_COMBO_BOX(priv->cbx_font_type),
1486                G_OBJECT(settings->fsd), "family", "family-set");
1487   
1488   /*size*/
1489   combo_active(settings->size, GTK_COMBO_BOX(priv->cbx_font_size),
1490                G_OBJECT(settings->fsd), "size", "size-set");
1491   
1492   /*block our signal handler indicating color has been changed by
1493    * the user before set the color, and unblock it after setting
1494    * is done*/
1495   
1496   if(settings->color == NULL || settings->color_inconsist)
1497     {
1498       GdkColor black;
1499
1500       black.red = black.green = black.blue = 0;
1501       g_signal_handler_block((gpointer) priv->font_color_button,
1502                              priv->color_modified_signal_handler);
1503       
1504       g_object_set(G_OBJECT(settings->fsd), "color", &black, "color-set", 
1505                    FALSE, NULL);
1506
1507       g_signal_handler_unblock((gpointer) priv->font_color_button,
1508                                priv->color_modified_signal_handler);
1509     }
1510   else 
1511       g_object_set(G_OBJECT(settings->fsd), "color", settings->color, NULL);
1512   
1513   /*weight*/
1514   bit_mask_toggle(settings->weight, GTK_TOGGLE_BUTTON(priv->chk_bold),
1515                   G_OBJECT(settings->fsd), "bold", "bold-set");
1516   
1517   /*style*/
1518   bit_mask_toggle(settings->style, GTK_TOGGLE_BUTTON(priv->chk_italic),
1519                   G_OBJECT(settings->fsd), "italic", "italic-set");
1520   
1521   /*underline*/
1522   bit_mask_toggle(settings->underline, 
1523                   GTK_TOGGLE_BUTTON(priv->chk_underline), 
1524                   G_OBJECT(settings->fsd), "underline", "underline-set");
1525   
1526   /*strikethrough*/
1527   bit_mask_toggle(settings->strikethrough, 
1528                   GTK_TOGGLE_BUTTON(priv->chk_strikethrough),
1529                   G_OBJECT(settings->fsd), "strikethrough", 
1530                   "strikethrough-set");
1531
1532   /*position*/
1533   combo_active(settings->position, GTK_COMBO_BOX(priv->cbx_positioning),
1534                G_OBJECT(settings->fsd), "position", "position-set");
1535 }
1536
1537 static void
1538 settings_destroy(HildonFontSelectionDialogSettings *settings)
1539 {
1540   if(settings->color != NULL)
1541     gdk_color_free(settings->color);
1542 }
1543
1544 static void
1545 toggle_clicked(GtkButton *button, gpointer data)
1546 {
1547   GtkToggleButton *t_b = GTK_TOGGLE_BUTTON(button);
1548
1549   /*we have to remove the inconsistent state ourselves*/
1550   if(gtk_toggle_button_get_inconsistent(t_b))
1551     {
1552       gtk_toggle_button_set_inconsistent(t_b, FALSE);
1553       gtk_toggle_button_set_active(t_b, FALSE);
1554     }
1555 }
1556
1557 /*******************/
1558 /*Public functions*/
1559 /*******************/
1560
1561 /**
1562  * hildon_font_selection_dialog_new:
1563  * @parent: the parent window.
1564  * @title: the title of font selection dialog.
1565  *
1566  * If NULL is passed for title, then default title
1567  * "Font" will be used.
1568  *
1569  * Return value: a new #HildonFontSelectionDialog.
1570  */
1571 GtkWidget *
1572 hildon_font_selection_dialog_new(GtkWindow * parent,
1573                                  const gchar * title)
1574 {
1575   HildonFontSelectionDialog *fontseldiag;
1576
1577   fontseldiag = g_object_new(HILDON_TYPE_FONT_SELECTION_DIALOG,
1578                              "has-separator", FALSE, NULL);
1579
1580   if (title)
1581     gtk_window_set_title(GTK_WINDOW(fontseldiag), title);
1582
1583   if (parent)
1584     gtk_window_set_transient_for(GTK_WINDOW(fontseldiag), parent);
1585
1586   return GTK_WIDGET(fontseldiag);
1587 }
1588
1589 /**
1590  * hildon_font_selection_dialog_get_preview_text:
1591  * @fsd: the font selection dialog.
1592  *
1593  * Gets the text in preview dialog, which does not include the 
1594  * reference text. The returned string must be freed by the user.
1595  *
1596  * Returns: a string pointer.
1597  */
1598 gchar *
1599 hildon_font_selection_dialog_get_preview_text(HildonFontSelectionDialog * fsd)
1600 {
1601   HildonFontSelectionDialogPrivate *priv;
1602
1603   g_return_val_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd), FALSE);
1604   priv = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd);
1605   return g_strdup(priv->preview_text);
1606 }
1607
1608 /**
1609  * hildon_font_selection_dialog_set_preview_text:
1610  * @fsd: the font selection dialog.
1611  * @text: the text to be set to the preview dialog.
1612  *
1613  * The default preview text is
1614  * "The quick brown fox jumped over the lazy dogs"
1615  */
1616 void
1617 hildon_font_selection_dialog_set_preview_text(HildonFontSelectionDialog *
1618                                               fsd, const gchar * text)
1619 {
1620   if (HILDON_IS_FONT_SELECTION_DIALOG(fsd)) ;
1621     {
1622       HildonFontSelectionDialogPrivate *priv =
1623         HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd);
1624       g_free(priv->preview_text);
1625       priv->preview_text = g_strdup(text);
1626       g_object_notify (G_OBJECT (fsd), "preview-text");
1627     }
1628 }
1629
1630 /**
1631  * hildon_font_selection_dialog_get_text_tag:
1632  * @fsd: the font selection dialog.
1633  *
1634  * Get the #GtkTextTag for selections. This function
1635  * is deprecated function. The best way to use
1636  * the text tags is to reuse them as much as possible.
1637  * The recommended way is to get the properties of font
1638  * selection dialog on GTK_RESPONSE_OK, according to
1639  * these property use the tags that you have pre-created.
1640  * 
1641  * Returns: a #GtkTextTag having corresponding properties
1642  * set. 
1643  */ 
1644 #ifndef HILDON_DISABLE_DEPRECATED
1645 GtkTextTag * 
1646 hildon_font_selection_dialog_get_text_tag (HildonFontSelectionDialog *fsd)
1647 {
1648   GtkTextTag *tag;
1649   gint size, position;
1650   gboolean family_set, size_set, color_set, bold, bold_set,
1651            italic, italic_set, underline, underline_set,
1652            strikethrough, strikethrough_set, position_set;
1653   GdkColor *color = NULL;
1654   gchar *family = NULL;
1655
1656   tag = gtk_text_tag_new(NULL);
1657   
1658   g_object_get(G_OBJECT(fsd),
1659                "family", &family, "family-set", &family_set,
1660                "size", &size, "size-set", &size_set,
1661                "color", &color, "color-set", &color_set,
1662                "bold", &bold, "bold-set", &bold_set,
1663                "italic", &italic, "italic-set", &italic_set,
1664                "underline", &underline, "underline-set", &underline_set,
1665                "strikethrough", &strikethrough, "strikethrough-set", 
1666                &strikethrough_set, "position", &position, 
1667                "position-set", &position_set, NULL);
1668   /*family*/
1669   if(family_set)
1670     g_object_set(G_OBJECT(tag), "family",
1671                  family, "family-set", TRUE, NULL);
1672   else
1673     g_object_set(G_OBJECT(tag), "family-set", FALSE, NULL);
1674
1675   g_free(family);
1676   
1677   /*size*/
1678   if(size_set)
1679     g_object_set(G_OBJECT(tag), "size", size * PANGO_SCALE, 
1680                  "size-set", TRUE, NULL);
1681   else
1682     g_object_set(G_OBJECT(tag), "size-set", FALSE, NULL);
1683   
1684   /*color*/
1685   if(color_set)
1686     g_object_set(G_OBJECT(tag), "foreground-gdk", color, 
1687                  "foreground-set", TRUE ,NULL);
1688   else
1689     g_object_set(G_OBJECT(tag), "foreground-set", FALSE, NULL);
1690
1691   if(color != NULL)
1692     gdk_color_free(color);
1693   
1694   /*weight*/
1695   if(bold_set)
1696     {
1697       if(bold)
1698         g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_BOLD, NULL);
1699       else
1700         g_object_set(G_OBJECT(tag), "weight", PANGO_WEIGHT_NORMAL, NULL);
1701         
1702       g_object_set(G_OBJECT(tag), "weight-set", TRUE, NULL);
1703     }
1704   else
1705     g_object_set(G_OBJECT(tag), "weight-set", FALSE, NULL);
1706   
1707   /*style*/
1708   if(italic_set)
1709     {
1710       if(italic)
1711         g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_ITALIC, NULL);
1712       else
1713         g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL);
1714         
1715       g_object_set(G_OBJECT(tag), "style-set", TRUE, NULL);
1716     }
1717   else
1718     g_object_set(G_OBJECT(tag), "style-set", FALSE, NULL);
1719   
1720   /*underline*/
1721   if(underline_set)
1722     {
1723       if(underline)
1724         g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_SINGLE, NULL);
1725       else
1726         g_object_set(G_OBJECT(tag), "underline", PANGO_UNDERLINE_NONE, NULL);
1727         
1728       g_object_set(G_OBJECT(tag), "underline-set", TRUE, NULL);
1729     }
1730   else
1731     g_object_set(G_OBJECT(tag), "underline-set", FALSE, NULL);
1732   
1733   /*strikethrough*/
1734   if(strikethrough_set)
1735     {
1736       if(strikethrough)
1737         g_object_set(G_OBJECT(tag), "strikethrough", TRUE, NULL);
1738       else
1739         g_object_set(G_OBJECT(tag), "strikethrough", FALSE, NULL);
1740         
1741       g_object_set(G_OBJECT(tag), "strikethrough-set", TRUE, NULL);
1742     }
1743   else
1744     g_object_set(G_OBJECT(tag), "strikethrough-set", FALSE, NULL);
1745   
1746   /*position*/
1747   if(position_set)
1748     {
1749       switch(position)
1750         {
1751         case 1: /*super*/
1752           g_object_set(G_OBJECT(tag), "rise", SUPERSCRIPT_RISE, NULL);
1753           break;
1754         case -1: /*sub*/
1755           g_object_set(G_OBJECT(tag), "rise", SUBSCRIPT_LOW, NULL);
1756           break;
1757         case 0: /*normal*/
1758           g_object_set(G_OBJECT(tag), "rise", 0, NULL);
1759           break;
1760         }
1761       g_object_set(G_OBJECT(tag), "rise-set", TRUE, NULL);
1762     }
1763   else
1764     g_object_set(G_OBJECT(tag), "rise-set", FALSE, NULL);
1765   
1766   return tag;
1767 }
1768 #endif
1769
1770 /** 
1771  * hildon_font_selection_dialog_set_buffer:
1772  * @fsd: the font selection dialog.
1773  * @buffer: a #GtkTextBuffer containing the text to which the selections will 
1774  * be applied. Applying is responsibility of application.
1775  *
1776  * This is deprecated function. GtkTextBuffer is not enough
1777  * to get the attributes of currently selected text. Please 
1778  * inspect the attributes yourself, and set the properties of
1779  * font selection dialog to reflect your inspection.
1780  * 
1781  */
1782 #ifndef HILDON_DISABLE_DEPRECATED
1783 void 
1784 hildon_font_selection_dialog_set_buffer (HildonFontSelectionDialog *fsd,
1785                                          GtkTextBuffer *buffer)
1786 {
1787   GtkTextIter begin, end, iter;
1788   HildonFontSelectionDialogSettings settings;
1789
1790   gtk_text_buffer_get_selection_bounds(buffer, &begin, &end);
1791   
1792   settings_init(&settings, fsd);
1793   
1794   iter = begin;
1795   if(gtk_text_iter_compare(&iter, &end) == 0)/*if no selection*/
1796     {
1797       GSList *slist;
1798       
1799       slist = gtk_text_iter_get_tags(&iter);
1800       g_slist_foreach(slist, check_tags, (gpointer) &settings);
1801       g_slist_free(slist);
1802     }
1803
1804   while(gtk_text_iter_compare(&iter, &end) < 0)
1805     {
1806       GSList *slist;
1807       
1808       slist = gtk_text_iter_get_tags(&iter);
1809       g_slist_foreach(slist, check_tags, (gpointer) &settings);
1810       g_slist_free(slist);
1811       
1812       if(!gtk_text_iter_forward_cursor_position(&iter))
1813         break;
1814     }
1815
1816   settings_apply(&settings);
1817   settings_destroy(&settings);
1818 }
1819 #endif
1820
1821 /**
1822  * hildon_font_selection_dialog_get_font:
1823  * @fsd: the font selection dialog.
1824  *
1825  * This is a deprecated function, @PangoAttrList needs
1826  * starting index, and end index on construction.
1827  *
1828  * Return value: pointer to @PangoAttrList.
1829  */
1830 #ifndef HILDON_DISABLE_DEPRECATED
1831 PangoAttrList
1832 *hildon_font_selection_dialog_get_font(HildonFontSelectionDialog * fsd)
1833 {
1834   HildonFontSelectionDialogPrivate *priv
1835     = HILDON_FONT_SELECTION_DIALOG_GET_PRIVATE(fsd);
1836   
1837   g_return_val_if_fail(HILDON_IS_FONT_SELECTION_DIALOG(fsd), FALSE);
1838   /*an approve of none working api, should have ask for start_index,
1839    * and length in bytes of the string, currently using preview_text 
1840    * length, KLUDGE!*/
1841   
1842   return hildon_font_selection_dialog_create_attrlist(fsd, 
1843                                 0, strlen(priv->preview_text));
1844 }
1845 #endif
1846
1847 /**
1848  * hildon_font_selection_dialog_set_font:
1849  * @fsd: the font selection dialog.
1850  * @list: the pango attribute list.
1851  *
1852  * This is a deprecated function.
1853  * 
1854  * Sets the font to the dialog.
1855  */
1856 #ifndef HILDON_DISABLE_DEPRECATED
1857 void 
1858 hildon_font_selection_dialog_set_font(HildonFontSelectionDialog * fsd,
1859                                       PangoAttrList * list)
1860 {
1861   PangoAttrIterator *iter;
1862   HildonFontSelectionDialogSettings settings;
1863
1864   iter = pango_attr_list_get_iterator(list);
1865   
1866   settings_init(&settings, fsd);
1867   
1868   while(iter != NULL)
1869     {
1870       GSList *slist;
1871       
1872       slist = pango_attr_iterator_get_attrs(iter);
1873       g_slist_foreach(slist, check_attrs, (gpointer) &settings);
1874       g_slist_free(slist);
1875       
1876       if(!pango_attr_iterator_next(iter))
1877         break;
1878     }
1879
1880   pango_attr_iterator_destroy(iter);
1881
1882   settings_apply(&settings);
1883   settings_destroy(&settings);
1884 }
1885 #endif