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