Not yet working stack checking (symbol STACKCHECK)
[gnokii.git] / xgnokii / xgnokii_speed.c
1 /*
2
3   X G N O K I I
4
5   A Linux/Unix GUI for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8
9 */
10
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <pthread.h>
15 #include <gtk/gtk.h>
16 #include "xgnokii_contacts.h"
17 #include "xgnokii.h"
18 #include "xgnokii_lowlevel.h"
19 #include "xgnokii_common.h"
20 #include "xgnokii_speed.h"
21 #include "xpm/Read.xpm"
22 #include "xpm/Send.xpm"
23 #include "xpm/Open.xpm"
24 #include "xpm/Save.xpm"
25 #include "xpm/Edit.xpm"
26 #include "xpm/quest.xpm"
27
28
29 static GtkWidget *GUI_SpeedDialWindow;
30 static ErrorDialog errorDialog = {NULL, NULL};
31 static InfoDialog infoDialog = {NULL, NULL};
32 static ExportDialogData exportDialogData = {NULL};
33 static GtkWidget *clist;
34 static QuestMark questMark;
35 static gint selectedKey;
36 static bool speedDialInitialized;
37
38
39 static inline void Help1 (GtkWidget *w, gpointer data)
40 {
41   gchar *indx = g_strdup_printf ("/%s/gnokii/xgnokii/speeddial/index.htm", xgnokiiConfig.locale);
42   Help (w, indx);
43   g_free (indx);
44 }
45
46
47 static void CloseSpeedDial (GtkWidget *w, gpointer data)
48 {
49   gtk_widget_hide (GUI_SpeedDialWindow);
50 }
51
52
53 static inline void DestroyCListData (gpointer data)
54 {
55   if (data)
56     g_free ((D_SpeedDial *) data);
57 }
58
59
60 static void DeleteSelectContactDialog (GtkWidget *widget, GdkEvent *event,
61                                        SelectContactData *data)
62 {
63   gtk_widget_destroy (GTK_WIDGET (data->clist));
64   gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
65   gtk_widget_destroy (GTK_WIDGET (widget));
66 }
67
68
69 static void CancelSelectContactDialog (GtkWidget *widget,
70                                        SelectContactData *data)
71 {
72   gtk_widget_destroy (GTK_WIDGET (data->clist));
73   gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
74   gtk_widget_destroy (GTK_WIDGET (data->dialog));
75 }
76
77
78 static void OkSelectContactDialog (GtkWidget *widget,
79                                    SelectContactData *data)
80 {
81   GList *sel;
82   PhonebookEntry *pbEntry;
83   gchar *key;
84
85   if ((sel = GTK_CLIST (data->clist)->selection) != NULL)
86   {
87     D_SpeedDial *d = (D_SpeedDial *) g_malloc (sizeof (D_SpeedDial));
88
89     gtk_clist_freeze (GTK_CLIST (clist));
90
91     pbEntry = gtk_clist_get_row_data (GTK_CLIST (data->clist),
92                                       GPOINTER_TO_INT (sel->data));
93
94     gtk_clist_get_text (GTK_CLIST (clist), selectedKey, 0, &key);
95
96     gtk_clist_set_text (GTK_CLIST (clist), selectedKey, 1, pbEntry->entry.Name);
97     gtk_clist_set_text (GTK_CLIST (clist), selectedKey, 2, pbEntry->entry.Number);
98
99     d->entry.Number = *key - '0';
100     d->entry.MemoryType = pbEntry->entry.MemoryType + 2;
101     d->entry.Location = pbEntry->entry.Location;
102
103     gtk_clist_set_row_data_full (GTK_CLIST (clist), selectedKey,
104                                  (gpointer) d, DestroyCListData);
105
106     gtk_clist_sort (GTK_CLIST (clist));
107     gtk_clist_thaw (GTK_CLIST (clist));
108   }
109
110   gtk_widget_destroy (GTK_WIDGET (data->clist));
111   gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
112   gtk_widget_destroy (GTK_WIDGET (data->dialog));
113 }
114
115 static void ShowSelectContactsDialog (void)
116 {
117   SelectContactData *r;
118
119   if (!GUI_ContactsIsIntialized ())
120     GUI_ReadContacts ();
121
122   if ((r = GUI_SelectContactDialog ()) == NULL)
123     return;
124
125   gtk_signal_connect (GTK_OBJECT (r->dialog), "delete_event",
126                       GTK_SIGNAL_FUNC (DeleteSelectContactDialog), (gpointer) r);
127
128   gtk_signal_connect (GTK_OBJECT (r->okButton), "clicked",
129                       GTK_SIGNAL_FUNC (OkSelectContactDialog), (gpointer) r);
130   gtk_signal_connect (GTK_OBJECT (r->cancelButton), "clicked",
131                       GTK_SIGNAL_FUNC (CancelSelectContactDialog), (gpointer) r);
132 }
133
134
135 static inline void EditKey (void)
136 {
137   GList *sel;
138
139   if ((sel = GTK_CLIST (clist)->selection) != NULL)
140   {
141     selectedKey = GPOINTER_TO_INT (sel->data);
142     ShowSelectContactsDialog ();
143   }
144 }
145
146
147 static inline void ClickEntry (GtkWidget      *clist,
148                  gint            row,
149                  gint            column,
150                  GdkEventButton *event,
151                  gpointer        data )
152 {
153   if(event && event->type == GDK_2BUTTON_PRESS)
154   {
155     selectedKey = row;
156     ShowSelectContactsDialog ();
157   }
158 }
159
160
161 static void ReadSpeedDial (void)
162 {
163   PhonebookEntry *pbEntry;
164   D_SpeedDial *d;
165   PhoneEvent *e;
166   gchar *row[3];
167   gchar buf[2] = " ";
168   gint location;
169   register gint i, row_i = 0;
170
171
172   if (!GUI_ContactsIsIntialized ())
173     GUI_ReadContacts ();
174
175   gtk_label_set_text (GTK_LABEL (infoDialog.text), _("Reading data ..."));
176   gtk_widget_show_now (infoDialog.dialog);
177   GUI_Refresh ();
178
179   gtk_clist_freeze (GTK_CLIST (clist));
180   gtk_clist_clear (GTK_CLIST (clist));
181
182   for (i = 1; i < 10; i++)
183   {
184     if ((d = (D_SpeedDial *) g_malloc (sizeof (D_SpeedDial))) == NULL)
185     {
186       g_print (_("Cannot allocate memory!"));
187       return;
188     }
189     d->entry.Number = i;
190     if ((e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent))) == NULL)
191     {
192       g_print (_("Cannot allocate memory!"));
193       g_free (d);
194       return;   
195     }
196     e->event = Event_GetSpeedDial;
197     e->data = d;
198     GUI_InsertEvent (e);
199     pthread_mutex_lock (&speedDialMutex);
200     pthread_cond_wait (&speedDialCond, &speedDialMutex);
201     pthread_mutex_unlock (&speedDialMutex);
202
203     if (d->status != GE_NONE)
204       g_print ("Cannot read speed dial key %d!\n", i);
205     else
206     {
207       if (d->entry.Location == 0)
208         location = i;
209       else
210         location = d->entry.Location;
211       if ((pbEntry = GUI_GetEntry (d->entry.MemoryType - 2, location)) == NULL)
212       {
213         g_free (d);
214         continue;
215       }
216       *buf = i + '0';
217       row[0] = buf;
218       row[1] = pbEntry->entry.Name;
219       row[2] = pbEntry->entry.Number;
220
221       gtk_clist_append (GTK_CLIST (clist), row);
222       gtk_clist_set_row_data_full (GTK_CLIST (clist), row_i++,
223                                    (gpointer) d, DestroyCListData);
224     }
225     //GUI_Refresh ();
226     gtk_widget_hide (infoDialog.dialog);
227   }
228
229   gtk_clist_sort (GTK_CLIST (clist));
230   gtk_clist_thaw (GTK_CLIST (clist));
231   speedDialInitialized = TRUE;
232 }
233
234
235 static void SaveSpeedDial (void)
236 {
237   //gchar buf[80];
238   D_SpeedDial *d;
239   PhoneEvent *e;
240   register gint i;
241
242   if (speedDialInitialized)
243     for(i = 1; i < 10; i++)
244     {
245       if ((d = (D_SpeedDial *) gtk_clist_get_row_data (GTK_CLIST (clist), i - 1)))
246       {
247         if (d->entry.Location == 0)
248           continue;
249         if ((e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent))) == NULL)
250         {
251           g_print (_("Cannot allocate memory!"));
252           return;   
253         }
254         e->event = Event_SendSpeedDial;
255         e->data = d;
256         GUI_InsertEvent (e);
257 /*        pthread_mutex_lock (&speedDialMutex);
258         pthread_cond_wait (&speedDialCond, &speedDialMutex);
259         pthread_mutex_unlock (&speedDialMutex);
260
261         if (d->status != GE_NONE)
262         {
263           g_snprintf (buf, 80, _("Error writing speed\ndial for key %d!\n"),
264                       d->entry.Number);
265           gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
266           gtk_widget_show (errorDialog.dialog);
267         } */
268       }
269 //      GUI_Refresh ();
270     }
271 }
272
273
274 static bool ParseLine (D_SpeedDial *d, gchar *buf)
275 {
276   gchar **strings = g_strsplit (buf, ";", 3);
277
278   d->entry.Number = *strings[0] - '0';
279   if (d->entry.Number < 1 || d->entry.Number > 9)
280   {
281     g_strfreev (strings);
282     return FALSE;
283   }
284
285   d->entry.MemoryType = *strings[1] - '0';
286   if (d->entry.MemoryType < 2 || d->entry.MemoryType > 3)
287   {
288     g_strfreev (strings);
289     return FALSE;
290   }
291
292   d->entry.Location = atoi (strings[2]);
293   if (d->entry.Location == LONG_MIN || d->entry.Location == LONG_MAX ||
294       d->entry.Location < 0)
295   {
296     g_strfreev (strings);
297     return FALSE;
298   }
299
300   g_strfreev (strings);
301   return TRUE;
302 }
303
304
305 static void OkImportDialog (GtkWidget *w, GtkFileSelection *fs)
306 {
307   FILE *f;
308   D_SpeedDial *d;
309   PhonebookEntry *pbEntry;
310   gchar buf[IO_BUF_LEN];
311   gchar *row[3];
312   gchar *fileName;
313   gint location;
314   register gint i, row_i = 0;
315
316   fileName = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
317   gtk_widget_hide (GTK_WIDGET (fs));
318
319   if ((f = fopen (fileName, "r")) == NULL)
320   {
321     g_snprintf (buf, IO_BUF_LEN, _("Can't open file %s for reading!"), fileName);
322     gtk_label_set_text (GTK_LABEL(errorDialog.text), buf);
323     gtk_widget_show (errorDialog.dialog);
324     return;
325   }
326
327   if (!GUI_ContactsIsIntialized ())
328     GUI_ReadContacts ();
329
330   gtk_clist_freeze (GTK_CLIST (clist));
331   gtk_clist_clear (GTK_CLIST (clist));
332   speedDialInitialized = FALSE;
333
334   i = 0;
335   while (fgets (buf, IO_BUF_LEN, f) && i++ < 9)
336   {
337     if ((d = (D_SpeedDial *) g_malloc (sizeof (D_SpeedDial))) == NULL)
338     {
339       g_print (_("Cannot allocate memory!\n"));
340       gtk_clist_clear (GTK_CLIST (clist));
341       gtk_clist_sort (GTK_CLIST (clist));
342       gtk_clist_thaw (GTK_CLIST (clist));
343       return;
344     }
345     if (ParseLine (d, buf))
346     {
347       if (d->entry.Number != i)
348       {
349         g_free (d);
350         gtk_clist_clear (GTK_CLIST (clist));
351         gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Error reading file!"));
352         gtk_widget_show (errorDialog.dialog);
353         gtk_clist_sort (GTK_CLIST (clist));
354         gtk_clist_thaw (GTK_CLIST (clist));
355         return;
356       }
357       if (d->entry.Location == 0)
358         location = i;
359       else
360         location = d->entry.Location;
361       if ((pbEntry = GUI_GetEntry (d->entry.MemoryType - 2, location)) == NULL)
362       {
363         g_free (d);
364         continue;
365       }
366       *buf = i + '0';
367       *(buf + 1) = '\0';
368       row[0] = buf;
369       row[1] = pbEntry->entry.Name;
370       row[2] = pbEntry->entry.Number;
371       gtk_clist_append (GTK_CLIST (clist), row);
372       gtk_clist_set_row_data_full (GTK_CLIST (clist), row_i++,
373                                    (gpointer) d, DestroyCListData);
374     }
375     else
376     {
377       g_free (d);
378       gtk_clist_clear (GTK_CLIST (clist));
379       gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Error reading file!"));
380       gtk_widget_show (errorDialog.dialog);
381       gtk_clist_sort (GTK_CLIST (clist));
382       gtk_clist_thaw (GTK_CLIST (clist));
383       return;
384     }
385   }
386
387   gtk_clist_sort (GTK_CLIST (clist));
388   gtk_clist_thaw (GTK_CLIST (clist));
389   speedDialInitialized = TRUE;
390 }
391
392
393 static void ImportSpeedDial (void)
394 {
395   static GtkWidget *fileDialog = NULL;
396
397   if (fileDialog == NULL)
398   {
399     fileDialog = gtk_file_selection_new (_("Import"));
400     gtk_signal_connect (GTK_OBJECT (fileDialog), "delete_event",
401                         GTK_SIGNAL_FUNC (DeleteEvent), NULL);
402     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->ok_button),
403                         "clicked", GTK_SIGNAL_FUNC (OkImportDialog), (gpointer) fileDialog);
404     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->cancel_button),
405                         "clicked", GTK_SIGNAL_FUNC (CancelDialog), (gpointer) fileDialog);
406   }  
407
408   gtk_widget_show (fileDialog);
409 }
410
411
412 static void ExportSpeedDialMain (gchar *name)
413 {
414   FILE *f;
415   D_SpeedDial *d;
416   gchar buf[IO_BUF_LEN];
417   register gint i;
418
419   if ((f = fopen( name, "w")) == NULL)
420   {
421     g_snprintf (buf, IO_BUF_LEN, _("Can't open file %s for writing!"), name);
422     gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
423     gtk_widget_show (errorDialog.dialog);
424     return;
425   }
426
427   for(i = 1; i < 10; i++)
428   {
429     if ((d = (D_SpeedDial *) gtk_clist_get_row_data (GTK_CLIST (clist), i - 1)))
430     {
431       sprintf (buf, "%d;%d;%d;", d->entry.Number, d->entry.MemoryType, d->entry.Location);
432       fprintf (f, "%s\n", buf);
433     }
434   }
435
436   fclose(f);
437 }
438
439
440 static void YesExportDialog (GtkWidget *w, gpointer data)
441 {
442   gtk_widget_hide (GTK_WIDGET (data));
443   ExportSpeedDialMain (exportDialogData.fileName);
444 }
445
446
447 static void OkExportDialog (GtkWidget *w, GtkFileSelection *fs)
448 {
449   static YesNoDialog dialog = { NULL, NULL};
450   FILE *f;
451   gchar err[80];
452
453
454   exportDialogData.fileName = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
455   gtk_widget_hide (GTK_WIDGET (fs));
456
457   if ((f = fopen (exportDialogData.fileName, "r")) != NULL)
458   {
459     fclose (f);
460     if (dialog.dialog == NULL)
461     {
462       CreateYesNoDialog (&dialog, YesExportDialog, CancelDialog, GUI_SpeedDialWindow);
463       gtk_window_set_title (GTK_WINDOW (dialog.dialog), _("Overwrite file?"));
464       g_snprintf ( err, 80, _("File %s already exist.\nOverwrite?"), exportDialogData.fileName); 
465       gtk_label_set_text (GTK_LABEL(dialog.text), err);
466     }
467     gtk_widget_show (dialog.dialog);
468   }
469   else
470     ExportSpeedDialMain (exportDialogData.fileName);
471 }    
472
473
474 static void ExportSpeedDial (void)
475 {
476   static GtkWidget *fileDialog = NULL;
477
478   if (speedDialInitialized)
479   {
480     if (fileDialog == NULL)
481     {
482       fileDialog = gtk_file_selection_new (_("Export"));
483       gtk_signal_connect (GTK_OBJECT (fileDialog), "delete_event",
484                           GTK_SIGNAL_FUNC (DeleteEvent), NULL);
485       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->ok_button),
486                           "clicked", GTK_SIGNAL_FUNC (OkExportDialog), (gpointer) fileDialog);
487       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->cancel_button),
488                           "clicked", GTK_SIGNAL_FUNC (CancelDialog), (gpointer) fileDialog);
489     }
490
491     gtk_widget_show (fileDialog);
492   }
493 }
494
495
496 inline void GUI_ShowSpeedDial (void)
497 {
498   ReadSpeedDial ();
499   gtk_widget_show (GUI_SpeedDialWindow);
500 }
501
502
503 static GtkItemFactoryEntry menu_items[] = {
504   { NULL,               NULL,           NULL, 0, "<Branch>"},
505   { NULL,               "<control>R",   ReadSpeedDial, 0, NULL},
506   { NULL,               "<control>S",   SaveSpeedDial, 0, NULL},
507   { NULL,               NULL,           NULL, 0, "<Separator>"},
508   { NULL, "<control>I", ImportSpeedDial, 0, NULL},
509   { NULL, "<control>E", ExportSpeedDial, 0, NULL},
510   { NULL,               NULL,           NULL, 0, "<Separator>"},
511   { NULL,               "<control>W",   CloseSpeedDial, 0, NULL},
512   { NULL,               NULL,           NULL, 0, "<Branch>"},
513   { NULL,               NULL,           EditKey, 0, NULL},
514   { NULL,               NULL,           NULL, 0, "<LastBranch>"},
515   { NULL,               NULL,           Help1, 0, NULL},
516   { NULL,               NULL,           GUI_ShowAbout, 0, NULL},
517 };
518
519
520 static void InitMainMenu (void)
521 {
522   menu_items[0].path = g_strdup (_("/_File"));
523   menu_items[1].path = g_strdup (_("/File/_Read from phone"));
524   menu_items[2].path = g_strdup (_("/File/_Save to phone"));
525   menu_items[3].path = g_strdup (_("/File/Sep1"));
526   menu_items[4].path = g_strdup (_("/File/_Import from file"));
527   menu_items[5].path = g_strdup (_("/File/_Export to file"));
528   menu_items[6].path = g_strdup (_("/File/Sep2"));
529   menu_items[7].path = g_strdup (_("/File/_Close"));
530   menu_items[8].path = g_strdup (_("/_Edit"));
531   menu_items[9].path = g_strdup (_("/Edit/_Edit"));
532   menu_items[10].path = g_strdup (_("/_Help"));
533   menu_items[11].path = g_strdup (_("/Help/_Help"));
534   menu_items[12].path = g_strdup (_("/Help/_About"));
535 }
536
537
538 void GUI_CreateSpeedDialWindow (void)
539 {
540   int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
541   GtkItemFactory *item_factory;
542   GtkAccelGroup *accel_group;
543   SortColumn *sColumn;
544   GtkWidget *menubar;
545   GtkWidget *main_vbox;
546   GtkWidget *toolbar;
547   GtkWidget *clistScrolledWindow;
548   register gint i;
549   gchar *titles[3] = {_("Key"), _("Name"), _("Number")};
550
551
552   InitMainMenu ();
553   GUI_SpeedDialWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
554   gtk_window_set_title (GTK_WINDOW (GUI_SpeedDialWindow), _("Speed Dial"));
555   gtk_widget_set_usize (GTK_WIDGET (GUI_SpeedDialWindow), 332, 220);
556   //gtk_container_set_border_width (GTK_CONTAINER (GUI_SpeedDialWindow), 10);
557   gtk_signal_connect (GTK_OBJECT (GUI_SpeedDialWindow), "delete_event",
558                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
559   gtk_widget_realize (GUI_SpeedDialWindow);
560
561   accel_group = gtk_accel_group_new ();
562   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
563                                        accel_group);
564
565   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
566
567   gtk_accel_group_attach (accel_group, GTK_OBJECT (GUI_SpeedDialWindow));
568
569   /* Finally, return the actual menu bar created by the item factory. */ 
570   menubar = gtk_item_factory_get_widget (item_factory, "<main>");
571
572   main_vbox = gtk_vbox_new (FALSE, 1);
573   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
574   gtk_container_add (GTK_CONTAINER (GUI_SpeedDialWindow), main_vbox);
575   gtk_widget_show (main_vbox);
576
577   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, FALSE, 0);
578   gtk_widget_show (menubar);
579
580   /* Create the toolbar */
581
582   toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
583   gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NORMAL);
584
585   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Read from phone"), NULL,
586                            NewPixmap(Read_xpm, GUI_SpeedDialWindow->window,
587                            &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
588                            (GtkSignalFunc) ReadSpeedDial, NULL);
589   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Save to phone"), NULL,
590                            NewPixmap(Send_xpm, GUI_SpeedDialWindow->window,
591                            &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
592                            (GtkSignalFunc) SaveSpeedDial, NULL);
593
594   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
595
596   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Import from file"), NULL,
597                            NewPixmap(Open_xpm, GUI_SpeedDialWindow->window,
598                            &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
599                            (GtkSignalFunc) ImportSpeedDial, NULL);
600   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Export to file"), NULL,
601                            NewPixmap(Save_xpm, GUI_SpeedDialWindow->window,
602                            &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
603                            (GtkSignalFunc) ExportSpeedDial, NULL);
604
605   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
606
607   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Edit entry"), NULL,
608                            NewPixmap(Edit_xpm, GUI_SpeedDialWindow->window,
609                            &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL]),
610                            (GtkSignalFunc) EditKey, NULL);
611
612   gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, FALSE, 0);
613   gtk_widget_show (toolbar);
614
615   clist = gtk_clist_new_with_titles (3, titles);
616   gtk_clist_set_shadow_type (GTK_CLIST (clist), GTK_SHADOW_OUT);
617 //  gtk_clist_set_compare_func (GTK_CLIST (clist), CListCompareFunc);
618   gtk_clist_set_sort_column (GTK_CLIST (clist), 0);
619   gtk_clist_set_sort_type (GTK_CLIST (clist), GTK_SORT_ASCENDING);
620   gtk_clist_set_auto_sort (GTK_CLIST (clist), FALSE);
621   //gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
622
623   gtk_clist_set_column_width (GTK_CLIST (clist), 1, 150);
624   gtk_clist_set_column_width (GTK_CLIST (clist), 2, 115);
625   gtk_clist_set_column_justification (GTK_CLIST (clist), 0, GTK_JUSTIFY_CENTER);
626 //  gtk_clist_set_column_visibility (GTK_CLIST (clist), 3, xgnokiiConfig.callerGroupsSupported);
627
628   for (i = 0; i < 3; i++)
629   {
630     if ((sColumn = g_malloc (sizeof (SortColumn))) == NULL)
631     {
632       g_print (_("Error: %s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
633       gtk_main_quit ();
634     }
635     sColumn->clist = clist;
636     sColumn->column = i;
637     gtk_signal_connect (GTK_OBJECT (GTK_CLIST (clist)->column[i].button), "clicked",
638                         GTK_SIGNAL_FUNC (SetSortColumn), (gpointer) sColumn);
639   }
640
641   gtk_signal_connect (GTK_OBJECT (clist), "select_row",
642                       GTK_SIGNAL_FUNC (ClickEntry), NULL);
643
644   clistScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
645   gtk_container_add (GTK_CONTAINER (clistScrolledWindow), clist);
646   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (clistScrolledWindow),
647                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
648   gtk_box_pack_start (GTK_BOX (main_vbox), clistScrolledWindow, 
649                       TRUE, TRUE, 0);
650
651   gtk_widget_show (clist);
652   gtk_widget_show (clistScrolledWindow);
653
654   questMark.pixmap = gdk_pixmap_create_from_xpm_d (GUI_SpeedDialWindow->window,
655                          &questMark.mask,
656                          &GUI_SpeedDialWindow->style->bg[GTK_STATE_NORMAL],
657                          quest_xpm);
658
659   CreateErrorDialog (&errorDialog, GUI_SpeedDialWindow);
660   CreateInfoDialog (&infoDialog, GUI_SpeedDialWindow);
661   speedDialInitialized = FALSE;
662 }