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