2006-08-30 Michael Dominic Kostrzewa <michael.kostrzewa@nokia.com>
[hildon] / hildon-widgets / hildon-telephone-editor.c
1 /*
2  * This file is part of hildon-libs
3  *
4  * Copyright (C) 2005, 2006 Nokia Corporation.
5  *
6  * Contact: Michael Dominic Kostrzewa <michael.kostrzewa@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; version 2.1 of
11  * the License.
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-telephone-editor.c
27  * @short_description: A widget which allows users to enter telephone numbers 
28  *
29  * A single-line editor which allows user to enter a telephone number. 
30  * There are two modes to choose from (coerce/free format). 
31  * Coerce format has three fields which are placed horizontally. 
32  * The fields are: country code, area code and number. When nothing is 
33  * entered in the fields, assisting text is displayed. Tapping on the 
34  * field highlights the field and allows users to input numbers.
35  *
36  * The widget is used where a user should enter a phone number. Free format 
37  * should be used wherever possible as it enables the user to enter the 
38  * phone number in the format she likes. Free format also supports DTMF 
39  * strings as a part of the phone number. The format can not be changed 
40  * at runtime.  
41  */
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46
47 #include <gdk/gdkkeysyms.h>
48 #include <gtk/gtk.h>
49 #include <libintl.h>
50 #include <string.h>
51 #include "hildon-telephone-editor.h"
52 #include "hildon-composite-widget.h"
53
54 #define _(String) gettext (String)
55 #define HILDON_TELEPHONE_EDITOR_GET_PRIVATE(obj) \
56         (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
57         HILDON_TELEPHONE_EDITOR_TYPE, HildonTelephoneEditorPriv));
58
59 #define AREA_LEN 4
60 #define COUNTRY_LEN 7
61 #define NUMBER_LEN 10
62
63 #define AREA_STR "Area"
64 #define COUNTRY_STR "Country"
65 #define NUMBER_STR "Number"
66
67 typedef struct _HildonTelephoneEditorPriv HildonTelephoneEditorPriv;
68
69 enum {
70     PROP_0,
71     PROP_COUNTRY_STR,
72     PROP_AREA_STR,
73     PROP_NUMBER_STR,
74     PROP_SHOW_BORDER,
75     PROP_SHOW_PLUS,
76     PROP_FORMAT
77 };
78
79 /*< private >*/
80 struct _HildonTelephoneEditorPriv {
81     HildonTelephoneEditorFormat format; /* format of the editor */
82
83     gboolean edited_country;    /* is the country edited */
84     gboolean edited_area;       /* is the area edited */
85     gboolean edited_number;     /* is the number edited */
86
87     gboolean editable_country;  /* is the country editable */
88     gboolean editable_area;     /* is the area editable */
89     gboolean editable_number;   /* is the number editable */
90
91     gboolean show_plus; /* show '+' sign in country */
92     gboolean show_border;       /* show border around the widget */
93
94     GtkWidget *frame;   /* frame for border lines */
95     GtkWidget *plus;    /* + in front of country code */
96     GtkWidget *plus_event;      /* event box for the + -label */
97     GtkWidget *country; /* country code */
98     GtkWidget *area;    /* area code */
99     GtkWidget *number;  /* telephone number */
100
101     gint j;
102 };
103
104
105 static GtkContainerClass *parent_class;
106
107 static void
108 hildon_telephone_editor_class_init(HildonTelephoneEditorClass *
109                                    editor_class);
110
111 static void 
112 hildon_telephone_editor_init(HildonTelephoneEditor * editor);
113
114 static void
115 hildon_telephone_editor_forall(GtkContainer * container,
116                                gboolean include_internals,
117                                GtkCallback callback,
118                                gpointer callback_data);
119 static void 
120 hildon_telephone_editor_destroy(GtkObject * self);
121
122 static void
123 hildon_telephone_editor_size_allocate(GtkWidget * widget,
124                                       GtkAllocation * allocation);
125
126 static void
127 hildon_telephone_editor_size_request(GtkWidget * widget,
128                                      GtkRequisition * requisition);
129
130 static gboolean
131 hildon_telephone_editor_button_release(GtkWidget * widget,
132                                      GdkEventButton * event,
133                                      gpointer data);
134 static void
135 hildon_telephone_editor_focus_dest_entry(GtkWidget * widget,
136                                          gboolean edited,
137                                          gboolean move_left);
138 static gboolean
139 hildon_telephone_editor_entry_keypress(GtkWidget * widget,
140                                        GdkEventKey * event, gpointer data);
141
142 static gboolean
143 hildon_telephone_editor_mnemonic_activate( GtkWidget *widget,
144                                            gboolean group_cycling);
145
146 static void
147 hildon_telephone_editor_set_property(GObject * object,
148                                      guint prop_id,
149                                      const GValue * value,
150                                      GParamSpec * pspec);
151 static void
152 hildon_telephone_editor_get_property(GObject * object,
153                                      guint prop_id,
154                                      GValue * value, GParamSpec * pspec);
155
156 GType hildon_telephone_editor_get_type(void)
157 {
158     static GType editor_type = 0;
159
160     if (!editor_type) {
161         static const GTypeInfo editor_info = {
162             sizeof(HildonTelephoneEditorClass),
163             NULL,       /* base_init */
164             NULL,       /* base_finalize */
165             (GClassInitFunc) hildon_telephone_editor_class_init,
166             NULL,       /* class_finalize */
167             NULL,       /* class_data */
168             sizeof(HildonTelephoneEditor),
169             0,  /* n_preallocs */
170             (GInstanceInitFunc) hildon_telephone_editor_init,
171         };
172         editor_type = g_type_register_static(GTK_TYPE_CONTAINER,
173                                              "HildonTelephoneEditor",
174                                              &editor_info, 0);
175     }
176     return editor_type;
177 }
178
179 static void
180 hildon_telephone_editor_class_init(HildonTelephoneEditorClass *
181                                    editor_class)
182 {
183     GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(editor_class);
184     GtkContainerClass *container_class = GTK_CONTAINER_CLASS(editor_class);
185     GObjectClass *object_class = G_OBJECT_CLASS(editor_class);
186
187     parent_class = g_type_class_peek_parent(editor_class);
188
189     g_type_class_add_private(editor_class, sizeof(HildonTelephoneEditorPriv));
190
191     widget_class->size_request = hildon_telephone_editor_size_request;
192     widget_class->size_allocate = hildon_telephone_editor_size_allocate;
193     container_class->forall = hildon_telephone_editor_forall;
194     widget_class->mnemonic_activate = hildon_telephone_editor_mnemonic_activate;
195     widget_class->focus = hildon_composite_widget_focus;
196     object_class->set_property = hildon_telephone_editor_set_property;
197     object_class->get_property = hildon_telephone_editor_get_property;
198
199     GTK_OBJECT_CLASS(editor_class)->destroy = hildon_telephone_editor_destroy;
200
201     /* Install properties */
202     g_object_class_install_property(object_class, PROP_COUNTRY_STR,
203         g_param_spec_string("country",
204                             ("Country string"),
205                             ("Country string"),
206                             COUNTRY_STR, G_PARAM_READWRITE));
207
208     g_object_class_install_property(object_class, PROP_AREA_STR,
209         g_param_spec_string("area",
210                             ("Area string"),
211                             ("Area string"),
212                             AREA_STR, G_PARAM_READWRITE));
213
214     g_object_class_install_property(object_class, PROP_NUMBER_STR,
215         g_param_spec_string("number",
216                             ("Number string"),
217                             ("Number string"),
218                             NUMBER_STR, G_PARAM_READWRITE));
219
220     g_object_class_install_property(object_class, PROP_SHOW_BORDER,
221         g_param_spec_boolean ("show-border",
222                               "Show Border",
223                               "Wether to show the border around the widget",
224                               TRUE, G_PARAM_READWRITE));
225
226     g_object_class_install_property(object_class, PROP_SHOW_PLUS,
227         g_param_spec_boolean ("show-plus",
228                               "Show Plus",
229                               "Wether to show the plus sign in front of"
230                               " coerce format's country field",
231                               TRUE, G_PARAM_READWRITE));
232
233     g_object_class_install_property(object_class, PROP_FORMAT,
234         g_param_spec_int("set-format",
235                          ("Format"),
236                          ("Sets telephoneditor format"),
237                          HILDON_TELEPHONE_EDITOR_FORMAT_FREE,
238                          HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA,
239                          0, G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
240 }
241
242 static void
243 hildon_telephone_editor_init(HildonTelephoneEditor * editor)
244 {
245     HildonTelephoneEditorPriv *priv;
246     gboolean use_frames = FALSE;       /* in entries, for debug purposes */
247
248     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
249
250     priv->frame = gtk_frame_new(NULL);
251     priv->plus = gtk_label_new("+");
252     priv->plus_event = gtk_event_box_new();
253     priv->country = gtk_entry_new();
254     priv->area = gtk_entry_new();
255     priv->number = gtk_entry_new();
256     priv->edited_country = FALSE;
257     priv->edited_area = FALSE;
258     priv->edited_number = FALSE;
259     priv->show_plus = TRUE;
260     priv->show_border = TRUE;
261     priv->editable_country = TRUE;
262     priv->editable_area = TRUE;
263     priv->editable_number = TRUE;
264
265     gtk_container_add(GTK_CONTAINER(priv->plus_event), priv->plus);
266
267     gtk_entry_set_has_frame(GTK_ENTRY(priv->country), use_frames);
268     gtk_entry_set_has_frame(GTK_ENTRY(priv->area), use_frames);
269     gtk_entry_set_has_frame(GTK_ENTRY(priv->number), use_frames);
270
271     gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor));
272     gtk_widget_set_parent(priv->plus_event, GTK_WIDGET(editor));
273     
274     hildon_telephone_editor_set_widths(editor, COUNTRY_LEN, AREA_LEN,
275                                        NUMBER_LEN);
276
277     /* set signals for country entry */
278     gtk_signal_connect(GTK_OBJECT(priv->country), "button_release_event",
279                        G_CALLBACK(hildon_telephone_editor_button_release),
280                        editor);
281
282     gtk_signal_connect(GTK_OBJECT(priv->country), "key-press-event",
283                        G_CALLBACK(hildon_telephone_editor_entry_keypress),
284                        editor);
285
286     /* set signals for plus label */
287     gtk_signal_connect(GTK_OBJECT(priv->plus_event), "button_press_event",
288                        G_CALLBACK(hildon_telephone_editor_button_release),
289                        editor);
290
291     /* set signals for area entry */
292     gtk_signal_connect(GTK_OBJECT(priv->area), "button_release_event",
293                        G_CALLBACK(hildon_telephone_editor_button_release),
294                        editor);
295
296     gtk_signal_connect(GTK_OBJECT(priv->area), "key-press-event",
297                        G_CALLBACK(hildon_telephone_editor_entry_keypress),
298                        editor);
299
300     /* set signals for number entry */
301     gtk_signal_connect(GTK_OBJECT(priv->number), "button_release_event",
302                        G_CALLBACK(hildon_telephone_editor_button_release),
303                        editor);
304
305     gtk_signal_connect(GTK_OBJECT(priv->number), "key-press-event",
306                        G_CALLBACK(hildon_telephone_editor_entry_keypress),
307                        editor);
308
309     GTK_WIDGET_SET_FLAGS(editor, GTK_NO_WINDOW);
310
311     gtk_widget_show(priv->number);
312     gtk_widget_show(priv->area);
313     gtk_widget_show(priv->country);
314     gtk_widget_show_all(priv->frame);
315     gtk_widget_show_all(priv->plus_event);
316 }
317
318 /**
319  * hildon_telephone_editor_new:
320  * @format: format of the editor
321  *
322  * Creates a new #HildonTelephoneEditor. The editor can be in a free
323  * format where the user can type in country code, area code and the
324  * phone number and can type in other characters than just digits. In
325  * coerse format the editor has fields where the user can input only
326  * digits. See #HildonTelephoneEditorFormat for the different coerse
327  * formats.
328  * 
329  * Returns: new #HildonTelephoneEditor
330  */
331 GtkWidget *
332 hildon_telephone_editor_new(HildonTelephoneEditorFormat format)
333 {
334
335     HildonTelephoneEditor *editor;
336
337     editor =
338         g_object_new(HILDON_TELEPHONE_EDITOR_TYPE, "set-format", format,
339                      "set-country", _(COUNTRY_STR), "set-area",
340                      _(AREA_STR), "set-number", _(NUMBER_STR), NULL);
341
342     return GTK_WIDGET(editor);
343 }
344
345 /**
346  * hildon_telephone_editor_new_with_strings:
347  * @format: format of the editor
348  * @country: default text for the country field
349  * @area: default text for the area field
350  * @number: default text for the number field
351  *
352  * Creates a new #HildonTelephoneEditor. See hildon_telephone_editor_new
353  * for details.
354  * 
355  * Returns: new #HildonTelephoneEditor
356  */
357 GtkWidget *
358 hildon_telephone_editor_new_with_strings(HildonTelephoneEditorFormat
359                                               format,
360                                               const gchar * country,
361                                               const gchar * area,
362                                               const gchar * number)
363 {
364     HildonTelephoneEditor *editor;
365
366     editor =
367         g_object_new(HILDON_TELEPHONE_EDITOR_TYPE, "set-format", format,
368                      "set-country", country, "set-area", area,
369                      "set-number", number, NULL);
370
371     return GTK_WIDGET(editor);
372 }
373
374 static void 
375 hildon_telephone_editor_get_property(GObject * object,
376                                                  guint prop_id,
377                                                  GValue * value,
378                                                  GParamSpec * pspec)
379 {
380     HildonTelephoneEditor *editor;
381     HildonTelephoneEditorPriv *priv;
382
383     editor = HILDON_TELEPHONE_EDITOR (object);
384     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(object);
385
386     switch (prop_id) {
387     case PROP_COUNTRY_STR:
388         g_value_set_string(value,
389                 hildon_telephone_editor_get_country(editor));
390         break;
391     case PROP_AREA_STR:
392         g_value_set_string(value, 
393                 hildon_telephone_editor_get_area(editor));
394         break;
395     case PROP_NUMBER_STR:
396         g_value_set_string(value,
397                     hildon_telephone_editor_get_number(editor));
398         break;
399     case PROP_SHOW_BORDER:
400         g_value_set_boolean(value, 
401                 hildon_telephone_editor_get_show_border(editor));
402         break;
403     case PROP_SHOW_PLUS:
404         g_value_set_boolean(value, 
405                 hildon_telephone_editor_get_show_plus(editor));
406         break;
407     case PROP_FORMAT:
408         g_value_set_int(value, priv->format);
409         break;
410     default:
411         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
412         break;
413     }
414 }
415
416 static void 
417 hildon_telephone_editor_set_property(GObject * object,
418                                                  guint prop_id,
419                                                  const GValue * value,
420                                                  GParamSpec * pspec)
421 {
422     HildonTelephoneEditor *editor;
423     HildonTelephoneEditorPriv *priv;
424    
425     editor = HILDON_TELEPHONE_EDITOR (object);
426     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(object);
427
428     switch (prop_id) {
429     case PROP_COUNTRY_STR:
430         hildon_telephone_editor_set_country(editor,
431                            _(g_value_get_string(value)));
432         break;
433     case PROP_AREA_STR:
434         hildon_telephone_editor_set_area(editor,
435                            _(g_value_get_string(value)));
436         break;
437     case PROP_NUMBER_STR:
438         hildon_telephone_editor_set_number(editor,
439                            _(g_value_get_string(value)));
440         break;
441     case PROP_SHOW_BORDER:
442         hildon_telephone_editor_set_show_border(
443                 editor, g_value_get_boolean(value));
444         break;
445     case PROP_SHOW_PLUS:
446         hildon_telephone_editor_set_show_plus(
447                 editor, g_value_get_boolean(value));
448         break;
449     case PROP_FORMAT:
450         priv->format = g_value_get_int(value);
451         if (priv->format != HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
452             gtk_entry_set_text(GTK_ENTRY(priv->number), _(NUMBER_STR));
453
454         /* set proper fields according to selected format */
455         switch (priv->format) {
456         case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE:
457             gtk_widget_set_parent(priv->number, GTK_WIDGET(object));
458         case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA:
459             gtk_widget_set_parent(priv->area, GTK_WIDGET(object));
460         case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY:
461             gtk_widget_set_parent(priv->country, GTK_WIDGET(object));
462             break;
463         case HILDON_TELEPHONE_EDITOR_FORMAT_FREE:
464             gtk_widget_set_parent(priv->number, GTK_WIDGET(object));
465             break;
466         default:
467             g_assert_not_reached();
468         }
469         break;
470     default:
471         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
472         break;
473     }
474 }
475
476 static gboolean
477 hildon_telephone_editor_mnemonic_activate( GtkWidget *widget,
478                                   gboolean group_cycling)
479 {
480   HildonTelephoneEditorPriv *priv;
481   priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(widget);
482
483   if (!GTK_CONTAINER(widget)->focus_child)
484   {
485     if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
486     {
487       gtk_widget_grab_focus(priv->number);
488
489       if (priv->editable_number && !priv->edited_number)
490         gtk_editable_select_region(GTK_EDITABLE(priv->number), 0, -1);
491     }
492     else
493     {
494       if (priv->editable_country)
495       {
496         gtk_widget_grab_focus(priv->country);
497         if (!priv->edited_country)
498           gtk_editable_select_region(GTK_EDITABLE(priv->country), 0, -1);
499       }
500       else if ((priv->editable_area) && (priv->format !=
501                HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY))
502       {
503         gtk_widget_grab_focus(priv->area);
504         if (!priv->edited_area)
505           gtk_editable_select_region(GTK_EDITABLE(priv->area), 0, -1);
506       }
507       else if ((priv->editable_number) && (priv->format ==
508                HILDON_TELEPHONE_EDITOR_FORMAT_COERCE))
509       {
510         gtk_widget_grab_focus(priv->number);
511         if (!priv->edited_number)
512           gtk_editable_select_region(GTK_EDITABLE(priv->number), 0, -1);
513       }
514       else
515         gtk_widget_grab_focus(priv->country);
516     }
517   }
518   return TRUE;
519 }
520
521 static void 
522 hildon_telephone_editor_forall(GtkContainer * container,
523                                            gboolean include_internals,
524                                            GtkCallback callback,
525                                            gpointer callback_data)
526 {
527     HildonTelephoneEditor *editor;
528     HildonTelephoneEditorPriv *priv;
529
530     editor = HILDON_TELEPHONE_EDITOR(container);
531     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
532
533     g_return_if_fail(container);
534     g_return_if_fail(callback);
535
536     if (!include_internals)
537         return;
538
539     switch (priv->format) {
540     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE:
541         (*callback) (priv->number, callback_data);
542     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA:
543         (*callback) (priv->area, callback_data);
544     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY:
545         (*callback) (priv->country, callback_data);
546         break;
547     case HILDON_TELEPHONE_EDITOR_FORMAT_FREE:
548         (*callback) (priv->number, callback_data);
549         break;
550     default:
551         g_return_if_reached();
552     }
553
554     if (priv->show_plus)
555         (*callback) (priv->plus_event, callback_data);
556
557     if (priv->show_border)
558         (*callback) (priv->frame, callback_data);
559
560 }
561
562 static void 
563 hildon_telephone_editor_destroy(GtkObject * self)
564 {
565     HildonTelephoneEditorPriv *priv;
566
567     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(self);
568
569     switch (priv->format) {
570     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE:
571         if (priv->number) {
572             gtk_widget_unparent(priv->number);
573             priv->number = NULL;
574         }
575     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA:
576         if (priv->area) {
577             gtk_widget_unparent(priv->area);
578             priv->area = NULL;
579         }
580     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY:
581         if (priv->country) {
582             gtk_widget_unparent(priv->country);
583             priv->country = NULL;
584         }
585         break;
586     case HILDON_TELEPHONE_EDITOR_FORMAT_FREE:
587         if (priv->number) {
588             gtk_widget_unparent(priv->number);
589             priv->number = NULL;
590         }
591         break;
592     default:
593         g_return_if_reached();
594     }
595
596     if (priv->plus_event) {
597         gtk_widget_unparent(priv->plus_event);
598         priv->plus_event = NULL;
599     }
600     if (priv->frame) {
601         gtk_widget_unparent(priv->frame);
602         priv->frame = NULL;
603     }
604     if (GTK_OBJECT_CLASS(parent_class)->destroy)
605         GTK_OBJECT_CLASS(parent_class)->destroy(self);
606 }
607
608 static void 
609 hildon_telephone_editor_size_request(GtkWidget *widget,
610                                      GtkRequisition *requisition)
611 {
612     HildonTelephoneEditor *editor;
613     HildonTelephoneEditorPriv *priv;
614     GtkRequisition req;
615
616     g_return_if_fail(requisition);
617
618     editor = HILDON_TELEPHONE_EDITOR(widget);
619     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
620
621     if (priv->show_border)
622         gtk_widget_size_request(priv->frame, requisition);
623
624     requisition->width = 0;
625     requisition->height = 0;
626
627     switch (priv->format)
628     {
629       case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE:
630         gtk_widget_size_request(priv->number, &req);
631         requisition->width += req.width;
632         if (requisition->height < req.height)
633             requisition->height = req.height;
634
635       case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA:
636         gtk_widget_size_request(priv->area, &req);
637         requisition->width += req.width;
638         if (requisition->height < req.height)
639             requisition->height = req.height;
640
641       case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY:
642         gtk_widget_size_request(priv->country, &req);
643         requisition->width += req.width;
644         if (requisition->height < req.height)
645             requisition->height = req.height;
646
647         break;
648       case HILDON_TELEPHONE_EDITOR_FORMAT_FREE:
649         gtk_widget_size_request(priv->number, &req);
650         requisition->width += req.width;
651         if (requisition->height < req.height)
652             requisition->height = req.height;
653
654         break;
655       default:
656         g_return_if_reached();
657     }
658
659     if (priv->show_plus)
660     {
661         gtk_widget_size_request(priv->plus_event, &req);
662         requisition->width += req.width;
663         if (requisition->height < req.height)
664             requisition->height = req.height;
665     }
666
667     requisition->width += GTK_CONTAINER(priv->frame)->border_width * 2;
668     requisition->height += GTK_CONTAINER(priv->frame)->border_width * 2;
669 }
670
671 static void 
672 hildon_telephone_editor_size_allocate(GtkWidget *widget,
673                                       GtkAllocation *allocation)
674 {
675     HildonTelephoneEditor *editor;
676     HildonTelephoneEditorPriv *priv;
677     gint header_x = 6, frame_w = 12;
678     GtkAllocation alloc, country_alloc, area_alloc, number_alloc;
679     GtkRequisition requisition, country_requisition, area_requisition,
680         number_requisition;
681
682     g_return_if_fail(widget);
683     g_return_if_fail(allocation);
684
685     if (allocation->height < 0 )
686       allocation->height = 0;
687     
688     widget->allocation = *allocation;
689     
690     header_x += allocation->x;
691     editor = HILDON_TELEPHONE_EDITOR(widget);
692     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
693
694
695     if (priv->show_plus &&
696         priv->format != HILDON_TELEPHONE_EDITOR_FORMAT_FREE) {
697         gtk_widget_get_child_requisition(priv->plus_event, &requisition);
698
699         alloc.x = header_x;
700         alloc.y = allocation->y + 1;
701         alloc.width = requisition.width;
702         alloc.height = requisition.height;
703
704         header_x += alloc.width;
705         gtk_widget_size_allocate(priv->plus_event, &alloc);
706         frame_w += alloc.width;
707     }
708     
709     gtk_widget_get_child_requisition(priv->number, &number_requisition);
710
711     number_alloc.width = number_requisition.width;
712
713     number_alloc.height = allocation->height - 4 -
714                           GTK_CONTAINER(priv->frame)->border_width * 2;
715
716     /* get sizes */
717     switch (priv->format) {
718     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE:
719     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA:
720         gtk_widget_get_child_requisition(priv->area, &area_requisition);
721
722         area_alloc.width = area_requisition.width;
723         area_alloc.height = number_alloc.height;
724     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY:
725         gtk_widget_get_child_requisition(priv->country, &country_requisition);
726
727         country_alloc.width = country_requisition.width;
728         country_alloc.height = number_alloc.height;
729         break;
730     case HILDON_TELEPHONE_EDITOR_FORMAT_FREE:
731         break;
732     default:
733         g_return_if_reached();
734     }
735
736
737     /* allocate in coerce formats */
738     switch (priv->format) {
739     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE:
740         number_alloc.x = header_x + country_alloc.width + area_alloc.width;
741         number_alloc.y = allocation->y + 1;
742
743         gtk_widget_size_allocate(priv->number, &number_alloc);
744         frame_w += number_alloc.width;
745     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA:
746         area_alloc.x = header_x + country_alloc.width;
747         area_alloc.y = allocation->y + 1;
748
749         gtk_widget_size_allocate(priv->area, &area_alloc);
750         frame_w += area_alloc.width;
751     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY:
752         country_alloc.x = header_x;
753         country_alloc.y = allocation->y + 1;
754
755         gtk_widget_size_allocate(priv->country, &country_alloc);
756         frame_w += country_alloc.width;
757         break;
758     case HILDON_TELEPHONE_EDITOR_FORMAT_FREE:
759         number_alloc.x = header_x;
760         number_alloc.y = allocation->y + 1;
761
762         gtk_widget_size_allocate(priv->number, &number_alloc);
763         frame_w += number_alloc.width;
764         break;
765     default:
766         g_return_if_reached();
767     }
768
769     if (priv->show_border)
770     {
771         alloc.x = allocation->x;
772         alloc.y = allocation->y;
773
774         alloc.width = frame_w - 4;
775
776         alloc.height = allocation->height;
777         gtk_widget_size_allocate( GTK_WIDGET(priv->frame), &alloc );
778     }
779 }
780
781 static gboolean
782 hildon_telephone_editor_button_release(GtkWidget * widget,
783                                      GdkEventButton * event, gpointer data)
784 {
785   gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
786   return FALSE;
787 }
788
789 static void 
790 hildon_telephone_editor_focus_dest_entry(GtkWidget * widget,
791                                                      gboolean edited,
792                                                      gboolean move_left)
793 {
794     /* full coerse mode, wrap to field */
795     gtk_widget_grab_focus(widget);
796
797     if (move_left)
798         gtk_editable_set_position(GTK_EDITABLE(widget), -1);
799     else
800         gtk_editable_set_position(GTK_EDITABLE(widget), 0);
801     /* new field not yet edited, select all */
802     if (!edited)
803         gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
804 }
805
806 static gboolean
807 hildon_telephone_editor_entry_keypress(GtkWidget * widget,
808                                        GdkEventKey * event, gpointer data)
809 {
810     HildonTelephoneEditor *editor;
811     HildonTelephoneEditorPriv *priv;
812     gint pos, width;
813     gint cpos, start, end;
814
815     g_return_val_if_fail(widget, FALSE);
816     g_return_val_if_fail(event, FALSE);
817     g_return_val_if_fail(data, FALSE);
818
819     editor = HILDON_TELEPHONE_EDITOR(data);
820     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
821     cpos = gtk_editable_get_position(GTK_EDITABLE(widget));
822     gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), &start, &end);
823
824     if( event->keyval == GDK_Up || event->keyval == GDK_KP_Up ||
825         event->keyval == GDK_Down || event->keyval == GDK_KP_Down )
826       return FALSE;
827
828     /* Wrap around should not happen; that's why following code */
829     switch (priv->format) {
830     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE:
831         if (((event->keyval == GDK_Left || event->keyval == GDK_KP_Left) &&
832              (widget == priv->country) && ((cpos == 0) ||
833              ((start == 0 && end == strlen(GTK_ENTRY(priv->country)->text)))))
834             ||
835             ((event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
836              && (widget == priv->number)
837              && (cpos >= strlen(GTK_ENTRY(priv->number)->text))))
838             return TRUE;
839         break;
840     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA:
841         if (((event->keyval == GDK_Left || event->keyval == GDK_KP_Left) &&
842              (widget == priv->country) && ((cpos == 0) ||
843                                            ((start == 0
844                                              && end ==
845                                              strlen(GTK_ENTRY
846                                                     (priv->country)->
847                                                     text)))))
848             ||
849             ((event->keyval == GDK_Right || event->keyval == GDK_KP_Right)
850              && (widget == priv->area)
851              && (cpos >= strlen(GTK_ENTRY(priv->area)->text))))
852             return TRUE;
853         break;
854     case HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY:
855         break;
856     case HILDON_TELEPHONE_EDITOR_FORMAT_FREE:
857         break;
858     }
859
860     /* valid key pressed */
861     if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left ||
862         event->keyval == GDK_Right || event->keyval == GDK_KP_Right ||
863         event->keyval == GDK_BackSpace || event->keyval == GDK_Delete ||
864         event->keyval == GDK_KP_Delete ||
865         (event->keyval >= GDK_0 && event->keyval <= GDK_9) ||
866         (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE &&
867          (event->keyval == GDK_slash || event->keyval == GDK_space ||
868           event->keyval == GDK_parenleft || event->keyval == GDK_parenright
869           || event->keyval == GDK_period || event->keyval == GDK_hyphen
870           || event->keyval == GDK_plus || event->keyval == GDK_asterisk
871           || event->keyval == GDK_KP_Multiply
872           || event->keyval == GDK_KP_Add || event->keyval == GDK_numbersign
873           || event->keyval == GDK_question || event->keyval == GDK_KP_Subtract
874           || event->keyval == GDK_minus)))
875     {
876         if ((event->keyval >= GDK_0 && event->keyval <= GDK_9) ||
877             (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE &&
878              (event->keyval == GDK_slash || event->keyval == GDK_space ||
879               event->keyval == GDK_parenleft ||
880               event->keyval == GDK_parenright ||
881               event->keyval == GDK_period || event->keyval == GDK_hyphen ||
882               event->keyval == GDK_plus || event->keyval == GDK_asterisk ||
883               event->keyval == GDK_KP_Add ||
884               event->keyval == GDK_KP_Multiply ||
885               event->keyval == GDK_numbersign ||
886               event->keyval == GDK_question ||
887               event->keyval == GDK_KP_Subtract || 
888               event->keyval == GDK_minus)))
889         {
890             if (widget == priv->country)
891                 priv->edited_country = TRUE;
892             if (widget == priv->area)
893                 priv->edited_area = TRUE;
894             if (widget == priv->number)
895                 priv->edited_number = TRUE;
896         }
897
898         pos = gtk_editable_get_position(GTK_EDITABLE(widget));
899
900         /* going left */
901         if (event->keyval == GDK_Left || event->keyval == GDK_KP_Left) {
902             /* not yet on the left edge and the widget is edited */
903             if (pos != 0 &&
904                 ((widget == priv->country && priv->edited_country == TRUE)
905                  || (widget == priv->area && priv->edited_area == TRUE)
906                  || (widget == priv->number
907                      && priv->edited_number == TRUE)))
908                 return FALSE;
909
910             /* left edge of number field */
911             if (widget == priv->number) {
912                 /* Stop signal handler, if only number field exists */
913                 if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
914                     return TRUE;
915                 else {
916                     /* Grab the focus to the area field, if it is editable 
917                      */
918                     if (priv->editable_area) {
919                         hildon_telephone_editor_focus_dest_entry
920                             (priv->area, priv->edited_area, TRUE);
921                     }
922                     /* Grab the focus to the country field, if it is
923                        editable */
924                     else if (priv->editable_country) {
925                         hildon_telephone_editor_focus_dest_entry
926                             (priv->country, priv->edited_country, TRUE);
927                     } else
928                         return TRUE;
929                 }
930             }
931
932             /* left edge of area field */
933             if (widget == priv->area) { /* grab the focus to the country
934                                            field, if it is editable */
935                 if (priv->editable_country) {
936                     hildon_telephone_editor_focus_dest_entry
937                         (priv->country, priv->edited_country, TRUE);
938                 } else
939                     return TRUE;
940             }
941
942             /* left edge of country field, let's wrap */
943             if (widget == priv->country) {
944                 /* Stop the signal handler, if only country field exists */
945                 if (priv->format ==
946                     HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY)
947                     return TRUE;
948                 /* wrap to area, if in AREA mode */
949                 else if (priv->format ==
950                          HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA) {
951                     hildon_telephone_editor_focus_dest_entry
952                         (priv->area, priv->edited_area, TRUE);
953                 }
954
955                 else {
956                     hildon_telephone_editor_focus_dest_entry
957                         (priv->number, priv->edited_number, TRUE);
958                 }
959             }
960         }
961         /* going right */
962         else if (event->keyval == GDK_Right || event->keyval == GDK_KP_Right) {
963             width = g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(widget)), -1);
964
965             /* not yet on the rigth edge and the widget is edited */
966             if (pos != width &&
967                 ((widget == priv->country && priv->edited_country == TRUE)
968                  || (widget == priv->area && priv->edited_area == TRUE)
969                  || (widget == priv->number
970                      && priv->edited_number == TRUE)))
971                 return FALSE;
972
973             /* rigth edge of number field */
974             if (widget == priv->number) {
975                 /* Stop signal handler, if only number field exists */
976                 if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
977                     return TRUE;
978                 else {
979                     hildon_telephone_editor_focus_dest_entry
980                         (priv->country, priv->edited_country, FALSE);
981                 }
982             }
983
984             /* rigth edge of area field */
985             if (widget == priv->area) {
986                 /* area mode, wrap to country field */
987                 if (priv->format ==
988                     HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA) {
989                     hildon_telephone_editor_focus_dest_entry
990                         (priv->country, priv->edited_country, FALSE);
991                 }
992                 /* grab the focus to the number field, if it is editable */
993                 else if (priv->editable_number) {
994                     hildon_telephone_editor_focus_dest_entry
995                         (priv->number, priv->edited_number, FALSE);
996                 } else
997                     return TRUE;
998             }
999
1000             /* rigth edge of country field */
1001             if (widget == priv->country) {
1002                 /* wrap around, if only country field exists */
1003                 if (priv->format ==
1004                     HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY)
1005                     return TRUE;
1006
1007                 /* area mode, move to area field */
1008                 else if (priv->format ==
1009                          HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA ||
1010                          priv->format ==
1011                          HILDON_TELEPHONE_EDITOR_FORMAT_COERCE) {
1012                     /* grab the focus to the area field, if it is editable 
1013                      */
1014                     if (priv->editable_area) {
1015                         hildon_telephone_editor_focus_dest_entry
1016                             (priv->area, priv->edited_area, FALSE);
1017                     }
1018                     /* grab the focus to the area field, if it is editable 
1019                      */
1020                     else if ((priv->format ==
1021                               HILDON_TELEPHONE_EDITOR_FORMAT_COERCE) &&
1022                              priv->editable_number) {
1023                         hildon_telephone_editor_focus_dest_entry
1024                             (priv->number, priv->edited_number, FALSE);
1025                     } else
1026                         return TRUE;
1027                 }
1028
1029                 else {
1030                     hildon_telephone_editor_focus_dest_entry
1031                         (priv->number, priv->edited_number, FALSE);
1032                 }
1033             }
1034         }
1035         return FALSE;
1036     }
1037     return TRUE;
1038 }
1039
1040 /**
1041  * hildon_telephone_editor_set_editable:
1042  * @hte: #HildonTelephoneEditor
1043  * @country: set the editable status of the country field in coarce format
1044  * @area: set the editable status of the area field in coarce format
1045  * @number: set the editable status of the number field in coarce format
1046  * 
1047  * Specify wheter the fields in coerse format are editable or
1048  * not. This function is ignored if the editor is in free mode. The
1049  * number or area and number parameters are ignored if the editor is
1050  * in HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or
1051  * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY formats,
1052  * respectively. 
1053  */
1054 void 
1055 hildon_telephone_editor_set_editable(HildonTelephoneEditor * editor,
1056                                           gboolean country,
1057                                           gboolean area, gboolean number)
1058 {
1059     HildonTelephoneEditorPriv *priv;
1060
1061     g_return_if_fail(editor);
1062
1063     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1064
1065     priv->editable_country = country;
1066     priv->editable_area = area;
1067     priv->editable_number = number;
1068
1069     if (priv->country)
1070     {
1071         gtk_editable_set_editable(GTK_EDITABLE(priv->country), country);
1072         gtk_widget_set_sensitive(GTK_WIDGET(priv->plus), country);
1073     }
1074
1075     if (priv->area)
1076         gtk_editable_set_editable(GTK_EDITABLE(priv->area), area);
1077
1078     if (priv->number)
1079         gtk_editable_set_editable(GTK_EDITABLE(priv->number), number);
1080 }
1081
1082 /**
1083  * hildon_telephone_editor_set_widths:
1084  * @hte: #HildonTelephoneEditor
1085  * @country: width (characters) of the country field in coarce mode
1086  * @area: width (characters) of the area field in coarce mode
1087  * @number: width (characters) of the number field in coarce mode
1088  *
1089  * Set widths of the fields in coecse format. Country and area parameters
1090  * are ignored, if the editor is in free mode. The number or area and number
1091  * parameters are ignored if the editor is in
1092  * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or
1093  * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode, respectively.
1094  */
1095 void 
1096 hildon_telephone_editor_set_widths(HildonTelephoneEditor * editor,
1097                                         guint country,
1098                                         guint area, guint number)
1099 {
1100     HildonTelephoneEditorPriv *priv;
1101
1102     g_return_if_fail(editor);
1103
1104     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1105
1106     if (priv->country) {
1107         /*gtk_entry_set_max_length(GTK_ENTRY(priv->country), country);*/
1108         gtk_entry_set_width_chars(GTK_ENTRY(priv->country), country);
1109     }
1110
1111     if (priv->area) {
1112         /*gtk_entry_set_max_length(GTK_ENTRY(priv->area), area);*/
1113         gtk_entry_set_width_chars(GTK_ENTRY(priv->area), area);
1114     }
1115
1116     if (priv->number) {
1117         /*gtk_entry_set_max_length(GTK_ENTRY(priv->number), number);*/
1118         gtk_entry_set_width_chars(GTK_ENTRY(priv->number), number);
1119     }
1120
1121 }
1122
1123 /**
1124  * hildon_telephone_editor_set_show_plus:
1125  * @hte: #HildonTelephoneEditor
1126  * @show: show the plus sign
1127  *
1128  * Show or hide the plus sign in front of coerce format's country field. 
1129  */
1130 void 
1131 hildon_telephone_editor_set_show_plus(HildonTelephoneEditor * editor,
1132                                            gboolean show)
1133 {
1134     HildonTelephoneEditorPriv *priv;
1135
1136     g_return_if_fail(editor);
1137
1138     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1139
1140     /* do nothing in FREE format */
1141     if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
1142         return;
1143
1144     if (show && !priv->show_plus) {
1145         priv->show_plus = TRUE;
1146         gtk_widget_set_parent(priv->plus_event, GTK_WIDGET(editor));
1147         gtk_widget_show(priv->plus_event);
1148     } else if (!show && priv->show_plus) {
1149         gtk_widget_hide(priv->plus_event);
1150         gtk_widget_unparent(priv->plus_event);
1151         priv->show_plus = FALSE;
1152     }
1153 }
1154
1155 /**
1156  * hildon_telephone_editor_get_show_plus:
1157  * @hte: #HildonTelephoneEditor
1158  *
1159  * Get the visibility status of the plus sign in
1160  * front of coerce format's country field.
1161  *
1162  * Returns: gboolean
1163  */
1164 gboolean 
1165 hildon_telephone_editor_get_show_plus(HildonTelephoneEditor *
1166                                                editor)
1167 {
1168     HildonTelephoneEditorPriv *priv;
1169     g_return_val_if_fail(editor, FALSE);
1170     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1171
1172     /* no plus in FREE format */
1173     if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
1174         return FALSE;
1175     return priv->show_plus;
1176 }
1177
1178 /**
1179  * hildon_telephone_editor_set_show_border:
1180  * @hte: #HildonTelephoneEditor
1181  * @show: show the border
1182  *
1183  * Show or hide the border around the widget
1184  */
1185 void 
1186 hildon_telephone_editor_set_show_border(HildonTelephoneEditor *
1187                                              editor, gboolean show)
1188 {
1189     HildonTelephoneEditorPriv *priv;
1190     g_return_if_fail(editor);
1191     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1192
1193     if (show && !priv->show_border) {
1194         priv->show_border = TRUE;
1195         gtk_widget_set_parent(priv->frame, GTK_WIDGET(editor));
1196         gtk_widget_show(priv->frame);
1197     } else if (!show && priv->show_border) {
1198         gtk_widget_hide(priv->frame);
1199         gtk_widget_unparent(priv->frame);
1200         priv->show_border = FALSE;
1201     }
1202 }
1203
1204 /**
1205  * hildon_telephone_editor_get_show_border:
1206  * @hte: #HildonTelephoneEditor
1207  *
1208  * Get the visibility status of the border around the widget.
1209  *
1210  * Returns: gboolean
1211  */
1212 gboolean
1213 hildon_telephone_editor_get_show_border(HildonTelephoneEditor * editor)
1214 {
1215     HildonTelephoneEditorPriv *priv;
1216     g_return_val_if_fail(editor, FALSE);
1217     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1218
1219     return priv->show_border;
1220 }
1221
1222 /**
1223  * hildon_telephone_editor_get_country:
1224  * @hte: #HildonTelephoneEditor
1225  *
1226  * Get text in the country field in coarse format. This function must
1227  * not be called if in free mode.
1228  *
1229  * Returns: pointer to the text in the country field. It must not
1230  * be changed or freed.
1231  */
1232 const gchar *
1233 hildon_telephone_editor_get_country(HildonTelephoneEditor *
1234                                                  editor)
1235 {
1236     HildonTelephoneEditorPriv *priv;
1237     g_return_val_if_fail(editor, NULL);
1238     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1239
1240     /* return NULL if in FREE format */
1241     if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
1242         return NULL;
1243
1244     return gtk_entry_get_text(GTK_ENTRY(priv->country));
1245 }
1246
1247 /**
1248  * hildon_telephone_editor_set_country:
1249  * @hte: #HildonTelephoneEditor
1250  * @country: text to be set in country field
1251  *
1252  * Set text in the country field in coarse format. This function must
1253  * not be called if in free mode.
1254  */
1255 void 
1256 hildon_telephone_editor_set_country(HildonTelephoneEditor * editor,
1257                                          const gchar * country)
1258 {
1259     HildonTelephoneEditorPriv *priv;
1260     const gchar *p;
1261     gunichar u;
1262
1263     g_return_if_fail(editor);
1264     g_return_if_fail(country);
1265
1266     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1267
1268     /* do nothing in FREE format */
1269     if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
1270         return;
1271
1272     if (!priv->country)
1273         return;
1274
1275     p = country;
1276     g_return_if_fail(g_utf8_validate(p, -1, NULL));
1277
1278     /* allow only digits */
1279     do {
1280         u = g_utf8_get_char(p);
1281         if (!g_unichar_isdigit(*p))
1282             return;
1283
1284         p = g_utf8_next_char(p);
1285     } while (*p);
1286
1287     gtk_entry_set_text(GTK_ENTRY(priv->country), country);
1288 }
1289
1290 /**
1291  * hildon_telephone_editor_get_area:
1292  * @hte: #HildonTelephoneEditor
1293  *
1294  * Get text in the area field in coarse format. This function must not
1295  * be called if in free mode or in
1296  * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode.
1297  *
1298  * Returns: pointer to the text in the area field. It must not be
1299  * changed or freed.
1300  */
1301 const gchar *
1302 hildon_telephone_editor_get_area(HildonTelephoneEditor *
1303                                               editor)
1304 {
1305     HildonTelephoneEditorPriv *priv;
1306     g_return_val_if_fail(editor, NULL);
1307     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1308
1309     /* return NULL if in FREE format or if in COERCE_COUNTRY format */
1310     if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
1311         return NULL;
1312     if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY)
1313         return NULL;
1314
1315     return gtk_entry_get_text(GTK_ENTRY(priv->area));
1316 }
1317
1318 /**
1319  * hildon_telephone_editor_set_area:
1320  * @hte: #HildonTelephoneEditor
1321  * @area: text to be set in area field
1322  *
1323  * Set text in the area field in coarse format. This function must not
1324  * be called if in free mode or in
1325  * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY mode.
1326  */
1327 void
1328 hildon_telephone_editor_set_area(HildonTelephoneEditor * editor,
1329                                       const gchar * area)
1330 {
1331     HildonTelephoneEditorPriv *priv;
1332     const gchar *p;
1333     gunichar u;
1334
1335     g_return_if_fail(editor);
1336     g_return_if_fail(area);
1337
1338     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1339
1340     /* do nothing in FREE format */
1341     if (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE)
1342         return;
1343
1344     if (!priv->area)
1345         return;
1346
1347     p = area;
1348     g_return_if_fail(g_utf8_validate(p, -1, NULL));
1349
1350     /* allow only digits */
1351     do {
1352         u = g_utf8_get_char(p);
1353         if (!g_unichar_isdigit(u))
1354             return;
1355
1356         p = g_utf8_next_char(p);
1357     } while (*p);
1358
1359     gtk_entry_set_text(GTK_ENTRY(priv->area), area);
1360 }
1361
1362 /**
1363  * hildon_telephone_editor_get_number:
1364  * @hte: #HildonTelephoneEditor
1365  *
1366  * Get text in the number field in all formats. In free mode, this
1367  * functions returns the whole phone number. In coarce mode, it returns
1368  * only the number field. This function must not be called if
1369  * the editor is in HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_AREA or
1370  * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY modes.
1371  *
1372  * Returns: pointer to text in the number field. It must not be
1373  * changed or freed.
1374  */
1375 const gchar *
1376 hildon_telephone_editor_get_number(HildonTelephoneEditor *
1377                                                 editor)
1378 {
1379     HildonTelephoneEditorPriv *priv;
1380     g_return_val_if_fail(editor, NULL);
1381     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1382
1383     return gtk_entry_get_text(GTK_ENTRY(priv->number));
1384 }
1385
1386 /**
1387  * hildon_telephone_editor_set_number:
1388  * @hte: #HildonTelephoneEditor
1389  * @number: text to be set to number field
1390  *
1391  * Set text in the number field in all formats. In free mode this
1392  * functions sets the whole phone number. In coerce mode, it sets
1393  * only the number field. This function must not be called if
1394  * the editor is in HILDON_TELEPHONE_EDITOR_FORMAT_COERSE_AREA or
1395  * HILDON_TELEPHONE_EDITOR_FORMAT_COERCE_COUNTRY modes.
1396  */
1397 void 
1398 hildon_telephone_editor_set_number(HildonTelephoneEditor * editor,
1399                                         const gchar * number)
1400 {
1401     HildonTelephoneEditorPriv *priv;
1402     const gchar *p;
1403     gunichar u;
1404
1405     g_return_if_fail(editor);
1406     g_return_if_fail(number);
1407
1408     priv = HILDON_TELEPHONE_EDITOR_GET_PRIVATE(editor);
1409
1410     if (!priv->number)
1411         return;
1412
1413     p = number;
1414     g_return_if_fail(g_utf8_validate(p, -1, NULL));
1415
1416     /* allow only digits in coerce format or some other in free format */
1417     do {
1418         u = g_utf8_get_char(p);
1419         if (g_unichar_isdigit(u) ||
1420             (priv->format == HILDON_TELEPHONE_EDITOR_FORMAT_FREE &&
1421              (u == '+' ||
1422               u == 'p' ||
1423               u == 'w' ||
1424               u == '(' ||
1425               u == ')' ||
1426               u == '/' ||
1427               u == ' ' ||
1428               u == '.' || u == '-' || u == '*' || u == '#' || u == '?')))
1429             p = g_utf8_next_char(p);
1430         else
1431             return;
1432
1433     } while (*p);
1434
1435     gtk_entry_set_text(GTK_ENTRY(priv->number), number);
1436 }