1 /*
2  * Callback functions for Xdialog.
3  */
4 
5 #ifdef HAVE_CONFIG_H
6 #  include <config.h>
7 #endif
8 
9 #include <stdio.h>
10 #ifdef STDC_HEADERS
11 #	include <stdlib.h>
12 #	include <string.h>
13 #endif
14 #ifdef HAVE_UNISTD_H
15 #	include <unistd.h>
16 #endif
17 #include <time.h>
18 
19 #include <gtk/gtk.h>
20 #include <gdk/gdkkeysyms.h>
21 
22 #include "callbacks.h"
23 #include "interface.h"
24 #include "support.h"
25 
26 extern Xdialog_data Xdialog;
27 
28 /* This function is called when a "delete_event" is received from the window
29  * manager. It is used to trigger a "destroy" event by returning FALSE
30  * (provided the "--no-close" option was not given).
31  */
delete_event(gpointer object,GdkEventAny * event,gpointer data)32 gboolean delete_event(gpointer object, GdkEventAny *event, gpointer data)
33 {
34 	return Xdialog.no_close;
35 }
36 
37 /* This function is called when a "destroy" event is received
38  * by the top level window.
39  */
destroy_event(gpointer object,GdkEventAny * event,gpointer data)40 gboolean destroy_event(gpointer object, GdkEventAny *event, gpointer data)
41 {
42 	if (Xdialog.timer != 0) {
43 		gtk_timeout_remove(Xdialog.timer);
44 		Xdialog.timer = 0;
45 	}
46 	if (Xdialog.timer2 != 0) {
47 		gtk_timeout_remove(Xdialog.timer2);
48 		Xdialog.timer2 = 0;
49 	}
50 	gtk_main_quit();
51 	Xdialog.window = Xdialog.widget1 = Xdialog.widget2 = Xdialog.widget3 = NULL;
52 
53 	if (Xdialog.file != NULL) {
54 		if (Xdialog.file != stdin)
55 			fclose(Xdialog.file);
56 		Xdialog.file = NULL;
57 	}
58 	if (Xdialog.array != NULL) {
59 		g_free(Xdialog.array);
60 		Xdialog.array = NULL;
61 	}
62 
63 	if (Xdialog.beep & BEEP_AFTER && Xdialog.exit_code != 2)
64 		gdk_beep();
65 
66 	return FALSE;
67 }
68 
69 /* These are the normal termination callback routines that are used by the
70  * OK, Cancel and Help buttons. They set the exit_code global variable (for
71  * use as the exit() parameter by main.c), and then call the destroy_event
72  * function that will cleanup everything, destroy the top level window and
73  * set the gtk main loop exit flag. They are used "as is" by most Xdialog
74  * widgets but care must be taken that they are connected with the
75  * gtk_signal_connect_after() function so that any other signal callbacks
76  * are executed BEFORE them (after them, the widget does not exists anymore).
77  */
exit_ok(gpointer object,gpointer data)78 gboolean exit_ok(gpointer object, gpointer data)
79 {
80 	if (Xdialog.check) {
81 		if (Xdialog.checked)
82 			fprintf(Xdialog.output, "checked\n");
83 		else
84 			fprintf(Xdialog.output, "unchecked\n");
85 	}
86 	gtk_widget_destroy(Xdialog.window);
87 	Xdialog.exit_code = 0;
88 	return FALSE;
89 }
90 
exit_cancel(gpointer object,gpointer data)91 gboolean exit_cancel(gpointer object, gpointer data)
92 {
93 	Xdialog.exit_code = 1;
94 	gtk_widget_destroy(Xdialog.window);
95 	return FALSE;
96 }
97 
exit_keypress(gpointer object,GdkEventKey * event,gpointer data)98 gint exit_keypress(gpointer object, GdkEventKey *event, gpointer data)
99 {
100 	if (event->type == GDK_KEY_PRESS && (event->keyval == GDK_Escape)) {
101 		return exit_cancel(object, data);
102 	}
103 	return TRUE;
104 }
105 
exit_help(gpointer object,gpointer data)106 gboolean exit_help(gpointer object, gpointer data)
107 {
108 	Xdialog.exit_code = 2;
109 	gtk_widget_destroy(Xdialog.window);
110 	return FALSE;
111 }
112 
exit_previous(gpointer object,gpointer data)113 gboolean exit_previous(gpointer object, gpointer data)
114 {
115 	Xdialog.exit_code = 3;
116 	gtk_widget_destroy(Xdialog.window);
117 	return FALSE;
118 }
119 
checked(GtkObject * button,gpointer data)120 gboolean checked(GtkObject *button, gpointer data)
121 {
122 	Xdialog.checked = GTK_TOGGLE_BUTTON(button)->active;
123 	return TRUE;
124 }
125 
timeout_exit(gpointer data)126 gboolean timeout_exit(gpointer data)
127 {
128 	Xdialog.exit_code = 255;
129 	gtk_widget_destroy(Xdialog.window);
130 	return FALSE;
131 }
132 
133 /* This function is called within the timeout functions so to force
134  * the processing of all queued GTK events.
135  */
empty_gtk_queue(void)136 gboolean empty_gtk_queue(void)
137 {
138 	while(gtk_events_pending()) {
139 		gtk_main_iteration();
140 		/* If the timeout function has been removed, return immediately */
141 		if (Xdialog.timer == 0)
142 			return FALSE;
143 	}
144 	/* All events have been taken into account... */
145 	return TRUE;
146 }
147 
148 /* infobox callbacks: the infobox_timeout_exit() is responsible for
149  * closing the infobox once the timeout is over (it therefore calls
150  * exit_ok()). The infobox_timeout() function is responsible for
151  * reading the stdin and changing the infobox label and/or exiting the
152  * infobox by calling exit_ok().
153  */
154 
infobox_timeout_exit(gpointer data)155 gboolean infobox_timeout_exit(gpointer data)
156 {
157 	return exit_ok(NULL, NULL);
158 }
159 
infobox_timeout(gpointer data)160 gboolean infobox_timeout(gpointer data)
161 {
162 	char temp[256];
163 	int ret;
164 
165 	if (!empty_gtk_queue())
166 		return FALSE;
167 
168 	/* Read the the data from stdin */
169 #ifdef USE_SCANF
170 	ret = scanf("%255s", temp);
171 #else
172 	ret = my_scanf(temp);
173 #endif
174 	if ((ret == EOF && !Xdialog.ignore_eof) || (strcmp(temp, "XXXX") == 0))
175 		return exit_ok(NULL, NULL);
176 	if (ret != 1)
177 		return TRUE;
178 
179 	if (strcmp(temp, "XXX") == 0) {
180 		/* If this is a new label delimiter, then check to see if it's the
181 		 * start or the end of the label. */
182 		if (Xdialog.new_label) {
183 			gtk_label_set_text(GTK_LABEL(Xdialog.widget1),
184 					   Xdialog.label_text);
185 			Xdialog.label_text[0] = 0 ;
186 			Xdialog.new_label = FALSE;
187 		} else {
188 			Xdialog.new_label = TRUE;
189 		}
190 	} else {
191 		/* Add this text to the new label text */
192 		if (strlen(Xdialog.label_text)+strlen(temp)+2 < MAX_LABEL_LENGTH) {
193 			if (strcmp(temp, "\\n") == 0) {
194 				strcat(Xdialog.label_text, "\n");
195 			} else {
196 				strcat(Xdialog.label_text, " ");
197 				strcat(Xdialog.label_text, temp);
198 			}
199 		}
200 	}
201 
202 	/* As this is a timeout function, return TRUE so that it
203 	 * continues to get called */
204 	return TRUE;
205 }
206 
207 /* gauge timeout callback */
208 
gauge_timeout(gpointer data)209 gboolean gauge_timeout(gpointer data)
210 {
211 	gfloat new_val;
212 	GtkAdjustment *adj;
213 	char temp[256];
214 	int ret;
215 
216 	if (!empty_gtk_queue())
217 		return FALSE;
218 
219 	/* Read the new progress bar value or the new label from stdin */
220 #ifdef USE_SCANF
221 	ret = scanf("%255s", temp);
222 #else
223 	ret = my_scanf(temp);
224 #endif
225 	if (ret == EOF && !Xdialog.ignore_eof)
226 		return exit_ok(NULL, NULL);
227 	if (ret != 1)
228 		return TRUE;
229 
230 	if (!Xdialog.new_label && strcmp(temp, "XXX")) {
231 		/* Try to convert the string into an integer for use as the new
232 	 	 * progress bar value... */
233 		new_val = (gfloat) atoi(temp);
234 		adj = GTK_PROGRESS(Xdialog.widget1)->adjustment;
235 		if ((new_val > adj->upper) || (new_val < adj->lower))
236 			return exit_ok(NULL, NULL);
237 		/* Set the new value */
238 		gtk_progress_set_value(GTK_PROGRESS(Xdialog.widget1), new_val);
239 	} else {
240 		if (strcmp(temp, "XXX") == 0) {
241 			/* If this is a new label delimiter, then check to see if it's the
242 			 * start or the end of the label. */
243 			if (Xdialog.new_label) {
244 				gtk_label_set_text(GTK_LABEL(Xdialog.widget2),
245 						   Xdialog.label_text);
246 				Xdialog.label_text[0] = 0 ;
247 				Xdialog.new_label = FALSE;
248 			} else {
249 				Xdialog.new_label = TRUE;
250 			}
251 		} else {
252 			/* Add this text to the new label text */
253 			if (strlen(Xdialog.label_text)+strlen(temp)+2 < MAX_LABEL_LENGTH) {
254 				if (strcmp(temp, "\\n") == 0) {
255 					strcat(Xdialog.label_text, "\n");
256 				} else {
257 					strcat(Xdialog.label_text, " ");
258 					strcat(Xdialog.label_text, temp);
259 				}
260 			}
261 		}
262 	}
263 
264 	/* As this is a timeout function, return TRUE so that it
265 	 * continues to get called */
266 	return TRUE;
267 }
268 
269 /* progress timeout callback */
270 
progress_timeout(gpointer data)271 gboolean progress_timeout(gpointer data)
272 {
273 	gfloat new_val;
274 	GtkAdjustment *adj;
275 	char temp[256];
276 	int ret;
277 
278 	if (!empty_gtk_queue())
279 		return FALSE;
280 
281 	adj = GTK_PROGRESS(Xdialog.widget1)->adjustment;
282 
283 	temp[255] = '\0';
284 
285 	/* Read the new progress bar value or the new "dot" from stdin,
286 	 * skipping any control character.
287 	 */
288 	do {
289 		ret = fgetc(stdin);
290 		if (ret == EOF)
291 			return exit_ok(NULL, NULL);
292 		temp[0] = (char) ret;
293 	} while (temp[0] <= ' ');
294 
295 	if (temp[0] >= '0' && temp[0] <= '9') {
296 		/* Get and convert a string into an integer for use as
297 		 * the new progress bar value... */
298 		ret = scanf("%254s", temp + 1);
299 		if (ret == EOF)
300 			return exit_ok(NULL, NULL);
301 		if (ret != 1)
302 			return TRUE;
303 		new_val = (gfloat) atoi(temp);
304 	} else {
305 		/* Increment the number of "dots" */
306 		new_val = adj->value + 1;
307 	}
308 
309 	if ((new_val > adj->upper) || (new_val < adj->lower))
310 		return exit_ok(NULL, NULL);
311 	/* Set the new value */
312 	gtk_progress_set_value(GTK_PROGRESS(Xdialog.widget1), new_val);
313 
314 	/* As this is a timeout function, return TRUE so that it
315 	 * continues to get called */
316 	return TRUE;
317 }
318 
319 /* tailbox and logbox callbacks */
320 
321 #ifdef USE_GTK2
tailbox_timeout(gpointer data)322 gboolean tailbox_timeout(gpointer data)
323 {
324 	gchar buffer[1024];
325 	int nchars = 0;
326 	GtkTextIter end_iter;
327 
328 	GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(Xdialog.widget1));
329 
330 	do {
331 		if (!empty_gtk_queue() && (Xdialog.file_init_size <= 0))
332 			return FALSE;
333 
334 		nchars = fread(buffer, sizeof(gchar), 1024, Xdialog.file);
335 		if (nchars == 0)
336 			break;
337 
338 		gtk_text_buffer_get_end_iter(text_buffer, &end_iter);
339 		gtk_text_buffer_insert(text_buffer, &end_iter, buffer, nchars);
340 
341 		if (Xdialog.file_init_size > 0)
342 			Xdialog.file_init_size -= nchars;
343 	} while (nchars == 1024);
344 
345 	if (nchars > 0) {
346 		GtkTextMark *mark;
347 		gtk_text_buffer_get_end_iter(text_buffer, &end_iter);
348 
349 		mark = gtk_text_buffer_create_mark(text_buffer, "end",
350 			&end_iter, TRUE);
351 
352 		gtk_text_view_scroll_to_mark(GTK_TEXT_VIEW(Xdialog.widget1),
353 			mark, 0, FALSE, 0, 0);
354 	}
355 
356 	return TRUE;
357 }
358 #else
tailbox_timeout(gpointer data)359 gboolean tailbox_timeout(gpointer data)
360 {
361 	GtkAdjustment *adj;
362 	gchar buffer[1024];
363 	int nchars;
364 	gboolean flag = FALSE;
365 
366 	adj = GTK_TEXT(Xdialog.widget1)->vadj;
367 
368 	if (Xdialog.file_init_size > 0)
369 		gtk_text_freeze(GTK_TEXT(Xdialog.widget1));
370 
371 	do {
372 		if (!empty_gtk_queue() && (Xdialog.file_init_size <= 0))
373 			return FALSE;
374 
375 		nchars = fread(buffer, sizeof(gchar), 1024, Xdialog.file);
376 
377 		if (nchars == 0)
378 			break;
379 
380 		if (Xdialog.file_init_size > 0) {
381 			Xdialog.file_init_size -= nchars;
382 			if (Xdialog.file_init_size <= 0)
383 				flag = TRUE;
384 		} else {
385 			if (!Xdialog.smooth)
386 				gtk_text_freeze(GTK_TEXT(Xdialog.widget1));
387 		}
388 
389 		gtk_text_insert(GTK_TEXT(Xdialog.widget1), NULL, NULL,
390 				NULL, buffer, nchars);
391 
392 		if ((!Xdialog.smooth || flag) && Xdialog.file_init_size <= 0) {
393 			gtk_text_thaw(GTK_TEXT(Xdialog.widget1));
394 			flag = FALSE;
395 		}
396 
397 		gtk_adjustment_set_value(adj, adj->upper);
398 
399 	} while (nchars == 1024);
400 
401 	return TRUE;
402 }
403 #endif
404 
tailbox_keypress(GtkObject * text,GdkEventKey * event,gpointer data)405 gint tailbox_keypress(GtkObject *text, GdkEventKey *event,
406 		      gpointer data)
407 {
408 	if (event->type == GDK_KEY_PRESS && (event->keyval == GDK_Return ||
409 					     event->keyval == GDK_KP_Enter)) {
410 		if (Xdialog.default_no)
411 			Xdialog.exit_code = 1;
412 		else
413 			Xdialog.exit_code = 0;
414 
415 		return(FALSE);
416 	}
417 	return(TRUE);
418 }
419 
420 #ifdef HAVE_STRSTR
421 
vt_to_gdk_color(gint color,GdkColor ** fgcolor,GdkColor ** bgcolor)422 static void vt_to_gdk_color(gint color, GdkColor **fgcolor, GdkColor **bgcolor)
423 {
424 	static const GdkColor BLACK     = { 0, 0x0000, 0x0000, 0x0000 };
425 	static const GdkColor RED       = { 0, 0xffff, 0x0000, 0x0000 };
426 	static const GdkColor GREEN     = { 0, 0x0000, 0xffff, 0x0000 };
427 	static const GdkColor BLUE      = { 0, 0x0000, 0x0000, 0xffff };
428 	static const GdkColor MAGENTA   = { 0, 0xffff, 0x0000, 0xffff };
429 	static const GdkColor YELLOW    = { 0, 0xffff, 0xffff, 0x0000 };
430 	static const GdkColor CYAN      = { 0, 0x0000, 0xffff, 0xffff };
431 	static const GdkColor WHITE     = { 0, 0xffff, 0xffff, 0xffff };
432 
433 	switch (color) {
434 		case 30:
435 			*fgcolor = (GdkColor *) &BLACK;
436 			break;
437 		case 31:
438 			*fgcolor = (GdkColor *) &RED;
439 			break;
440 		case 32:
441 			*fgcolor = (GdkColor *) &GREEN;
442 			break;
443 		case 33:
444 			*fgcolor = (GdkColor *) &YELLOW;
445 			break;
446 		case 34:
447 			*fgcolor = (GdkColor *) &BLUE;
448 			break;
449 		case 35:
450 			*fgcolor = (GdkColor *) &MAGENTA;
451 			break;
452 		case 36:
453 			*fgcolor = (GdkColor *) &CYAN;
454 			break;
455 		case 37:
456 			*fgcolor = (GdkColor *) &WHITE;
457 			break;
458 		case 38:
459 			*fgcolor = NULL;
460 			break;
461 		case 40:
462 			*bgcolor = (GdkColor *) &BLACK;
463 			break;
464 		case 41:
465 			*bgcolor = (GdkColor *) &RED;
466 			break;
467 		case 42:
468 			*bgcolor = (GdkColor *) &GREEN;
469 			break;
470 		case 43:
471 			*bgcolor = (GdkColor *) &YELLOW;
472 			break;
473 		case 44:
474 			*bgcolor = (GdkColor *) &BLUE;
475 			break;
476 		case 45:
477 			*bgcolor = (GdkColor *) &MAGENTA;
478 			break;
479 		case 46:
480 			*bgcolor = (GdkColor *) &CYAN;
481 			break;
482 		case 47:
483 			*bgcolor = (GdkColor *) &WHITE;
484 			break;
485 		case 48:
486 			*bgcolor = NULL;
487 			break;
488 	}
489 }
490 
remove_vt_sequences(char * str)491 static void remove_vt_sequences(char *str)
492 {
493 	char *p, *q;
494 
495 	while ((p = strstr(str, "\033[")) != NULL) {
496 		q = p;
497 		while (++p < str + strlen(str)) {
498 			if (*p == 'm')
499 				break;
500 		}
501 		strcpy(q, ++p);
502 	}
503 }
504 
505 static GdkColor *old_fgcolor = NULL;
506 static GdkColor *old_bgcolor = NULL;
507 
logbox_timeout(gpointer data)508 gboolean logbox_timeout(gpointer data)
509 {
510 	GtkCList *clist = GTK_CLIST(Xdialog.widget1);
511 	GdkColor *fgcolor, *bgcolor;
512 	gchar buffer[MAX_LABEL_LENGTH], *p;
513 	static gchar *null_single_row[] = { NULL };
514 	static gchar *null_double_row[] = { NULL, NULL };
515 	gint rownum;
516 	int color, len;
517 	struct tm *localdate = NULL;
518 	time_t curr_time;
519 	gboolean flag = FALSE;
520 
521 	if (!Xdialog.smooth && (Xdialog.file_init_size > 0))
522 		gtk_clist_freeze(clist);
523 	else {
524 		if (!empty_gtk_queue())
525 			return FALSE;
526 	}
527 
528 	while (fgets(buffer, MAX_LABEL_LENGTH, Xdialog.file) != NULL) {
529 
530 		len = strlen(buffer);
531 
532 		if (Xdialog.file_init_size > 0) {
533 			Xdialog.file_init_size -= len;
534 			if (Xdialog.file_init_size <= 0)
535 				flag = TRUE;
536 		}
537 
538 		if ((len > 0) && (buffer[len - 1] == '\n'))
539 			buffer[--len] = 0;
540 
541 		if (Xdialog.time_stamp) {
542 			time(&curr_time);
543 			localdate = localtime(&curr_time);
544 		}
545 
546 		if (Xdialog.keep_colors) {
547 			fgcolor = old_fgcolor;
548 			bgcolor = old_bgcolor;
549 		} else
550 			fgcolor = bgcolor = NULL;
551 
552 		if ((p = strstr(buffer, "\033[1;")) != NULL) {
553 			p += 4;
554 			color = atoi(p);
555 			vt_to_gdk_color(color, &fgcolor, &bgcolor);
556 
557 			while (++p < buffer + len) {
558 				if (*p == ';') {
559 					color = atoi(++p);
560 					vt_to_gdk_color(color, &fgcolor, &bgcolor);
561 					p += 2;
562 				}
563 				if (*p == 'm')
564 					break;
565 			}
566 
567 			if (Xdialog.keep_colors) {
568 				old_fgcolor = fgcolor;
569 				old_bgcolor = bgcolor;
570 			}
571 
572 			remove_vt_sequences(buffer);
573 		}
574 
575 		if (Xdialog.reverse)
576 			rownum = gtk_clist_prepend(clist,
577 						   Xdialog.time_stamp ? null_double_row : null_single_row);
578 		else
579 			rownum = gtk_clist_append(clist,
580 						  Xdialog.time_stamp ? null_double_row : null_single_row);
581 		gtk_clist_set_selectable(clist, rownum, FALSE);
582 		if (fgcolor != NULL)
583 			gtk_clist_set_foreground(clist, rownum, fgcolor);
584 		if (bgcolor != NULL)
585 			gtk_clist_set_background(clist, rownum, bgcolor);
586 		if (Xdialog.time_stamp) {
587 			gtk_clist_set_text(clist, rownum, 1, buffer);
588 			if (Xdialog.date_stamp)
589 				sprintf(buffer, "%02d/%02d/%d %02d:%02d:%02d ",
590 					localdate->tm_mday, localdate->tm_mon+1, localdate->tm_year+1900,
591 					localdate->tm_hour, localdate->tm_min, localdate->tm_sec);
592 			else
593 				sprintf(buffer, "%02d:%02d:%02d",
594 					localdate->tm_hour, localdate->tm_min, localdate->tm_sec);
595 			gtk_clist_set_text(clist, rownum, 0, buffer);
596 		} else
597 			gtk_clist_set_text(clist, rownum, 0, buffer);
598 		gtk_clist_columns_autosize(clist);
599 
600 		if ((Xdialog.file_init_size <= 0) || Xdialog.smooth) {
601 			if (flag) {
602 				gtk_clist_thaw(clist);
603 				flag = FALSE;
604 			}
605 
606 			if (Xdialog.reverse)
607 				gtk_clist_moveto(clist, rownum, 0, 0.0, 0.0);
608 			else
609 				gtk_clist_moveto(clist, rownum, 0, 1.0, 0.0);
610 		}
611 
612 		if (!empty_gtk_queue())
613 			return FALSE;
614 	}
615 
616 	return TRUE;
617 }
618 
619 #else
620 #error strstr() function is needed by Xdialog !
621 #endif
622 
623 /* Here are the callback functions for the inputboxes and combobox (OK button
624  * callback and entry RETURN/ENTER keypress callback).
625  */
inputbox_ok(gpointer object,gpointer data)626 gint inputbox_ok(gpointer object, gpointer data)
627 {
628 	fprintf(Xdialog.output, "%s",
629 		gtk_entry_get_text(GTK_ENTRY(Xdialog.widget1)));
630 	if (Xdialog.widget2 != NULL)
631 		fprintf(Xdialog.output, "%s%s", Xdialog.separator,
632 			gtk_entry_get_text(GTK_ENTRY(Xdialog.widget2)));
633 	if (Xdialog.widget3 != NULL)
634 		fprintf(Xdialog.output, "%s%s", Xdialog.separator,
635 			gtk_entry_get_text(GTK_ENTRY(Xdialog.widget3)));
636 	fprintf(Xdialog.output, "\n");
637 
638 	return TRUE;
639 }
640 
inputbox_timeout(gpointer data)641 gboolean inputbox_timeout(gpointer data)
642 {
643 	return inputbox_ok(NULL, NULL);
644 }
645 
646 
input_keypress(GtkObject * entry,GdkEventKey * event,gpointer data)647 gint input_keypress(GtkObject *entry, GdkEventKey *event, gpointer data)
648 {
649 	if (event->type == GDK_KEY_PRESS && (event->keyval == GDK_Return ||
650 					     event->keyval == GDK_KP_Enter)) {
651 		if (Xdialog.default_no) {
652 			Xdialog.exit_code = 1;
653 		} else {
654 			inputbox_ok(NULL, NULL);
655 			Xdialog.exit_code = 0;
656 		}
657 		if (Xdialog.check) {
658 			if (Xdialog.checked)
659 				fprintf(Xdialog.output, "checked\n");
660 			else
661 				fprintf(Xdialog.output, "unchecked\n");
662 		}
663 		gtk_widget_destroy(Xdialog.window);
664 		return FALSE;
665 	}
666 	return TRUE;
667 }
668 
hide_passwords(GtkObject * button,gpointer data)669 gboolean hide_passwords(GtkObject *button, gpointer data)
670 {
671 	gint entries;
672 	gboolean visible;
673 
674 	entries = 1 + (Xdialog.widget2 != NULL ? 1 : 0) + (Xdialog.widget3 != NULL ? 1 : 0);
675 
676 	visible = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)) == FALSE);
677 
678 	if ((Xdialog.passwd < 10 && Xdialog.passwd >= entries) || Xdialog.passwd == 11)
679 		gtk_entry_set_visibility(GTK_ENTRY(Xdialog.widget1), visible);
680 	if (entries > 1 && ((Xdialog.passwd < 10 && Xdialog.passwd >= entries-1) || Xdialog.passwd == 12))
681 		gtk_entry_set_visibility(GTK_ENTRY(Xdialog.widget2), visible);
682 	if (entries > 2 && ((Xdialog.passwd < 10 && Xdialog.passwd > 0) || Xdialog.passwd == 13))
683 		gtk_entry_set_visibility(GTK_ENTRY(Xdialog.widget3), visible);
684 
685 	return TRUE;
686 }
687 
688 /* editbox callback */
689 
690 #ifdef USE_GTK2
editbox_ok(gpointer object,gpointer data)691 gboolean editbox_ok(gpointer object, gpointer data)
692 {
693 	GtkTextIter start_iter, end_iter;
694 
695 	GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(Xdialog.widget1));
696 	gtk_text_buffer_get_bounds(text_buffer, &start_iter, &end_iter);
697 	fputs(gtk_text_buffer_get_text(text_buffer, &start_iter, &end_iter,
698 		FALSE), Xdialog.output);
699 
700 	return TRUE;
701 }
702 #else
editbox_ok(gpointer object,gpointer data)703 gboolean editbox_ok(gpointer object, gpointer data)
704 {
705 	int length, i;
706 
707 	length = gtk_text_get_length(GTK_TEXT(Xdialog.widget1));
708 	for (i = 0; i < length; i++)
709 		fputc(GTK_TEXT_INDEX(GTK_TEXT(Xdialog.widget1), i),
710 		      Xdialog.output);
711 
712 	return TRUE;
713 }
714 #endif
715 
716 /* The print button callback (used by editbox, textbox and tailbox) */
717 
718 #ifdef USE_GTK2
print_text(gpointer object,gpointer data)719 gboolean print_text(gpointer object, gpointer data)
720 {
721 	gint length;
722 	char cmd[MAX_PRTCMD_LENGTH];
723 	FILE * temp;
724 	GtkTextIter start_iter, end_iter;
725 	GtkTextBuffer *text_buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(Xdialog.widget1));
726 
727 	gtk_text_buffer_get_bounds(text_buffer, &start_iter, &end_iter);
728 
729 	strcpysafe(cmd, PRINTER_CMD, MAX_PRTCMD_LENGTH);
730 	if (strlen(Xdialog.printer) != 0) {
731 		strcatsafe(cmd, " "PRINTER_CMD_OPTION, MAX_PRTCMD_LENGTH);
732 		strcatsafe(cmd, Xdialog.printer, MAX_PRTCMD_LENGTH);
733 	}
734 
735 	length = gtk_text_buffer_get_char_count(text_buffer);
736 
737 	temp = popen(cmd, "w");
738 	if (temp != NULL) {
739 		fwrite(gtk_text_buffer_get_text(text_buffer, &start_iter,
740 			&end_iter, FALSE), sizeof(gchar), length, temp);
741 		pclose(temp);
742 	}
743 
744 	return TRUE;
745 }
746 #else
print_text(gpointer object,gpointer data)747 gboolean print_text(gpointer object, gpointer data)
748 {
749 	int length, i;
750 	gchar * buffer;
751 	char cmd[MAX_PRTCMD_LENGTH];
752 	FILE * temp;
753 
754 	strcpysafe(cmd, PRINTER_CMD, MAX_PRTCMD_LENGTH);
755 	if (strlen(Xdialog.printer) != 0) {
756 		strcatsafe(cmd, " "PRINTER_CMD_OPTION, MAX_PRTCMD_LENGTH);
757 		strcatsafe(cmd, Xdialog.printer, MAX_PRTCMD_LENGTH);
758 	}
759 
760 	length = gtk_text_get_length(GTK_TEXT(Xdialog.widget1));
761 	buffer = g_malloc((length+1)*sizeof(gchar));
762 	for (i = 0; i < length; i++)
763 		buffer[i] = GTK_TEXT_INDEX(GTK_TEXT(Xdialog.widget1), i);
764 
765 	temp = popen(cmd, "w");
766 	if (temp != NULL) {
767 		i = fwrite(buffer, sizeof(gchar), length, temp);
768 		pclose(temp);
769 	}
770 	g_free(buffer);
771 
772 	return TRUE;
773 }
774 #endif
775 
776 /* rangebox callbacks */
777 
rangebox_exit(GtkButton * button,gpointer data)778 gboolean rangebox_exit(GtkButton *button, gpointer data)
779 {
780 	GtkAdjustment *adj;
781 
782 	adj = GTK_ADJUSTMENT((GtkObject *) Xdialog.widget1);
783 	fprintf(Xdialog.output, "%d", (gint) adj->value);
784 	if (Xdialog.widget2 != NULL) {
785 		adj = GTK_ADJUSTMENT((GtkObject *) Xdialog.widget2);
786 		fprintf(Xdialog.output, "%s%d", Xdialog.separator,
787 			(gint) adj->value);
788 	}
789 	if (Xdialog.widget3 != NULL) {
790 		adj = GTK_ADJUSTMENT((GtkObject *) Xdialog.widget3);
791 		fprintf(Xdialog.output, "%s%d", Xdialog.separator,
792 			(gint) adj->value);
793 	}
794 	fprintf(Xdialog.output, "\n");
795 
796 	return TRUE;
797 }
798 
799 
rangebox_timeout(gpointer data)800 gboolean rangebox_timeout(gpointer data)
801 {
802 	return rangebox_exit(NULL, NULL);
803 }
804 
805 /* spin boxes callbacks */
806 
spinbox_exit(GtkButton * button,gpointer data)807 gboolean spinbox_exit(GtkButton *button, gpointer data)
808 {
809 	fprintf(Xdialog.output, "%d",
810 		gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Xdialog.widget1)));
811 
812 	if (Xdialog.widget2 != NULL)
813 		fprintf(Xdialog.output, "%s%d", Xdialog.separator,
814 			gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Xdialog.widget2)));
815 
816 	if (Xdialog.widget3 != NULL)
817 		fprintf(Xdialog.output, "%s%d", Xdialog.separator,
818 			gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Xdialog.widget3)));
819 
820 	fprintf(Xdialog.output, "\n");
821 
822 	return TRUE;
823 }
824 
spinbox_timeout(gpointer data)825 gboolean spinbox_timeout(gpointer data)
826 {
827 	return spinbox_exit(NULL, NULL);
828 }
829 
830 /* Double-click event is processed as a button click in menubox, radiolist and
831  * checklist... The button widget is to be passed as "data".
832  */
double_click_event(GtkObject * object,GdkEventButton * event,gpointer data)833 gint double_click_event(GtkObject *object, GdkEventButton *event,
834 			gpointer data)
835 {
836 	if (event->type == GDK_2BUTTON_PRESS || event->type == GDK_3BUTTON_PRESS)
837 		gtk_signal_emit_by_name(GTK_OBJECT(data), "clicked");
838 
839 	return FALSE;
840 }
841 
842 /* radiolist and checklist callbacks */
843 
item_toggle(GtkObject * item,int i)844 void item_toggle(GtkObject *item, int i)
845 {
846 	if (GTK_TOGGLE_BUTTON(item)->active) {
847 		Xdialog.array[i].state = 1;
848 	} else
849 		Xdialog.array[i].state = 0;
850 }
851 
print_items(GtkButton * button,gpointer data)852 gboolean print_items(GtkButton *button, gpointer data)
853 {
854 	int i;
855 	gboolean flag = FALSE;
856 
857 	for (i = 0 ; Xdialog.array[i].state != -1 ; i++) {
858 		if (Xdialog.array[i].state) {
859 			if (flag)
860 				fprintf(Xdialog.output, "%s", Xdialog.separator);
861 			fprintf(Xdialog.output, "%s", Xdialog.array[i].tag);
862 			flag = TRUE;
863 		}
864 	}
865 	if (flag)
866 		fprintf(Xdialog.output, "\n");
867 
868 	return TRUE;
869 }
870 
itemlist_timeout(gpointer data)871 gboolean itemlist_timeout(gpointer data)
872 {
873 	return print_items(NULL, NULL);
874 }
875 
876 /* menubox callback */
877 
item_select(GtkObject * clist,gint row,gint column,GdkEventButton * event,gpointer data)878 void item_select(GtkObject *clist, gint row, gint column,
879 		 GdkEventButton *event, gpointer data)
880 {
881 	/* If the tag is empty, then this is an unavailable item:
882 	 * select back the last selected row and exit.
883 	 */
884 	if (strlen(Xdialog.array[row].tag) == 0) {
885 		gtk_clist_select_row(GTK_CLIST(clist), Xdialog.array[0].state, 0);
886 		return;
887 	}
888 
889 	/* Just remember which row was last selected (we use the first
890 	 * row status variable IOT do so)...
891 	 */
892 	Xdialog.array[0].state = row;
893 
894 	if (Xdialog.tips == 1) {
895 		gtk_statusbar_pop(GTK_STATUSBAR(Xdialog.widget1), Xdialog.status_id);
896 		gtk_statusbar_push(GTK_STATUSBAR(Xdialog.widget1), Xdialog.status_id,
897 				   Xdialog.array[row].tips);
898 	}
899 }
900 
901 /* menubox and treeview callback */
902 
print_selection(GtkButton * button,gpointer data)903 gboolean print_selection(GtkButton *button, gpointer data)
904 {
905 	if ( Xdialog.array[0].state >= 0) {
906 		fprintf(Xdialog.output, "%s\n", Xdialog.array[Xdialog.array[0].state].tag);
907 		return TRUE;
908 	} else
909 		return FALSE;
910 }
911 
912 #ifdef USE_GTK2
print_tree_selection(GtkButton * button,gpointer data)913 gboolean print_tree_selection(GtkButton *button, gpointer data)
914 {
915 	int i = 0;
916 	for (i = 0 ; Xdialog.array[i].state != -1 ; i++) {
917 		if (Xdialog.array[i].state > 0) {
918 			fprintf(Xdialog.output, "%s\n", Xdialog.array[i].tag);
919  			return TRUE;
920 		}
921 	}
922 	return FALSE;
923 }
924 #endif
925 
menu_timeout(gpointer data)926 gboolean menu_timeout(gpointer data)
927 {
928 	return print_selection(NULL, NULL);
929 }
930 
move_to_row_timeout(gpointer data)931 gboolean move_to_row_timeout(gpointer data)
932 {
933 	gtk_clist_moveto(GTK_CLIST(Xdialog.widget2),
934 			 Xdialog.array[0].state, 0, 0.5, 0.0);
935 
936 	/* Run this timeout function only once ! */
937 	return FALSE;
938 }
939 
940 #ifdef USE_GTK2
cb_selection_changed(GtkObject * tree)941 void cb_selection_changed(GtkObject *tree)
942 {
943 	GtkTreeIter tree_iter;
944 	GtkTreeModel *model;
945 	GtkTreeSelection* selection;
946 	gchar *name, *tag;
947 	int i = 0;
948 
949 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(Xdialog.widget1));
950 	selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(Xdialog.widget1));
951 
952 	if (gtk_tree_selection_get_selected(selection, &model, &tree_iter))
953 		gtk_tree_model_get(model, &tree_iter, 0, &name, 1, &tag, -1);
954 
955 	for (i = 0 ; Xdialog.array[i].state != -1 ; i++) {
956 		if (!strncmp(Xdialog.array[i].name, name, strlen(name)))
957 			Xdialog.array[i].state = 1;
958 		else
959 			Xdialog.array[i].state = 0;
960 	}
961 
962 	g_free(name);
963 	g_free(tag);
964 }
965 #else
cb_selection_changed(GtkObject * tree)966 void cb_selection_changed(GtkObject *tree)
967 {
968 	GList *list;
969 	GtkWidget *item;
970 	int i;
971 
972 	list = GTK_TREE_SELECTION(tree);
973 	if (list != NULL) {
974 		item = GTK_WIDGET(list->data);
975 		for (i = 0 ; Xdialog.array[i].state != -1 ; i++) {
976 			if (Xdialog.array[i].widget == item) {
977 				Xdialog.array[0].state = i;
978 				break;
979 			}
980 		}
981 	}
982 }
983 #endif
984 
985 /* buildlist callbacks */
986 
987 /* the following function is to be called after each glist update so to
988  * set the proper (in)sensitive status onto the Add/Remove buttons.
989  */
990 #ifdef USE_GTK2
sensitive_buttons(void)991 void sensitive_buttons(void)
992 {
993 	GtkTreeIter tree_iter;
994 	GtkTreeModel *model;
995 
996 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(Xdialog.widget1));
997 
998 	if (gtk_tree_model_get_iter_first(model, &tree_iter)) {
999 		gtk_widget_set_sensitive(Xdialog.widget3, TRUE);
1000 	} else {
1001 		gtk_widget_set_sensitive(Xdialog.widget3, FALSE);
1002 	}
1003 
1004 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(Xdialog.widget2));
1005 
1006 	if (gtk_tree_model_get_iter_first(model, &tree_iter)) {
1007 		gtk_widget_set_sensitive(Xdialog.widget4, TRUE);
1008 	} else {
1009 		gtk_widget_set_sensitive(Xdialog.widget4, FALSE);
1010 	}
1011 }
1012 #else
sensitive_buttons(void)1013 void sensitive_buttons(void)
1014 {
1015 	gtk_widget_set_sensitive(Xdialog.widget3,
1016 				 g_list_length(GTK_LIST(Xdialog.widget1)->children) != 0);
1017 	gtk_widget_set_sensitive(Xdialog.widget4,
1018 				 g_list_length(GTK_LIST(Xdialog.widget2)->children) != 0);
1019 }
1020 #endif
1021 
1022 #ifdef USE_GTK2
add_to_list(GtkButton * button,gpointer data)1023 gboolean add_to_list(GtkButton *button, gpointer data)
1024 {
1025 	GtkTreeIter tree_iter1, tree_iter2;
1026 	GtkTreeModel *model1, *model2;
1027 	GtkTreeSelection* selection1;
1028 
1029 	model1 = gtk_tree_view_get_model(GTK_TREE_VIEW(Xdialog.widget1));
1030 	selection1 = gtk_tree_view_get_selection(GTK_TREE_VIEW(Xdialog.widget1));
1031 	model2 = gtk_tree_view_get_model(GTK_TREE_VIEW(Xdialog.widget2));
1032 
1033 	if (gtk_tree_selection_get_selected(selection1, &model1, &tree_iter1)) {
1034 		gchar *name, *tag;
1035 		gtk_tree_model_get(model1, &tree_iter1, 0, &name, 1, &tag, -1);
1036 
1037 		gtk_list_store_append(GTK_LIST_STORE(model2), &tree_iter2);
1038 		gtk_list_store_set(GTK_LIST_STORE(model2), &tree_iter2, 0,
1039 			 name, 1, tag, -1);
1040 		gtk_list_store_remove(GTK_LIST_STORE(model1), &tree_iter1);
1041 
1042 		g_free(name);
1043 		g_free(tag);
1044 	}
1045 
1046 	sensitive_buttons();
1047 
1048 	return TRUE;
1049 }
1050 #else
add_to_list(GtkButton * button,gpointer data)1051 gboolean add_to_list(GtkButton *button, gpointer data)
1052 {
1053 	GList *selected;
1054 
1055 	selected = g_list_copy(GTK_LIST(Xdialog.widget1)->selection);
1056 	gtk_list_remove_items_no_unref(GTK_LIST(Xdialog.widget1), selected);
1057 	gtk_list_append_items(GTK_LIST(Xdialog.widget2), selected);
1058 
1059 	sensitive_buttons();
1060 
1061 	return TRUE;
1062 }
1063 #endif
1064 
1065 #ifdef USE_GTK2
remove_from_list(GtkButton * button,gpointer data)1066 gboolean remove_from_list(GtkButton *button, gpointer data)
1067 {
1068 	GtkTreeIter tree_iter1, tree_iter2;
1069 	GtkTreeModel *model1, *model2;
1070 	GtkTreeSelection* selection2;
1071 
1072 	model1 = gtk_tree_view_get_model(GTK_TREE_VIEW(Xdialog.widget1));
1073 	model2 = gtk_tree_view_get_model(GTK_TREE_VIEW(Xdialog.widget2));
1074 	selection2 = gtk_tree_view_get_selection(GTK_TREE_VIEW(Xdialog.widget2));
1075 
1076 	if (gtk_tree_selection_get_selected(selection2, &model2, &tree_iter2)) {
1077 		gchar *name, *tag;
1078 		gtk_tree_model_get(model2, &tree_iter2, 0, &name, 1, &tag, -1);
1079 
1080 		gtk_list_store_append(GTK_LIST_STORE(model1), &tree_iter1);
1081 		gtk_list_store_set(GTK_LIST_STORE(model1), &tree_iter1, 0, name, 1, tag, -1);
1082 		gtk_list_store_remove(GTK_LIST_STORE(model2), &tree_iter2);
1083 
1084 		g_free(name);
1085 		g_free(tag);
1086 	}
1087 
1088 	sensitive_buttons();
1089 
1090 	return TRUE;
1091 }
1092 #else
remove_from_list(GtkButton * button,gpointer data)1093 gboolean remove_from_list(GtkButton *button, gpointer data)
1094 {
1095 	GList *selected;
1096 
1097 	selected = g_list_copy(GTK_LIST(Xdialog.widget2)->selection);
1098 	gtk_list_remove_items_no_unref(GTK_LIST(Xdialog.widget2), selected);
1099 	gtk_list_append_items(GTK_LIST(Xdialog.widget1), selected);
1100 
1101 	sensitive_buttons();
1102 
1103 	return TRUE;
1104 }
1105 #endif
1106 
1107 #ifdef USE_GTK2
print_list(GtkButton * button,gpointer data)1108 gboolean print_list(GtkButton *button, gpointer data)
1109 {
1110 	GtkTreeModel *model;
1111 	GtkTreeIter iter;
1112 	gboolean valid;
1113 	gboolean flag = FALSE;
1114 
1115 	model = gtk_tree_view_get_model(GTK_TREE_VIEW(Xdialog.widget2));
1116 	valid = gtk_tree_model_get_iter_first(model, &iter);
1117 
1118 	while (valid) {
1119 		gchar *name_data, *tag_data;
1120 
1121 		gtk_tree_model_get(model, &iter, 0, &name_data, 1, &tag_data, -1);
1122 
1123 		if (flag)
1124 			fprintf(Xdialog.output, "%s", Xdialog.separator);
1125 
1126 		fprintf(Xdialog.output, "%s", tag_data);
1127 		flag = TRUE;
1128 
1129 		g_free(name_data);
1130 		g_free(tag_data);
1131 
1132 		valid = gtk_tree_model_iter_next(model, &iter);
1133 	}
1134 
1135 	if (flag)
1136 		fprintf(Xdialog.output, "\n");
1137 
1138 	return TRUE;
1139 }
1140 #else
print_list(GtkButton * button,gpointer data)1141 gboolean print_list(GtkButton *button, gpointer data)
1142 {
1143 	GList *children;
1144 	int i;
1145 	gboolean flag = FALSE;
1146 
1147 	children = GTK_LIST(Xdialog.widget2)->children;
1148 	while (children != NULL) {
1149 		for (i = 0 ; Xdialog.array[i].state != -1 ; i++) {
1150 			if (Xdialog.array[i].widget == children->data) {
1151 				if (flag)
1152 					fprintf(Xdialog.output, "%s", Xdialog.separator);
1153 				fprintf(Xdialog.output, "%s", Xdialog.array[i].tag);
1154 				flag = TRUE;
1155 				break;
1156 			}
1157 		}
1158 		children = g_list_next(children);
1159 	}
1160 	if (flag)
1161 		fprintf(Xdialog.output, "\n");
1162 
1163 	return TRUE;
1164 }
1165 #endif
1166 
buildlist_timeout(gpointer data)1167 gboolean buildlist_timeout(gpointer data)
1168 {
1169 	return print_list(NULL, NULL);
1170 }
1171 
1172 /* fselect and dselect callback */
1173 
filesel_exit(GtkObject * filesel,gpointer client_data)1174 gboolean filesel_exit(GtkObject *filesel, gpointer client_data)
1175 {
1176 	fprintf(Xdialog.output, "%s\n",
1177 		gtk_file_selection_get_filename(GTK_FILE_SELECTION(client_data)));
1178 	return exit_ok(NULL, NULL);
1179 }
1180 
1181 /* colorsel callback */
1182 
colorsel_exit(GtkObject * colorsel,gpointer client_data)1183 gboolean colorsel_exit(GtkObject *colorsel, gpointer client_data)
1184 {
1185 	gdouble colors[4];
1186 
1187 	gtk_color_selection_get_color(GTK_COLOR_SELECTION(client_data), colors);
1188 	fprintf(Xdialog.output, "%d %d %d\n",
1189                 (int) (255.0 * colors[0]), (int) (255.0 * colors[1]), (int) (255.0 * colors[2]));
1190 	return exit_ok(NULL, NULL);
1191 }
1192 
1193 /* fontsel callback */
1194 
fontsel_exit(GtkObject * fontsel,gpointer client_data)1195 gboolean fontsel_exit(GtkObject *fontsel, gpointer client_data)
1196 {
1197 	fprintf(Xdialog.output, "%s\n",
1198                 gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(client_data)));
1199 	return exit_ok(NULL, NULL);
1200 }
1201 
1202 /* calendar callbacks */
1203 
calendar_exit(gpointer object,gpointer data)1204 gboolean calendar_exit(gpointer object, gpointer data)
1205 {
1206 	gint day, month, year;
1207 
1208 	gtk_calendar_get_date(GTK_CALENDAR(Xdialog.widget1), &year, &month, &day);
1209 	fprintf(Xdialog.output, "%02d/%02d/%d\n", day, month+1, year);
1210 
1211 	return TRUE;
1212 }
1213 
calendar_timeout(gpointer data)1214 gboolean calendar_timeout(gpointer data)
1215 {
1216 	return calendar_exit(NULL, NULL);
1217 }
1218 
1219 /* timebox callbacks */
1220 
timebox_exit(gpointer object,gpointer data)1221 gboolean timebox_exit(gpointer object, gpointer data)
1222 {
1223 	fprintf(Xdialog.output, "%02d:%02d:%02d\n",
1224 		gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Xdialog.widget1)),
1225 		gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Xdialog.widget2)),
1226 		gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(Xdialog.widget3)));
1227 
1228 	return TRUE;
1229 }
1230 
timebox_timeout(gpointer data)1231 gboolean timebox_timeout(gpointer data)
1232 {
1233 	return timebox_exit(NULL, NULL);
1234 }
1235