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