Implemented connection type "tcp" (GCT_TCP), use <hostname>:<port> as "port"
[gnokii.git] / xgnokii / xgnokii_common.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: Mon May 01 2000
12   Modified by Jan Derfinak
13
14 */
15
16 #ifndef WIN32
17 # include <unistd.h>
18 # include <sys/types.h>
19 # include <sys/wait.h>
20 # include <signal.h>
21 #endif
22 #include <string.h>
23 #include <gtk/gtk.h>
24 #include "misc.h"  /* for _() */
25 #include "xgnokii_common.h"
26 #include "xgnokii.h"
27 #include "xpm/quest.xpm"
28 #include "xpm/stop.xpm"
29 #include "xpm/info.xpm"
30
31
32 typedef struct {
33   GUIEventType type;
34   void (*func)(void);
35 } GUIEvent;
36
37 static GSList *guiEvents = NULL;
38
39
40 inline void DeleteEvent (const GtkWidget *widget, const GdkEvent *event, const gpointer data)
41 {
42   gtk_widget_hide (GTK_WIDGET (widget));
43 }
44
45
46 inline void CancelDialog (const GtkWidget *widget, const gpointer data)
47 {
48   gtk_widget_hide (GTK_WIDGET (data));
49 }
50
51
52 void CreateErrorDialog (ErrorDialog *errorDialog, GtkWidget *window)
53 {
54   GtkWidget *button, *hbox, *pixmap;
55
56   errorDialog->dialog = gtk_dialog_new ();
57   gtk_window_set_title (GTK_WINDOW (errorDialog->dialog), _("Error"));
58   gtk_window_set_modal (GTK_WINDOW (errorDialog->dialog), TRUE);
59   gtk_window_position (GTK_WINDOW (errorDialog->dialog), GTK_WIN_POS_MOUSE);
60   gtk_container_set_border_width (GTK_CONTAINER (errorDialog->dialog), 5);
61   gtk_signal_connect (GTK_OBJECT (errorDialog->dialog), "delete_event",
62                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
63
64   button = gtk_button_new_with_label (_("Cancel"));
65   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (errorDialog->dialog)->action_area),
66                       button, FALSE, FALSE, 0);
67   gtk_signal_connect (GTK_OBJECT (button), "clicked",
68                       GTK_SIGNAL_FUNC (CancelDialog), (gpointer) errorDialog->dialog);
69   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
70   gtk_widget_grab_default (button);
71   gtk_widget_show (button);
72
73   hbox = gtk_hbox_new (FALSE, 0);
74   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (errorDialog->dialog)->vbox), hbox);
75   gtk_widget_show (hbox);
76
77   if (window)
78   {
79     pixmap = NewPixmap (stop_xpm, window->window,
80                         &window->style->bg[GTK_STATE_NORMAL]);
81     gtk_box_pack_start (GTK_BOX(hbox), pixmap, FALSE, FALSE, 10);
82     gtk_widget_show (pixmap);
83   }
84
85   errorDialog->text = gtk_label_new ("");
86   gtk_box_pack_start (GTK_BOX(hbox), errorDialog->text, FALSE, FALSE, 10);
87   gtk_widget_show (errorDialog->text);
88 }
89
90
91 void CreateInfoDialog (InfoDialog *infoDialog, GtkWidget *window)
92 {
93   GtkWidget *hbox, *pixmap;
94
95   infoDialog->dialog = gtk_dialog_new ();
96   gtk_window_set_title (GTK_WINDOW (infoDialog->dialog), _("Info"));
97   gtk_window_set_modal (GTK_WINDOW (infoDialog->dialog), TRUE);
98   gtk_window_position (GTK_WINDOW (infoDialog->dialog), GTK_WIN_POS_MOUSE);
99   gtk_container_set_border_width (GTK_CONTAINER (infoDialog->dialog), 5);
100   gtk_signal_connect (GTK_OBJECT (infoDialog->dialog), "delete_event",
101                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
102
103   hbox = gtk_hbox_new (FALSE, 0);
104   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (infoDialog->dialog)->vbox), hbox);
105   gtk_widget_show_now (hbox);
106   
107   if (window)
108   {
109     pixmap = NewPixmap (info_xpm, window->window,
110                         &window->style->bg[GTK_STATE_NORMAL]);
111     gtk_box_pack_start (GTK_BOX(hbox), pixmap, FALSE, FALSE, 10);
112     gtk_widget_show_now (pixmap);
113   }
114
115   infoDialog->text = gtk_label_new ("");
116   gtk_box_pack_start (GTK_BOX(hbox), infoDialog->text, FALSE, FALSE, 10);
117   gtk_widget_show_now (infoDialog->text);
118 }
119
120
121 void CreateYesNoDialog (YesNoDialog *yesNoDialog, const GtkSignalFunc yesFunc,
122                         const GtkSignalFunc noFunc, GtkWidget *window)
123 {
124   GtkWidget *button, *hbox, *pixmap;
125
126   yesNoDialog->dialog = gtk_dialog_new ();
127   gtk_window_position (GTK_WINDOW (yesNoDialog->dialog), GTK_WIN_POS_MOUSE);
128   gtk_window_set_modal (GTK_WINDOW (yesNoDialog->dialog), TRUE);
129   gtk_container_set_border_width (GTK_CONTAINER (yesNoDialog->dialog), 5);
130   gtk_signal_connect (GTK_OBJECT (yesNoDialog->dialog), "delete_event",
131                       GTK_SIGNAL_FUNC (DeleteEvent), NULL);
132
133
134   button = gtk_button_new_with_label (_("Yes"));
135   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (yesNoDialog->dialog)->action_area),
136                       button, FALSE, TRUE, 0);
137   gtk_signal_connect (GTK_OBJECT (button), "clicked",
138                       GTK_SIGNAL_FUNC (yesFunc), (gpointer) yesNoDialog->dialog);
139   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);                               
140   gtk_widget_grab_default (button);
141   gtk_widget_show (button);
142
143   button = gtk_button_new_with_label (_("No"));
144   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (yesNoDialog->dialog)->action_area),
145                       button, FALSE, TRUE, 0);
146   gtk_signal_connect (GTK_OBJECT (button), "clicked",
147                       GTK_SIGNAL_FUNC (noFunc), (gpointer) yesNoDialog->dialog);
148   gtk_widget_show (button);
149
150   button = gtk_button_new_with_label (_("Cancel"));
151   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (yesNoDialog->dialog)->action_area),
152                       button, FALSE, TRUE, 0);
153   gtk_signal_connect (GTK_OBJECT (button), "clicked",
154                       GTK_SIGNAL_FUNC (CancelDialog), (gpointer) yesNoDialog->dialog);
155   gtk_widget_show (button);
156
157   hbox = gtk_hbox_new (FALSE, 0);
158   gtk_container_add (GTK_CONTAINER (GTK_DIALOG (yesNoDialog->dialog)->vbox), hbox);
159   gtk_widget_show (hbox);
160   
161   if (window)
162   {
163     pixmap = NewPixmap (quest_xpm, window->window,
164                         &window->style->bg[GTK_STATE_NORMAL]);
165     gtk_box_pack_start (GTK_BOX (hbox), pixmap, FALSE, FALSE, 10);
166     gtk_widget_show (pixmap);
167   }
168
169   yesNoDialog->text = gtk_label_new ("");
170   gtk_box_pack_start (GTK_BOX (hbox), yesNoDialog->text, FALSE, FALSE, 10);
171   gtk_widget_show (yesNoDialog->text);
172 }
173
174
175 GtkWidget* NewPixmap (gchar **data, GdkWindow *window, GdkColor *background)
176 {
177   GtkWidget *wpixmap;
178   GdkPixmap *pixmap;
179   GdkBitmap *mask;
180
181   pixmap = gdk_pixmap_create_from_xpm_d (window, &mask, background, data);
182
183   wpixmap = gtk_pixmap_new (pixmap, mask);
184
185   return wpixmap;
186 }
187
188
189 gint LaunchProcess (const gchar *p, const gchar *arg, const gint infile,
190                     const gint outfile, const gint errfile)
191 {
192   pid_t pid;
193
194   if (p == 0)
195     return (1);
196   pid = fork ();
197   if (pid == -1)
198     return (-1);
199   if (pid == 0)
200   {
201     pid = getpid ();
202     setpgid (pid, pid);
203     if (getuid () != geteuid ())
204       seteuid (getuid ());
205
206     signal (SIGINT, SIG_DFL);
207     signal (SIGQUIT, SIG_DFL);
208     signal (SIGTSTP, SIG_DFL);
209     signal (SIGTTIN, SIG_DFL);
210     signal (SIGTTOU, SIG_DFL);
211     signal (SIGCHLD, SIG_DFL);
212
213     if (infile != STDIN_FILENO)
214     {
215       dup2 (infile, STDIN_FILENO);
216       close (infile);
217     }
218     if (outfile != STDOUT_FILENO)
219     {
220       dup2 (outfile, STDOUT_FILENO);
221       close (outfile);
222     }
223     if (errfile != STDERR_FILENO)
224     {
225       dup2 (errfile, STDERR_FILENO);
226       close (errfile);
227     }
228
229     execlp (p, p, arg, NULL);
230     g_print (_("Can't exec %s\n"), p);
231     execlp ("/bin/false", p, NULL);
232     return (-1);
233   }
234
235   setpgid (pid, pid);
236   return (0);
237 }
238
239
240 void RemoveZombie (const gint sign)
241 {
242   gint status;
243
244   wait (&status);
245 }
246
247
248 void Help (const GtkWidget *w, const gpointer data)
249 {
250   gchar buf[255] = "file:";
251
252   strncat (buf, xgnokiiConfig.xgnokiidir, 255 - strlen (buf));
253   buf[254] = '\0';
254   strncat (buf, (gchar *) data, 255 - strlen (buf));
255   buf[254] = '\0';
256   LaunchProcess (xgnokiiConfig.helpviewer, buf, STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO);
257 }
258
259
260 inline gint strrncmp (const gchar * const s1, const gchar * const s2, size_t n)
261 {
262   gint l1 = strlen (s1);
263   gint l2 = strlen (s2);
264
265   if (l1 == 0 && l2 != 0)
266     return (-1);
267   else if (l1 != 0 && l2 == 0)
268     return (1);
269
270   while (l1-- > 0 && l2-- > 0 && n-- > 0)
271   {
272     if (s1[l1] < s2[l2])
273       return (-1);
274     else if (s1[l1] > s2[l2])
275       return (1);
276   }
277
278   return (0);
279 }
280
281
282 inline void GUI_Refresh (void)
283 {
284   while (gtk_events_pending())
285     gtk_main_iteration();
286 }
287
288
289 inline void SetSortColumn (GtkWidget *widget, SortColumn *data)
290 {
291   gtk_clist_set_sort_column (GTK_CLIST (data->clist), data->column);
292   gtk_clist_sort (GTK_CLIST (data->clist));
293 }
294
295
296 inline void GUIEventAdd (GUIEventType type, void (*func)(void))
297 {
298   GUIEvent *event = g_malloc (sizeof (GUIEvent));
299   
300   event->type = type;
301   event->func = func;
302   
303   guiEvents = g_slist_append (guiEvents, event);
304 }
305
306
307 bool GUIEventRemove (GUIEventType type, void (*func)(void))
308 {
309   GUIEvent event;
310   GSList *list;
311   
312   event.type = type;
313   event.func = func;
314   
315   list = g_slist_find (guiEvents, &event);
316   if (list)
317   {
318     g_print ("Nasiel som\n");
319     guiEvents = g_slist_remove_link (guiEvents, list);
320     g_slist_free_1 (list);
321     return (TRUE);
322   }
323   
324   return (FALSE);
325 }
326
327 static inline void CallEvent (gpointer data, gpointer user_data)
328 {
329   GUIEvent *event = (GUIEvent *) data;
330   
331   if (event->type == GPOINTER_TO_INT (user_data))
332     event->func ();
333 }
334
335 inline void GUIEventSend (GUIEventType type)
336 {
337   g_slist_foreach (guiEvents, CallEvent, GINT_TO_POINTER (type));
338 }