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