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