Found in "gnokii-working" directory, some November-patches version
[gnokii.git] / xgnokii / xgnokii_sms.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   Last modification: Sun Apr 30 2000
12   Modified by Jan Derfinak
13
14 */
15 #include <unistd.h>
16 #include <locale.h>
17 #include <fcntl.h>
18 #include <pthread.h>
19 #include <time.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include <gdk/gdkkeysyms.h>
25 #include "misc.h"
26 #include "gsm-api.h"
27 #include "xgnokii_common.h"
28 #include "xgnokii.h"
29 #include "xgnokii_lowlevel.h"
30 #include "xgnokii_contacts.h"
31 #include "xgnokii_sms.h"
32 #include "xpm/Edit.xpm"
33 #include "xpm/Delete.xpm"
34 #include "xpm/Forward.xpm"
35 #include "xpm/Reply.xpm"
36 #include "xpm/Send.xpm"
37 #include "xpm/SendSMS.xpm"
38 #include "xpm/Check.xpm"
39 #include "xpm/Names.xpm"
40 #include "xpm/BCard.xpm"
41 #include "xpm/quest.xpm"
42
43 typedef struct {
44   gint  count;          // Messages count
45   gint  number;         // Number of tail in Long SMS;
46   gint *msgPtr;         // Array of MessageNumber;
47   gint  validity;
48   gint  class;
49   gchar sender[GSM_MAX_SENDER_LENGTH + 1];
50   gchar destination[GSM_MAX_DESTINATION_LENGTH + 1];
51 } MessagePointers;
52
53 typedef struct {
54   gchar *number;
55   gchar *name;
56   gint used:1;
57 } AddressPar;
58
59 typedef struct {
60   GtkWidget *smsClist;
61   GtkWidget *smsText;
62   GSList    *messages;
63   GdkColor   colour;
64   gint       row_i;
65   gint       currentBox;
66 } SMSWidget;
67
68 typedef struct {
69   GtkWidget *SMSSendWindow;
70   GtkWidget *smsSendText;
71   GtkWidget *addr;
72   GtkWidget *status;
73   GtkWidget *report;
74   GtkWidget *longSMS;
75   GtkWidget *smscOptionMenu;
76   GtkTooltips *addrTip;
77   gint       center;
78   GSList    *addressLine;
79 } SendSMSWidget;
80
81 static GtkWidget *GUI_SMSWindow;
82 static SMSWidget SMS = {NULL, NULL, NULL};
83 static SendSMSWidget sendSMS = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL};
84 static ErrorDialog errorDialog = {NULL, NULL};
85 static InfoDialog infoDialog = {NULL, NULL};
86 static QuestMark questMark;
87
88
89 static inline void Help1 (GtkWidget *w, gpointer data)
90 {
91   gchar *indx = g_strdup_printf ("/help/%s/windows/sms/index.html", xgnokiiConfig.locale);
92   Help (w, indx);
93   g_free (indx);
94 }
95
96
97 static inline void Help2 (GtkWidget *w, gpointer data)
98 {
99   gchar *indx = g_strdup_printf ("/help/%s/sms_send.html", xgnokiiConfig.locale);
100   Help (w, indx);
101   g_free (indx);
102 }
103
104
105 static inline void CloseSMS (GtkWidget *w, gpointer data)
106 {
107   gtk_widget_hide (GUI_SMSWindow);
108 }
109
110
111 static inline void CloseSMSSend (GtkWidget *w, gpointer data)
112 {
113   gtk_widget_hide (sendSMS.SMSSendWindow);
114 }
115
116
117 static gint CListCompareFunc (GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
118 {
119   gchar *text1 = NULL;
120   gchar *text2 = NULL;
121
122   GtkCListRow *row1 = (GtkCListRow *) ptr1;
123   GtkCListRow *row2 = (GtkCListRow *) ptr2;
124
125   switch (row1->cell[clist->sort_column].type)
126   {
127     case GTK_CELL_TEXT:
128       text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
129       break;
130     case GTK_CELL_PIXTEXT:
131       text1 = GTK_CELL_PIXTEXT (row1->cell[clist->sort_column])->text;
132       break;
133     default:
134       break;
135   }
136   switch (row2->cell[clist->sort_column].type)
137   {
138     case GTK_CELL_TEXT:
139       text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
140       break;
141     case GTK_CELL_PIXTEXT:
142       text2 = GTK_CELL_PIXTEXT (row2->cell[clist->sort_column])->text;
143       break;
144     default:
145       break;
146   }
147
148   if (!text2)
149     return (text1 != NULL);
150
151   if (!text1)
152     return -1;
153
154   if (clist->sort_column == 1 && !SMS.currentBox)
155   {
156     struct tm bdTime;
157     time_t time1, time2;
158
159     bdTime.tm_sec  = atoi (text1 + 15);
160     bdTime.tm_min  = atoi (text1 + 12);
161     bdTime.tm_hour = atoi (text1 + 9);
162     bdTime.tm_mday = atoi (text1);
163     bdTime.tm_mon  = atoi (text1 + 3) - 1;
164     bdTime.tm_year = atoi (text1 + 6);
165     if (bdTime.tm_year < 70)
166       bdTime.tm_year += 100;
167 #ifdef HAVE_TM_GMTON
168     if (text1[17] != '\0')
169       bdTime.tm_gmtoff = atoi (text1 + 18) * 3600;
170 #endif
171     bdTime.tm_isdst = -1;
172
173     time1 = mktime (&bdTime);
174
175     bdTime.tm_sec  = atoi (text2 + 15);
176     bdTime.tm_min  = atoi (text2 + 12);
177     bdTime.tm_hour = atoi (text2 + 9);
178     bdTime.tm_mday = atoi (text2);
179     bdTime.tm_mon  = atoi (text2 + 3) - 1;
180     bdTime.tm_year = atoi (text2 + 6);
181     if (bdTime.tm_year < 70)
182       bdTime.tm_year += 100;
183 #ifdef HAVE_TM_GMTON
184     if (text2[17] != '\0')
185       bdTime.tm_gmtoff = atoi (text2 + 18) * 3600;
186 #endif
187     bdTime.tm_isdst = -1;
188
189     time2 = mktime (&bdTime);
190
191     if (time1 < time2)
192       return (1);
193     else if (time1 > time2)
194       return (-1);
195     else 
196       return 0;
197   }
198
199   return (g_strcasecmp (text1, text2));
200 }
201
202
203 static inline void DestroyMsgPtrs (gpointer data)
204 {
205   g_free (((MessagePointers *) data)->msgPtr);
206   g_free ((MessagePointers *) data);
207 }
208
209
210 static void InsertInboxElement (gpointer d, gpointer userData)
211 {
212   GSM_SMSMessage *data = (GSM_SMSMessage *) d;
213   MessagePointers *msgPtrs;
214   GSM_DateTime *dt;
215
216   if (data->Type == GST_MT || data->Type == GST_DR)
217   {
218 /*    if (data->Type == GST_MT && data->UDHType == GSM_ConcatenatedMessages)
219     {
220       //FIX ME
221
222       msgPtrs = (MessagePointers *) g_malloc (sizeof (MessagePointers));
223       msgPtrs->count = data->UDH[4];
224       msgPtrs->number = data->UDH[5];
225       msgPtrs->validity = data->Validity;
226       msgPtrs->class = data->Class;
227       strcpy (msgPtrs->sender, data->Sender);
228       msgPtrs->msgPtr = (gint *) g_malloc (msgPtrs->count * sizeof (gint));
229       *(msgPtrs->msgPtr + msgPtrs->number - 1) = data->MessageNumber;
230     }
231     else */
232     {
233       gchar *row[4];
234
235       if (data->Type == GST_DR)
236       {
237         row[0] = g_strdup (_("report"));
238         dt = &(data->SMSCTime);
239       }
240       else if (data->Status)
241       {
242         row[0] = g_strdup (_("read"));
243         dt = &(data->Time);
244       }
245       else
246       {
247         row[0] = g_strdup (_("unread"));
248         dt = &(data->Time);
249       }
250
251       if (dt->Timezone)
252         row[1] = g_strdup_printf ("%02d/%02d/%02d %02d:%02d:%02d %c%02d00",
253                                   dt->Day, dt->Month, dt->Year,
254                                   dt->Hour, dt->Minute, dt->Second,
255                                   dt->Timezone > 0 ? '+' : '-', abs (dt->Timezone));
256       else
257         row[1] = g_strdup_printf ("%02d/%02d/%02d %02d:%02d:%02d",
258                                   dt->Day, dt->Month, dt->Year,
259                                   dt->Hour, dt->Minute, dt->Second);
260
261       row[2] = GUI_GetName (data->Sender);
262       if (row[2] == NULL)
263         row[2] = data->Sender;
264       row[3] = data->MessageText;
265
266       gtk_clist_append (GTK_CLIST (SMS.smsClist), row);
267       msgPtrs = (MessagePointers *) g_malloc (sizeof (MessagePointers));
268       msgPtrs->count = msgPtrs->number = 1;
269       msgPtrs->validity = data->Validity;
270       msgPtrs->class = data->Class;
271       strcpy (msgPtrs->sender, data->Sender);
272       msgPtrs->destination[0]='\0';
273       msgPtrs->msgPtr = (gint *) g_malloc (sizeof (gint));
274       *(msgPtrs->msgPtr) = data->MessageNumber;
275       gtk_clist_set_row_data_full (GTK_CLIST (SMS.smsClist), SMS.row_i++,
276                                    msgPtrs, DestroyMsgPtrs);
277       g_free (row[0]);
278       g_free (row[1]);
279     }
280   }
281 }
282
283
284 static inline void RefreshInbox (void)
285 {
286   gtk_clist_freeze (GTK_CLIST (SMS.smsClist));
287   gtk_clist_clear (GTK_CLIST (SMS.smsClist));
288   gtk_clist_set_column_title(GTK_CLIST (SMS.smsClist), 2/*column*/, _("Sender"));
289
290   SMS.row_i = 0;
291   g_slist_foreach (phoneMonitor.sms.messages, InsertInboxElement, (gpointer) NULL);
292
293   gtk_clist_sort (GTK_CLIST (SMS.smsClist));
294   gtk_clist_thaw (GTK_CLIST (SMS.smsClist));
295 }
296
297
298 static void InsertOutboxElement (gpointer d, gpointer userData)
299 {
300   GSM_SMSMessage *data = (GSM_SMSMessage *) d;
301   MessagePointers *msgPtrs;
302
303   if (data->Type == GST_MO)
304   {
305     gchar *row[4];
306
307     if (data->Status)
308       row[0] = g_strdup (_("sent"));
309     else
310       row[0] = g_strdup (_("unsent"));
311
312     row[1] = g_strdup ("");     /* time */
313
314     row[2] = GUI_GetName (data->Destination);
315     if (row[2] == NULL)
316       row[2] = data->Destination;
317
318     row[3] = data->MessageText;
319
320     gtk_clist_append( GTK_CLIST (SMS.smsClist), row);
321     msgPtrs = (MessagePointers *) g_malloc (sizeof (MessagePointers));
322     msgPtrs->count = msgPtrs->number = 1;
323     msgPtrs->validity = data->Validity;
324     msgPtrs->class = data->Class;
325     msgPtrs->sender[0]='\0';
326     strcpy (msgPtrs->destination, data->Destination);
327     msgPtrs->msgPtr = (gint *) g_malloc (sizeof (gint));
328     *(msgPtrs->msgPtr) = data->MessageNumber;
329     gtk_clist_set_row_data_full (GTK_CLIST (SMS.smsClist), SMS.row_i++,
330                                  msgPtrs, DestroyMsgPtrs);
331     g_free (row[0]);
332     g_free (row[1]);
333   }
334 }
335
336
337 static inline void RefreshOutbox (void)
338 {
339   gtk_clist_freeze (GTK_CLIST (SMS.smsClist));
340   gtk_clist_clear (GTK_CLIST (SMS.smsClist));
341   gtk_clist_set_column_title(GTK_CLIST (SMS.smsClist), 2/*column*/, _("Destination"));
342
343   SMS.row_i = 0;
344   g_slist_foreach (phoneMonitor.sms.messages, InsertOutboxElement, (gpointer) NULL);
345
346   gtk_clist_sort (GTK_CLIST (SMS.smsClist));
347   gtk_clist_thaw (GTK_CLIST (SMS.smsClist));
348 }
349
350
351 inline void GUI_RefreshMessageWindow (void)
352 {
353   if (!GTK_WIDGET_VISIBLE (GUI_SMSWindow))
354     return;
355
356   if (SMS.currentBox)
357     RefreshOutbox ();
358   else
359     RefreshInbox ();
360 }
361
362
363 static void SelectTreeItem (GtkWidget *item, gpointer data)
364 {
365   SMS.currentBox = GPOINTER_TO_INT (data);
366   GUI_RefreshMessageWindow ();
367 }
368
369
370 static void ClickEntry (GtkWidget      *clist,
371                         gint            row,
372                         gint            column,
373                         GdkEventButton *event,
374                         gpointer        data )
375 {
376   gchar *buf;
377
378   /* FIXME - We must mark SMS as readed */
379   gtk_text_freeze (GTK_TEXT (SMS.smsText));
380
381   gtk_text_set_point (GTK_TEXT (SMS.smsText), 0);
382   gtk_text_forward_delete (GTK_TEXT (SMS.smsText), gtk_text_get_length (GTK_TEXT (SMS.smsText)));
383
384   gtk_text_insert (GTK_TEXT (SMS.smsText), NULL, &(SMS.colour), NULL,
385                    (SMS.currentBox ? _("To: ") : _("From: ")), -1);
386   gtk_clist_get_text (GTK_CLIST (clist), row, 2, &buf);
387   gtk_text_insert (GTK_TEXT (SMS.smsText), NULL, &(SMS.smsText->style->black), NULL,
388                    buf, -1);
389   gtk_text_insert (GTK_TEXT (SMS.smsText), NULL, &(SMS.smsText->style->black), NULL,
390                    "\n", -1);
391
392   gtk_text_insert (GTK_TEXT (SMS.smsText), NULL, &(SMS.colour), NULL,
393                    _("Date: "), -1);
394   gtk_clist_get_text (GTK_CLIST (clist), row, 1, &buf);
395   gtk_text_insert (GTK_TEXT (SMS.smsText), NULL, &(SMS.smsText->style->black), NULL,
396                    buf, -1);
397   gtk_text_insert (GTK_TEXT (SMS.smsText), NULL, &(SMS.smsText->style->black), NULL,
398                    "\n\n", -1);
399
400   gtk_clist_get_text (GTK_CLIST (clist), row, 3, &buf);
401   gtk_text_insert (GTK_TEXT (SMS.smsText), NULL, &(SMS.smsText->style->black), NULL,
402                    buf, -1);
403
404   gtk_text_thaw (GTK_TEXT (SMS.smsText));
405 }
406
407
408 inline void GUI_ShowSMS (void)
409 {
410   gtk_widget_show (GUI_SMSWindow);
411   GUI_RefreshMessageWindow ();
412 }
413
414
415 static void OkDeleteSMSDialog (GtkWidget *widget, gpointer data)
416 {
417   GSM_SMSMessage *message;
418   PhoneEvent *e;
419   GList *sel;
420 //  GSM_Error error;
421   gint row;
422   gint count;
423
424
425   sel = GTK_CLIST (SMS.smsClist)->selection;
426
427   gtk_clist_freeze (GTK_CLIST (SMS.smsClist));
428
429   while (sel != NULL)
430   {
431     row = GPOINTER_TO_INT (sel->data);
432     sel = sel->next;
433     for (count = 0; count < ((MessagePointers *) gtk_clist_get_row_data (GTK_CLIST (SMS.smsClist), row))->count; count++)
434     {
435       message = (GSM_SMSMessage *) g_malloc (sizeof (GSM_SMSMessage));
436       message->Location = *(((MessagePointers *) gtk_clist_get_row_data (GTK_CLIST (SMS.smsClist), row))->msgPtr + count);
437       if (message->Location == -1)
438       {
439         g_free (message);
440         continue;
441       }
442       message->MemoryType = GMT_SM;
443
444       e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
445       e->event = Event_DeleteSMSMessage;
446       e->data = message;
447       GUI_InsertEvent (e);
448
449 /*      error = GSM->DeleteSMSMessage(&message);
450
451       if (error != GE_NONE)
452       {
453         if (error == GE_NOTIMPLEMENTED)
454         {
455           gtk_label_set_text(GTK_LABEL(errorDialog.text), _("Function not implemented!"));  
456           gtk_widget_show(errorDialog.dialog);
457         }
458         else
459         {
460           gtk_label_set_text(GTK_LABEL(errorDialog.text), _("Delete SMS failed!"));  
461           gtk_widget_show(errorDialog.dialog);
462         }
463       }
464 */
465     }
466   }
467
468   gtk_widget_hide (GTK_WIDGET (data));
469
470   gtk_clist_thaw (GTK_CLIST (SMS.smsClist));
471 }
472
473
474 static void DeleteSMS (void)
475 {
476   static GtkWidget *dialog = NULL;
477   GtkWidget *button, *hbox, *label, *pixmap;
478
479   if (dialog == NULL)
480   {
481     dialog = gtk_dialog_new();
482     gtk_window_set_title (GTK_WINDOW (dialog), _("Delete SMS"));
483     gtk_window_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
484     gtk_window_set_modal(GTK_WINDOW (dialog), TRUE);
485     gtk_container_set_border_width (GTK_CONTAINER (dialog), 10);
486     gtk_signal_connect (GTK_OBJECT (dialog), "delete_event",
487                         GTK_SIGNAL_FUNC (DeleteEvent), NULL);
488
489     button = gtk_button_new_with_label (_("Ok"));
490     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
491                         button, TRUE, TRUE, 10);
492     gtk_signal_connect (GTK_OBJECT (button), "clicked",
493                         GTK_SIGNAL_FUNC (OkDeleteSMSDialog), (gpointer) dialog);
494     GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
495     gtk_widget_grab_default (button);
496     gtk_widget_show (button);
497     button = gtk_button_new_with_label (_("Cancel"));
498     gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
499                         button, TRUE, TRUE, 10);
500     gtk_signal_connect (GTK_OBJECT (button), "clicked",
501                         GTK_SIGNAL_FUNC (CancelDialog), (gpointer) dialog);
502     gtk_widget_show (button);
503
504     gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5);
505
506     hbox = gtk_hbox_new (FALSE, 0);
507     gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
508     gtk_widget_show (hbox);
509
510     pixmap = gtk_pixmap_new (questMark.pixmap, questMark.mask);
511     gtk_box_pack_start (GTK_BOX (hbox), pixmap, FALSE, FALSE, 10);
512     gtk_widget_show (pixmap);
513
514     label = gtk_label_new (_("Do you want to delete selected SMS?"));
515     gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 10);
516     gtk_widget_show (label);
517   }
518
519   gtk_widget_show (GTK_WIDGET (dialog));
520 }
521
522
523 static void SaveToMailbox (void)
524 {
525   gchar buf[255];
526   FILE *f;
527   gint fd;
528   GList *sel;
529   struct tm t, *loctime;
530   struct flock lock;
531   time_t caltime;
532   gint row;
533   gchar *number, *text, *loc;
534
535
536   if ((f = fopen (xgnokiiConfig.mailbox, "a")) == NULL)
537   {
538     snprintf (buf, 255, _("Cannot open mailbox %s for appending!"), xgnokiiConfig.mailbox);
539     gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
540     gtk_widget_show (errorDialog.dialog);
541     return;
542   }
543
544   fd = fileno (f);
545   lock.l_type = F_WRLCK;
546   lock.l_whence = SEEK_SET;
547   lock.l_start = 0;
548   lock.l_len = 0;
549   
550   if (fcntl (fd, F_GETLK, &lock) != -1 && lock.l_type != F_UNLCK)
551   {
552     snprintf (buf, 255, _("Cannot save to mailbox %s.\n\
553 %s is locked for process %d!"), xgnokiiConfig.mailbox, xgnokiiConfig.mailbox,
554               lock.l_pid);
555     gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
556     gtk_widget_show (errorDialog.dialog);
557     fclose (f);
558     return;
559   }
560   
561   lock.l_type = F_WRLCK;
562   lock.l_whence = SEEK_SET;
563   lock.l_start = 0;
564   lock.l_len = 0;
565   if (fcntl (fd, F_SETLK, &lock) == -1)
566   {
567     snprintf (buf, 255, _("Cannot lock mailbox %s!"), xgnokiiConfig.mailbox);
568     gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
569     gtk_widget_show (errorDialog.dialog);
570     fclose (f);
571     return;
572   }
573   
574   sel = GTK_CLIST (SMS.smsClist)->selection;
575
576   while (sel != NULL)
577   {
578     row = GPOINTER_TO_INT (sel->data);
579     sel = sel->next;
580     gtk_clist_get_text (GTK_CLIST (SMS.smsClist), row, 1, &text);
581     t.tm_sec  = atoi (text + 15);
582     t.tm_min  = atoi (text + 12);
583     t.tm_hour = atoi (text + 9);
584     t.tm_mday = atoi (text);
585     t.tm_mon  = atoi (text + 3) - 1;
586     t.tm_year = atoi (text + 6);
587     if (t.tm_year < 70)
588       t.tm_year += 100;
589 #ifdef HAVE_TM_GMTON
590     if (text[17] != '\0')
591       t.tm_gmtoff = atoi (text + 18) * 3600;
592 #endif
593
594     caltime = mktime (&t);
595     loctime = localtime (&caltime);
596
597     gtk_clist_get_text (GTK_CLIST (SMS.smsClist), row, 2, &number);
598     gtk_clist_get_text (GTK_CLIST (SMS.smsClist), row, 3, &text);
599
600     fprintf (f, "From %s@xgnokii %s", number, asctime (loctime));
601     loc = setlocale (LC_ALL, "C");
602     strftime (buf, 255, "Date: %a, %d %b %Y %H:%M:%S %z (%Z)\n", loctime);
603     setlocale (LC_ALL, loc);
604     fprintf (f, "%s", buf);
605     fprintf (f, "From: %s@xgnokii\n", number);
606     strncpy (buf, text, 20);
607     buf[20] = '\0'; 
608     fprintf (f, "Subject: %s\n\n", buf);
609     fprintf (f, "%s\n\n", text);
610   }
611
612   lock.l_type = F_UNLCK;
613   lock.l_whence = SEEK_SET;
614   lock.l_start = 0;
615   lock.l_len = 0;
616   if (fcntl (fd, F_SETLK, &lock) == -1)
617   {
618     snprintf (buf, 255, _("Cannot unlock mailbox %s!"), xgnokiiConfig.mailbox);
619     gtk_label_set_text (GTK_LABEL (errorDialog.text), buf);
620     gtk_widget_show (errorDialog.dialog);
621   }
622
623   fclose (f);
624 }
625
626
627 static inline void RefreshSMSStatus (void)
628 {
629   gchar *buf;
630   guint l, m;
631
632   l = gtk_text_get_length (GTK_TEXT (sendSMS.smsSendText));
633
634   if (l <= GSM_MAX_SMS_LENGTH)
635     buf = g_strdup_printf ("%d/1", l);
636   else
637   {
638     m = l % 153;
639     buf = g_strdup_printf ("%d/%d", l > 0 && !m ? 153 : m, l == 0 ? 1 : ((l - 1) / 153) + 1);
640   }
641
642   gtk_frame_set_label (GTK_FRAME (sendSMS.status), buf);
643   g_free (buf);
644 }
645
646
647 static inline gint RefreshSMSLength (GtkWidget   *widget,
648                                      GdkEventKey *event,
649                                      gpointer     callback_data)
650 {
651   RefreshSMSStatus ();
652   if (GTK_EDITABLE (widget)->editable == FALSE)
653     return (FALSE);
654   if (event->keyval == GDK_BackSpace || event->keyval == GDK_Clear ||
655       event->keyval == GDK_Insert || event->keyval == GDK_Delete ||
656       event->keyval == GDK_Home || event->keyval == GDK_End ||
657       event->keyval == GDK_Left || event->keyval == GDK_Right ||
658       event->keyval == GDK_Up || event->keyval == GDK_Down ||
659       event->keyval == GDK_Return ||
660       (event->keyval >= 0x20 && event->keyval <= 0xFF))
661     return (TRUE);
662   
663   return (FALSE);
664 }
665
666
667 static inline void SetActiveCenter (GtkWidget *item, gpointer data)
668 {
669   sendSMS.center = GPOINTER_TO_INT (data);
670 }
671
672
673 void GUI_RefreshSMSCenterMenu (void)
674 {
675   static GtkWidget *smscMenu = NULL;
676   GtkWidget *item;
677   register gint i;
678
679   if (!sendSMS.smscOptionMenu)
680     return;
681
682   if (smscMenu)
683   {
684     gtk_option_menu_remove_menu (GTK_OPTION_MENU (sendSMS.smscOptionMenu));
685     if (GTK_IS_WIDGET (smscMenu))
686       gtk_widget_destroy (GTK_WIDGET (smscMenu));
687     smscMenu = NULL;
688   }
689
690   smscMenu = gtk_menu_new();
691
692   for (i = 0; i < xgnokiiConfig.smsSets; i++)
693   {
694     if (*(xgnokiiConfig.smsSetting[i].Name) == '\0')
695     {
696       gchar *buf = g_strdup_printf (_("Set %d"), i + 1);
697       item = gtk_menu_item_new_with_label (buf);
698       g_free (buf);
699     }
700     else
701       item = gtk_menu_item_new_with_label (xgnokiiConfig.smsSetting[i].Name);
702
703     gtk_signal_connect (GTK_OBJECT (item), "activate",
704                         GTK_SIGNAL_FUNC (SetActiveCenter),
705                         (gpointer) i);
706
707     gtk_widget_show (item);
708     gtk_menu_append (GTK_MENU (smscMenu), item);
709   }
710   gtk_option_menu_set_menu (GTK_OPTION_MENU (sendSMS.smscOptionMenu), smscMenu);
711 }
712
713
714 static inline void InitAddressLine (gpointer d, gpointer userData)
715 {
716   ((AddressPar *) d)->used = 0;
717 }
718
719
720 #ifdef XDEBUG
721 static inline void PrintAddressLine (gpointer d, gpointer userData)
722 {
723   g_print ("Name: %s\nNumber: %s\nUsed: %d\n",
724            ((AddressPar *) d)->name,
725            ((AddressPar *) d)->number,
726            ((AddressPar *) d)->used);
727 }
728 #endif
729
730
731 static inline gint CompareAddressLineName (gconstpointer a, gconstpointer b)
732 {
733   return strcmp (((AddressPar *) a)->name, ((AddressPar *) b)->name);
734 }
735
736
737 static inline gint CompareAddressLineUsed (gconstpointer a, gconstpointer b)
738 {
739   return !(((AddressPar *) a)->used == ((AddressPar *) b)->used);
740 }
741
742
743 static gint CheckAddressMain (void)
744 {
745   AddressPar aps;
746   GSList *r;
747   register gint i = 0;
748   gint ret = 0;
749   gchar *buf;
750   GString *tooltipBuf;
751   gchar **strings = g_strsplit (gtk_entry_get_text (GTK_ENTRY (sendSMS.addr)), ",", 0);
752
753   tooltipBuf = g_string_new ("");
754   gtk_entry_set_text (GTK_ENTRY (sendSMS.addr), "");
755   g_slist_foreach (sendSMS.addressLine, InitAddressLine, (gpointer) NULL);
756
757   while (strings[i])
758   {
759     g_strstrip (strings[i]);
760     if (*strings[i] == '\0')
761     { 
762       i++;
763       continue;
764     }
765     if ((buf = GUI_GetName (strings[i])) != NULL)
766     {
767       AddressPar *ap = g_malloc (sizeof (AddressPar));
768       ap->number = g_strdup (strings[i]);
769       ap->name = g_strdup (buf);
770       ap->used = 1;
771       sendSMS.addressLine = g_slist_append (sendSMS.addressLine, ap);
772       gtk_entry_append_text (GTK_ENTRY (sendSMS.addr), buf);
773       g_string_append (tooltipBuf, ap->number);
774     }
775     else 
776     if ((buf = GUI_GetNumber (strings[i])) != NULL)
777     {
778       aps.name = strings[i];
779       r = g_slist_find_custom (sendSMS.addressLine, &aps, CompareAddressLineName);
780       if (r)
781       {
782         ((AddressPar *) r->data)->used = 1;
783         g_string_append (tooltipBuf, ((AddressPar *) r->data)->number);
784       }
785       else
786         g_string_append (tooltipBuf, buf);
787       gtk_entry_append_text (GTK_ENTRY (sendSMS.addr), strings[i]);
788     }
789     else
790     {
791       gint len = strlen (strings[i]);
792       gint j;
793
794       for (j = 0; j < len; j++)
795         if (strings[i][j] != '*' && strings[i][j] != '#' && strings[i][j] != '+'
796             && (strings[i][j] < '0' || strings[i][j] > '9'))
797           ret = 1;
798       gtk_entry_append_text (GTK_ENTRY (sendSMS.addr), strings[i]);
799       g_string_append (tooltipBuf, strings[i]);
800     }
801     if (strings[i + 1] != NULL)
802     {
803       gtk_entry_append_text (GTK_ENTRY (sendSMS.addr), ", ");
804       g_string_append (tooltipBuf, ", ");
805     }
806     i++;
807   }
808
809   aps.used = 0;
810   while ((r = g_slist_find_custom (sendSMS.addressLine, &aps, CompareAddressLineUsed)))
811     sendSMS.addressLine = g_slist_remove (sendSMS.addressLine, r->data);
812   
813   if (tooltipBuf->len > 0)
814   {
815     gtk_tooltips_set_tip (sendSMS.addrTip, sendSMS.addr, tooltipBuf->str, NULL);
816     gtk_tooltips_enable (sendSMS.addrTip);
817   }
818   else
819     gtk_tooltips_disable (sendSMS.addrTip);
820
821 #ifdef XDEBUG  
822   g_slist_foreach (sendSMS.addressLine, PrintAddressLine, (gpointer) NULL);
823 #endif
824
825   g_strfreev (strings);
826   g_string_free (tooltipBuf, TRUE);
827
828   return ret;
829 }
830
831
832 static inline void CheckAddress (void)
833 {
834   if (CheckAddressMain ())
835   {
836     gtk_label_set_text(GTK_LABEL(errorDialog.text), _("Address line contains illegal address!"));
837     gtk_widget_show(errorDialog.dialog);
838   }
839 }
840
841
842 static void DeleteSelectContactDialog (GtkWidget *widget, GdkEvent *event,
843                                        SelectContactData *data)
844 {
845   gtk_widget_destroy (GTK_WIDGET (data->clist));
846   gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
847   gtk_widget_destroy (GTK_WIDGET (widget));
848 }
849
850
851 static void CancelSelectContactDialog (GtkWidget *widget,
852                                        SelectContactData *data)
853 {
854   gtk_widget_destroy (GTK_WIDGET (data->clist));
855   gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
856   gtk_widget_destroy (GTK_WIDGET (data->dialog));
857 }
858
859
860 static void OkSelectContactDialog (GtkWidget *widget,
861                                    SelectContactData *data)
862 {
863   GList *sel;
864   PhonebookEntry *pbEntry;
865
866   if ((sel = GTK_CLIST (data->clist)->selection) != NULL)
867     while (sel != NULL)
868     {
869       AddressPar *ap = g_malloc (sizeof (AddressPar));
870       
871       pbEntry = gtk_clist_get_row_data (GTK_CLIST (data->clist),
872                                         GPOINTER_TO_INT (sel->data));
873       ap->number = g_strdup (pbEntry->entry.Number);
874       ap->name = g_strdup (pbEntry->entry.Name);
875       ap->used = 1;
876       sendSMS.addressLine = g_slist_append (sendSMS.addressLine, ap);
877       if (strlen (gtk_entry_get_text (GTK_ENTRY (sendSMS.addr))) > 0)
878         gtk_entry_append_text (GTK_ENTRY (sendSMS.addr), ", ");
879       gtk_entry_append_text (GTK_ENTRY (sendSMS.addr), ap->name);
880
881       sel = sel->next;
882     }
883
884   gtk_widget_destroy (GTK_WIDGET (data->clist));
885   gtk_widget_destroy (GTK_WIDGET (data->clistScrolledWindow));
886   gtk_widget_destroy (GTK_WIDGET (data->dialog));
887
888   CheckAddressMain ();
889 }
890
891
892 static void ShowSelectContactsDialog (void)
893 {
894   SelectContactData *r;
895
896   if (!GUI_ContactsIsIntialized ())
897     GUI_ReadContacts ();
898
899   if ((r = GUI_SelectContactDialog ()) == NULL)
900     return;
901
902   gtk_signal_connect (GTK_OBJECT (r->dialog), "delete_event",
903                       GTK_SIGNAL_FUNC (DeleteSelectContactDialog), (gpointer) r);
904
905   gtk_signal_connect (GTK_OBJECT (r->okButton), "clicked",
906                       GTK_SIGNAL_FUNC (OkSelectContactDialog), (gpointer) r);
907   gtk_signal_connect (GTK_OBJECT (r->cancelButton), "clicked",
908                       GTK_SIGNAL_FUNC (CancelSelectContactDialog), (gpointer) r);
909 }
910
911 typedef gint (*SaveSendSMSCore_func)(GSM_SMSMessage *sms);
912
913 static gint SendSMSCore (GSM_SMSMessage *sms)
914 {
915   GSM_Error error;
916   PhoneEvent *e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
917   D_SMSMessage *m = (D_SMSMessage *) g_malloc (sizeof (D_SMSMessage));
918   
919   m->sms = sms;
920   e->event = Event_SendSMSMessage;
921   e->data = m;
922   GUI_InsertEvent (e);
923   pthread_mutex_lock (&sendSMSMutex);
924   pthread_cond_wait (&sendSMSCond, &sendSMSMutex);
925   pthread_mutex_unlock (&sendSMSMutex);
926
927 #ifdef XDEBUG
928   g_print ("Address: %s\nText: %s\nDelivery report: %d\nSMS Center: %d\n",
929            sms->Destination,
930            sms->MessageText,
931            GTK_TOGGLE_BUTTON (sendSMS.report)->active,
932            sendSMS.center);
933 #endif
934
935   error = m->status;
936   g_free (m);
937
938   if (error != GE_SMSSENDOK)
939   {
940     gchar *buf = g_strdup_printf (_("SMS send to %s failed\n(error=%d)"),
941                                   sms->Destination, error);
942     gtk_label_set_text (GTK_LABEL(errorDialog.text), buf);
943     gtk_widget_show (errorDialog.dialog);
944     g_free (buf);
945   }
946   else
947     g_print ("Message sent to: %s\n", sms->Destination);
948
949   return (error);
950 }
951
952 static gint SaveSMSCore (GSM_SMSMessage *sms)
953 {
954   GSM_Error error;
955   PhoneEvent *e = (PhoneEvent *) g_malloc (sizeof (PhoneEvent));
956   D_SMSMessage *m = (D_SMSMessage *) g_malloc (sizeof (D_SMSMessage));
957   
958   /* FIXME: Give user a choice of choosing target memory type, currently
959    * we implicitely always force SIM storage.
960    */
961   sms->MemoryType = GMT_SM;
962   
963   m->sms = sms;
964   e->event = Event_SaveSMSMessage;
965   e->data = m;
966   GUI_InsertEvent (e);
967   pthread_mutex_lock (&saveSMSMutex);
968   pthread_cond_wait (&saveSMSCond, &saveSMSMutex);
969   pthread_mutex_unlock (&saveSMSMutex);
970
971 #ifdef XDEBUG
972   g_print ("Address: %s\nText: %s\nDelivery report: %d\nSMS Center: %d\n",
973            sms->Destination,
974            sms->MessageText,
975            GTK_TOGGLE_BUTTON (sendSMS.report)->active,
976            sendSMS.center);
977 #endif
978
979   error = m->status;
980   g_free (m);
981
982   if (error != GE_NONE)
983   {
984     gchar *buf = g_strdup_printf (_("SMS save of message to %s failed\n(error=%d)"),
985                                   sms->Destination, error);
986     gtk_label_set_text (GTK_LABEL(errorDialog.text), buf);
987     gtk_widget_show (errorDialog.dialog);
988     g_free (buf);
989   }
990   else
991     g_print ("Message saved, destination to: %s\n", sms->Destination);
992
993   return (error);
994 }
995
996 static void SaveSendSMS (SaveSendSMSCore_func corefunc)
997 {
998   GSM_SMSMessage sms;
999   AddressPar aps;
1000   GSList *r;
1001   gchar *text, *number;
1002   gchar **addresses;
1003   gchar *buf;
1004   gint l;
1005   gint longSMS;
1006   register gint i = 0;
1007   GSM_Deconcatenate_state SMS_Deconcatenate_state;
1008
1009   if (CheckAddressMain ())
1010   {
1011     gtk_label_set_text(GTK_LABEL(errorDialog.text), _("Address line contains illegal address!"));
1012     gtk_widget_show(errorDialog.dialog);
1013     return;
1014   }
1015
1016   text = gtk_editable_get_chars (GTK_EDITABLE (sendSMS.smsSendText), 0, -1);
1017   l = strlen (text);
1018
1019   addresses = g_strsplit (gtk_entry_get_text (GTK_ENTRY (sendSMS.addr)), ",", 0);
1020
1021   longSMS = GTK_TOGGLE_BUTTON (sendSMS.longSMS)->active;
1022
1023   while (addresses[i])
1024   {
1025     g_strstrip (addresses[i]);
1026     if ((number = GUI_GetNumber (addresses[i])))
1027     {
1028       aps.name = addresses[i];
1029       if ((r = g_slist_find_custom (sendSMS.addressLine, &aps, CompareAddressLineName)))
1030         number = ((AddressPar *) r->data)->number;
1031     }
1032     else
1033       number = addresses[i];
1034
1035     sms.MessageCenter = xgnokiiConfig.smsSetting[sendSMS.center];
1036     sms.MessageCenter.No = 0;
1037
1038     if (GTK_TOGGLE_BUTTON (sendSMS.report)->active)
1039       sms.Type = GST_DR;
1040     else
1041       sms.Type = GST_MO;
1042
1043     sms.Class = -1;
1044     sms.Compression = false;
1045     sms.EightBit = false;
1046     sms.Validity = sms.MessageCenter.Validity;
1047     sms.UDHPresent = false;
1048
1049     strncpy (sms.Destination, number, GSM_MAX_DESTINATION_LENGTH + 1);
1050     sms.Destination[GSM_MAX_DESTINATION_LENGTH] = '\0';
1051
1052     buf = g_strdup_printf ((corefunc==SendSMSCore ? _("Sending SMS to %s ...\n") : _("Saving SMS to %s ...\n")),
1053             sms.Destination);
1054     gtk_label_set_text (GTK_LABEL (infoDialog.text), buf);
1055     gtk_widget_show_now (infoDialog.dialog);
1056     g_free (buf);
1057     GUI_Refresh ();
1058
1059     SMS_Deconcatenate_state.first=true;
1060     while (SMS_Deconcatenate(&SMS_Deconcatenate_state,&sms,text,l,longSMS)) {
1061
1062             (void) (*corefunc)(&sms);   /* errors ignored, ugh */
1063
1064             /* Here the sleep have no meaning.
1065              * If it is required by some backend phone driver, it should be done THERE!
1066              */
1067             /* sleep(1); */
1068     }
1069
1070     gtk_widget_hide (infoDialog.dialog);
1071     GUI_Refresh ();
1072
1073     i++;
1074   }
1075
1076   g_strfreev (addresses);
1077
1078   g_free (text);
1079 }
1080
1081 static void SendSMS (void)
1082 {
1083   SaveSendSMS(SendSMSCore);
1084 }
1085
1086 static void SaveSMS (void)
1087 {
1088   SaveSendSMS(SaveSMSCore);
1089 }
1090
1091 static GtkItemFactoryEntry send_menu_items[] = {
1092   { NULL,               NULL,           NULL,           0, "<Branch>"},
1093   { NULL,               "<control>X",   SendSMS,        0, NULL},
1094   { NULL,               "<control>S",   SaveSMS,        0, NULL},
1095   { NULL,               NULL,           NULL,           0, "<Separator>"},
1096   { NULL,               "<control>N",   CheckAddress,   0, NULL},
1097   { NULL,               "<control>C",   ShowSelectContactsDialog, 0, NULL},
1098   { NULL,               NULL,           NULL,           0, "<Separator>"},
1099   { NULL,               "<control>W",   CloseSMSSend,   0, NULL},
1100   { NULL,               NULL,           NULL,           0, "<LastBranch>"},
1101   { NULL,               NULL,           Help2,          0, NULL},
1102   { NULL,               NULL,           GUI_ShowAbout,  0, NULL},
1103 };
1104
1105
1106 static void InitSendMenu (void)
1107 {
1108   send_menu_items[0].path = g_strdup (_("/_File"));
1109   send_menu_items[1].path = g_strdup (_("/File/Sen_d"));
1110   send_menu_items[2].path = g_strdup (_("/File/_Save"));
1111   send_menu_items[3].path = g_strdup (_("/File/Sep1"));
1112   send_menu_items[4].path = g_strdup (_("/File/Check _Names"));
1113   send_menu_items[5].path = g_strdup (_("/File/C_ontacts"));
1114   send_menu_items[6].path = g_strdup (_("/File/Sep2"));
1115   send_menu_items[7].path = g_strdup (_("/File/_Close"));
1116   send_menu_items[8].path = g_strdup (_("/_Help"));
1117   send_menu_items[9].path = g_strdup (_("/Help/_Help"));
1118   send_menu_items[10].path = g_strdup (_("/Help/_About"));
1119 }
1120
1121
1122 static void CreateSMSSendWindow (void)
1123 {
1124   int nmenu_items = sizeof (send_menu_items) / sizeof (send_menu_items[0]);
1125   GtkItemFactory *item_factory;
1126   GtkAccelGroup *accel_group;
1127   GtkWidget *menubar;
1128   GtkWidget *main_vbox;
1129   GtkWidget *hbox, *vbox;
1130   GtkWidget *button;
1131   GtkWidget *pixmap;
1132   GtkWidget *label;
1133   GtkWidget *toolbar;
1134   GtkWidget *scrolledWindow;
1135   GtkTooltips *tooltips;
1136
1137   if (sendSMS.SMSSendWindow)
1138     return;
1139
1140   InitSendMenu ();
1141   sendSMS.SMSSendWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1142   gtk_window_set_wmclass (GTK_WINDOW(sendSMS.SMSSendWindow), "SMSSendWindow", "Xgnokii");
1143
1144   //gtk_widget_set_usize (GTK_WIDGET (sendSMS.SMSSendWindow), 436, 220);
1145   gtk_signal_connect (GTK_OBJECT (sendSMS.SMSSendWindow), "delete_event",
1146                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1147   gtk_widget_realize (sendSMS.SMSSendWindow);
1148
1149   accel_group = gtk_accel_group_new ();
1150   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
1151                                        accel_group);
1152
1153   gtk_item_factory_create_items (item_factory, nmenu_items, send_menu_items, NULL);
1154
1155   gtk_accel_group_attach (accel_group, GTK_OBJECT (sendSMS.SMSSendWindow));
1156
1157   /* Finally, return the actual menu bar created by the item factory. */ 
1158   menubar = gtk_item_factory_get_widget (item_factory, "<main>");
1159
1160   main_vbox = gtk_vbox_new (FALSE, 1);
1161   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
1162   gtk_container_add (GTK_CONTAINER (sendSMS.SMSSendWindow), main_vbox);
1163   gtk_widget_show (main_vbox);
1164
1165   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, FALSE, 0);
1166   gtk_widget_show (menubar);
1167
1168   /* Create the toolbar */
1169
1170   toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
1171   gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NORMAL);
1172
1173   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Send message"), NULL,
1174                            NewPixmap(SendSMS_xpm, GUI_SMSWindow->window,
1175                            &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL]),
1176                            (GtkSignalFunc) SendSMS, NULL);
1177   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Save message to outbox"), NULL,
1178                            NewPixmap(Send_xpm, GUI_SMSWindow->window,
1179                            &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL]),
1180                            (GtkSignalFunc) SaveSMS, NULL);
1181
1182   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1183
1184   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Check names"), NULL,
1185                            NewPixmap(Check_xpm, GUI_SMSWindow->window,
1186                            &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL]),
1187                            (GtkSignalFunc) CheckAddress, NULL);
1188
1189   gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, FALSE, 0);
1190   gtk_widget_show (toolbar);
1191
1192   /* Address line */
1193   hbox = gtk_hbox_new (FALSE, 3);
1194   gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 3);
1195   gtk_widget_show (hbox);
1196
1197   label = gtk_label_new (_("To:"));
1198   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 3);
1199   gtk_widget_show (label);
1200
1201   sendSMS.addr = gtk_entry_new ();
1202   gtk_box_pack_start (GTK_BOX (hbox), sendSMS.addr, TRUE, TRUE, 1);
1203
1204   sendSMS.addrTip = gtk_tooltips_new ();
1205   gtk_tooltips_set_tip (sendSMS.addrTip, sendSMS.addr, "", NULL);
1206   gtk_tooltips_disable (sendSMS.addrTip);
1207
1208   gtk_widget_show (sendSMS.addr);
1209
1210   button = gtk_button_new ();
1211   gtk_signal_connect (GTK_OBJECT (button), "clicked",
1212                       GTK_SIGNAL_FUNC (ShowSelectContactsDialog), (gpointer) NULL);
1213
1214   pixmap = NewPixmap(Names_xpm, sendSMS.SMSSendWindow->window,
1215                      &sendSMS.SMSSendWindow->style->bg[GTK_STATE_NORMAL]);
1216   gtk_container_add (GTK_CONTAINER (button), pixmap);
1217   gtk_widget_show (pixmap);
1218   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 5);
1219
1220   tooltips = gtk_tooltips_new ();
1221   gtk_tooltips_set_tip (tooltips, button, _("Select contacts"), NULL);
1222
1223   gtk_widget_show (button);
1224
1225   hbox = gtk_hbox_new (FALSE, 3);
1226   gtk_box_pack_end (GTK_BOX (main_vbox), hbox, TRUE, TRUE, 3);
1227   gtk_widget_show (hbox);
1228
1229   /* Edit SMS widget */
1230   vbox = gtk_vbox_new (FALSE, 3);
1231   gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 3);
1232   gtk_widget_show (vbox);
1233
1234   sendSMS.status = gtk_frame_new ("0/1");
1235   gtk_frame_set_label_align (GTK_FRAME (sendSMS.status), 1.0, 0.0);
1236   gtk_frame_set_shadow_type (GTK_FRAME (sendSMS.status), GTK_SHADOW_OUT);
1237
1238   gtk_box_pack_end (GTK_BOX (vbox), sendSMS.status, TRUE, TRUE, 5);
1239   gtk_widget_show (sendSMS.status);
1240
1241   sendSMS.smsSendText = gtk_text_new (NULL, NULL);
1242   gtk_widget_set_usize (GTK_WIDGET (sendSMS.smsSendText), 0, 120);
1243   gtk_text_set_editable (GTK_TEXT (sendSMS.smsSendText), TRUE);
1244   gtk_text_set_word_wrap (GTK_TEXT (sendSMS.smsSendText), TRUE);
1245   gtk_signal_connect_after (GTK_OBJECT (sendSMS.smsSendText),
1246                       "key_press_event",
1247                       GTK_SIGNAL_FUNC(RefreshSMSLength), (gpointer) NULL);
1248   gtk_signal_connect_after (GTK_OBJECT (sendSMS.smsSendText),
1249                       "button_press_event",
1250                       GTK_SIGNAL_FUNC(RefreshSMSLength), (gpointer) NULL);
1251
1252   scrolledWindow = gtk_scrolled_window_new (NULL, NULL);
1253   gtk_container_set_border_width (GTK_CONTAINER (scrolledWindow), 5);
1254   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledWindow),
1255                                   GTK_POLICY_NEVER,
1256                                   GTK_POLICY_AUTOMATIC);
1257
1258   gtk_container_add (GTK_CONTAINER (scrolledWindow), sendSMS.smsSendText);
1259   gtk_container_add (GTK_CONTAINER (sendSMS.status), scrolledWindow);
1260
1261   gtk_widget_show (sendSMS.smsSendText);
1262   gtk_widget_show (scrolledWindow);
1263
1264   /* Options widget */
1265   vbox = gtk_vbox_new (FALSE, 3);
1266   gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 5);
1267   gtk_widget_show (vbox);
1268
1269   sendSMS.report = gtk_check_button_new_with_label (_("Delivery report"));
1270   gtk_box_pack_start (GTK_BOX (vbox), sendSMS.report, FALSE, FALSE, 3);
1271   gtk_widget_show (sendSMS.report);
1272
1273   sendSMS.longSMS = gtk_check_button_new_with_label (_("Send as Long SMS"));
1274   gtk_box_pack_start (GTK_BOX (vbox), sendSMS.longSMS, FALSE, FALSE, 3);
1275   gtk_widget_show (sendSMS.longSMS);
1276
1277   label = gtk_label_new (_("SMS Center:"));
1278   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 1);
1279   gtk_widget_show (label);
1280
1281   GUI_InitSMSSettings ();
1282   sendSMS.smscOptionMenu = gtk_option_menu_new();
1283
1284   GUIEventSend (GUI_EVENT_SMS_CENTERS_CHANGED);
1285
1286   gtk_box_pack_start (GTK_BOX (vbox), sendSMS.smscOptionMenu, FALSE, FALSE, 1);
1287   gtk_widget_show (sendSMS.smscOptionMenu);
1288 }
1289
1290
1291 static void NewSMS (void)
1292 {
1293   if (!sendSMS.SMSSendWindow)
1294     CreateSMSSendWindow ();
1295
1296   gtk_window_set_title (GTK_WINDOW (sendSMS.SMSSendWindow), _("New Message"));
1297
1298   gtk_tooltips_disable (sendSMS.addrTip);
1299
1300   gtk_text_freeze (GTK_TEXT (sendSMS.smsSendText));
1301   gtk_text_set_point (GTK_TEXT (sendSMS.smsSendText), 0);
1302   gtk_text_forward_delete (GTK_TEXT (sendSMS.smsSendText), gtk_text_get_length (GTK_TEXT (sendSMS.smsSendText)));
1303   gtk_text_thaw (GTK_TEXT (sendSMS.smsSendText));
1304
1305   gtk_entry_set_text (GTK_ENTRY (sendSMS.addr), "");
1306
1307   RefreshSMSStatus ();
1308
1309   gtk_widget_show (sendSMS.SMSSendWindow);
1310 }
1311
1312
1313 static void ForwardSMS (void)
1314 {
1315   gchar *buf;
1316
1317   if (GTK_CLIST (SMS.smsClist)->selection == NULL)
1318     return;
1319
1320   if (!sendSMS.SMSSendWindow)
1321     CreateSMSSendWindow ();
1322
1323   gtk_window_set_title (GTK_WINDOW (sendSMS.SMSSendWindow), _("Forward Message"));
1324
1325   gtk_tooltips_disable (sendSMS.addrTip);
1326
1327   gtk_text_freeze (GTK_TEXT (sendSMS.smsSendText));
1328   gtk_text_set_point (GTK_TEXT (sendSMS.smsSendText), 0);
1329   gtk_text_forward_delete (GTK_TEXT (sendSMS.smsSendText), gtk_text_get_length (GTK_TEXT (sendSMS.smsSendText)));
1330   gtk_clist_get_text (GTK_CLIST (SMS.smsClist),
1331                       GPOINTER_TO_INT(GTK_CLIST (SMS.smsClist)->selection->data),
1332                       3, &buf);
1333
1334   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1335                    buf, -1);
1336
1337   gtk_text_thaw (GTK_TEXT (sendSMS.smsSendText));
1338
1339   gtk_entry_set_text (GTK_ENTRY (sendSMS.addr), "");
1340
1341   RefreshSMSStatus ();
1342
1343   gtk_widget_show (sendSMS.SMSSendWindow);
1344 }
1345
1346
1347 /*
1348 static inline gint CompareSMSMessageLocation (gconstpointer a, gconstpointer b)
1349 {
1350   return !(((GSM_SMSMessage *) a)->Location == ((GSM_SMSMessage *) b)->Location);
1351 }
1352 */
1353
1354
1355 static void ReplySMS (void)
1356 {
1357   gchar *buf;
1358 //  GSList *r;
1359 //  GSM_SMSMessage msg;
1360   MessagePointers *msgPtrs;
1361
1362   if (GTK_CLIST (SMS.smsClist)->selection == NULL)
1363     return;
1364
1365   if (!sendSMS.SMSSendWindow)
1366     CreateSMSSendWindow ();
1367
1368   gtk_window_set_title (GTK_WINDOW (sendSMS.SMSSendWindow), _("Reply Message"));
1369
1370   gtk_text_freeze (GTK_TEXT (sendSMS.smsSendText));
1371   gtk_text_set_point (GTK_TEXT (sendSMS.smsSendText), 0);
1372   gtk_text_forward_delete (GTK_TEXT (sendSMS.smsSendText),
1373                            gtk_text_get_length (GTK_TEXT (sendSMS.smsSendText)));
1374   gtk_clist_get_text (GTK_CLIST (SMS.smsClist),
1375                       GPOINTER_TO_INT(GTK_CLIST (SMS.smsClist)->selection->data),
1376                       3, &buf);
1377
1378   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL,
1379                    &(sendSMS.smsSendText->style->black), NULL, buf, -1);
1380
1381   gtk_text_thaw (GTK_TEXT (sendSMS.smsSendText));
1382
1383   //msg.Location = *(((MessagePointers *) gtk_clist_get_row_data(GTK_CLIST (SMS.smsClist),
1384   //               GPOINTER_TO_INT (GTK_CLIST (SMS.smsClist)->selection->data)))->msgPtr);
1385
1386   //r = g_slist_find_custom (SMS.messages, &msg, CompareSMSMessageLocation);
1387   //if (r)
1388   msgPtrs = ((MessagePointers *) gtk_clist_get_row_data(GTK_CLIST (SMS.smsClist),
1389                 GPOINTER_TO_INT (GTK_CLIST (SMS.smsClist)->selection->data)));
1390
1391   /* We don't have GSM_SMSMessageType stored in MessagePointers so we just
1392    * look at both the "sender" and "destination", shouldn't matter.
1393    * Anyway to "Reply" to Outbox message is a bit weird, the icon/menu should
1394    * be automatically changed when switched to the Outbox mode. Not my business.
1395    */
1396   gtk_entry_set_text (GTK_ENTRY (sendSMS.addr), (msgPtrs->sender[0] ? msgPtrs->sender : msgPtrs->destination));
1397
1398   CheckAddressMain ();
1399   RefreshSMSStatus ();
1400
1401   gtk_widget_show (sendSMS.SMSSendWindow);
1402 }
1403
1404
1405 static void NewBC (void)
1406 {
1407   if (!sendSMS.SMSSendWindow)
1408     CreateSMSSendWindow ();
1409
1410   gtk_window_set_title (GTK_WINDOW (sendSMS.SMSSendWindow), _("Bussiness Card"));
1411
1412   gtk_tooltips_disable (sendSMS.addrTip);
1413
1414   gtk_text_freeze (GTK_TEXT (sendSMS.smsSendText));
1415   gtk_text_set_point (GTK_TEXT (sendSMS.smsSendText), 0);
1416   gtk_text_forward_delete (GTK_TEXT (sendSMS.smsSendText), gtk_text_get_length (GTK_TEXT (sendSMS.smsSendText)));
1417
1418   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(SMS.colour), NULL,
1419                    "Business Card\n", -1);
1420
1421   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1422                    xgnokiiConfig.user.name, -1);
1423
1424   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1425                    ", ", -1);
1426
1427   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1428                    xgnokiiConfig.user.title, -1);
1429
1430   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1431                    "\n", -1);
1432
1433   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1434                    xgnokiiConfig.user.company, -1);
1435
1436   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1437                    "\n\n", -1);
1438
1439   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(SMS.colour), NULL,
1440                    "tel ", -1);
1441
1442   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1443                    xgnokiiConfig.user.telephone, -1);
1444
1445   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1446                    "\n", -1);
1447
1448   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(SMS.colour), NULL,
1449                    "fax ", -1);
1450
1451   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1452                    xgnokiiConfig.user.fax, -1);
1453
1454   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1455                    "\n", -1);
1456
1457   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1458                    xgnokiiConfig.user.email, -1);
1459
1460   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1461                    "\n", -1);
1462
1463   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1464                    xgnokiiConfig.user.address, -1);
1465
1466   gtk_text_insert (GTK_TEXT (sendSMS.smsSendText), NULL, &(sendSMS.smsSendText->style->black), NULL,
1467                    "\n", -1);
1468
1469   gtk_text_thaw (GTK_TEXT (sendSMS.smsSendText));
1470
1471   gtk_entry_set_text (GTK_ENTRY (sendSMS.addr), "");
1472
1473   RefreshSMSStatus ();
1474
1475   gtk_widget_show (sendSMS.SMSSendWindow);
1476 }
1477
1478
1479 static GtkItemFactoryEntry menu_items[] = {
1480   { NULL,               NULL,           NULL,           0, "<Branch>"},
1481   { NULL,               "<control>S",   NULL,           0, NULL},
1482   { NULL,               "<control>M",   SaveToMailbox,  0, NULL},
1483   { NULL,               NULL,           NULL,           0, "<Separator>"},
1484   { NULL,               "<control>W",   CloseSMS,       0, NULL},
1485   { NULL,               NULL,           NULL,           0, "<Branch>"},
1486   { NULL,               "<control>N",   NewSMS,         0, NULL},
1487   { NULL,               "<control>F",   ForwardSMS,     0, NULL},
1488   { NULL,               "<control>R",   ReplySMS,       0, NULL},
1489   { NULL,               "<control>D",   DeleteSMS,      0, NULL},
1490   { NULL,               NULL,           NULL,           0, "<Separator>"},
1491   { NULL,               "<control>B",   NewBC,          0, NULL},
1492   { NULL,               NULL,           NULL,           0, "<LastBranch>"},
1493   { NULL,               NULL,           Help1,          0, NULL},
1494   { NULL,               NULL,           GUI_ShowAbout,  0, NULL},
1495 };
1496
1497
1498 static void InitMainMenu (void)
1499 {
1500   register gint i = 0;
1501   
1502   menu_items[i++].path = g_strdup (_("/_File"));
1503   menu_items[i++].path = g_strdup (_("/File/_Save"));
1504   menu_items[i++].path = g_strdup (_("/File/Save to mailbo_x"));
1505   menu_items[i++].path = g_strdup (_("/File/Sep1"));
1506   menu_items[i++].path = g_strdup (_("/File/_Close"));
1507   menu_items[i++].path = g_strdup (_("/_Messages"));
1508   menu_items[i++].path = g_strdup (_("/_Messages/_New"));
1509   menu_items[i++].path = g_strdup (_("/_Messages/_Forward"));
1510   menu_items[i++].path = g_strdup (_("/_Messages/_Reply"));
1511   menu_items[i++].path = g_strdup (_("/_Messages/_Delete"));
1512   menu_items[i++].path = g_strdup (_("/Messages/Sep3"));
1513   menu_items[i++].path = g_strdup (_("/_Messages/_Bussiness card"));
1514   menu_items[i++].path = g_strdup (_("/_Help"));
1515   menu_items[i++].path = g_strdup (_("/Help/_Help"));
1516   menu_items[i++].path = g_strdup (_("/Help/_About"));
1517 }
1518
1519
1520 void GUI_CreateSMSWindow (void)
1521 {
1522   int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
1523   GtkItemFactory *item_factory;
1524   GtkAccelGroup *accel_group;
1525   GtkWidget *menubar;
1526   GtkWidget *main_vbox;
1527   GtkWidget *toolbar;
1528   GtkWidget *scrolledWindow;
1529   GtkWidget *vpaned, *hpaned;
1530   GtkWidget *tree, *treeSMSItem, *treeInboxItem, *treeOutboxItem, *subTree;
1531   SortColumn *sColumn;
1532   GdkColormap *cmap;
1533   register gint i;
1534   gchar *titles[4] = { _("Status"), _("Date / Time"), _("Sender"), _("Message")};
1535
1536
1537   InitMainMenu ();
1538   GUI_SMSWindow = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1539   gtk_window_set_wmclass (GTK_WINDOW (GUI_SMSWindow), "SMSWindow", "Xgnokii");
1540   gtk_window_set_title (GTK_WINDOW (GUI_SMSWindow), _("Short Message Service"));
1541   //gtk_widget_set_usize (GTK_WIDGET (GUI_SMSWindow), 436, 220);
1542   gtk_signal_connect (GTK_OBJECT (GUI_SMSWindow), "delete_event",
1543                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
1544   gtk_widget_realize (GUI_SMSWindow);
1545
1546   accel_group = gtk_accel_group_new ();
1547   item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", 
1548                                        accel_group);
1549
1550   gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
1551
1552   gtk_accel_group_attach (accel_group, GTK_OBJECT (GUI_SMSWindow));
1553
1554   /* Finally, return the actual menu bar created by the item factory. */ 
1555   menubar = gtk_item_factory_get_widget (item_factory, "<main>");
1556
1557   main_vbox = gtk_vbox_new (FALSE, 1);
1558   gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
1559   gtk_container_add (GTK_CONTAINER (GUI_SMSWindow), main_vbox);
1560   gtk_widget_show (main_vbox);
1561
1562   gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, FALSE, 0);
1563   gtk_widget_show (menubar);
1564
1565   /* Create the toolbar */
1566   toolbar = gtk_toolbar_new (GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_ICONS);
1567   gtk_toolbar_set_button_relief (GTK_TOOLBAR (toolbar), GTK_RELIEF_NORMAL);
1568
1569   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("New message"), NULL,
1570                            NewPixmap(Edit_xpm, GUI_SMSWindow->window,
1571                            &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL]),
1572                            (GtkSignalFunc) NewSMS, NULL);
1573   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Forward message"), NULL,
1574                            NewPixmap(Forward_xpm, GUI_SMSWindow->window,
1575                            &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL]),
1576                            (GtkSignalFunc) ForwardSMS, NULL);
1577   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Reply message"), NULL,
1578                            NewPixmap(Reply_xpm, GUI_SMSWindow->window,
1579                            &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL]),
1580                            (GtkSignalFunc) ReplySMS, NULL);
1581
1582   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Bussiness Card"), NULL,
1583                            NewPixmap(BCard_xpm, GUI_SMSWindow->window,
1584                            &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL]),
1585                            (GtkSignalFunc) NewBC, NULL);
1586
1587   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1588
1589   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), NULL, _("Delete message"), NULL,
1590                            NewPixmap(Delete_xpm, GUI_SMSWindow->window,
1591                            &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL]),
1592                            (GtkSignalFunc) DeleteSMS, NULL);
1593
1594   gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, FALSE, 0);
1595   gtk_widget_show (toolbar);
1596
1597   vpaned = gtk_vpaned_new ();
1598   gtk_paned_set_handle_size (GTK_PANED (vpaned), 10);
1599   gtk_paned_set_gutter_size (GTK_PANED (vpaned), 15);
1600   gtk_box_pack_end (GTK_BOX (main_vbox), vpaned, TRUE, TRUE, 0);
1601   gtk_widget_show (vpaned);
1602
1603   hpaned = gtk_hpaned_new ();
1604   gtk_paned_set_handle_size (GTK_PANED (hpaned), 8);
1605   gtk_paned_set_gutter_size (GTK_PANED (hpaned), 10);                       
1606   gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
1607   gtk_widget_show (hpaned);
1608
1609   /* Navigation tree */
1610   tree = gtk_tree_new ();
1611   gtk_tree_set_selection_mode (GTK_TREE (tree), GTK_SELECTION_SINGLE);
1612   gtk_widget_show (tree);
1613
1614   treeSMSItem = gtk_tree_item_new_with_label (_("SMS's"));
1615   gtk_tree_append (GTK_TREE (tree), treeSMSItem);
1616   gtk_widget_show (treeSMSItem);
1617
1618   subTree = gtk_tree_new ();
1619   gtk_tree_set_selection_mode (GTK_TREE (subTree), GTK_SELECTION_SINGLE);
1620   gtk_tree_set_view_mode (GTK_TREE (subTree), GTK_TREE_VIEW_ITEM);
1621   gtk_tree_item_set_subtree (GTK_TREE_ITEM (treeSMSItem), subTree);
1622
1623   treeInboxItem = gtk_tree_item_new_with_label (_("Inbox"));
1624   gtk_tree_append (GTK_TREE (subTree), treeInboxItem);
1625   gtk_signal_connect (GTK_OBJECT (treeInboxItem), "select",
1626                       GTK_SIGNAL_FUNC (SelectTreeItem), GINT_TO_POINTER (0));
1627   gtk_widget_show (treeInboxItem);
1628
1629   treeOutboxItem = gtk_tree_item_new_with_label (_("Outbox"));
1630   gtk_tree_append (GTK_TREE (subTree), treeOutboxItem);
1631   gtk_signal_connect (GTK_OBJECT (treeOutboxItem), "select",
1632                       GTK_SIGNAL_FUNC (SelectTreeItem), GINT_TO_POINTER (1));
1633   gtk_widget_show (treeOutboxItem);
1634
1635   scrolledWindow = gtk_scrolled_window_new (NULL, NULL);
1636   gtk_widget_set_usize (scrolledWindow, 75, 80);
1637   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledWindow),
1638                                   GTK_POLICY_AUTOMATIC,
1639                                   GTK_POLICY_AUTOMATIC);
1640
1641   gtk_paned_add1 (GTK_PANED (hpaned), scrolledWindow);
1642
1643   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolledWindow),
1644                                          tree);
1645   gtk_widget_show (scrolledWindow);
1646
1647
1648   /* Message viewer */
1649   SMS.smsText = gtk_text_new (NULL, NULL);
1650   gtk_text_set_editable (GTK_TEXT (SMS.smsText), FALSE);
1651   gtk_text_set_word_wrap (GTK_TEXT (SMS.smsText), TRUE);
1652   //gtk_text_set_line_wrap (GTK_TEXT (SMS.smsText), TRUE);
1653
1654   scrolledWindow = gtk_scrolled_window_new (NULL, NULL);
1655   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledWindow),
1656                                   GTK_POLICY_NEVER,
1657                                   GTK_POLICY_AUTOMATIC);
1658
1659   gtk_paned_add2 (GTK_PANED (hpaned), scrolledWindow);
1660
1661   gtk_container_add (GTK_CONTAINER (scrolledWindow), SMS.smsText);
1662   gtk_widget_show_all (scrolledWindow);
1663
1664   /* Messages list */
1665   SMS.smsClist = gtk_clist_new_with_titles (4, titles);
1666   gtk_clist_set_shadow_type (GTK_CLIST (SMS.smsClist), GTK_SHADOW_OUT);
1667   gtk_clist_set_compare_func (GTK_CLIST (SMS.smsClist), CListCompareFunc);
1668   gtk_clist_set_sort_column (GTK_CLIST (SMS.smsClist), 1);
1669   gtk_clist_set_sort_type (GTK_CLIST (SMS.smsClist), GTK_SORT_ASCENDING);
1670   gtk_clist_set_auto_sort (GTK_CLIST (SMS.smsClist), FALSE);
1671   gtk_clist_set_selection_mode (GTK_CLIST (SMS.smsClist), GTK_SELECTION_EXTENDED);
1672
1673   gtk_clist_set_column_width (GTK_CLIST (SMS.smsClist), 0, 40);
1674   gtk_clist_set_column_width (GTK_CLIST (SMS.smsClist), 1, 142);
1675   gtk_clist_set_column_width (GTK_CLIST (SMS.smsClist), 2, 135);
1676   //gtk_clist_set_column_justification (GTK_CLIST (SMS.smsClist), 2, GTK_JUSTIFY_CENTER);
1677
1678   for (i = 0; i < 4; i++)
1679   {
1680     if ((sColumn = g_malloc (sizeof (SortColumn))) == NULL)
1681     {
1682       g_print (_("Error: %s: line %d: Can't allocate memory!\n"), __FILE__, __LINE__);
1683       gtk_main_quit ();
1684     }
1685     sColumn->clist = SMS.smsClist;
1686     sColumn->column = i;
1687     gtk_signal_connect (GTK_OBJECT (GTK_CLIST (SMS.smsClist)->column[i].button), "clicked",
1688                         GTK_SIGNAL_FUNC (SetSortColumn), (gpointer) sColumn);
1689   }
1690
1691   gtk_signal_connect (GTK_OBJECT (SMS.smsClist), "select_row",
1692                       GTK_SIGNAL_FUNC (ClickEntry), NULL);
1693
1694   scrolledWindow = gtk_scrolled_window_new (NULL, NULL);
1695   gtk_widget_set_usize (scrolledWindow, 550, 100);
1696   gtk_container_add (GTK_CONTAINER (scrolledWindow), SMS.smsClist);
1697   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledWindow),
1698                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1699
1700   gtk_paned_add2 (GTK_PANED (vpaned), scrolledWindow);
1701
1702   gtk_widget_show (SMS.smsClist);
1703   gtk_widget_show (scrolledWindow);
1704
1705   CreateErrorDialog (&errorDialog, GUI_SMSWindow);
1706   CreateInfoDialog (&infoDialog, GUI_SMSWindow);
1707
1708   gtk_signal_emit_by_name(GTK_OBJECT (treeSMSItem), "expand");
1709
1710   cmap = gdk_colormap_get_system();
1711   SMS.colour.red = 0xffff;
1712   SMS.colour.green = 0;
1713   SMS.colour.blue = 0;
1714   if (!gdk_color_alloc (cmap, &(SMS.colour)))
1715     g_error (_("couldn't allocate colour"));
1716
1717   questMark.pixmap = gdk_pixmap_create_from_xpm_d (GUI_SMSWindow->window,
1718                          &questMark.mask,
1719                          &GUI_SMSWindow->style->bg[GTK_STATE_NORMAL],
1720                          quest_xpm);
1721
1722   GUIEventAdd (GUI_EVENT_SMS_CENTERS_CHANGED, GUI_RefreshSMSCenterMenu);
1723   GUIEventAdd (GUI_EVENT_SMS_NUMBER_CHANGED, GUI_RefreshMessageWindow);
1724 }