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