Update: orig2001_11_27_05_17 -> orig2001_12_04_22_45
[gnokii.git] / xgnokii / xgnokii_contacts.c
1 /*
2
3   $Id$
4   
5   X G N O K I I
6
7   A Linux/Unix GUI for Nokia mobile phones.
8   Copyright (C) 1999 Pavel Janík ml., Hugh Blemings
9   & Ján Derfiòák <ja@mail.upjs.sk>.
10
11   Released under the terms of the GNU GPL, see file COPYING for more details.
12
13 */
14
15
16 #include "misc.h"
17
18 #include <stdio.h>
19 #include <pthread.h>
20
21 #ifndef WIN32
22 # include <unistd.h>
23 #else
24 # include <windows.h>
25 # define sleep(x) Sleep((x) * 1000)
26 # define usleep(x) Sleep(((x) < 1000) ? 1 : ((x) / 1000))
27 # define index strchr
28 #endif
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <gtk/gtk.h>
33
34 #include "gsm-common.h"
35 #include "xgnokii_contacts.h"
36 #include "xgnokii_lowlevel.h"
37 #include "xgnokii.h"
38 #include "xgnokii_common.h"
39 #include "xgnokii_lowlevel.h"
40 #include "xgnokii_sms.h"
41 #include "xpm/Read.xpm"
42 #include "xpm/Send.xpm"
43 #include "xpm/Open.xpm"
44 #include "xpm/Save.xpm"
45 #include "xpm/New.xpm"
46 #include "xpm/Duplicate.xpm"
47 #include "xpm/Edit.xpm"
48 #include "xpm/Delete.xpm"
49 #include "xpm/Dial.xpm"
50 #include "xpm/sim.xpm"
51 #include "xpm/phone.xpm"
52 #include "xpm/quest.xpm"
53
54
55 typedef struct {
56   GtkWidget *dialog;
57   GtkWidget *entry;
58 } DialVoiceDialog;
59
60 typedef struct {
61   GtkWidget *dialog;
62   GtkWidget *entry;
63   gint row;
64   GtkWidget *gbutton;
65   GtkWidget *mbutton;
66   GtkWidget *wbutton;
67   GtkWidget *fbutton;
68   GtkWidget *hbutton;
69   PhonebookEntry *pbEntry;
70 } ExtPbkDialog;
71
72 static GtkWidget *GUI_ContactsWindow;
73 static bool fbus3810;
74 static bool contactsMemoryInitialized;
75 static MemoryStatus memoryStatus;
76 static ContactsMemory contactsMemory;   /* Hold contacts. */
77 static GtkWidget *clist;
78 static StatusInfo statusInfo;
79 static ProgressDialog progressDialog = {NULL, NULL, NULL};
80 static ErrorDialog errorDialog = {NULL, NULL};
81 static FindEntryStruct findEntryStruct = { "", 0};
82 static ExportDialogData exportDialogData = {NULL};
83 static MemoryPixmaps memoryPixmaps;
84 static QuestMark questMark;
85 static EditEntryData newEditEntryData = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
86 static EditEntryData editEditEntryData = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
87 static EditEntryData duplicateEditEntryData = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
88 static EditNumbersData editNumbersData = {NULL, NULL};
89
90 /* return != 0 if user has unsaved changes in contacts memory */
91 inline gint GUI_ContactsIsChanged (void)
92 {
93   return statusInfo.ch_ME | statusInfo.ch_SM;
94 }
95
96
97 /* return TRUE if Contacts memory was read from phone or from file */
98 inline bool GUI_ContactsIsIntialized (void)
99 {
100   return contactsMemoryInitialized;
101 }
102
103
104 static inline void Help1 (GtkWidget *w, gpointer data)
105 {
106   gchar *indx = g_strdup_printf ("/help/%s/windows/contacts/index.html", xgnokiiConfig.locale);
107   Help (w, indx);
108   g_free (indx);
109 }
110
111
112 void RefreshStatusInfo (void)
113 {
114   char p,s;
115   
116   if (statusInfo.ch_ME)
117     p = '*';
118   else
119     p = ' ';
120   
121   if (statusInfo.ch_SM)
122     s = '*';
123   else
124     s = ' ';
125   g_snprintf(statusInfo.text, STATUS_INFO_LENGTH, "SIM: %d/%d%c  Phone: %d/%d%c",
126               memoryStatus.UsedSM, memoryStatus.MaxSM, s,
127               memoryStatus.UsedME, memoryStatus.MaxME, p);
128   gtk_label_set_text(GTK_LABEL (statusInfo.label), statusInfo.text);
129 }
130
131
132 static inline void SetGroup0 (GtkWidget *item, gpointer data)
133 {
134   ((EditEntryData *) data)->newGroup = 0;
135 }
136
137
138 static inline void SetGroup1 (GtkWidget *item, gpointer data)
139 {
140   ((EditEntryData *) data)->newGroup = 1;
141 }
142
143
144 static inline void SetGroup2 (GtkWidget *item, gpointer data)
145 {
146   ((EditEntryData *) data)->newGroup = 2;
147 }
148
149
150 static inline void SetGroup3 (GtkWidget *item, gpointer data)
151 {
152   ((EditEntryData *) data)->newGroup = 3;
153 }
154
155
156 static inline void SetGroup4 (GtkWidget *item, gpointer data)
157 {
158   ((EditEntryData *) data)->newGroup = 4;
159 }
160
161
162 static inline void SetGroup5 (GtkWidget *item, gpointer data)
163 {
164   ((EditEntryData *) data)->newGroup = 5;
165 }
166
167
168 PhonebookEntry *FindFreeEntry (GSM_MemoryType type)
169 {
170   PhonebookEntry *entry;
171   gint start, end;
172   register gint i;
173
174   if (type == GMT_ME)
175   {
176     if (memoryStatus.FreeME == 0)
177       return NULL;
178     start = 0;
179     end = memoryStatus.MaxME;
180   }
181   else
182   {
183     if (memoryStatus.FreeSM == 0)
184       return NULL;
185     start = memoryStatus.MaxME;
186     end = memoryStatus.MaxME + memoryStatus.MaxSM;
187   }
188
189   for(i = start; i < end; i++)
190   {
191     entry = g_ptr_array_index(contactsMemory, i);
192     if (entry->status == E_Empty || entry->status == E_Deleted)
193       return entry;
194   }
195
196   return NULL;
197 }
198
199
200 inline PhonebookEntry *GUI_GetEntry (GSM_MemoryType type, gint nr)
201 {
202   if ((type == GMT_ME && (nr < 1 || nr >= memoryStatus.MaxME)) ||
203       (type == GMT_SM && (nr < 1 || nr >= memoryStatus.MaxSM)))
204     return NULL;
205
206   if (type == GMT_ME)
207     return g_ptr_array_index (contactsMemory, nr - 1);
208   else
209     return g_ptr_array_index (contactsMemory, nr + memoryStatus.MaxME - 1);
210 }
211
212
213 static void CloseContacts (GtkWidget *w, gpointer data)
214 {
215   gtk_widget_hide (GUI_ContactsWindow);
216 }
217
218
219 /* I don't want to allow window to close */
220 static void ProgressDialogDeleteEvent (GtkWidget *w, gpointer data)
221 {
222   return;
223 }
224
225
226 static void CancelEditDialog (GtkWidget *widget, gpointer data )
227 {
228   gtk_widget_hide(GTK_WIDGET(((EditEntryData*) data)->dialog));
229 }
230
231
232
233 static void OkEditEntryDialog (GtkWidget *widget, gpointer data)
234 {
235   gchar *clist_row[4];
236   PhonebookEntry *entry;
237
238   if (GTK_TOGGLE_BUTTON(((EditEntryData*) data)->memoryTypePhone)->active &&
239       ((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_SM)
240   {
241     if ((entry = FindFreeEntry(GMT_ME)) == NULL)
242     {
243       gtk_label_set_text(GTK_LABEL(errorDialog.text), _("Can't change memory type!"));  
244       gtk_widget_show (errorDialog.dialog);
245       return;
246     }
247     strncpy(entry->entry.Name, 
248             gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name)),
249             max_phonebook_name_length);
250     entry->entry.Name[max_phonebook_name_length] = '\0';
251
252     if (phoneMonitor.supported & PM_EXTPBK)
253     {
254     }
255     else
256     {
257       strncpy(entry->entry.Number,
258               gtk_entry_get_text (GTK_ENTRY(((EditEntryData*) data)->number)),
259               max_phonebook_number_length);
260       entry->entry.Name[max_phonebook_number_length] = '\0';
261     }
262
263     entry->entry.Group = ((EditEntryData*) data)->newGroup;
264
265     entry->status = E_Changed;
266
267     ((EditEntryData*) data)->pbEntry->status = E_Deleted;
268
269     memoryStatus.UsedME++;
270     memoryStatus.FreeME--;
271     memoryStatus.UsedSM--;
272     memoryStatus.FreeSM++;
273     statusInfo.ch_ME = statusInfo.ch_SM = 1;
274
275     ((EditEntryData*) data)->pbEntry = entry;
276   }
277   else if (GTK_TOGGLE_BUTTON(((EditEntryData*) data)->memoryTypeSIM)->active &&
278       ((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_ME)
279   {
280     if ((entry = FindFreeEntry(GMT_SM)) == NULL)
281     {
282       gtk_label_set_text(GTK_LABEL (errorDialog.text), _("Can't change memory type!"));
283       gtk_widget_show (errorDialog.dialog);
284       return;
285     }
286     strncpy(entry->entry.Name, 
287             gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name)),
288             max_phonebook_sim_name_length);
289     entry->entry.Name[max_phonebook_sim_name_length] = '\0';
290
291     if (strlen(gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name))) > max_phonebook_sim_name_length)
292     {
293       gtk_label_set_text( GTK_LABEL (errorDialog.text), _("Sorry, phonebook name will be truncated,\n\
294 because you save it into SIM memory!"));
295       gtk_widget_show (errorDialog.dialog);
296     }
297
298     if (phoneMonitor.supported & PM_EXTPBK)
299     {
300     }
301     else
302     {
303       strncpy(entry->entry.Number,
304               gtk_entry_get_text (GTK_ENTRY(((EditEntryData*) data)->number)),
305               max_phonebook_sim_number_length);
306       entry->entry.Name[max_phonebook_sim_number_length] = '\0';
307     }
308
309     entry->entry.Group = ((EditEntryData*) data)->newGroup;
310
311     entry->status = E_Changed;    
312
313     ((EditEntryData*) data)->pbEntry->status = E_Deleted;
314
315     memoryStatus.UsedME--;
316     memoryStatus.FreeME++;
317     memoryStatus.UsedSM++;
318     memoryStatus.FreeSM--;
319     statusInfo.ch_ME = statusInfo.ch_SM = 1;    
320
321     ((EditEntryData*) data)->pbEntry = entry;
322   }
323   else
324   {
325     if (GTK_TOGGLE_BUTTON(((EditEntryData*) data)->memoryTypePhone)->active)
326     {
327       strncpy(((EditEntryData*) data)->pbEntry->entry.Name, 
328               gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name)),
329               max_phonebook_name_length);
330       ((EditEntryData*) data)->pbEntry->entry.Name[max_phonebook_name_length] = '\0';
331
332       if (phoneMonitor.supported & PM_EXTPBK)
333       {
334       }
335       else
336       {
337         strncpy(((EditEntryData*) data)->pbEntry->entry.Number,
338                 gtk_entry_get_text (GTK_ENTRY(((EditEntryData*) data)->number)),
339                 max_phonebook_number_length);
340         ((EditEntryData*) data)->pbEntry->entry.Name[max_phonebook_number_length] = '\0';
341       }
342     }
343     else
344     {
345       strncpy(((EditEntryData*) data)->pbEntry->entry.Name, 
346               gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name)),
347               max_phonebook_sim_name_length);
348       ((EditEntryData*) data)->pbEntry->entry.Name[max_phonebook_sim_name_length] = '\0';
349
350       if (strlen(gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name))) > max_phonebook_sim_name_length)
351       {
352         gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Sorry, phonebook name will be truncated,\n\
353 because you save it into SIM memory!"));
354         gtk_widget_show (errorDialog.dialog);
355       }
356
357       if (phoneMonitor.supported & PM_EXTPBK)
358       {
359       }
360       else
361       {
362         strncpy(((EditEntryData*) data)->pbEntry->entry.Number,
363                 gtk_entry_get_text (GTK_ENTRY(((EditEntryData*) data)->number)),
364                 max_phonebook_sim_number_length);
365         ((EditEntryData*) data)->pbEntry->entry.Name[max_phonebook_sim_number_length] = '\0';
366       }
367     }
368
369     ((EditEntryData*) data)->pbEntry->entry.Group = ((EditEntryData*) data)->newGroup;
370
371     ((EditEntryData*) data)->pbEntry->status = E_Changed;
372
373     if (((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_ME)
374       statusInfo.ch_ME = 1;
375     else
376       statusInfo.ch_SM = 1;
377   }
378
379   gtk_widget_hide (GTK_WIDGET(((EditEntryData*) data)->dialog));
380
381   RefreshStatusInfo ();
382
383   gtk_clist_freeze (GTK_CLIST (clist));
384   gtk_clist_remove (GTK_CLIST (clist), ((EditEntryData*) data)->row);
385
386   clist_row[0] = ((EditEntryData*) data)->pbEntry->entry.Name;
387
388   clist_row[1] = ((EditEntryData*) data)->pbEntry->entry.Number;
389   
390   if( ((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_ME)
391     clist_row[2] = "P";
392   else
393     clist_row[2] = "S";
394   if (phoneMonitor.supported & PM_CALLERGROUP)
395     clist_row[3] = xgnokiiConfig.callerGroups[((EditEntryData*) data)->pbEntry->entry.Group];
396   else
397     clist_row[3] = "";
398   gtk_clist_insert(GTK_CLIST (clist), ((EditEntryData*) data)->row, clist_row);
399   if (((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_ME)
400     gtk_clist_set_pixmap( GTK_CLIST (clist), ((EditEntryData*) data)->row, 2,
401                           memoryPixmaps.phoneMemPix, memoryPixmaps.mask);
402   else
403     gtk_clist_set_pixmap( GTK_CLIST (clist), ((EditEntryData*) data)->row, 2,
404                           memoryPixmaps.simMemPix, memoryPixmaps.mask);
405
406   gtk_clist_set_row_data(GTK_CLIST (clist), ((EditEntryData*) data)->row, (gpointer) ((EditEntryData*) data)->pbEntry);
407
408   gtk_clist_sort(GTK_CLIST (clist));
409   gtk_clist_thaw(GTK_CLIST (clist));
410 }
411
412
413 static void OkDeleteEntryDialog(GtkWidget *widget, gpointer data )
414 {
415   PhonebookEntry *pbEntry;
416   GList *sel;
417   gint row;
418
419   sel = GTK_CLIST (clist)->selection;
420
421   gtk_clist_freeze(GTK_CLIST (clist));
422
423   while (sel != NULL)
424   {
425     row = GPOINTER_TO_INT(sel->data); 
426     pbEntry = (PhonebookEntry *) gtk_clist_get_row_data(GTK_CLIST (clist), row);
427     sel = sel->next;
428
429     pbEntry->status = E_Deleted;
430
431     if (pbEntry->entry.MemoryType == GMT_ME)
432     {
433       memoryStatus.UsedME--;
434       memoryStatus.FreeME++;
435       statusInfo.ch_ME = 1;
436     }
437     else
438     {
439       memoryStatus.UsedSM--;
440       memoryStatus.FreeSM++;
441       statusInfo.ch_SM = 1;
442     }
443
444     gtk_clist_remove(GTK_CLIST (clist), row);
445   }
446
447   RefreshStatusInfo ();
448
449   gtk_widget_hide(GTK_WIDGET (data));
450
451   gtk_clist_thaw(GTK_CLIST (clist));
452 }
453
454
455 static void OkNewEntryDialog(GtkWidget *widget, gpointer data )
456 {
457   gchar *clist_row[4];
458   PhonebookEntry *entry;
459
460   if (GTK_TOGGLE_BUTTON(((EditEntryData*) data)->memoryTypePhone)->active &&
461       ((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_SM)
462   {
463     if ((entry = FindFreeEntry (GMT_ME)) == NULL)
464     {
465       gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't change memory type!"));
466       gtk_widget_show (errorDialog.dialog);
467       return;
468     }
469     strncpy(entry->entry.Name, 
470             gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name)),
471             max_phonebook_name_length);
472     entry->entry.Name[max_phonebook_name_length] = '\0';
473
474     if (phoneMonitor.supported & PM_EXTPBK)
475     {
476     }
477     else
478     {
479       strncpy(entry->entry.Number,
480               gtk_entry_get_text (GTK_ENTRY(((EditEntryData*) data)->number)),
481               max_phonebook_number_length);
482       entry->entry.Name[max_phonebook_number_length] = '\0';
483     }
484
485     entry->entry.Group = ((EditEntryData*) data)->newGroup;
486
487     entry->status = E_Changed;
488
489     ((EditEntryData*) data)->pbEntry = entry;
490   }
491   else if (GTK_TOGGLE_BUTTON(((EditEntryData*) data)->memoryTypeSIM)->active &&
492       ((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_ME)
493   {
494     if ((entry = FindFreeEntry (GMT_SM)) == NULL)
495     {
496       gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't change memory type!"));
497       gtk_widget_show (errorDialog.dialog);
498       return;
499     }
500     strncpy(entry->entry.Name, 
501             gtk_entry_get_text (GTK_ENTRY (((EditEntryData*) data)->name)),
502             max_phonebook_sim_name_length);
503     entry->entry.Name[max_phonebook_sim_name_length] = '\0';
504
505     if (strlen(gtk_entry_get_text (GTK_ENTRY (((EditEntryData*) data)->name))) > max_phonebook_sim_name_length)
506     {
507       gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Sorry, phonebook name will be truncated\n\
508 because you save it into SIM memory!"));
509       gtk_widget_show (errorDialog.dialog);
510     }
511
512     if (phoneMonitor.supported & PM_EXTPBK)
513     {
514     }
515     else
516     {
517       strncpy(entry->entry.Number,
518               gtk_entry_get_text (GTK_ENTRY(((EditEntryData*) data)->number)),
519               max_phonebook_sim_number_length);
520       entry->entry.Name[max_phonebook_sim_number_length] = '\0';
521     }
522
523     entry->entry.Group = ((EditEntryData*) data)->newGroup;
524
525     entry->status = E_Changed;
526
527     ((EditEntryData*) data)->pbEntry = entry;
528   }
529   else
530   {
531     if (GTK_TOGGLE_BUTTON(((EditEntryData*) data)->memoryTypePhone)->active)
532     {
533       strncpy(((EditEntryData*) data)->pbEntry->entry.Name, 
534               gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name)),
535               max_phonebook_name_length);
536       ((EditEntryData*) data)->pbEntry->entry.Name[max_phonebook_name_length] = '\0';
537
538       if (phoneMonitor.supported & PM_EXTPBK)
539       {
540       }
541       else
542       {
543         strncpy(((EditEntryData*) data)->pbEntry->entry.Number,
544                 gtk_entry_get_text (GTK_ENTRY(((EditEntryData*) data)->number)),
545                 max_phonebook_number_length);
546         ((EditEntryData*) data)->pbEntry->entry.Name[max_phonebook_number_length] = '\0';
547       }
548     }
549     else
550     {
551       strncpy (((EditEntryData*) data)->pbEntry->entry.Name, 
552               gtk_entry_get_text(GTK_ENTRY (((EditEntryData*) data)->name)),
553               max_phonebook_sim_name_length);
554       ((EditEntryData*) data)->pbEntry->entry.Name[max_phonebook_sim_name_length] = '\0';
555
556       if (strlen(gtk_entry_get_text (GTK_ENTRY (((EditEntryData*) data)->name))) > max_phonebook_sim_name_length)
557       {
558         gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Sorry, phonebook name will be truncated\n\
559 because you save it into SIM memory!"));
560         gtk_widget_show (errorDialog.dialog);
561       }
562
563       if (phoneMonitor.supported & PM_EXTPBK)
564       {
565       }
566       else
567       {
568         strncpy (((EditEntryData*) data)->pbEntry->entry.Number,
569                 gtk_entry_get_text (GTK_ENTRY(((EditEntryData*) data)->number)),
570                 max_phonebook_sim_number_length);
571         ((EditEntryData*) data)->pbEntry->entry.Name[max_phonebook_sim_number_length] = '\0';
572       }
573     }
574
575     ((EditEntryData*) data)->pbEntry->entry.Group = ((EditEntryData*) data)->newGroup;
576
577     ((EditEntryData*) data)->pbEntry->status = E_Changed;
578   }
579
580   if (((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_ME)
581   {
582     memoryStatus.UsedME++;
583     memoryStatus.FreeME--;
584     statusInfo.ch_ME = 1;
585   }
586   else
587   {
588     memoryStatus.UsedSM++;
589     memoryStatus.FreeSM--;
590     statusInfo.ch_SM = 1;
591   }
592
593   gtk_widget_hide(GTK_WIDGET(((EditEntryData*) data)->dialog));
594
595   RefreshStatusInfo ();
596
597   gtk_clist_freeze (GTK_CLIST (clist));
598   clist_row[0] = ((EditEntryData*) data)->pbEntry->entry.Name;
599
600   clist_row[1] = ((EditEntryData*) data)->pbEntry->entry.Number;
601
602   if( ((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_ME)
603     clist_row[2] = "P";
604   else
605     clist_row[2] = "S";
606   if (phoneMonitor.supported & PM_CALLERGROUP)
607     clist_row[3] = xgnokiiConfig.callerGroups[((EditEntryData*) data)->pbEntry->entry.Group];
608   else
609     clist_row[3] = "";
610   gtk_clist_insert (GTK_CLIST (clist), 1, clist_row);
611
612   if (((EditEntryData*) data)->pbEntry->entry.MemoryType == GMT_ME)
613     gtk_clist_set_pixmap (GTK_CLIST (clist), 1, 2,
614                           memoryPixmaps.phoneMemPix, memoryPixmaps.mask);
615   else
616     gtk_clist_set_pixmap (GTK_CLIST (clist), 1, 2,
617                           memoryPixmaps.simMemPix, memoryPixmaps.mask);
618
619   gtk_clist_set_row_data (GTK_CLIST (clist), 1, (gpointer) ((EditEntryData*) data)->pbEntry);
620
621   gtk_clist_sort (GTK_CLIST (clist));
622   gtk_clist_thaw (GTK_CLIST (clist));
623 }
624
625
626 static void OkChangeEntryDialog( GtkWidget *widget, gpointer data)
627 {
628   gchar *clist_row[4];
629   gint row;
630   PhonebookEntry *oldPbEntry, *newPbEntry;
631   GList *sel;
632   gchar string[100];
633
634   sel = GTK_CLIST (clist)->selection;
635
636   gtk_widget_hide(GTK_WIDGET (data));
637
638   gtk_clist_freeze(GTK_CLIST (clist));
639
640   while (sel != NULL)
641   {
642     row = GPOINTER_TO_INT (sel->data);
643     oldPbEntry = (PhonebookEntry *) gtk_clist_get_row_data(GTK_CLIST (clist), row);
644
645     sel = sel->next;
646
647     if (oldPbEntry->entry.MemoryType == GMT_SM)
648     {
649       if ((newPbEntry = FindFreeEntry (GMT_ME)) == NULL)
650       {
651         gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't change memory type!"));  
652         gtk_widget_show (errorDialog.dialog);
653         return;
654       }
655
656       newPbEntry->entry = oldPbEntry->entry;
657       newPbEntry->entry.MemoryType = GMT_ME;
658
659       newPbEntry->status = E_Changed;
660       oldPbEntry->status = E_Deleted;
661
662       memoryStatus.UsedME++;
663       memoryStatus.FreeME--;
664       memoryStatus.UsedSM--;
665       memoryStatus.FreeSM++;
666       statusInfo.ch_ME = statusInfo.ch_SM = 1;
667
668     }
669     else
670     {
671       if ((newPbEntry = FindFreeEntry(GMT_SM)) == NULL)
672       {
673         gtk_label_set_text(GTK_LABEL (errorDialog.text), _("Can't change memory type!"));
674         gtk_widget_show (errorDialog.dialog);
675         return;
676       }
677
678       newPbEntry->entry = oldPbEntry->entry;
679       newPbEntry->entry.Name[max_phonebook_sim_name_length] = '\0';
680       newPbEntry->entry.MemoryType = GMT_SM;
681
682       newPbEntry->status = E_Changed;
683       oldPbEntry->status = E_Deleted;
684
685       memoryStatus.UsedME--;
686       memoryStatus.FreeME++;
687       memoryStatus.UsedSM++;
688       memoryStatus.FreeSM--;
689       statusInfo.ch_ME = statusInfo.ch_SM = 1;
690     }
691
692     gtk_clist_remove(GTK_CLIST (clist), row);
693
694     clist_row[0] = newPbEntry->entry.Name;
695
696     if (newPbEntry->entry.SubEntriesCount>0) {
697       snprintf(string,100,"%s *",newPbEntry->entry.Number);
698       clist_row[1]=string;
699     } else clist_row[1] = newPbEntry->entry.Number;
700     
701     if( newPbEntry->entry.MemoryType == GMT_ME)
702       clist_row[2] = "P";
703     else
704       clist_row[2] = "S";
705     if (phoneMonitor.supported & PM_CALLERGROUP)
706       clist_row[3] = xgnokiiConfig.callerGroups[newPbEntry->entry.Group];
707     else
708       clist_row[3] = "";
709     gtk_clist_insert (GTK_CLIST (clist), row, clist_row);
710     if (newPbEntry->entry.MemoryType == GMT_ME)
711       gtk_clist_set_pixmap (GTK_CLIST (clist), row, 2,
712                             memoryPixmaps.phoneMemPix, memoryPixmaps.mask);
713     else
714       gtk_clist_set_pixmap (GTK_CLIST (clist), row, 2,
715                             memoryPixmaps.simMemPix, memoryPixmaps.mask);
716
717     gtk_clist_set_row_data (GTK_CLIST (clist), row, (gpointer) newPbEntry);
718   }
719
720   RefreshStatusInfo ();  
721   gtk_clist_sort (GTK_CLIST (clist));
722   gtk_clist_thaw (GTK_CLIST (clist));
723 }
724
725
726 static void SearchEntry (void)
727 {
728   gchar *buf;
729   gchar *entry;
730   gint i;
731
732   if (!contactsMemoryInitialized || *findEntryStruct.pattern == '\0')
733     return;
734
735   gtk_clist_unselect_all( GTK_CLIST (clist));
736   g_strup(findEntryStruct.pattern);
737
738   gtk_clist_get_text( GTK_CLIST (clist), findEntryStruct.lastRow,
739                       findEntryStruct.type, &entry);
740   i = (findEntryStruct.lastRow + 1) % (memoryStatus.MaxME + memoryStatus.MaxSM);
741
742   while (findEntryStruct.lastRow != i)
743   {
744     buf = g_strdup (entry);
745     g_strup (buf);
746
747     if (strstr( buf, findEntryStruct.pattern))
748     {
749       g_free(buf);
750       findEntryStruct.lastRow = i;
751       gtk_clist_select_row( GTK_CLIST (clist),
752                             (i + memoryStatus.MaxME + memoryStatus.MaxSM - 1)
753                             % (memoryStatus.MaxME + memoryStatus.MaxSM),
754                             findEntryStruct.type);
755       gtk_clist_moveto( GTK_CLIST (clist),
756                         (i + memoryStatus.MaxME + memoryStatus.MaxSM - 1)
757                         % (memoryStatus.MaxME + memoryStatus.MaxSM),
758                         findEntryStruct.type, 0.5, 0.5);
759       return;
760     }
761     g_free(buf);
762     gtk_clist_get_text (GTK_CLIST (clist), i, findEntryStruct.type, &entry);
763
764     i = (i + 1) % (memoryStatus.MaxME + memoryStatus.MaxSM);
765   }
766
767   gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't find pattern!"));
768   gtk_widget_show (errorDialog.dialog);  
769 }
770
771
772 static void OkFindEntryDialog (GtkWidget *widget, gpointer data)
773 {
774   if (GTK_TOGGLE_BUTTON (((FindEntryData*) data)->nameB)->active)
775     findEntryStruct.type = FIND_NAME;
776   else
777     findEntryStruct.type = FIND_NUMBER;
778
779   strncpy(findEntryStruct.pattern, 
780           gtk_entry_get_text (GTK_ENTRY (((FindEntryData*) data)->pattern)),
781           max_phonebook_number_length);
782   findEntryStruct.pattern[max_phonebook_number_length] = '\0';
783
784   findEntryStruct.lastRow = 0;
785
786   gtk_widget_hide( ((FindEntryData*) data)->dialog);
787
788   SearchEntry ();
789 }
790
791
792 void CreateGroupMenu (EditEntryData *data)
793 {
794   GtkWidget *item;
795
796   if (data->groupMenu)
797   {
798     gtk_option_menu_remove_menu (GTK_OPTION_MENU (data->group));
799     if (GTK_IS_WIDGET (data->groupMenu))
800       gtk_widget_destroy (GTK_WIDGET (data->groupMenu));
801     data->groupMenu = NULL;
802   }
803
804   data->groupMenu = gtk_menu_new ();
805
806   item = gtk_menu_item_new_with_label (xgnokiiConfig.callerGroups[0]);
807   gtk_signal_connect (GTK_OBJECT (item), "activate",
808                       GTK_SIGNAL_FUNC (SetGroup0),
809                       (gpointer) data);
810   gtk_widget_show (item);
811   gtk_menu_append (GTK_MENU (data->groupMenu), item);
812
813   item = gtk_menu_item_new_with_label (xgnokiiConfig.callerGroups[1]);
814   gtk_signal_connect (GTK_OBJECT (item), "activate",
815                       GTK_SIGNAL_FUNC (SetGroup1),
816                       (gpointer) data);
817   gtk_widget_show (item);
818   gtk_menu_append (GTK_MENU (data->groupMenu), item);
819
820   item = gtk_menu_item_new_with_label (xgnokiiConfig.callerGroups[2]);
821   gtk_signal_connect (GTK_OBJECT (item), "activate",
822                       GTK_SIGNAL_FUNC (SetGroup2),
823                       (gpointer) data);
824   gtk_widget_show (item);
825   gtk_menu_append (GTK_MENU (data->groupMenu), item);
826
827   item = gtk_menu_item_new_with_label (xgnokiiConfig.callerGroups[3]);
828   gtk_signal_connect (GTK_OBJECT (item), "activate",
829                       GTK_SIGNAL_FUNC (SetGroup3),
830                       (gpointer) data);
831   gtk_widget_show (item);
832   gtk_menu_append (GTK_MENU (data->groupMenu), item);
833
834   item = gtk_menu_item_new_with_label (xgnokiiConfig.callerGroups[4]);
835   gtk_signal_connect (GTK_OBJECT (item), "activate",
836                       GTK_SIGNAL_FUNC (SetGroup4),
837                       (gpointer) data);
838   gtk_widget_show (item);
839   gtk_menu_append (GTK_MENU (data->groupMenu), item);
840
841   item = gtk_menu_item_new_with_label (xgnokiiConfig.callerGroups[5]);
842   gtk_signal_connect (GTK_OBJECT (item), "activate",
843                       GTK_SIGNAL_FUNC (SetGroup5),
844                       (gpointer) data);
845   gtk_widget_show (item);
846   gtk_menu_append (GTK_MENU (data->groupMenu), item);
847
848   gtk_option_menu_set_menu (GTK_OPTION_MENU (data->group), data->groupMenu);
849 }
850
851
852 inline void GUI_RefreshGroupMenu (void)
853 {
854   if (newEditEntryData.group)
855     CreateGroupMenu (&newEditEntryData);
856
857   if (editEditEntryData.group)
858     CreateGroupMenu (&editEditEntryData);
859
860   if (duplicateEditEntryData.group)
861     CreateGroupMenu (&duplicateEditEntryData);
862 }
863
864
865 static void EditSubEntries (GtkWidget      *clist,
866                             gint            row,
867                             gint            column,
868                             GdkEventButton *event,
869                             gpointer        data )
870 {
871   if(event && event->type == GDK_2BUTTON_PRESS)
872 //    EditPbEntry((PhonebookEntry *) gtk_clist_get_row_data(GTK_CLIST (clist), row),
873 //                row);
874   {
875     gchar *buf;
876
877     gtk_clist_get_text (GTK_CLIST (clist), row, 1, &buf);
878     g_print (buf);
879   }
880 }
881
882
883 static void EditNumbers (GtkWidget *widget, void *data)
884 {
885   GtkWidget *button, *clistScrolledWindow;
886   gchar *row[3];
887   register gint i;
888   
889   
890   if (editNumbersData.dialog == NULL)
891   {
892     editNumbersData.dialog = gtk_dialog_new ();
893     gtk_window_set_title (GTK_WINDOW (editNumbersData.dialog), _("Numbers"));
894     gtk_window_set_modal (GTK_WINDOW (editNumbersData.dialog), TRUE);
895     gtk_container_set_border_width (GTK_CONTAINER (editNumbersData.dialog), 10);
896     gtk_signal_connect (GTK_OBJECT (editNumbersData.dialog), "delete_event",
897                         GTK_SIGNAL_FUNC (DeleteEvent), NULL);
898
899     button = gtk_button_new_with_label (_("Ok"));
900     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editNumbersData.dialog)->action_area),
901                         button, TRUE, TRUE, 10);
902 //    gtk_signal_connect (GTK_OBJECT (button), "clicked",
903 //                        GTK_SIGNAL_FUNC (okFunc), (gpointer) editEntryData);
904     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
905     gtk_widget_grab_default (button);
906     gtk_widget_show (button);
907     
908     button = gtk_button_new_with_label (_("New"));
909     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editNumbersData.dialog)->action_area),
910                         button, TRUE, TRUE, 10);
911 //    gtk_signal_connect (GTK_OBJECT (button), "clicked",
912 //                        GTK_SIGNAL_FUNC (okFunc), (gpointer) editEntryData);
913     gtk_widget_show (button);
914     
915     button = gtk_button_new_with_label (_("Cancel"));
916     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editNumbersData.dialog)->action_area),
917                         button, TRUE, TRUE, 10);
918     gtk_signal_connect (GTK_OBJECT (button), "clicked",
919                         GTK_SIGNAL_FUNC (CancelDialog), (gpointer) editNumbersData.dialog);
920     gtk_widget_show (button);
921
922     gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (editNumbersData.dialog)->vbox), 5);
923     
924     editNumbersData.clist = gtk_clist_new (3);
925     gtk_clist_set_shadow_type (GTK_CLIST (editNumbersData.clist), GTK_SHADOW_OUT);
926
927     gtk_clist_set_column_width (GTK_CLIST (editNumbersData.clist), 0, 4);
928     gtk_clist_set_column_width (GTK_CLIST (editNumbersData.clist), 1, 115);
929     gtk_clist_set_column_width (GTK_CLIST (editNumbersData.clist), 2, 10);
930     //gtk_clist_set_column_justification (GTK_CLIST (editNumbersData.clist), 2, GTK_JUSTIFY_CENTER);
931
932     gtk_signal_connect (GTK_OBJECT (editNumbersData.clist), "select_row",
933                         GTK_SIGNAL_FUNC (EditSubEntries), NULL);
934
935     clistScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
936     gtk_container_add (GTK_CONTAINER (clistScrolledWindow), editNumbersData.clist);
937     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (clistScrolledWindow),
938                                     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
939
940     gtk_container_add (GTK_CONTAINER (GTK_DIALOG (editNumbersData.dialog)->vbox),
941                        clistScrolledWindow);
942                        
943     gtk_widget_show (editNumbersData.clist);
944     gtk_widget_show (clistScrolledWindow);
945   }
946
947   gtk_clist_freeze (GTK_CLIST (editNumbersData.clist));
948   gtk_clist_clear (GTK_CLIST (editNumbersData.clist));
949
950   for(i = 0; i < editNumbersData.pbEntry->entry.SubEntriesCount; i++)
951   {
952     if (strcmp (editNumbersData.pbEntry->entry.Number,
953                 editNumbersData.pbEntry->entry.SubEntries[i].data.Number) == 0)
954       row[0] = "*";
955     else
956       row[0] = "";
957       
958     row[1] = editNumbersData.pbEntry->entry.SubEntries[i].data.Number;
959
960     switch (editNumbersData.pbEntry->entry.SubEntries[i].EntryType)
961     {
962       case GSM_Number:
963         switch (editNumbersData.pbEntry->entry.SubEntries[i].NumberType)
964         {
965           case GSM_General:
966             row[2] = "General";
967             break;
968
969           case GSM_Mobile:
970             row[2] = "Mobile";
971             break;
972
973           case GSM_Work:
974             row[2] = "Work";
975             break;
976
977           case GSM_Fax:
978             row[2] = "Fax";
979             break;
980
981           case GSM_Home:
982             row[2] = "Home";
983             break;
984
985           default:
986             row[2] = "Unknown";
987             break;
988         }
989         break;
990
991       case GSM_Note:
992         row[2] = "Note";
993         break;
994
995       case GSM_Postal:
996         row[2] = "Postal";
997         break;
998
999       case GSM_Email:
1000         row[2] = "E-Mail";
1001         break;
1002
1003       case GSM_Name:
1004         row[2] = "Name";
1005         break;
1006
1007       default:
1008         row[2] = "Unknown";
1009         break;
1010     }
1011     
1012     gtk_clist_append (GTK_CLIST (editNumbersData.clist), row);
1013 /*      if (pbEntry->entry.MemoryType == GMT_ME)
1014       gtk_clist_set_pixmap (GTK_CLIST (clist), row_i, 2,
1015                             memoryPixmaps.phoneMemPix, memoryPixmaps.mask);
1016     else
1017       gtk_clist_set_pixmap (GTK_CLIST (clist), row_i, 2,
1018                             memoryPixmaps.simMemPix, memoryPixmaps.mask);
1019 */
1020   }
1021     
1022   gtk_clist_thaw (GTK_CLIST (editNumbersData.clist));
1023   
1024   gtk_widget_show (editNumbersData.dialog);
1025 }
1026
1027
1028 static void CreateEditDialog (EditEntryData *editEntryData, gchar *title,
1029                               GtkSignalFunc okFunc)
1030 {
1031   GtkWidget *button, *label, *hbox;
1032
1033   editEntryData->dialog = gtk_dialog_new ();
1034   gtk_window_set_title (GTK_WINDOW (editEntryData->dialog), title);
1035   gtk_window_set_modal (GTK_WINDOW (editEntryData->dialog), TRUE);
1036   gtk_container_set_border_width (GTK_CONTAINER (editEntryData->dialog), 10);
1037   gtk_signal_connect (GTK_OBJECT (editEntryData->dialog), "delete_event",
1038                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1039
1040   button = gtk_button_new_with_label (_("Ok"));
1041   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editEntryData->dialog)->action_area),
1042                       button, TRUE, TRUE, 10);
1043   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1044                       GTK_SIGNAL_FUNC (okFunc), (gpointer) editEntryData);
1045   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1046   gtk_widget_grab_default (button);
1047   gtk_widget_show (button);
1048   button = gtk_button_new_with_label (_("Cancel"));
1049   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (editEntryData->dialog)->action_area),
1050                       button, TRUE, TRUE, 10);
1051   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1052                       GTK_SIGNAL_FUNC (CancelEditDialog), (gpointer) editEntryData);
1053   gtk_widget_show (button);
1054
1055   gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (editEntryData->dialog)->vbox), 5);
1056
1057   hbox = gtk_hbox_new (FALSE, 0);
1058   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (editEntryData->dialog)->vbox), hbox);
1059   gtk_widget_show (hbox);
1060
1061   label = gtk_label_new (_("Name:"));
1062   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1063   gtk_widget_show (label);
1064
1065   editEntryData->name = gtk_entry_new_with_max_length (100);
1066
1067   gtk_box_pack_end(GTK_BOX(hbox), editEntryData->name, FALSE, FALSE, 2);
1068   gtk_widget_show (editEntryData->name);
1069
1070   hbox = gtk_hbox_new (FALSE, 0);
1071   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (editEntryData->dialog)->vbox), hbox);
1072   gtk_widget_show (hbox);
1073
1074   label = gtk_label_new (_("Number:"));
1075   gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1076   gtk_widget_show (label);
1077
1078   if (phoneMonitor.supported & PM_EXTPBK)
1079   {
1080     button = gtk_button_new ();
1081     editEntryData->number = gtk_label_new ("");
1082
1083     gtk_container_add (GTK_CONTAINER (button), editEntryData->number);
1084
1085     gtk_box_pack_end(GTK_BOX(hbox), button, TRUE, TRUE, 2);
1086
1087     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1088                         GTK_SIGNAL_FUNC (EditNumbers), NULL);
1089     gtk_widget_show_all (button);
1090   }
1091   else
1092   {
1093     editEntryData->number = gtk_entry_new_with_max_length (max_phonebook_number_length);
1094     gtk_box_pack_end(GTK_BOX(hbox), editEntryData->number, FALSE, FALSE, 2);
1095     gtk_widget_show (editEntryData->number);
1096   }
1097
1098 /*  if (phoneMonitor.supported & PM_EXTPBK) {
1099
1100     hbox = gtk_hbox_new (FALSE, 0);
1101     gtk_container_add (GTK_CONTAINER (GTK_DIALOG (editEntryData->dialog)->vbox), hbox);
1102 //    gtk_widget_show (hbox);
1103
1104     label = gtk_label_new (_("Extended:"));
1105     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 2);
1106 //    gtk_widget_show (label);
1107     
1108     editEntryData->extended = gtk_combo_new();
1109     gtk_box_pack_end(GTK_BOX(hbox), editEntryData->extended, FALSE, FALSE, 2);
1110 //    gtk_widget_show (editEntryData->extended);
1111
1112     gtk_signal_connect (GTK_OBJECT (GTK_COMBO(editEntryData->extended)->entry), "activate",
1113                         GTK_SIGNAL_FUNC (ExtPbkChanged), (gpointer) editEntryData);    
1114   }
1115 */
1116     
1117   editEntryData->memoryBox = gtk_hbox_new (FALSE, 0);
1118   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (editEntryData->dialog)->vbox),
1119                      editEntryData->memoryBox);
1120     
1121   label = gtk_label_new (_("Memory:"));
1122   gtk_box_pack_start(GTK_BOX (editEntryData->memoryBox), label, FALSE, FALSE, 2);
1123   gtk_widget_show (label);
1124
1125   editEntryData->memoryTypePhone = gtk_radio_button_new_with_label (NULL, _("phone"));
1126   gtk_box_pack_end (GTK_BOX (editEntryData->memoryBox), editEntryData->memoryTypePhone, TRUE, FALSE, 2);
1127   gtk_widget_show (editEntryData->memoryTypePhone);
1128
1129   editEntryData->memoryTypeSIM = gtk_radio_button_new_with_label( 
1130         gtk_radio_button_group (GTK_RADIO_BUTTON (editEntryData->memoryTypePhone)), "SIM");
1131   gtk_box_pack_end(GTK_BOX (editEntryData->memoryBox), editEntryData->memoryTypeSIM, TRUE, FALSE, 2);
1132   gtk_widget_show (editEntryData->memoryTypeSIM);
1133
1134   hbox = gtk_hbox_new (FALSE, 0);
1135   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (editEntryData->dialog)->vbox), hbox);
1136   gtk_widget_show (hbox);
1137
1138   editEntryData->groupLabel = gtk_label_new (_("Caller group:"));
1139   gtk_box_pack_start (GTK_BOX (hbox), editEntryData->groupLabel, FALSE, FALSE, 2);
1140
1141   editEntryData->group = gtk_option_menu_new ();
1142
1143   CreateGroupMenu (editEntryData);
1144
1145   gtk_box_pack_start (GTK_BOX (hbox), editEntryData->group, TRUE, TRUE, 0);
1146 }
1147
1148
1149 static void EditPbEntry(PhonebookEntry *pbEntry, gint row)
1150 {
1151   if (editEditEntryData.dialog == NULL)
1152     CreateEditDialog(&editEditEntryData, _("Edit entry"), OkEditEntryDialog);
1153
1154   editEditEntryData.pbEntry = pbEntry;
1155   editEditEntryData.newGroup = pbEntry->entry.Group;
1156   editEditEntryData.row = row;
1157   editNumbersData.pbEntry = pbEntry;
1158
1159   gtk_entry_set_text (GTK_ENTRY (editEditEntryData.name), pbEntry->entry.Name);
1160
1161   if (phoneMonitor.supported & PM_EXTPBK)
1162     gtk_label_set_text (GTK_LABEL (editEditEntryData.number), pbEntry->entry.Number);
1163   else
1164     gtk_entry_set_text (GTK_ENTRY (editEditEntryData.number), pbEntry->entry.Number);
1165
1166   if (pbEntry->entry.MemoryType == GMT_ME)
1167     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editEditEntryData.memoryTypePhone), TRUE);
1168   else
1169     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (editEditEntryData.memoryTypeSIM), TRUE);
1170
1171   gtk_option_menu_set_history( GTK_OPTION_MENU (editEditEntryData.group),
1172                                pbEntry->entry.Group);
1173
1174   if (phoneMonitor.supported & PM_CALLERGROUP)
1175   {
1176     gtk_widget_show (editEditEntryData.group);
1177     gtk_widget_show (editEditEntryData.groupLabel);
1178   }
1179   else
1180   {
1181     gtk_widget_hide (editEditEntryData.group);
1182     gtk_widget_hide (editEditEntryData.groupLabel);
1183   }
1184
1185   if (memoryStatus.MaxME > 0)
1186     gtk_widget_show (GTK_WIDGET (editEditEntryData.memoryBox));
1187   else
1188     gtk_widget_hide (GTK_WIDGET (editEditEntryData.memoryBox));
1189
1190   gtk_widget_show (GTK_WIDGET (editEditEntryData.dialog));
1191 }
1192
1193
1194 void DeletePbEntry (void)
1195 {
1196   static GtkWidget *dialog = NULL;
1197   GtkWidget *button, *hbox, *label, *pixmap;
1198
1199   if (dialog == NULL)
1200   {
1201     dialog = gtk_dialog_new ();
1202     gtk_window_set_title (GTK_WINDOW (dialog), _("Delete entries"));
1203     gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
1204     gtk_window_set_modal(GTK_WINDOW (dialog), TRUE);
1205     gtk_container_set_border_width (GTK_CONTAINER (dialog), 10);
1206     gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
1207                         GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1208
1209     button = gtk_button_new_with_label (_("Ok"));
1210     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
1211                         button, TRUE, TRUE, 10);
1212     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1213                         GTK_SIGNAL_FUNC (OkDeleteEntryDialog), (gpointer) dialog);
1214     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1215     gtk_widget_grab_default (button);
1216     gtk_widget_show (button);
1217     button = gtk_button_new_with_label (_("Cancel"));
1218     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
1219                         button, TRUE, TRUE, 10);
1220     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1221                         GTK_SIGNAL_FUNC (CancelDialog), (gpointer) dialog);
1222     gtk_widget_show (button);
1223
1224     gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5);
1225
1226     hbox = gtk_hbox_new (FALSE, 0);
1227     gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
1228     gtk_widget_show (hbox);
1229
1230     pixmap = gtk_pixmap_new (questMark.pixmap, questMark.mask);
1231     gtk_box_pack_start(GTK_BOX(hbox), pixmap, FALSE, FALSE, 10);
1232     gtk_widget_show(pixmap);
1233
1234     label = gtk_label_new(_("Do you want to delete selected entries?"));
1235     gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 10);
1236     gtk_widget_show(label);
1237   }
1238
1239   gtk_widget_show(GTK_WIDGET (dialog));
1240 }
1241
1242
1243 void NewPbEntry(PhonebookEntry *pbEntry)
1244 {
1245   if (newEditEntryData.dialog == NULL)
1246     CreateEditDialog (&newEditEntryData, _("New entry"), OkNewEntryDialog);
1247
1248   newEditEntryData.pbEntry = pbEntry;
1249   newEditEntryData.newGroup = 5;
1250   editNumbersData.pbEntry = pbEntry;
1251
1252   gtk_entry_set_text (GTK_ENTRY (newEditEntryData.name), "");
1253   
1254   if (phoneMonitor.supported & PM_EXTPBK)
1255     gtk_label_set_text (GTK_LABEL (newEditEntryData.number), "");
1256   else
1257     gtk_entry_set_text (GTK_ENTRY (newEditEntryData.number), "");
1258
1259   if (pbEntry->entry.MemoryType == GMT_ME)
1260     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (newEditEntryData.memoryTypePhone), TRUE);
1261   else
1262     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (newEditEntryData.memoryTypeSIM), TRUE);
1263
1264   gtk_option_menu_set_history( GTK_OPTION_MENU (newEditEntryData.group),
1265                                pbEntry->entry.Group);
1266
1267   if (phoneMonitor.supported & PM_CALLERGROUP)
1268   {
1269     gtk_widget_show (newEditEntryData.group);
1270     gtk_widget_show (newEditEntryData.groupLabel);
1271   }
1272   else
1273   {
1274     gtk_widget_hide (newEditEntryData.group);
1275     gtk_widget_hide (newEditEntryData.groupLabel);
1276   }
1277
1278   if (memoryStatus.MaxME > 0)
1279     gtk_widget_show (GTK_WIDGET (newEditEntryData.memoryBox));
1280   else
1281     gtk_widget_hide (GTK_WIDGET (newEditEntryData.memoryBox));
1282
1283   gtk_widget_show(GTK_WIDGET (newEditEntryData.dialog));
1284 }
1285
1286
1287 void DuplicatePbEntry (PhonebookEntry *pbEntry)
1288 {
1289   if (duplicateEditEntryData.dialog == NULL)
1290     CreateEditDialog (&duplicateEditEntryData, _("Duplicate entry"), OkNewEntryDialog);
1291
1292   duplicateEditEntryData.pbEntry = pbEntry;
1293   duplicateEditEntryData.newGroup = pbEntry->entry.Group;
1294   editNumbersData.pbEntry = pbEntry;
1295
1296   gtk_entry_set_text (GTK_ENTRY (duplicateEditEntryData.name), pbEntry->entry.Name);
1297
1298   if (phoneMonitor.supported & PM_EXTPBK)
1299     gtk_label_set_text (GTK_LABEL (duplicateEditEntryData.number), pbEntry->entry.Number);
1300   else
1301     gtk_entry_set_text (GTK_ENTRY (duplicateEditEntryData.number), pbEntry->entry.Number);
1302
1303   if (pbEntry->entry.MemoryType == GMT_ME)
1304     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (duplicateEditEntryData.memoryTypePhone), TRUE);
1305   else
1306     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (duplicateEditEntryData.memoryTypeSIM), TRUE);
1307
1308   gtk_option_menu_set_history( GTK_OPTION_MENU (duplicateEditEntryData.group),
1309                                pbEntry->entry.Group);
1310
1311   if (phoneMonitor.supported & PM_CALLERGROUP)
1312   {
1313     gtk_widget_show (duplicateEditEntryData.group);
1314     gtk_widget_show (duplicateEditEntryData.groupLabel);
1315   }
1316   else
1317   {
1318     gtk_widget_hide (duplicateEditEntryData.group);
1319     gtk_widget_hide (duplicateEditEntryData.groupLabel);
1320   }
1321
1322   if (memoryStatus.MaxME > 0)
1323     gtk_widget_show (GTK_WIDGET (duplicateEditEntryData.memoryBox));
1324   else
1325     gtk_widget_hide (GTK_WIDGET (duplicateEditEntryData.memoryBox));
1326
1327   gtk_widget_show(GTK_WIDGET (duplicateEditEntryData.dialog));
1328 }
1329
1330
1331 static void EditEntry (void)
1332 {
1333   if (contactsMemoryInitialized)
1334   {
1335     if (GTK_CLIST (clist)->selection == NULL)
1336       return;
1337
1338     EditPbEntry((PhonebookEntry *) gtk_clist_get_row_data(GTK_CLIST (clist),
1339                 GPOINTER_TO_INT(GTK_CLIST (clist)->selection->data)),
1340                 GPOINTER_TO_INT(GTK_CLIST (clist)->selection->data));
1341   }
1342 }
1343
1344
1345 static void DuplicateEntry (void)
1346 {
1347   PhonebookEntry *new, *old;
1348
1349   if (contactsMemoryInitialized)
1350   {
1351     if (GTK_CLIST (clist)->selection == NULL)
1352       return;
1353
1354     old = (PhonebookEntry *) gtk_clist_get_row_data (GTK_CLIST (clist), GPOINTER_TO_INT(GTK_CLIST (clist)->selection->data));
1355
1356     if ( old->entry.MemoryType == GMT_ME)
1357     {
1358       if ((new = FindFreeEntry (GMT_ME)) == NULL)
1359         if ((new = FindFreeEntry (GMT_SM)) == NULL)
1360         {
1361           gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't find free memory."));
1362           gtk_widget_show (errorDialog.dialog);
1363           return;
1364         }
1365     }
1366     else
1367     {
1368       if ((new = FindFreeEntry(GMT_SM)) == NULL)
1369         if ((new = FindFreeEntry(GMT_ME)) == NULL)
1370         {
1371           gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't find free memory."));
1372           gtk_widget_show (errorDialog.dialog);
1373           return;
1374         }
1375     }
1376
1377     new->entry = old->entry;
1378
1379     DuplicatePbEntry (new);
1380   }
1381 }
1382
1383
1384 static void NewEntry (void)
1385 {
1386   PhonebookEntry *entry;
1387
1388   if (contactsMemoryInitialized)
1389   {
1390     if ((entry = FindFreeEntry (GMT_SM)) != NULL)
1391       NewPbEntry(entry);
1392     else if ((entry = FindFreeEntry (GMT_ME)) != NULL)
1393       NewPbEntry(entry);
1394     else
1395     {
1396       gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't find free memory."));
1397       gtk_widget_show (errorDialog.dialog);
1398     }
1399   }
1400 }
1401
1402
1403 static inline void ClickEntry (GtkWidget      *clist,
1404                  gint            row,
1405                  gint            column,
1406                  GdkEventButton *event,
1407                  gpointer        data )
1408 {
1409   if(event && event->type == GDK_2BUTTON_PRESS)
1410     EditPbEntry((PhonebookEntry *) gtk_clist_get_row_data(GTK_CLIST (clist), row),
1411                 row);
1412 }
1413
1414
1415 static inline void DeleteEntry (void)
1416 {
1417   if (contactsMemoryInitialized)
1418   {
1419     if (GTK_CLIST (clist)->selection == NULL)
1420       return;
1421
1422     DeletePbEntry ();
1423   }
1424 }
1425
1426
1427 static void ChMemType (void)
1428 {
1429   static GtkWidget *dialog = NULL;
1430   GtkWidget *button, *hbox, *label;
1431
1432   if (contactsMemoryInitialized)
1433   {
1434     if (GTK_CLIST (clist)->selection == NULL)
1435       return;
1436
1437     if (dialog == NULL)
1438     {
1439       dialog = gtk_dialog_new ();
1440       gtk_window_set_title (GTK_WINDOW (dialog), _("Changing memory type"));
1441       gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
1442       gtk_window_set_modal(GTK_WINDOW (dialog), TRUE);
1443       gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
1444       gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
1445                           GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1446
1447       button = gtk_button_new_with_label (_("Continue"));
1448       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
1449                           button, FALSE, FALSE, 0);
1450       gtk_signal_connect (GTK_OBJECT (button), "clicked",
1451                           GTK_SIGNAL_FUNC (OkChangeEntryDialog), (gpointer) dialog);
1452       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1453       gtk_widget_grab_default (button);
1454       gtk_widget_show (button);
1455
1456       button = gtk_button_new_with_label (_("Cancel"));
1457       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
1458                           button, FALSE, FALSE, 0);
1459       gtk_signal_connect (GTK_OBJECT (button), "clicked",
1460                           GTK_SIGNAL_FUNC (CancelDialog), (gpointer) dialog);
1461       gtk_widget_show (button);
1462
1463       hbox = gtk_hbox_new (FALSE, 0);
1464       gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
1465       gtk_widget_show (hbox);
1466
1467       label = gtk_label_new (_("If you change from phone memory to SIM memory\nsome entries may be truncated."));
1468       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 10);
1469       gtk_widget_show (label);
1470     }
1471
1472     gtk_widget_show (dialog);
1473   }
1474 }
1475
1476
1477 static void FindFirstEntry (void)
1478 {
1479   static FindEntryData findEntryData = { NULL };
1480   GtkWidget *button, *label, *hbox;
1481
1482   if (contactsMemoryInitialized)
1483   {
1484     if (findEntryData.dialog == NULL)
1485     {
1486       findEntryData.dialog = gtk_dialog_new ();
1487       gtk_window_set_title (GTK_WINDOW (findEntryData.dialog), _("Find"));
1488       gtk_window_set_modal (GTK_WINDOW (findEntryData.dialog), TRUE);
1489       gtk_container_set_border_width (GTK_CONTAINER (findEntryData.dialog), 10);
1490       gtk_signal_connect (GTK_OBJECT (findEntryData.dialog), "delete_event",
1491                           GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1492
1493       button = gtk_button_new_with_label (_("Find"));
1494       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (findEntryData.dialog)->action_area),
1495                           button, TRUE, TRUE, 10);
1496       gtk_signal_connect (GTK_OBJECT (button), "clicked",
1497                           GTK_SIGNAL_FUNC (OkFindEntryDialog), (gpointer) &findEntryData);
1498       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1499       gtk_widget_grab_default (button);
1500       gtk_widget_show (button);
1501
1502       button = gtk_button_new_with_label (_("Cancel"));
1503       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (findEntryData.dialog)->action_area),
1504                           button, TRUE, TRUE, 10);
1505       gtk_signal_connect (GTK_OBJECT (button), "clicked",
1506                           GTK_SIGNAL_FUNC (CancelEditDialog), (gpointer) &findEntryData);
1507       gtk_widget_show (button);
1508
1509       gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (findEntryData.dialog)->vbox), 5);
1510
1511       hbox = gtk_hbox_new (FALSE, 0);
1512       gtk_container_add (GTK_CONTAINER (GTK_DIALOG (findEntryData.dialog)->vbox), hbox);
1513       gtk_widget_show (hbox);
1514
1515       label = gtk_label_new (_("Pattern:"));
1516       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
1517       gtk_widget_show (label);
1518
1519       findEntryData.pattern = gtk_entry_new_with_max_length (max_phonebook_name_length);
1520
1521       gtk_box_pack_end (GTK_BOX (hbox), findEntryData.pattern, FALSE, FALSE, 2);
1522       gtk_widget_show (findEntryData.pattern);
1523
1524       hbox = gtk_hbox_new (FALSE, 0);
1525       gtk_container_add (GTK_CONTAINER (GTK_DIALOG (findEntryData.dialog)->vbox), hbox);
1526       gtk_widget_show (hbox);
1527
1528       findEntryData.nameB = gtk_radio_button_new_with_label (NULL, _("Name"));
1529       gtk_box_pack_start (GTK_BOX (hbox), findEntryData.nameB, TRUE, FALSE, 2);
1530       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (findEntryData.nameB), TRUE);
1531       gtk_widget_show (findEntryData.nameB);
1532
1533       findEntryData.numberB = gtk_radio_button_new_with_label ( 
1534         gtk_radio_button_group (GTK_RADIO_BUTTON (findEntryData.nameB)), _("Number"));
1535       gtk_box_pack_start (GTK_BOX(hbox), findEntryData.numberB, TRUE, FALSE, 2);
1536       gtk_widget_show (findEntryData.numberB);
1537     }
1538
1539     gtk_widget_show (findEntryData.dialog);
1540   }
1541 }
1542
1543
1544 static inline void SelectAll (void)
1545 {
1546   gtk_clist_select_all (GTK_CLIST (clist));
1547 }
1548
1549
1550 static inline void OkDialVoiceDialog (GtkWidget *w, gpointer data)
1551 {
1552   PhoneEvent *e;
1553   gchar *buf = g_strdup (gtk_entry_get_text (GTK_ENTRY (((DialVoiceDialog *) data)->entry)));
1554
1555   if (strlen (buf) > 0)
1556   {
1557     e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
1558     e->event = Event_DialVoice;
1559     e->data = buf;
1560     GUI_InsertEvent (e);
1561   }
1562   else
1563     g_free (buf);
1564
1565   gtk_widget_hide (((DialVoiceDialog *) data)->dialog);
1566 }
1567
1568
1569 static void DialVoice (void)
1570 {
1571   static DialVoiceDialog dialVoiceDialog = {NULL, NULL};
1572   GtkWidget *button, *label;
1573   PhonebookEntry *pbEntry;
1574
1575   if (dialVoiceDialog.dialog == NULL)
1576   {
1577     dialVoiceDialog.dialog = gtk_dialog_new ();
1578     gtk_window_set_title (GTK_WINDOW (dialVoiceDialog.dialog), _("Dial voice"));
1579     gtk_window_set_modal(GTK_WINDOW (dialVoiceDialog.dialog), TRUE);
1580     gtk_container_set_border_width (GTK_CONTAINER (dialVoiceDialog.dialog), 10);
1581     gtk_signal_connect (GTK_OBJECT (dialVoiceDialog.dialog), "delete_event",
1582                         GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1583
1584     button = gtk_button_new_with_label (_("Ok"));
1585     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialVoiceDialog.dialog)->action_area),
1586                         button, TRUE, TRUE, 10);
1587     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1588                         GTK_SIGNAL_FUNC (OkDialVoiceDialog), (gpointer) &dialVoiceDialog);
1589     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1590     gtk_widget_grab_default (button);
1591     gtk_widget_show (button);
1592
1593     button = gtk_button_new_with_label (_("Cancel"));
1594     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialVoiceDialog.dialog)->action_area),
1595                         button, TRUE, TRUE, 10);
1596     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1597                         GTK_SIGNAL_FUNC (CancelDialog), (gpointer) dialVoiceDialog.dialog);
1598     gtk_widget_show (button);
1599
1600     gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialVoiceDialog.dialog)->vbox), 5);
1601
1602     label = gtk_label_new (_("Number:"));
1603     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialVoiceDialog.dialog)->vbox), label, FALSE, FALSE, 5);
1604     gtk_widget_show (label);
1605
1606     dialVoiceDialog.entry = gtk_entry_new_with_max_length (GSM_MAX_PHONEBOOK_NUMBER_LENGTH);
1607     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialVoiceDialog.dialog)->vbox), dialVoiceDialog.entry, FALSE, FALSE, 5);
1608     gtk_widget_show (dialVoiceDialog.entry);
1609   }
1610
1611   if (GTK_CLIST (clist)->selection != NULL)
1612   {
1613     pbEntry = (PhonebookEntry *) gtk_clist_get_row_data (GTK_CLIST (clist),
1614                GPOINTER_TO_INT (GTK_CLIST (clist)->selection->data));
1615
1616     gtk_entry_set_text (GTK_ENTRY (dialVoiceDialog.entry), pbEntry->entry.Number);
1617   }
1618
1619   gtk_widget_show (dialVoiceDialog.dialog);  
1620 }
1621
1622
1623 static gint CListCompareFunc (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
1624 {
1625   static gchar phoneText[] = "B";
1626   static gchar simText[] = "A";
1627   char *text1 = NULL;
1628   char *text2 = NULL;
1629   gint ret;
1630
1631   GtkCListRow *row1 = (GtkCListRow *) ptr1;
1632   GtkCListRow *row2 = (GtkCListRow *) ptr2;
1633
1634   switch (row1->cell[clist->sort_column].type)
1635   {
1636     case GTK_CELL_TEXT:
1637       text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
1638       break;
1639     case GTK_CELL_PIXTEXT:
1640       text1 = GTK_CELL_PIXTEXT (row1->cell[clist->sort_column])->text;
1641       break;
1642     default:
1643       break;
1644   }
1645   switch (row2->cell[clist->sort_column].type)
1646   {
1647     case GTK_CELL_TEXT:
1648       text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
1649       break;
1650     case GTK_CELL_PIXTEXT:
1651       text2 = GTK_CELL_PIXTEXT (row2->cell[clist->sort_column])->text;
1652       break;
1653     default:
1654       break;
1655   }
1656
1657   if (clist->sort_column == 2)
1658   {
1659     if (((PhonebookEntry *) row1->data)->entry.MemoryType == GMT_ME)
1660       text1 = phoneText;
1661     else
1662       text1 = simText;
1663     if (((PhonebookEntry *) row2->data)->entry.MemoryType == GMT_ME)
1664       text2 = phoneText;
1665     else
1666       text2 = simText;
1667   }
1668
1669   if (!text2)
1670     return (text1 != NULL);
1671
1672   if (!text1)
1673     return -1;
1674
1675   if ((ret = g_strcasecmp (text1, text2)) == 0)
1676   {
1677     if (((PhonebookEntry *) row1->data)->entry.MemoryType < ((PhonebookEntry *) row2->data)->entry.MemoryType)
1678       ret = -1;
1679     else if (((PhonebookEntry *) row1->data)->entry.MemoryType > ((PhonebookEntry *) row2->data)->entry.MemoryType)
1680       ret = 1;
1681   }
1682
1683   return ret;      
1684 }
1685
1686
1687 static void CreateProgressDialog (gint maxME, gint maxSM)
1688 {
1689   GtkWidget *vbox, *label;
1690   GtkAdjustment *adj;
1691   
1692   progressDialog.dialog = gtk_window_new (GTK_WINDOW_DIALOG);
1693   gtk_window_position (GTK_WINDOW (progressDialog.dialog), GTK_WIN_POS_MOUSE);
1694   gtk_window_set_modal (GTK_WINDOW (progressDialog.dialog), TRUE);
1695   gtk_signal_connect (GTK_OBJECT (progressDialog.dialog), "delete_event",
1696                       GTK_SIGNAL_FUNC (ProgressDialogDeleteEvent), NULL);
1697
1698   vbox = gtk_vbox_new (FALSE, 10);
1699   gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
1700   gtk_container_add (GTK_CONTAINER (progressDialog.dialog), vbox);
1701
1702   gtk_widget_show (vbox);
1703
1704   label = gtk_label_new (_("Phone memory..."));
1705   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1706
1707   gtk_widget_show (label);
1708
1709   adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, maxME, 0, 0, 0);
1710   progressDialog.pbarME = gtk_progress_bar_new_with_adjustment (adj);
1711
1712   gtk_box_pack_start (GTK_BOX (vbox), progressDialog.pbarME, FALSE, FALSE, 0);
1713   gtk_widget_show (progressDialog.pbarME);
1714
1715   label = gtk_label_new (_("SIM memory..."));
1716   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1717
1718   gtk_widget_show (label);
1719
1720   adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, maxSM, 0, 0, 0);
1721   progressDialog.pbarSM = gtk_progress_bar_new_with_adjustment (adj);
1722
1723   gtk_box_pack_start (GTK_BOX (vbox), progressDialog.pbarSM, FALSE, FALSE, 0);
1724   gtk_widget_show (progressDialog.pbarSM);
1725 }
1726
1727
1728 static void SaveContacts (void)
1729 {
1730   register gint i;
1731   PhonebookEntry *pbEntry;
1732   PhoneEvent *e;
1733   D_MemoryLocation *ml;
1734
1735   if (progressDialog.dialog == NULL)
1736   {
1737     CreateProgressDialog (memoryStatus.MaxME, memoryStatus.MaxSM);
1738   }
1739
1740   if (contactsMemoryInitialized && progressDialog.dialog)
1741   {
1742     gtk_progress_set_value (GTK_PROGRESS (progressDialog.pbarME), 0);
1743     gtk_progress_set_value (GTK_PROGRESS (progressDialog.pbarSM), 0);
1744     gtk_window_set_title (GTK_WINDOW (progressDialog.dialog), _("Saving entries"));  
1745     gtk_widget_show_now (progressDialog.dialog);
1746
1747     /* Save Phone memory */
1748     for(i = 0; i < memoryStatus.MaxME; i++)
1749     {
1750       pbEntry = g_ptr_array_index(contactsMemory, i);
1751 #ifdef XDEBUG    
1752       g_print ("%d;%s;%s;%d;%d;%d\n", pbEntry->entry.Empty, pbEntry->entry.Name,
1753                pbEntry->entry.Number, (int) pbEntry->entry.MemoryType, pbEntry->entry.Group,
1754                (int) pbEntry->status);
1755 #endif
1756       if (pbEntry->status == E_Changed || pbEntry->status == E_Deleted)
1757       {
1758         if (pbEntry->status == E_Deleted)
1759         {
1760           pbEntry->entry.Name[0] = '\0';
1761           pbEntry->entry.Number[0] = '\0';
1762           pbEntry->entry.Group = 5;
1763         }
1764
1765         pbEntry->entry.Location = i + 1;
1766         ml = (D_MemoryLocation *) g_malloc (sizeof (D_MemoryLocation));
1767         ml->entry = &(pbEntry->entry);
1768         e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
1769         e->event = Event_WriteMemoryLocation;
1770         e->data = ml;
1771         GUI_InsertEvent (e);
1772         pthread_mutex_lock (&memoryMutex);
1773         pthread_cond_wait (&memoryCond, &memoryMutex);
1774         pthread_mutex_unlock (&memoryMutex);
1775
1776         if (ml->status != GE_NONE)
1777         {
1778           g_print (_("%s: line: %d:Can't write ME memory entry number %d! Error: %d\n"),
1779                    __FILE__, __LINE__, i + 1, ml->status);
1780         }
1781         g_free (ml);
1782       }
1783       gtk_progress_set_value (GTK_PROGRESS (progressDialog.pbarME), i + 1);
1784       GUI_Refresh ();
1785     }
1786
1787     /* Save SIM memory */
1788     for (i = memoryStatus.MaxME; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
1789     {
1790       pbEntry = g_ptr_array_index (contactsMemory, i);
1791
1792 #ifdef XDEBUG    
1793       g_print ("%d;%s;%s;%d;%d;%d\n", pbEntry->entry.Empty, pbEntry->entry.Name,
1794                pbEntry->entry.Number, (int) pbEntry->entry.MemoryType, pbEntry->entry.Group,
1795                (int) pbEntry->status);
1796 #endif
1797
1798       if (pbEntry->status == E_Changed || pbEntry->status == E_Deleted)
1799       {
1800         if (pbEntry->status == E_Deleted)
1801         {
1802           pbEntry->entry.Name[0] = '\0';
1803           pbEntry->entry.Number[0] = '\0';
1804           pbEntry->entry.Group = 5;
1805         }
1806
1807         pbEntry->entry.Location = i - memoryStatus.MaxME + 1;
1808         ml = (D_MemoryLocation *) g_malloc (sizeof (D_MemoryLocation));
1809         ml->entry = &(pbEntry->entry);
1810         e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
1811         e->event = Event_WriteMemoryLocation;
1812         e->data = ml;
1813         GUI_InsertEvent (e);
1814         pthread_mutex_lock (&memoryMutex);
1815         pthread_cond_wait (&memoryCond, &memoryMutex);
1816         pthread_mutex_unlock (&memoryMutex);
1817
1818         if (ml->status != GE_NONE)
1819         {
1820           g_print(_("%s: line %d:Can't write SM memory entry number %d! Error: %d\n"),
1821                    __FILE__, __LINE__, i - memoryStatus.MaxME + 1, ml->status);
1822         }
1823         g_free (ml);
1824       }
1825       gtk_progress_set_value (GTK_PROGRESS (progressDialog.pbarSM), i - memoryStatus.MaxME + 1);
1826       GUI_Refresh ();
1827     }
1828
1829     statusInfo.ch_ME = statusInfo.ch_SM = 0;
1830     RefreshStatusInfo ();
1831     gtk_widget_hide (progressDialog.dialog);
1832   }
1833 }
1834
1835
1836 static GtkWidget *CreateSaveQuestionDialog (GtkSignalFunc SaveFunc,
1837                                             GtkSignalFunc DontSaveFunc)
1838 {
1839   GtkWidget *dialog;
1840   GtkWidget *button, *label, *hbox, *pixmap;
1841
1842   dialog = gtk_dialog_new ();
1843   gtk_window_set_title (GTK_WINDOW (dialog), _("Save changes?"));
1844   gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
1845   gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1846   gtk_container_set_border_width (GTK_CONTAINER (dialog), 10);
1847   gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
1848                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1849
1850   button = gtk_button_new_with_label (_("Save"));
1851   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
1852                       button, TRUE, TRUE, 10);
1853   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1854                       GTK_SIGNAL_FUNC (SaveFunc), (gpointer) dialog);
1855   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1856   gtk_widget_grab_default (button);
1857   gtk_widget_show (button);
1858
1859   button = gtk_button_new_with_label (_("Don't save"));
1860   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
1861                       button, TRUE, TRUE, 10);
1862   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1863                       GTK_SIGNAL_FUNC (DontSaveFunc), (gpointer) dialog);
1864   gtk_widget_show (button);
1865
1866   button = gtk_button_new_with_label (_("Cancel"));
1867   gtk_box_pack_start(GTK_BOX (GTK_DIALOG (dialog)->action_area),
1868                     button, TRUE, TRUE, 10);
1869   gtk_signal_connect(GTK_OBJECT (button), "clicked",
1870                      GTK_SIGNAL_FUNC (CancelDialog), (gpointer) dialog);
1871   gtk_widget_show (button);
1872
1873   gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5);
1874
1875   hbox = gtk_hbox_new (FALSE, 0);
1876   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
1877   gtk_widget_show (hbox);
1878
1879   pixmap = gtk_pixmap_new (questMark.pixmap, questMark.mask);
1880   gtk_box_pack_start (GTK_BOX (hbox), pixmap, FALSE, FALSE, 10);
1881   gtk_widget_show (pixmap);
1882
1883   label = gtk_label_new (_("You have made changes in your\ncontacts directory.\n\
1884 \n\nDo you want save these changes into phone?\n"));
1885   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 2);
1886   gtk_widget_show (label);
1887
1888   return dialog;
1889 }
1890
1891
1892 static void OkExtPbkDialog (GtkWidget *w, gpointer data) {
1893
1894   ExtPbkDialog *d=(ExtPbkDialog*)data;
1895   SMS_NumberType numtype;
1896   gint i, found=999;
1897   gchar *chars;
1898
1899   if (w==d->gbutton) numtype=GSM_General;
1900   else if (w==d->mbutton) numtype=GSM_Mobile;
1901   else if (w==d->wbutton) numtype=GSM_Work;
1902   else if (w==d->fbutton) numtype=GSM_Fax;
1903   else if (w==d->hbutton) numtype=GSM_Home;
1904   else numtype=GSM_General;
1905
1906   /* Search through subentries */
1907
1908   for (i=0;i<d->pbEntry->entry.SubEntriesCount;i++) {
1909      if (d->pbEntry->entry.SubEntries[i].EntryType==GSM_Number)
1910        if (d->pbEntry->entry.SubEntries[i].NumberType==numtype)
1911          found=i;
1912   }
1913
1914   if (found>i) { /* Not found */
1915     found=d->pbEntry->entry.SubEntriesCount;
1916     d->pbEntry->entry.SubEntriesCount++;
1917     d->pbEntry->entry.SubEntries[found].EntryType=GSM_Number;
1918     d->pbEntry->entry.SubEntries[found].NumberType=numtype;
1919   }
1920
1921   chars=gtk_editable_get_chars(GTK_EDITABLE(d->entry),0,-1);
1922   strcpy(d->pbEntry->entry.SubEntries[found].data.Number,chars);
1923   g_free(chars);
1924
1925   /* Update the entry dialog */
1926   EditPbEntry(d->pbEntry,d->row);
1927
1928   gtk_widget_hide (d->dialog);
1929 }
1930
1931
1932 void ExtPbkChanged (GtkWidget *widget, gpointer data )
1933 {
1934   static ExtPbkDialog dialog = {NULL,NULL,0,NULL,NULL,NULL,NULL,NULL};
1935   GtkWidget *button;
1936   static GtkWidget *label;
1937   gchar *chars;
1938
1939
1940   if (dialog.dialog==NULL) {
1941
1942     dialog.dialog=gtk_dialog_new();
1943     
1944     gtk_window_set_title (GTK_WINDOW (dialog.dialog), _("Which Extended Phonebook Entry?"));
1945     gtk_window_set_modal(GTK_WINDOW (dialog.dialog), TRUE);
1946     gtk_container_set_border_width (GTK_CONTAINER (dialog.dialog), 10);
1947     gtk_signal_connect (GTK_OBJECT (dialog.dialog), "delete_event",
1948                         GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1949
1950     dialog.gbutton = gtk_button_new_with_label (_("General"));
1951     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog.dialog)->vbox),
1952                         dialog.gbutton, TRUE, TRUE, 10);
1953     gtk_signal_connect (GTK_OBJECT (dialog.gbutton), "clicked",
1954                         GTK_SIGNAL_FUNC (OkExtPbkDialog), (gpointer)&dialog );
1955     gtk_widget_show (dialog.gbutton);
1956     dialog.mbutton = gtk_button_new_with_label (_("Mobile"));
1957     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog.dialog)->vbox),
1958                         dialog.mbutton, TRUE, TRUE, 10);
1959     gtk_signal_connect (GTK_OBJECT (dialog.mbutton), "clicked",
1960                         GTK_SIGNAL_FUNC (OkExtPbkDialog), (gpointer)&dialog );
1961     gtk_widget_show (dialog.mbutton);
1962     dialog.wbutton = gtk_button_new_with_label (_("Work"));
1963     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog.dialog)->vbox),
1964                         dialog.wbutton, TRUE, TRUE, 10);
1965     gtk_signal_connect (GTK_OBJECT (dialog.wbutton), "clicked",
1966                         GTK_SIGNAL_FUNC (OkExtPbkDialog), (gpointer)&dialog );
1967     gtk_widget_show (dialog.wbutton);
1968     dialog.fbutton = gtk_button_new_with_label (_("Fax"));
1969     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog.dialog)->vbox),
1970                         dialog.fbutton, TRUE, TRUE, 10);
1971     gtk_signal_connect (GTK_OBJECT (dialog.fbutton), "clicked",
1972                         GTK_SIGNAL_FUNC (OkExtPbkDialog), (gpointer)&dialog );
1973     gtk_widget_show (dialog.fbutton);
1974     dialog.hbutton = gtk_button_new_with_label (_("Home"));
1975     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog.dialog)->vbox),
1976                         dialog.hbutton, TRUE, TRUE, 10);
1977     gtk_signal_connect (GTK_OBJECT (dialog.hbutton), "clicked",
1978                         GTK_SIGNAL_FUNC (OkExtPbkDialog), (gpointer)&dialog );
1979     gtk_widget_show (dialog.hbutton);
1980
1981     button = gtk_button_new_with_label (_("Cancel"));
1982     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog.dialog)->action_area),
1983                         button, TRUE, TRUE, 10);
1984     gtk_signal_connect (GTK_OBJECT (button), "clicked",
1985                         GTK_SIGNAL_FUNC (CancelDialog), (gpointer) dialog.dialog);
1986     gtk_widget_show (button);
1987
1988     label = gtk_label_new("");
1989     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog.dialog)->vbox), label, FALSE, FALSE, 5);
1990     gtk_widget_show(label);
1991   }
1992
1993   chars=gtk_editable_get_chars(GTK_EDITABLE(widget),0,-1);
1994   gtk_label_set_text(GTK_LABEL(label),chars);
1995   g_free(chars);
1996   dialog.pbEntry=((EditEntryData*)data)->pbEntry;
1997   dialog.row=((EditEntryData*)data)->row;
1998   dialog.entry=widget;
1999   gtk_widget_show(dialog.dialog);
2000 }
2001
2002
2003
2004 void GUI_RefreshContacts (void)
2005 {
2006   PhonebookEntry *pbEntry;
2007   gint row_i = 0;
2008   register gint i;
2009
2010   if (contactsMemoryInitialized == FALSE)
2011     return;
2012
2013   gtk_clist_freeze (GTK_CLIST (clist));
2014   gtk_clist_clear (GTK_CLIST (clist));
2015
2016   for (i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
2017   {
2018     gchar *row[4];
2019
2020     pbEntry = g_ptr_array_index (contactsMemory, i);
2021     if (pbEntry->status != E_Empty && pbEntry->status != E_Deleted)
2022     {
2023       row[0] = pbEntry->entry.Name;
2024
2025       row[1] = pbEntry->entry.Number;
2026
2027       if (pbEntry->entry.MemoryType == GMT_ME)
2028         row[2] = "P";
2029       else
2030         row[2] = "S";
2031       if (phoneMonitor.supported & PM_CALLERGROUP)
2032         row[3] = xgnokiiConfig.callerGroups[pbEntry->entry.Group];
2033       else
2034         row[3] = "";
2035       gtk_clist_append (GTK_CLIST (clist), row);
2036       if (pbEntry->entry.MemoryType == GMT_ME)
2037         gtk_clist_set_pixmap (GTK_CLIST (clist), row_i, 2,
2038                               memoryPixmaps.phoneMemPix, memoryPixmaps.mask);
2039       else
2040         gtk_clist_set_pixmap (GTK_CLIST (clist), row_i, 2,
2041                               memoryPixmaps.simMemPix, memoryPixmaps.mask);
2042
2043       gtk_clist_set_row_data (GTK_CLIST (clist), row_i++, (gpointer) pbEntry);
2044     }
2045 #ifdef XDEBUG    
2046     g_print ("%d;%s;%s;%d;%d;%d\n", pbEntry->entry.Empty, pbEntry->entry.Name,
2047             pbEntry->entry.Number, (int) pbEntry->entry.MemoryType, pbEntry->entry.Group,
2048             (int) pbEntry->status);
2049 #endif
2050   }
2051
2052   gtk_clist_sort (GTK_CLIST (clist));
2053   gtk_clist_thaw (GTK_CLIST (clist));
2054 }
2055
2056
2057 static gint InsertPBEntryME (GSM_PhonebookEntry *entry)
2058 {
2059   PhonebookEntry *pbEntry;
2060
2061   if ((pbEntry = (PhonebookEntry *) g_malloc (sizeof (PhonebookEntry))) == NULL)
2062   {
2063     g_print (_("%s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
2064     g_ptr_array_free (contactsMemory, TRUE);
2065     gtk_widget_hide (progressDialog.dialog);
2066     return (-1);
2067   }
2068
2069   pbEntry->entry = *entry;
2070
2071   if (*pbEntry->entry.Name == '\0' && *pbEntry->entry.Number == '\0')
2072     pbEntry->status = E_Empty;
2073   else
2074     pbEntry->status = E_Unchanged;
2075
2076   g_ptr_array_add (contactsMemory, (gpointer) pbEntry);
2077   gtk_progress_set_value (GTK_PROGRESS (progressDialog.pbarME), entry->Location);
2078   GUI_Refresh ();
2079
2080   return (GE_NONE);  
2081 }
2082
2083
2084 static gint InsertPBEntrySM (GSM_PhonebookEntry *entry)
2085 {
2086   PhonebookEntry *pbEntry;
2087
2088   if ((pbEntry = (PhonebookEntry *) g_malloc (sizeof (PhonebookEntry))) == NULL)
2089   {
2090     g_print (_("%s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
2091     g_ptr_array_free (contactsMemory, TRUE);
2092     gtk_widget_hide (progressDialog.dialog);
2093     return (-1);
2094   }
2095
2096   pbEntry->entry = *entry;
2097
2098   if (*pbEntry->entry.Name == '\0' && *pbEntry->entry.Number == '\0')
2099     pbEntry->status = E_Empty;
2100   else
2101   {
2102     pbEntry->status = E_Unchanged;
2103     if (fbus3810)
2104     {
2105       memoryStatus.UsedSM++;
2106       memoryStatus.FreeSM--;
2107     }
2108   }
2109
2110   g_ptr_array_add (contactsMemory, (gpointer) pbEntry);
2111   gtk_progress_set_value (GTK_PROGRESS (progressDialog.pbarSM), entry->Location);
2112   GUI_Refresh ();
2113
2114   return (GE_NONE);  
2115 }
2116
2117
2118 static inline gint ReadFailedPBEntry (gint i)
2119 {
2120   g_ptr_array_free (contactsMemory, TRUE);
2121   gtk_widget_hide (progressDialog.dialog);
2122   return (0);
2123 }
2124
2125
2126 static void ReadContactsMain (void)
2127 {
2128   PhoneEvent *e;
2129   D_MemoryStatus *ms;
2130   D_MemoryLocationAll *mla;
2131   PhonebookEntry *pbEntry;
2132   register gint i;
2133
2134   fbus3810 = FALSE;
2135
2136   if (contactsMemoryInitialized == TRUE)
2137   {
2138     for (i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
2139     {
2140       pbEntry = g_ptr_array_index (contactsMemory, i);
2141       g_free (pbEntry);
2142     }
2143     g_ptr_array_free (contactsMemory, TRUE);
2144     contactsMemory = NULL;
2145     gtk_clist_clear (GTK_CLIST (clist));
2146     contactsMemoryInitialized = FALSE;
2147     memoryStatus.MaxME = memoryStatus.UsedME = memoryStatus.FreeME =
2148     memoryStatus.MaxSM = memoryStatus.UsedSM = memoryStatus.FreeSM = 0;
2149     statusInfo.ch_ME = statusInfo.ch_SM = 0;
2150     RefreshStatusInfo ();
2151   }
2152
2153   ms = (D_MemoryStatus *) g_malloc (sizeof (D_MemoryStatus));
2154   ms->memoryStatus.MemoryType = GMT_ME;
2155   e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
2156   e->event = Event_GetMemoryStatus;
2157   e->data = ms;
2158   GUI_InsertEvent (e);
2159   pthread_mutex_lock (&memoryMutex);
2160   pthread_cond_wait (&memoryCond, &memoryMutex);
2161   pthread_mutex_unlock (&memoryMutex);
2162
2163   if (ms->status != GE_NONE)
2164     /* Phone don't support ME (5110) */
2165     memoryStatus.MaxME = memoryStatus.UsedME = memoryStatus.FreeME = 0;
2166   else
2167   {
2168     memoryStatus.MaxME = ms->memoryStatus.Used + ms->memoryStatus.Free;
2169     memoryStatus.UsedME = ms->memoryStatus.Used;
2170     memoryStatus.FreeME = ms->memoryStatus.Free;
2171   }
2172
2173   ms->memoryStatus.MemoryType = GMT_SM;
2174   e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
2175   e->event = Event_GetMemoryStatus;
2176   e->data = ms;
2177   GUI_InsertEvent (e);
2178   pthread_mutex_lock (&memoryMutex);
2179   pthread_cond_wait (&memoryCond, &memoryMutex);
2180   pthread_mutex_unlock (&memoryMutex);
2181
2182   if (ms->status != GE_NONE)
2183   {
2184     fbus3810 = TRUE; /* I try to recognize memoryStatus.UsedSM while reading */
2185     gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't get SM memory status!\n\n\
2186 Setting max SIM entries to 100!\n"));
2187     memoryStatus.MaxSM = memoryStatus.FreeSM = 100;
2188     memoryStatus.UsedSM = 0;
2189     gtk_widget_show (errorDialog.dialog);
2190   }
2191   else
2192   {
2193     memoryStatus.MaxSM = ms->memoryStatus.Used + ms->memoryStatus.Free;
2194     memoryStatus.UsedSM = ms->memoryStatus.Used;
2195     memoryStatus.FreeSM = ms->memoryStatus.Free;
2196   }
2197   g_free (ms);
2198
2199   statusInfo.ch_ME = statusInfo.ch_SM = 0;
2200
2201   RefreshStatusInfo ();
2202
2203   if (progressDialog.dialog == NULL)
2204   {
2205     CreateProgressDialog (memoryStatus.MaxME, memoryStatus.MaxSM);
2206   }
2207
2208   gtk_progress_set_value (GTK_PROGRESS (progressDialog.pbarME), 0);
2209   gtk_progress_set_value (GTK_PROGRESS (progressDialog.pbarSM), 0);
2210   gtk_window_set_title (GTK_WINDOW (progressDialog.dialog), _("Getting entries"));
2211   gtk_widget_show_now (progressDialog.dialog);
2212
2213   contactsMemory = g_ptr_array_new ();
2214
2215   mla = (D_MemoryLocationAll *) g_malloc (sizeof (D_MemoryLocationAll));
2216   if (memoryStatus.MaxME > 0)
2217   {
2218     mla->min = 1;
2219     mla->max = memoryStatus.MaxME;
2220     mla->type = GMT_ME;
2221     mla->InsertEntry = InsertPBEntryME;
2222     mla->ReadFailed = ReadFailedPBEntry;
2223
2224     e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
2225     e->event = Event_GetMemoryLocationAll;
2226     e->data = mla;
2227     GUI_InsertEvent (e);
2228     pthread_mutex_lock (&memoryMutex);
2229     pthread_cond_wait (&memoryCond, &memoryMutex);
2230     pthread_mutex_unlock (&memoryMutex);
2231
2232     if (mla->status != GE_NONE)
2233     {
2234       g_free (mla);
2235       gtk_widget_hide (progressDialog.dialog);
2236       return;
2237     }
2238   }
2239
2240   mla->min = 1;
2241   mla->max = memoryStatus.MaxSM;
2242   mla->type = GMT_SM;
2243   mla->InsertEntry = InsertPBEntrySM;
2244   mla->ReadFailed = ReadFailedPBEntry;
2245
2246   e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
2247   e->event = Event_GetMemoryLocationAll;
2248   e->data = mla;
2249   GUI_InsertEvent (e);
2250   pthread_mutex_lock (&memoryMutex);
2251   pthread_cond_wait (&memoryCond, &memoryMutex);
2252   pthread_mutex_unlock (&memoryMutex);
2253
2254   if (mla->status != GE_NONE)
2255   {
2256     g_free (mla);
2257     gtk_widget_hide (progressDialog.dialog);
2258     return;
2259   }
2260
2261   g_free (mla);
2262
2263   gtk_widget_hide (progressDialog.dialog);
2264
2265   contactsMemoryInitialized = TRUE;
2266   statusInfo.ch_ME = statusInfo.ch_SM = 0;
2267   GUIEventSend (GUI_EVENT_CONTACTS_CHANGED);
2268   GUIEventSend (GUI_EVENT_SMS_NUMBER_CHANGED);
2269 }
2270
2271
2272 static void ReadSaveCallback (GtkWidget *widget, gpointer data)
2273 {
2274   gtk_widget_hide (GTK_WIDGET (data));
2275   SaveContacts ();
2276   ReadContactsMain ();
2277 }
2278
2279
2280 static void ReadDontSaveCallback (GtkWidget *widget, gpointer data)
2281 {
2282   gtk_widget_hide (GTK_WIDGET (data));
2283   ReadContactsMain ();
2284 }
2285
2286
2287 static void ReadSaveContacts (void)
2288 {
2289   static GtkWidget *dialog = NULL;
2290
2291   if (dialog == NULL)
2292     dialog = CreateSaveQuestionDialog (ReadSaveCallback, ReadDontSaveCallback);
2293
2294   gtk_widget_show (dialog);
2295 }
2296
2297
2298 static void ReadContacts (void)
2299 {
2300   if (contactsMemoryInitialized == TRUE && (statusInfo.ch_ME || statusInfo.ch_SM))
2301     ReadSaveContacts ();
2302   else
2303     ReadContactsMain ();
2304 }
2305
2306
2307 inline void GUI_ReadContacts (void)
2308 {
2309   ReadContacts ();
2310 }
2311
2312
2313 inline void GUI_SaveContacts (void)
2314 {
2315   SaveContacts ();
2316 }
2317
2318
2319 inline void GUI_ShowContacts (void)
2320 {
2321   if (xgnokiiConfig.callerGroups[0] == NULL)
2322   {
2323     GUI_Refresh ();
2324     GUI_InitCallerGroupsInf ();
2325   }
2326   gtk_clist_set_column_visibility (GTK_CLIST (clist), 3, phoneMonitor.supported & PM_CALLERGROUP);
2327   GUI_RefreshContacts ();
2328   gtk_widget_show (GUI_ContactsWindow);
2329 //  if (!contactsMemoryInitialized)
2330 //    ReadContacts ();
2331 }
2332
2333 static void ExportVCARD (FILE *f)
2334 {
2335   gchar buf2[10];
2336   register gint i,j;
2337   PhonebookEntry *pbEntry;
2338
2339   for(i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
2340   {
2341     pbEntry = g_ptr_array_index (contactsMemory, i);
2342
2343     if (pbEntry->status == E_Deleted || pbEntry->status == E_Empty)
2344       continue;
2345
2346     fprintf (f, "BEGIN:VCARD\n");
2347     fprintf (f, "VERSION:3.0\n");
2348     fprintf (f, "FN:%s\n", pbEntry->entry.Name);
2349     fprintf (f, "TEL;PREF:%s\n", pbEntry->entry.Number);
2350
2351     if (pbEntry->entry.MemoryType == GMT_ME)
2352       sprintf (buf2, "ME%d", i + 1);
2353     else
2354       sprintf (buf2, "SM%d", i - memoryStatus.MaxME + 1);
2355
2356     fprintf (f, "X_GSM_STORE_AT:%s\n", buf2);
2357     fprintf (f, "X_GSM_CALLERGROUP:%d\n", pbEntry->entry.Group);
2358
2359     /* Add ext. pbk info if required */
2360     if (phoneMonitor.supported & PM_EXTPBK)
2361       for (j = 0; j < pbEntry->entry.SubEntriesCount; j++)
2362       {
2363         if (pbEntry->entry.SubEntries[j].EntryType == GSM_Number)
2364           fprintf (f, "TEL;UNKNOWN_%d:%s\n", pbEntry->entry.SubEntries[j].NumberType,
2365                    pbEntry->entry.SubEntries[j].data.Number);
2366       }
2367
2368     fprintf (f, "END:VCARD\n\n");
2369   }
2370   
2371   fclose (f);
2372 }
2373
2374
2375 static void ExportNative (FILE *f)
2376 {
2377   gchar buf[IO_BUF_LEN], buf2[10];
2378   register gint i,j;
2379   PhonebookEntry *pbEntry;
2380
2381
2382   for(i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
2383   {
2384     pbEntry = g_ptr_array_index (contactsMemory, i);
2385
2386     if (pbEntry->status != E_Deleted && pbEntry->status != E_Empty)
2387     {
2388       if (index (pbEntry->entry.Name, ';') != NULL)
2389       {
2390         strcpy (buf, "\"");
2391         strcat (buf, pbEntry->entry.Name);
2392         strcat (buf, "\";");
2393       }
2394       else
2395       {
2396         strcpy (buf, pbEntry->entry.Name);
2397         strcat (buf, ";");
2398       }
2399       
2400       if (index (pbEntry->entry.Number, ';') != NULL)
2401       {
2402         strcat (buf, "\"");
2403         strcat (buf, pbEntry->entry.Number);
2404         strcat (buf, "\";");
2405       }
2406       else
2407       {
2408         strcat (buf, pbEntry->entry.Number);
2409         strcat (buf, ";");
2410       }
2411
2412       if (pbEntry->entry.MemoryType == GMT_ME)
2413         sprintf (buf2, "B;%d;%d;", i + 1, pbEntry->entry.Group);
2414       else
2415         sprintf (buf2, "A;%d;%d;", i - memoryStatus.MaxME + 1, pbEntry->entry.Group);
2416       strcat (buf, buf2);
2417
2418       /* Add ext. pbk info if required */
2419       if (phoneMonitor.supported & PM_EXTPBK)
2420       {
2421         for (j = 0; j < pbEntry->entry.SubEntriesCount; j++)
2422           if (pbEntry->entry.SubEntries[j].EntryType==GSM_Number)
2423           {
2424             sprintf(buf2,"%d;",pbEntry->entry.SubEntries[j].NumberType);
2425             strcat(buf,buf2);
2426
2427             if (index (pbEntry->entry.SubEntries[j].data.Number, ';') != NULL)
2428             {
2429               strcat (buf, "\"");
2430               strcat (buf, pbEntry->entry.SubEntries[j].data.Number);
2431               strcat (buf, "\";");
2432             }
2433             else
2434             {
2435               strcat (buf, pbEntry->entry.SubEntries[j].data.Number);
2436               strcat (buf, ";");
2437             }
2438           }
2439       }
2440       fprintf (f, "%s\n", buf);
2441     }
2442   }
2443   
2444   fclose(f);
2445 }
2446
2447
2448 static void ExportContactsMain (gchar *name)
2449 {
2450   FILE *f;
2451   gchar buf[IO_BUF_LEN];
2452
2453   if ((f = fopen (name, "w")) == NULL)
2454   {
2455     g_snprintf (buf, IO_BUF_LEN, _("Can't open file %s for writing!"), name);
2456     gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
2457     gtk_widget_show (errorDialog.dialog);
2458     return;
2459   }
2460
2461   if (strstr (name, ".vcard") || strstr (name, ".gcrd"))
2462     ExportVCARD (f);
2463   else
2464     ExportNative (f);
2465 }
2466
2467
2468 static void YesExportDialog (GtkWidget *w, gpointer data)
2469 {
2470   gtk_widget_hide (GTK_WIDGET (data));
2471   ExportContactsMain (exportDialogData.fileName);
2472 }
2473
2474
2475 static void OkExportDialog (GtkWidget *w, GtkFileSelection *fs)
2476 {
2477   static YesNoDialog dialog = { NULL, NULL};
2478   FILE *f;
2479   gchar err[80];
2480
2481   exportDialogData.fileName = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
2482   gtk_widget_hide (GTK_WIDGET (fs));
2483
2484   if ((f = fopen (exportDialogData.fileName, "r")) != NULL)
2485   {
2486     fclose (f);
2487     if (dialog.dialog == NULL)
2488     {
2489       CreateYesNoDialog (&dialog, YesExportDialog, CancelDialog, GUI_ContactsWindow);
2490       gtk_window_set_title (GTK_WINDOW (dialog.dialog), _("Overwrite file?"));
2491       g_snprintf ( err, 80, _("File %s already exist.\nOverwrite?"), exportDialogData.fileName); 
2492       gtk_label_set_text (GTK_LABEL(dialog.text), err);
2493     }
2494     gtk_widget_show (dialog.dialog);
2495   }
2496   else
2497     ExportContactsMain (exportDialogData.fileName);
2498 }
2499
2500
2501 static void ExportContacts (void)
2502 {
2503   static GtkWidget *fileDialog = NULL;
2504
2505   if (contactsMemoryInitialized)
2506   {
2507     if (fileDialog == NULL)
2508     {
2509       fileDialog = gtk_file_selection_new (_("Export"));
2510       gtk_signal_connect (GTK_OBJECT (fileDialog), "delete_event",
2511                           GTK_SIGNAL_FUNC (DeleteEvent), NULL);
2512       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->ok_button),
2513                           "clicked", GTK_SIGNAL_FUNC (OkExportDialog), (gpointer) fileDialog);
2514       gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->cancel_button),
2515                           "clicked", GTK_SIGNAL_FUNC (CancelDialog), (gpointer) fileDialog);
2516     }
2517
2518     gtk_widget_show (fileDialog);
2519   }
2520 }
2521
2522
2523 static bool ParseLine (GSM_PhonebookEntry *entry, gint *num, gchar *buf)
2524 {
2525   register gint i = 0;
2526   size_t len;
2527   gchar s_num[5];
2528   gchar *endptr;
2529
2530   entry->Empty = FALSE;
2531   entry->SubEntriesCount=0;
2532
2533   len = strlen (buf);
2534   if (buf[i] == '"')
2535   {
2536     i++;
2537     while (i < len && i <= GSM_MAX_PHONEBOOK_NAME_LENGTH && buf[i] != '"')
2538     {
2539       entry->Name[i - 1] = buf[i];
2540       i++;
2541     }
2542     entry->Name[i - 1] = '\0';
2543     if (i >= len)
2544       return FALSE;
2545     if (buf[++i] != ';')
2546       return FALSE;
2547   }
2548   else
2549   {
2550     while (i < len && i < GSM_MAX_PHONEBOOK_NAME_LENGTH && buf[i] != ';')
2551     {
2552       entry->Name[i] = buf[i];
2553       i++;
2554     }
2555     entry->Name[i] = '\0';
2556     if (buf[i] != ';')
2557       return FALSE;
2558     if (i >= len)
2559       return FALSE;
2560   }
2561   buf += (i + 1);
2562   i = 0;
2563
2564   len = strlen (buf);
2565   if (buf[i] == '"')
2566   {
2567     i++;
2568     while (i < len && i <= GSM_MAX_PHONEBOOK_NUMBER_LENGTH && buf[i] != '"')
2569     {
2570       entry->Number[i - 1] = buf[i];
2571       i++;
2572     }
2573     entry->Number[i - 1] = '\0';
2574     if (i >= len)
2575       return FALSE;
2576     if (buf[++i] != ';')
2577       return FALSE;
2578   }
2579   else
2580   {
2581     while (i < len && i < GSM_MAX_PHONEBOOK_NUMBER_LENGTH && buf[i] != ';')
2582     {
2583       entry->Number[i] = buf[i];
2584       i++;
2585     }
2586     entry->Number[i] = '\0';
2587     if (buf[i] != ';')
2588       return FALSE;
2589     if (i >= len)
2590       return FALSE;
2591   }
2592   buf += (i + 1);
2593   i = 0;
2594
2595   if (!strncmp(buf, "B;", 2))
2596   {
2597     entry->MemoryType = GMT_ME;
2598     buf += 2;
2599   }
2600   else
2601   if (!strncmp(buf, "A;", 2))
2602   {
2603     entry->MemoryType = GMT_SM;
2604     buf += 2;
2605   }
2606   else
2607   if (!strncmp(buf, "ME;", 3))
2608   {
2609     entry->MemoryType = GMT_ME;
2610     buf += 3;
2611   }
2612   else
2613   if (!strncmp(buf, "SM;", 3))
2614   {
2615     entry->MemoryType = GMT_SM;
2616     buf += 3;
2617   }
2618   else
2619     return FALSE;
2620
2621   len = strlen (buf);
2622   while (i < len && i < 4 && buf[i] != ';')
2623   {
2624     s_num[i] = buf[i];
2625     i++;
2626   }
2627   s_num[i] = '\0';
2628   if (buf[i] != ';')
2629     return FALSE;
2630   if (i >= len)
2631     return FALSE;
2632   buf += (i + 1);
2633   i = 0;
2634
2635   *num = strtol (s_num, &endptr, 10);
2636   if (s_num == endptr)
2637     return FALSE;
2638   if (*num == LONG_MIN || *num == LONG_MAX)
2639     return FALSE;
2640
2641
2642   if ( *buf == '\n' || *buf == '\r')   /* for compatibility with NCDS */
2643     entry->Group = 5;
2644   else
2645   {
2646     len = strlen (buf);
2647     while (i < len && i < 4 && buf[i] != ';')
2648     {
2649       s_num[i] = buf[i];
2650       i++;
2651     }
2652     s_num[i] = '\0';
2653     if (buf[i] != ';')
2654       return FALSE;
2655     if (i >= len)
2656       return FALSE;
2657     
2658     entry->Group = strtol (s_num, &endptr, 10);
2659     if (s_num == endptr)
2660       return FALSE;
2661     if (entry->Group == LONG_MIN || entry->Group == LONG_MAX)
2662       return FALSE;
2663     if (entry->Group < 0 || entry->Group > 5)
2664       return FALSE;
2665
2666     buf += (i + 1);
2667     i = 0;
2668
2669     /* Ext Pbk Support */
2670     
2671     while (*buf!='\n')
2672     {
2673       entry->SubEntries[entry->SubEntriesCount].EntryType=GSM_Number;
2674       len = strlen (buf);
2675       while (i < len && i < 4 && buf[i] != ';')
2676       {
2677         s_num[i] = buf[i];
2678         i++;
2679       }
2680       s_num[i] = '\0';
2681       if (buf[i] != ';')
2682         return FALSE;
2683       if (i >= len)
2684         return FALSE;
2685       entry->SubEntries[entry->SubEntriesCount].NumberType=(SMS_NumberType)strtol (s_num, &endptr, 10);
2686       if (s_num == endptr)
2687         return FALSE;
2688       buf += (i + 1);
2689       i = 0;
2690       len = strlen (buf);
2691       while (i < len && i < GSM_MAX_PHONEBOOK_TEXT_LENGTH && buf[i] != ';')
2692       {
2693         entry->SubEntries[entry->SubEntriesCount].data.Number[i] = buf[i];
2694         i++;
2695       }
2696       entry->SubEntries[entry->SubEntriesCount].data.Number[i] = '\0';
2697       buf += (i + 1);
2698       i = 0;
2699       if (i >= len)
2700         return FALSE;
2701       entry->SubEntriesCount++;
2702     }
2703   }
2704
2705   return TRUE;
2706 }
2707
2708
2709 static void OkImportDialog (GtkWidget *w, GtkFileSelection *fs)
2710 {
2711   FILE *f;
2712   PhoneEvent *e;
2713   D_MemoryStatus *ms;
2714   PhonebookEntry *pbEntry;
2715   GSM_PhonebookEntry gsmEntry;
2716   gchar buf[IO_BUF_LEN];
2717   gchar *fileName;
2718   gint i;
2719
2720   fileName = gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs));
2721   gtk_widget_hide (GTK_WIDGET (fs));
2722
2723   if ((f = fopen (fileName, "r")) == NULL)
2724   {
2725     g_snprintf (buf, IO_BUF_LEN, _("Can't open file %s for reading!"), fileName);
2726     gtk_label_set_text (GTK_LABEL(errorDialog.text), buf);
2727     gtk_widget_show (errorDialog.dialog);
2728     return;
2729   }
2730
2731   if (contactsMemoryInitialized == TRUE)
2732   {
2733     for(i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
2734     {
2735       pbEntry = g_ptr_array_index(contactsMemory, i);
2736       g_free(pbEntry);
2737     }
2738     g_ptr_array_free (contactsMemory, TRUE);
2739     contactsMemory = NULL;
2740     gtk_clist_clear (GTK_CLIST (clist));
2741     contactsMemoryInitialized = FALSE;
2742     memoryStatus.MaxME = memoryStatus.UsedME = memoryStatus.FreeME =
2743     memoryStatus.MaxSM = memoryStatus.UsedSM = memoryStatus.FreeSM = 0;
2744     statusInfo.ch_ME = statusInfo.ch_SM = 0;
2745     RefreshStatusInfo ();
2746   }
2747
2748   ms = (D_MemoryStatus *) g_malloc (sizeof (D_MemoryStatus));
2749   ms->memoryStatus.MemoryType = GMT_ME;
2750   e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
2751   e->event = Event_GetMemoryStatus;
2752   e->data = ms;
2753   GUI_InsertEvent (e);
2754   pthread_mutex_lock (&memoryMutex);
2755   pthread_cond_wait (&memoryCond, &memoryMutex);
2756   pthread_mutex_unlock (&memoryMutex);
2757
2758   if (ms->status != GE_NONE)
2759     /* Phone don't support ME (5110) */
2760     memoryStatus.MaxME = memoryStatus.UsedME = memoryStatus.FreeME = 0;
2761   else
2762   {
2763     memoryStatus.MaxME = ms->memoryStatus.Used + ms->memoryStatus.Free;
2764     memoryStatus.UsedME = 0;
2765     memoryStatus.FreeME = memoryStatus.MaxME;
2766   }
2767
2768   ms->memoryStatus.MemoryType = GMT_SM;
2769   e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
2770   e->event = Event_GetMemoryStatus;
2771   e->data = ms;
2772   GUI_InsertEvent (e);
2773   pthread_mutex_lock (&memoryMutex);
2774   pthread_cond_wait (&memoryCond, &memoryMutex);
2775   pthread_mutex_unlock (&memoryMutex);
2776
2777   if (ms->status != GE_NONE)
2778   {
2779     gtk_label_set_text (GTK_LABEL (errorDialog.text), _("Can't get SM memory status!\n\n\
2780 Setting max SIM entries set to 100!\n"));
2781     memoryStatus.MaxSM = memoryStatus.FreeSM = 100;
2782     memoryStatus.UsedSM = 0;
2783     gtk_widget_show (errorDialog.dialog);
2784   }
2785   else
2786   {
2787     memoryStatus.MaxSM = ms->memoryStatus.Used + ms->memoryStatus.Free;
2788     memoryStatus.UsedSM = 0;
2789     memoryStatus.FreeSM = memoryStatus.MaxSM;
2790   }
2791   g_free (ms);
2792
2793   statusInfo.ch_ME = statusInfo.ch_SM = 0;
2794
2795   RefreshStatusInfo ();
2796
2797   contactsMemory = g_ptr_array_new ();
2798
2799   for (i = 1; i <= memoryStatus.MaxME; i++)
2800   {
2801     if ((pbEntry = (PhonebookEntry *) g_malloc (sizeof (PhonebookEntry))) == NULL)
2802     {
2803       fclose (f);
2804       g_print (_("%s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
2805       g_ptr_array_free (contactsMemory, TRUE);
2806       return;
2807     }
2808
2809     pbEntry->entry.Empty = FALSE;
2810     pbEntry->entry.Name[0] = '\0';
2811     pbEntry->entry.Number[0] = '\0';
2812     pbEntry->entry.MemoryType = GMT_ME;
2813     pbEntry->entry.Group = 5;
2814     pbEntry->status = E_Deleted; /* I must set status to E_Deleted, since I   */
2815                                  /* I want clear empty entries when saving to */
2816                                  /* to phone                                  */
2817     pbEntry->entry.SubEntriesCount=0;
2818
2819     g_ptr_array_add (contactsMemory, (gpointer) pbEntry);
2820     pbEntry = NULL;
2821   }
2822
2823   for (i = 1; i <= memoryStatus.MaxSM; i++)
2824   {
2825     if ((pbEntry = (PhonebookEntry *) g_malloc (sizeof (PhonebookEntry))) == NULL)
2826     {
2827       fclose (f);
2828       g_print (_("%s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
2829       g_ptr_array_free (contactsMemory, TRUE);
2830       return;
2831     }
2832
2833     pbEntry->entry.Empty = FALSE;
2834     pbEntry->entry.Name[0] = '\0';
2835     pbEntry->entry.Number[0] = '\0';
2836     pbEntry->entry.MemoryType = GMT_SM;
2837     pbEntry->entry.Group = 5;
2838     pbEntry->status = E_Deleted;
2839     pbEntry->entry.SubEntriesCount=0;
2840
2841     g_ptr_array_add (contactsMemory, (gpointer) pbEntry);
2842     pbEntry = NULL;
2843   }
2844
2845
2846   while (fgets (buf, IO_BUF_LEN, f))
2847   {
2848     if (ParseLine (&gsmEntry, &i, buf))
2849     {
2850       if (gsmEntry.MemoryType == GMT_ME && memoryStatus.FreeME > 0 
2851           && i > 0 && i <= memoryStatus.MaxME)
2852       {
2853         pbEntry = g_ptr_array_index (contactsMemory, i - 1);
2854
2855         if (pbEntry->status == E_Deleted)
2856         {
2857           pbEntry->entry = gsmEntry;
2858           pbEntry->status = E_Changed;
2859           memoryStatus.UsedME++;
2860           memoryStatus.FreeME--;
2861           statusInfo.ch_ME = 1;
2862         }
2863       }
2864       else if (gsmEntry.MemoryType == GMT_SM && memoryStatus.FreeSM > 0
2865                && i > 0 && i <= memoryStatus.MaxSM)
2866       {
2867         pbEntry = g_ptr_array_index (contactsMemory, memoryStatus.MaxME + i - 1);
2868
2869         if (pbEntry->status == E_Deleted)
2870         {
2871           pbEntry->entry = gsmEntry;
2872           pbEntry->status = E_Changed;
2873           memoryStatus.UsedSM++;
2874           memoryStatus.FreeSM--;
2875           statusInfo.ch_SM = 1;
2876         }
2877       }
2878     }
2879   }
2880
2881   contactsMemoryInitialized = TRUE;
2882   RefreshStatusInfo ();
2883   GUIEventSend (GUI_EVENT_CONTACTS_CHANGED);
2884   GUIEventSend (GUI_EVENT_SMS_NUMBER_CHANGED);
2885 }
2886
2887
2888 static void ImportContactsFileDialog ()
2889 {
2890   static GtkWidget *fileDialog = NULL;
2891
2892   if (fileDialog == NULL)
2893   {
2894     fileDialog = gtk_file_selection_new (_("Import"));
2895     gtk_signal_connect (GTK_OBJECT (fileDialog), "delete_event",
2896                         GTK_SIGNAL_FUNC (DeleteEvent), NULL);
2897     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->ok_button),
2898                         "clicked", GTK_SIGNAL_FUNC (OkImportDialog), (gpointer) fileDialog);
2899     gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (fileDialog)->cancel_button),
2900                         "clicked", GTK_SIGNAL_FUNC (CancelDialog), (gpointer) fileDialog);
2901   }
2902
2903   gtk_widget_show (fileDialog);
2904 }
2905
2906
2907 static void ImportSaveCallback (GtkWidget *widget, gpointer data)
2908 {
2909   gtk_widget_hide (GTK_WIDGET (data));
2910   SaveContacts ();
2911   ImportContactsFileDialog ();
2912 }
2913
2914
2915 static void ImportDontSaveCallback (GtkWidget *widget, gpointer data)
2916 {
2917   gtk_widget_hide (GTK_WIDGET (data));
2918   ImportContactsFileDialog ();
2919 }
2920
2921
2922 void static ImportSaveContacts (void)
2923 {
2924   static GtkWidget *dialog = NULL;
2925
2926   if (dialog == NULL)
2927     dialog = CreateSaveQuestionDialog (ImportSaveCallback, ImportDontSaveCallback);
2928
2929   gtk_widget_show (dialog);
2930 }
2931
2932
2933 static void ImportContacts (void)
2934 {
2935   if (contactsMemoryInitialized == TRUE && (statusInfo.ch_ME || statusInfo.ch_SM))
2936     ImportSaveContacts ();
2937   else
2938     ImportContactsFileDialog ();
2939 }
2940
2941
2942 static void QuitSaveCallback (GtkWidget *widget, gpointer data)
2943 {
2944   PhoneEvent *e;
2945
2946   gtk_widget_hide (GTK_WIDGET (data));
2947   SaveContacts ();
2948   e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
2949   e->event = Event_Exit;
2950   e->data = NULL;
2951   GUI_InsertEvent (e);
2952   pthread_join (monitor_th, NULL); 
2953   gtk_main_quit ();
2954 }
2955
2956
2957 static void QuitDontSaveCallback (GtkWidget *widget, gpointer data)
2958 {
2959   PhoneEvent *e;
2960
2961   gtk_widget_hide (GTK_WIDGET (data));
2962   e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
2963   e->event = Event_Exit;
2964   e->data = NULL;
2965   GUI_InsertEvent (e);
2966   pthread_join (monitor_th, NULL); 
2967   gtk_main_quit ();
2968 }
2969
2970
2971 void GUI_QuitSaveContacts (void)
2972 {
2973   static GtkWidget *dialog = NULL;
2974
2975   if (dialog == NULL)
2976     dialog = CreateSaveQuestionDialog (QuitSaveCallback, QuitDontSaveCallback);
2977
2978   gtk_widget_show (dialog);
2979 }
2980
2981
2982 /* Function take number and return name belonged to number.
2983    If no name is found, return NULL;
2984    Do not modify returned name!
2985 */
2986 gchar *GUI_GetName (gchar *number)
2987 {
2988   PhonebookEntry *pbEntry;
2989   register gint i;
2990
2991   if (contactsMemoryInitialized == FALSE || number == NULL)
2992     return (gchar *)NULL;
2993
2994   for(i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
2995   {
2996     pbEntry = g_ptr_array_index (contactsMemory, i);
2997
2998     if (pbEntry->status == E_Empty || pbEntry->status == E_Deleted)
2999       continue;
3000
3001     if (strcmp (pbEntry->entry.Number, number) == 0)
3002       return pbEntry->entry.Name;
3003   }
3004
3005   for (i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
3006   {
3007     pbEntry = g_ptr_array_index (contactsMemory, i);
3008
3009     if (pbEntry->status == E_Empty || pbEntry->status == E_Deleted)
3010       continue;
3011
3012     if (strrncmp (pbEntry->entry.Number, number, 9) == 0)
3013       return pbEntry->entry.Name;
3014   }
3015
3016   return NULL;
3017 }
3018
3019
3020 gchar *GUI_GetNameExact (gchar *number)
3021 {
3022   PhonebookEntry *pbEntry;
3023   register gint i;
3024
3025   if (contactsMemoryInitialized == FALSE || number == NULL)
3026     return (gchar *)NULL;
3027
3028   for(i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
3029   {
3030     pbEntry = g_ptr_array_index (contactsMemory, i);
3031
3032     if (pbEntry->status == E_Empty || pbEntry->status == E_Deleted)
3033       continue;
3034
3035     if (strcmp (pbEntry->entry.Number, number) == 0)
3036       return pbEntry->entry.Name;
3037   }
3038
3039   return NULL;
3040 }
3041
3042
3043 gchar *GUI_GetNumber (gchar *name)
3044 {
3045   PhonebookEntry *pbEntry;
3046   register gint i;
3047
3048   if (contactsMemoryInitialized == FALSE || name == NULL || *name == '\0')
3049     return (gchar *)NULL;
3050
3051   for(i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
3052   {
3053     pbEntry = g_ptr_array_index (contactsMemory, i);
3054
3055     if (pbEntry->status == E_Empty || pbEntry->status == E_Deleted)
3056       continue;
3057
3058     if (strcmp (pbEntry->entry.Name, name) == 0)
3059       return pbEntry->entry.Number;
3060   }
3061
3062   return NULL;
3063 }
3064
3065
3066 static void SelectDialogClickEntry (GtkWidget        *clist,
3067                                     gint              row,
3068                                     gint              column,
3069                                     GdkEventButton   *event,
3070                                     SelectContactData *data )
3071 {
3072   if(event && event->type == GDK_2BUTTON_PRESS)
3073     gtk_signal_emit_by_name(GTK_OBJECT (data->okButton), "clicked");
3074 }
3075
3076
3077 SelectContactData *GUI_SelectContactDialog (void)
3078 {
3079   PhonebookEntry *pbEntry;
3080   static SelectContactData selectContactData;
3081   SortColumn *sColumn;
3082   gchar *titles[4] = { "Name", "Number", "Memory", "Group"};
3083   gint row_i = 0;
3084   register gint i;
3085   gchar string[100];
3086
3087   if (contactsMemoryInitialized == FALSE)
3088     return NULL;
3089
3090   selectContactData.dialog = gtk_dialog_new ();
3091   gtk_widget_set_usize (GTK_WIDGET (selectContactData.dialog), 436, 200);
3092   gtk_window_set_title (GTK_WINDOW (selectContactData.dialog), _("Select contacts"));
3093   gtk_window_set_modal (GTK_WINDOW (selectContactData.dialog), TRUE);
3094
3095   selectContactData.okButton = gtk_button_new_with_label (_("Ok"));
3096   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (selectContactData.dialog)->action_area),
3097                       selectContactData.okButton, TRUE, TRUE, 10);
3098   GTK_WIDGET_SET_FLAGS (selectContactData.okButton, GTK_CAN_DEFAULT);
3099   gtk_widget_grab_default (selectContactData.okButton);
3100   gtk_widget_show (selectContactData.okButton);
3101
3102   selectContactData.cancelButton = gtk_button_new_with_label (_("Cancel"));
3103   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (selectContactData.dialog)->action_area),
3104                       selectContactData.cancelButton, TRUE, TRUE, 10);
3105   gtk_widget_show (selectContactData.cancelButton);
3106
3107   selectContactData.clist = gtk_clist_new_with_titles (4, titles);
3108   gtk_clist_set_shadow_type (GTK_CLIST (selectContactData.clist), GTK_SHADOW_OUT);
3109   gtk_clist_set_compare_func (GTK_CLIST (selectContactData.clist), CListCompareFunc);
3110   gtk_clist_set_sort_column (GTK_CLIST (selectContactData.clist), 0);
3111   gtk_clist_set_sort_type (GTK_CLIST (selectContactData.clist), GTK_SORT_ASCENDING);
3112   gtk_clist_set_auto_sort (GTK_CLIST (selectContactData.clist), FALSE);
3113   gtk_clist_set_selection_mode (GTK_CLIST (selectContactData.clist), GTK_SELECTION_EXTENDED);
3114
3115   gtk_clist_set_column_width (GTK_CLIST(selectContactData.clist), 0, 150);
3116   gtk_clist_set_column_width (GTK_CLIST(selectContactData.clist), 1, 115);
3117   gtk_clist_set_column_width (GTK_CLIST(selectContactData.clist), 3, 70);
3118   gtk_clist_set_column_justification (GTK_CLIST(selectContactData.clist), 2, GTK_JUSTIFY_CENTER);
3119   gtk_clist_set_column_visibility (GTK_CLIST(selectContactData.clist), 3, phoneMonitor.supported & PM_CALLERGROUP);
3120
3121   for (i = 0; i < 4; i++)
3122   {
3123     if ((sColumn = g_malloc (sizeof (SortColumn))) == NULL)
3124     {
3125       g_print (_("Error: %s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
3126       return NULL;
3127     }
3128     sColumn->clist = selectContactData.clist;
3129     sColumn->column = i;
3130     gtk_signal_connect (GTK_OBJECT (GTK_CLIST (selectContactData.clist)->column[i].button), "clicked",
3131                         GTK_SIGNAL_FUNC (SetSortColumn), (gpointer) sColumn);
3132   }
3133
3134   gtk_signal_connect (GTK_OBJECT (selectContactData.clist), "select_row",
3135                       GTK_SIGNAL_FUNC (SelectDialogClickEntry),
3136                       (gpointer) &selectContactData);
3137
3138   selectContactData.clistScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
3139   gtk_container_add (GTK_CONTAINER (selectContactData.clistScrolledWindow),
3140                      selectContactData.clist);
3141   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (selectContactData.clistScrolledWindow),
3142                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3143   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (selectContactData.dialog)->vbox),
3144                       selectContactData.clistScrolledWindow, 
3145                       TRUE, TRUE, 0);
3146
3147   gtk_widget_show (selectContactData.clist);
3148   gtk_widget_show (selectContactData.clistScrolledWindow);
3149
3150   if (xgnokiiConfig.callerGroups[0] == NULL)
3151     GUI_InitCallerGroupsInf ();
3152
3153   gtk_clist_freeze (GTK_CLIST (selectContactData.clist));
3154   for (i = 0; i < memoryStatus.MaxME + memoryStatus.MaxSM; i++)
3155   {
3156     gchar *row[4];
3157
3158     pbEntry = g_ptr_array_index (contactsMemory, i);
3159     if (pbEntry->status != E_Empty && pbEntry->status != E_Deleted)
3160     {
3161       row[0] = pbEntry->entry.Name;
3162  
3163       if (pbEntry->entry.SubEntriesCount>0) {
3164         snprintf(string,100,"%s *",pbEntry->entry.Number);
3165         row[1]=string;
3166       } else row[1] = pbEntry->entry.Number;
3167
3168
3169       if (pbEntry->entry.MemoryType == GMT_ME)
3170         row[2] = "P";
3171       else
3172         row[2] = "S";
3173       if (phoneMonitor.supported & PM_CALLERGROUP)
3174         row[3] = xgnokiiConfig.callerGroups[pbEntry->entry.Group];
3175       else
3176         row[3] = "";
3177       gtk_clist_append (GTK_CLIST (selectContactData.clist), row);
3178       if (pbEntry->entry.MemoryType == GMT_ME)
3179         gtk_clist_set_pixmap (GTK_CLIST (selectContactData.clist), row_i, 2,
3180                               memoryPixmaps.phoneMemPix, memoryPixmaps.mask);
3181       else
3182         gtk_clist_set_pixmap (GTK_CLIST (selectContactData.clist), row_i, 2,
3183                               memoryPixmaps.simMemPix, memoryPixmaps.mask);
3184
3185      gtk_clist_set_row_data (GTK_CLIST (selectContactData.clist), row_i++, (gpointer) pbEntry);
3186     }
3187   }
3188
3189   gtk_clist_sort (GTK_CLIST (selectContactData.clist));
3190   gtk_clist_thaw (GTK_CLIST (selectContactData.clist));
3191
3192   gtk_widget_show (selectContactData.dialog);
3193
3194   return &selectContactData;
3195 }
3196
3197
3198 static GtkItemFactoryEntry menu_items[] = {
3199   { NULL,               NULL,           NULL, 0, "<Branch>"},
3200   { NULL,               "<control>R",   ReadContacts, 0, NULL},
3201   { NULL,               "<control>S",   SaveContacts, 0, NULL},
3202   { NULL,               NULL,           NULL, 0, "<Separator>"},
3203   { NULL,               "<control>I",   ImportContacts, 0, NULL},
3204   { NULL,               "<control>E",   ExportContacts, 0, NULL},
3205   { NULL,               NULL,           NULL, 0, "<Separator>"},
3206   { NULL,               "<control>W",   CloseContacts, 0, NULL},
3207   { NULL,               NULL,           NULL, 0, "<Branch>"},
3208   { NULL,               "<control>N",   NewEntry, 0, NULL},
3209   { NULL,               "<control>U",   DuplicateEntry, 0, NULL},
3210   { NULL,               NULL,           EditEntry, 0, NULL},
3211   { NULL,               "<control>D",   DeleteEntry, 0, NULL},
3212   { NULL,               NULL,           NULL, 0, "<Separator>"},
3213   { NULL,               "<control>C",   ChMemType, 0, NULL},
3214   { NULL,               NULL,           NULL, 0, "<Separator>"},
3215   { NULL,               "<control>F",   FindFirstEntry, 0, NULL},
3216   { NULL,               "<control>L",   SearchEntry, 0, NULL},
3217   { NULL,               NULL,           NULL, 0, "<Separator>"},
3218   { NULL,               "<control>A",   SelectAll, 0, NULL},
3219   { NULL,               NULL,           NULL, 0, "<Branch>"},
3220   { NULL,               "<control>V",   DialVoice, 0, NULL},
3221   { NULL,               NULL,           NULL, 0, "<LastBranch>"},
3222   { NULL,               NULL,           Help1, 0, NULL},
3223   { NULL,               NULL,           GUI_ShowAbout, 0, NULL},
3224 };
3225
3226
3227 static void InitMainMenu (void)
3228 {
3229   menu_items[0].path = g_strdup (_("/_File"));
3230   menu_items[1].path = g_strdup (_("/File/_Read from phone"));
3231   menu_items[2].path = g_strdup (_("/File/_Save to phone"));
3232   menu_items[3].path = g_strdup (_("/File/Sep1"));
3233   menu_items[4].path = g_strdup (_("/File/_Import from file"));
3234   menu_items[5].path = g_strdup (_("/File/_Export to file"));
3235   menu_items[6].path = g_strdup (_("/File/Sep2"));
3236   menu_items[7].path = g_strdup (_("/File/_Close"));
3237   menu_items[8].path = g_strdup (_("/_Edit"));
3238   menu_items[9].path = g_strdup (_("/Edit/_New"));
3239   menu_items[10].path = g_strdup (_("/Edit/D_uplicate"));
3240   menu_items[11].path = g_strdup (_("/Edit/_Edit"));
3241   menu_items[12].path = g_strdup (_("/Edit/_Delete"));
3242   menu_items[13].path = g_strdup (_("/Edit/Sep3"));
3243   menu_items[14].path = g_strdup (_("/Edit/_Change memory type"));
3244   menu_items[15].path = g_strdup (_("/Edit/Sep4"));
3245   menu_items[16].path = g_strdup (_("/Edit/_Find"));
3246   menu_items[17].path = g_strdup (_("/Edit/Find ne_xt"));
3247   menu_items[18].path = g_strdup (_("/Edit/Sep5"));
3248   menu_items[19].path = g_strdup (_("/Edit/Select _all"));
3249   menu_items[20].path = g_strdup (_("/_Dial"));
3250   menu_items[21].path = g_strdup (_("/Dial/Dial _voice"));
3251   menu_items[22].path = g_strdup (_("/_Help"));
3252   menu_items[23].path = g_strdup (_("/Help/_Help"));
3253   menu_items[24].path = g_strdup (_("/Help/_About"));
3254 }
3255
3256
3257 void GUI_CreateContactsWindow (void)
3258 {
3259   int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
3260   GtkItemFactory *item_factory;
3261   GtkAccelGroup *accel_group;
3262   SortColumn *sColumn;
3263   GtkWidget *menubar;
3264   GtkWidget *main_vbox;
3265   GtkWidget *toolbar;
3266   GtkWidget *clistScrolledWindow;
3267   GtkWidget *status_hbox;
3268   register gint i;
3269   gchar *titles[4] = { _("Name"), _("Number"), _("Memory"), _("Group")};
3270
3271   InitMainMenu ();
3272   contactsMemoryInitialized = FALSE;
3273   GUI_ContactsWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3274   gtk_window_set_wmclass (GTK_WINDOW (GUI_ContactsWindow), "ContactsWindow", "Xgnokii");
3275   gtk_window_set_title (GTK_WINDOW (GUI_ContactsWindow), _("Contacts"));
3276   gtk_widget_set_usize (GTK_WIDGET (GUI_ContactsWindow), 436, 220);
3277   //gtk_container_set_border_width (GTK_CONTAINER (GUI_ContactsWindow), 10);
3278   gtk_signal_connect (GTK_OBJECT (GUI_ContactsWindow), "delete_event",
3279                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
3280   gtk_widget_realize (GUI_ContactsWindow);
3281
3282   accel_group = gtk_accel_group_new ();
3283   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
3284                                        accel_group);
3285
3286   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
3287
3288   gtk_accel_group_attach (accel_group, GTK_OBJECT (GUI_ContactsWindow));
3289
3290   /* Finally, return the actual menu bar created by the item factory. */ 
3291   menubar = gtk_item_factory_get_widget (item_factory, "<main>");
3292
3293   main_vbox = gtk_vbox_new (FALSE, 1);
3294   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
3295   gtk_container_add (GTK_CONTAINER (GUI_ContactsWindow), main_vbox);
3296   gtk_widget_show (main_vbox);
3297
3298   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, FALSE, 0);
3299   gtk_widget_show (menubar);
3300
3301   /* Create the toolbar */
3302
3303   toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
3304   gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NORMAL);
3305
3306   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Read from phone"), NULL,
3307                            NewPixmap(Read_xpm, GUI_ContactsWindow->window,
3308                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3309                            (GtkSignalFunc) ReadContacts, NULL);
3310   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Save to phone"), NULL,
3311                            NewPixmap(Send_xpm, GUI_ContactsWindow->window,
3312                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3313                            (GtkSignalFunc) SaveContacts, NULL);
3314
3315   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
3316
3317   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Import from file"), NULL,
3318                            NewPixmap(Open_xpm, GUI_ContactsWindow->window,
3319                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3320                            (GtkSignalFunc) ImportContacts, NULL);
3321   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Export to file"), NULL,
3322                            NewPixmap(Save_xpm, GUI_ContactsWindow->window,
3323                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3324                            (GtkSignalFunc) ExportContacts, NULL);
3325
3326   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
3327
3328   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("New entry"), NULL,
3329                            NewPixmap(New_xpm, GUI_ContactsWindow->window,
3330                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3331                            (GtkSignalFunc) NewEntry, NULL);
3332   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Duplicate entry"), NULL,
3333                            NewPixmap(Duplicate_xpm, GUI_ContactsWindow->window,
3334                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3335                            (GtkSignalFunc) DuplicateEntry, NULL);
3336   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Edit entry"), NULL,
3337                            NewPixmap(Edit_xpm, GUI_ContactsWindow->window,
3338                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3339                            (GtkSignalFunc) EditEntry, NULL);
3340   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Delete entry"), NULL,
3341                            NewPixmap(Delete_xpm, GUI_ContactsWindow->window,
3342                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3343                            (GtkSignalFunc) DeleteEntry, NULL);
3344
3345   gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
3346
3347   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Dial voice"), NULL,
3348                            NewPixmap(Dial_xpm, GUI_ContactsWindow->window,
3349                            &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL]),
3350                            (GtkSignalFunc) DialVoice, NULL);
3351
3352 //  gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
3353
3354   gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, FALSE, 0);
3355   gtk_widget_show (toolbar);
3356
3357
3358   clist = gtk_clist_new_with_titles (4, titles);
3359   gtk_clist_set_shadow_type (GTK_CLIST (clist), GTK_SHADOW_OUT);
3360   gtk_clist_set_compare_func (GTK_CLIST (clist), CListCompareFunc);
3361   gtk_clist_set_sort_column (GTK_CLIST (clist), 0);
3362   gtk_clist_set_sort_type (GTK_CLIST (clist), GTK_SORT_ASCENDING);
3363   gtk_clist_set_auto_sort (GTK_CLIST (clist), FALSE);
3364   gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
3365
3366   gtk_clist_set_column_width (GTK_CLIST (clist), 0, 150);
3367   gtk_clist_set_column_width (GTK_CLIST (clist), 1, 115);
3368   gtk_clist_set_column_width (GTK_CLIST (clist), 3, 70);
3369   gtk_clist_set_column_justification (GTK_CLIST (clist), 2, GTK_JUSTIFY_CENTER);
3370 //  gtk_clist_set_column_visibility (GTK_CLIST (clist), 3, phoneMonitor.supported & PM_CALLERGROUP);
3371
3372   for (i = 0; i < 4; i++)
3373   {
3374     if ((sColumn = g_malloc (sizeof (SortColumn))) == NULL)
3375     {
3376       g_print (_("Error: %s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
3377       gtk_main_quit ();
3378     }
3379     sColumn->clist = clist;
3380     sColumn->column = i;
3381     gtk_signal_connect (GTK_OBJECT (GTK_CLIST (clist)->column[i].button), "clicked",
3382                         GTK_SIGNAL_FUNC (SetSortColumn), (gpointer) sColumn);
3383   }
3384
3385   gtk_signal_connect (GTK_OBJECT (clist), "select_row",
3386                       GTK_SIGNAL_FUNC (ClickEntry), NULL);
3387
3388   clistScrolledWindow = gtk_scrolled_window_new (NULL, NULL);
3389   gtk_container_add (GTK_CONTAINER (clistScrolledWindow), clist);
3390   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (clistScrolledWindow),
3391                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3392   gtk_box_pack_start (GTK_BOX (main_vbox), clistScrolledWindow, 
3393                       TRUE, TRUE, 0);
3394
3395   gtk_widget_show (clist);
3396   gtk_widget_show (clistScrolledWindow);
3397
3398   status_hbox = gtk_hbox_new (FALSE,20);
3399   gtk_box_pack_start (GTK_BOX (main_vbox), status_hbox, FALSE, FALSE, 0);
3400   gtk_widget_show (status_hbox);
3401
3402   memoryStatus.MaxME = memoryStatus.UsedME = memoryStatus.FreeME =
3403   memoryStatus.MaxSM = memoryStatus.UsedSM = memoryStatus.FreeSM = 0;
3404   statusInfo.ch_ME = statusInfo.ch_SM = 0; 
3405
3406   statusInfo.label = gtk_label_new ("");
3407   RefreshStatusInfo ();
3408   gtk_box_pack_start (GTK_BOX (status_hbox), statusInfo.label, FALSE, FALSE, 10);
3409   gtk_widget_show (statusInfo.label);
3410
3411   memoryPixmaps.simMemPix = gdk_pixmap_create_from_xpm_d (GUI_ContactsWindow->window,
3412                                 &memoryPixmaps.mask,
3413                                 &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL],
3414                                 sim_xpm);
3415
3416   memoryPixmaps.phoneMemPix = gdk_pixmap_create_from_xpm_d (GUI_ContactsWindow->window,
3417                                   &memoryPixmaps.mask,
3418                                   &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL],
3419                                   phone_xpm);
3420
3421   questMark.pixmap = gdk_pixmap_create_from_xpm_d (GUI_ContactsWindow->window,
3422                          &questMark.mask,
3423                          &GUI_ContactsWindow->style->bg[GTK_STATE_NORMAL],
3424                          quest_xpm);
3425
3426   CreateErrorDialog (&errorDialog, GUI_ContactsWindow);
3427   GUIEventAdd (GUI_EVENT_CONTACTS_CHANGED, GUI_RefreshContacts);
3428   GUIEventAdd (GUI_EVENT_CALLERS_GROUPS_CHANGED, GUI_RefreshGroupMenu);
3429 }
3430