1 /*
2  * gsdlg.c - Simple GTK dialog wrapper
3  *
4  * Copyright 2007-2008 Jeff Pohlmeyer <yetanothergeek(at)gmail(dot)com>
5  *
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program; if not, write to the Free Software Foundation, Inc.,
20  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #ifndef GSDLG_ALL_IN_ONE
25 #include "gsdlg.h"
26 #endif
27 
28 #include <stdlib.h>
29 
30 #include <geanyplugin.h>
31 
32 
33 #define TextKey "gsdlg_TextKey_bc4871f4e3478ab5234e28432460a6b8"
34 #define DataKey "gsdlg_DataKey_bc4871f4e3478ab5234e28432460a6b8"
35 
36 
destroy_slist_and_data(gpointer list)37 static void destroy_slist_and_data(gpointer list)
38 {
39 	GSList*p;
40 	for (p=list; p ; p=p->next) {
41 		if (p->data) g_free(p->data);
42 		p->data=NULL;
43 	}
44 	g_slist_free(list);
45 }
46 
47 
48 
gsdlg_textarea(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr label)49 void gsdlg_textarea(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
50 {
51 	GtkWidget*tv;
52 	GtkWidget*sw;
53 	GtkWidget*frm;
54 	g_return_if_fail(dlg);
55 	tv=gtk_text_view_new();
56 	gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(tv),GTK_WRAP_WORD_CHAR);
57 	gtk_text_view_set_accepts_tab(GTK_TEXT_VIEW(tv),FALSE);
58 	if (value) {
59 		GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(tv));
60 		gtk_text_buffer_set_text (tb, value, -1);
61 	}
62 	sw=gtk_scrolled_window_new(NULL, NULL);
63 	gtk_widget_set_size_request(sw, gdk_screen_get_width(gdk_screen_get_default())/3,
64 		gdk_screen_get_height(gdk_screen_get_default())/10);
65 	gtk_container_add(GTK_CONTAINER(sw),tv);
66 	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
67 	frm=gtk_frame_new(label);
68 	gtk_frame_set_shadow_type(GTK_FRAME(frm), GTK_SHADOW_ETCHED_IN);
69 	gtk_container_add(GTK_CONTAINER(frm),sw);
70 	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),frm);
71 	g_object_set_data_full(G_OBJECT(tv), TextKey, g_strdup(key), g_free);
72 }
73 
74 
75 
make_modal(GtkWidget * w,GtkWidget * p)76 static void make_modal(GtkWidget *w, GtkWidget*p)
77 {
78 	gtk_window_set_modal(GTK_WINDOW(w), TRUE);
79 	gtk_window_set_transient_for(GTK_WINDOW(w),GTK_WINDOW(p));
80 }
81 
82 
83 
file_dlg_map(GtkWidget * w,gpointer user_data)84 static void  file_dlg_map(GtkWidget *w, gpointer user_data)
85 {
86 	GtkWidget* entry=gtk_window_get_focus (GTK_WINDOW(w));
87 	if (entry && GTK_IS_ENTRY(entry)) {
88 		gtk_entry_set_text(GTK_ENTRY(entry), (gchar*)user_data);
89 	}
90 }
91 
92 
93 
file_btn_clicked(GtkButton * button,gpointer user_data)94 static void file_btn_clicked(GtkButton *button, gpointer user_data)
95 {
96 	GtkWidget*dlg;
97 	const gchar *fn=NULL;
98 	gchar *bn=NULL;
99 	gint resp;
100 	dlg=gtk_file_chooser_dialog_new(_("Open file"),
101 				gsdlg_toplevel,	GTK_FILE_CHOOSER_ACTION_OPEN,
102 				GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
103 				GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,	NULL);
104 	gtk_window_set_title(GTK_WINDOW(dlg), _("Select file"));
105 	make_modal(dlg, gtk_widget_get_toplevel(GTK_WIDGET(user_data)));
106 	fn=gtk_entry_get_text(GTK_ENTRY(user_data));
107 	if (fn && *fn) {
108 		if (g_file_test(fn,G_FILE_TEST_IS_REGULAR)) {
109 			gchar *rp=utils_get_real_path(fn);
110 			gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dlg), rp);
111 			if (rp) g_free(rp);
112 		} else {
113 			if (g_file_test(fn,G_FILE_TEST_IS_DIR)) {
114 				gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dlg), fn);
115 			} else {
116 				gchar *dn=g_path_get_dirname(fn);
117 				if (g_file_test(dn,G_FILE_TEST_IS_DIR)) {
118 					gchar *rp=utils_get_real_path(dn);
119 					gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dlg), rp);
120 					if (rp) g_free(rp);
121 					bn=g_path_get_basename(fn);
122 					g_signal_connect(G_OBJECT(dlg), "map", G_CALLBACK(file_dlg_map), bn);
123 				}
124 				g_free(dn);
125 			}
126 		}
127 	}
128 	resp=gtk_dialog_run(GTK_DIALOG(dlg));
129 	if (resp == GTK_RESPONSE_ACCEPT) {
130 		gchar *fcfn=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlg));
131 		if (fcfn) {
132 			gtk_entry_set_text(GTK_ENTRY(user_data), fcfn);
133 			g_free(fcfn);
134 		}
135 	}
136 	gtk_widget_destroy(dlg);
137 	if (bn) { g_free(bn); }
138 }
139 
140 
141 
gsdlg_file(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr label)142 void gsdlg_file(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
143 {
144 	GtkWidget *hbox;
145 	GtkWidget *input;
146 	GtkWidget*frm;
147 	GtkWidget*btn;
148 	g_return_if_fail(dlg);
149 	input=gtk_entry_new();
150 	if (value) { gtk_entry_set_text(GTK_ENTRY(input),value); }
151 	btn=gtk_button_new_with_label(_("Browse..."));
152 	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(file_btn_clicked), input);
153 	hbox=gtk_hbox_new(FALSE,FALSE);
154 	gtk_box_pack_start(GTK_BOX(hbox), input,TRUE,TRUE,1);
155 	gtk_box_pack_start(GTK_BOX(hbox), btn,FALSE,FALSE,1);
156 	frm=gtk_frame_new(label);
157 	gtk_frame_set_shadow_type(GTK_FRAME(frm), GTK_SHADOW_ETCHED_IN);
158 	gtk_container_add(GTK_CONTAINER(frm),hbox);
159 	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),frm);
160 	g_object_set_data_full(G_OBJECT(input), TextKey, g_strdup(key), g_free);
161 }
162 
163 
164 
color_btn_clicked(GtkButton * button,gpointer user_data)165 static void color_btn_clicked(GtkButton *button, gpointer user_data)
166 {
167 	GtkWidget*dlg;
168 	GtkColorSelectionDialog *csdlg;
169 	const gchar *cn=NULL;
170 	gint resp;
171 	GdkColor rgb;
172 
173 	dlg=gtk_color_selection_dialog_new (_("Select Color"));
174 	csdlg=GTK_COLOR_SELECTION_DIALOG(dlg);
175 	make_modal(dlg, gtk_widget_get_toplevel(GTK_WIDGET(user_data)));
176 	cn=gtk_entry_get_text(GTK_ENTRY(user_data));
177 	if (cn && *cn && gdk_color_parse(cn,&rgb)) {
178 		gtk_color_selection_set_current_color(
179 			GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(csdlg)), &rgb);
180 	}
181 	resp=gtk_dialog_run(GTK_DIALOG(dlg));
182 	if (resp == GTK_RESPONSE_OK) {
183 		gchar *rv=NULL;
184 		gtk_color_selection_get_current_color(
185 			GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(csdlg)), &rgb);
186 		rv=g_strdup_printf("#%2.2X%2.2X%2.2X",rgb.red/256,rgb.green/256,rgb.blue/256);
187 		gtk_entry_set_text(GTK_ENTRY(user_data), rv);
188 		g_free(rv);
189 	}
190 	gtk_widget_destroy(dlg);
191 }
192 
193 
194 
gsdlg_color(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr prompt)195 void gsdlg_color(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr prompt)
196 {
197 	GtkWidget *hbox;
198 	GtkWidget *input;
199 	GtkWidget *label;
200 	GtkWidget*btn;
201 	g_return_if_fail(dlg);
202 	input=gtk_entry_new();
203 	if (value) { gtk_entry_set_text(GTK_ENTRY(input),value); }
204 	btn=gtk_button_new_with_label(_("Choose..."));
205 	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(color_btn_clicked), input);
206 	hbox=gtk_hbox_new(FALSE,FALSE);
207 	if (prompt) {
208 		label=gtk_label_new(prompt);
209 		gtk_box_pack_start(GTK_BOX(hbox), label,FALSE,FALSE,1);
210 	}
211 	gtk_box_pack_start(GTK_BOX(hbox), input,TRUE,TRUE,1);
212 	gtk_box_pack_start(GTK_BOX(hbox), btn,FALSE,FALSE,1);
213 	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),hbox);
214 	g_object_set_data_full(G_OBJECT(input), TextKey, g_strdup(key), g_free);
215 }
216 
217 
218 
font_btn_clicked(GtkButton * button,gpointer user_data)219 static void font_btn_clicked(GtkButton *button, gpointer user_data)
220 {
221 	GtkWidget*dlg;
222 	const gchar *fn=NULL;
223 	gint resp;
224 	fn=gtk_entry_get_text(GTK_ENTRY(user_data));
225 	dlg=gtk_font_selection_dialog_new(_("Select Font"));
226 	make_modal(dlg, gtk_widget_get_toplevel(GTK_WIDGET(user_data)));
227 	if (fn && *fn) {
228 		gtk_font_selection_dialog_set_font_name(GTK_FONT_SELECTION_DIALOG(dlg),fn);
229 	}
230 	resp=gtk_dialog_run(GTK_DIALOG(dlg));
231 	if (resp==GTK_RESPONSE_OK) {
232 		gchar *gfn=gtk_font_selection_dialog_get_font_name(GTK_FONT_SELECTION_DIALOG(dlg));
233 		if (gfn) {
234 			gtk_entry_set_text(GTK_ENTRY(user_data), gfn);
235 			g_free(gfn);
236 		}
237 	}
238 	gtk_widget_destroy(dlg);
239 }
240 
241 
242 
gsdlg_font(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr prompt)243 void gsdlg_font(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr prompt)
244 {
245 	GtkWidget *hbox;
246 	GtkWidget *input;
247 	GtkWidget *label;
248 	GtkWidget*btn;
249 	g_return_if_fail(dlg);
250 	input=gtk_entry_new();
251 	if (value) { gtk_entry_set_text(GTK_ENTRY(input),value); }
252 	btn=gtk_button_new_with_label(_("Select..."));
253 	g_signal_connect(G_OBJECT(btn), "clicked", G_CALLBACK(font_btn_clicked), input);
254 	hbox=gtk_hbox_new(FALSE,FALSE);
255 	if (prompt) {
256 		label=gtk_label_new(prompt);
257 		gtk_box_pack_start(GTK_BOX(hbox), label,FALSE,FALSE,1);
258 	}
259 	gtk_box_pack_start(GTK_BOX(hbox), input,TRUE,TRUE,1);
260 	gtk_box_pack_start(GTK_BOX(hbox), btn,FALSE,FALSE,1);
261 	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),hbox);
262 	g_object_set_data_full(G_OBJECT(input), TextKey, g_strdup(key), g_free);
263 }
264 
265 
266 
gsdlg_entry(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr prompt,gboolean masked)267 static void gsdlg_entry(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr prompt, gboolean masked)
268 {
269 	GtkWidget *hbox;
270 	GtkWidget *input;
271 	GtkWidget *label;
272 	g_return_if_fail(dlg);
273 	input=gtk_entry_new();
274 	if (value) { gtk_entry_set_text(GTK_ENTRY(input),value); }
275 	label=gtk_label_new(prompt);
276 	hbox=gtk_hbox_new(FALSE,FALSE);
277 	gtk_box_pack_start(GTK_BOX(hbox), label,FALSE,FALSE,1);
278 	gtk_box_pack_start(GTK_BOX(hbox), input,TRUE,TRUE,1);
279 	gtk_entry_set_visibility(GTK_ENTRY(input), !masked);
280 	gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(dlg)),hbox);
281 	g_object_set_data_full(G_OBJECT(input), TextKey, g_strdup(key), g_free);
282 }
283 
284 
gsdlg_text(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr label)285 void gsdlg_text(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
286 {
287 	gsdlg_entry(dlg, key, value, label, FALSE);
288 }
289 
290 
291 
gsdlg_password(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr label)292 void gsdlg_password(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
293 {
294 	gsdlg_entry(dlg, key, value, label, TRUE);
295 }
296 
297 
gsdlg_checkbox(GtkDialog * dlg,GsDlgStr key,gboolean value,GsDlgStr label)298 void gsdlg_checkbox(GtkDialog *dlg, GsDlgStr key, gboolean value, GsDlgStr label)
299 {
300 	GtkWidget *cb=NULL;
301 	g_return_if_fail(dlg);
302 	cb=gtk_check_button_new_with_label(label);
303 	g_object_set_data_full(G_OBJECT(cb),TextKey,g_strdup(key), g_free);
304 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(cb),value);
305 	gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),cb);
306 }
307 
308 
309 
310 typedef struct _KeySearchData {
311 	const gchar *key;
312 	GType type;
313 	GtkWidget*value;
314 } KeySearchData;
315 
316 
317 
find_widget_by_key_cb(GtkWidget * w,gpointer p)318 static void find_widget_by_key_cb(GtkWidget *w, gpointer p)
319 {
320 	KeySearchData*kv=p;
321 	if (kv->value) {return;}
322 
323 	if (G_OBJECT_TYPE(G_OBJECT(w)) == kv->type) {
324 		gchar*key=g_object_get_data(G_OBJECT(w), TextKey);
325 		if (key && g_str_equal(kv->key,key)) { kv->value=w;	}
326 	}
327 }
328 
329 
find_widget_by_key(GtkDialog * dlg,GType type,GsDlgStr key)330 static GtkWidget *find_widget_by_key(GtkDialog *dlg, GType type, GsDlgStr key)
331 {
332 	KeySearchData kv={NULL,0,NULL};
333 	g_return_val_if_fail(dlg, NULL);
334 	kv.key=key;
335 	kv.type=type;
336 	gtk_container_foreach(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),find_widget_by_key_cb,&kv);
337 	return kv.value;
338 }
339 
340 
select_radio(GtkWidget * parent,GsDlgStr value)341 static void select_radio(GtkWidget*parent, GsDlgStr value)
342 {
343 	GList *kids=gtk_container_get_children(GTK_CONTAINER(parent));
344 	if (!kids) { return;}
345 	if (kids->data && GTK_IS_RADIO_BUTTON(kids->data)) {
346 		GList *kid=kids;
347 		for (kid=kids; kid; kid=kid->next) {
348 			if (kid->data && GTK_IS_RADIO_BUTTON(kid->data)) {
349 				gchar*kval=g_object_get_data(G_OBJECT(kid->data),TextKey);
350 				gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(kid->data),
351 																				kval && g_str_equal(kval,value));
352 			}
353 		}
354 	}
355 }
356 
357 
358 
gsdlg_group(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr label)359 void gsdlg_group(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
360 {
361 	GtkWidget*frm;
362 	GtkWidget*vbox;
363 
364 	g_return_if_fail(dlg);
365 	frm=find_widget_by_key(dlg,GTK_TYPE_FRAME,key);
366 	if (frm) {
367 		vbox=gtk_bin_get_child(GTK_BIN(frm));
368 		gtk_frame_set_label(GTK_FRAME(frm), label);
369 	} else {
370 		frm=gtk_frame_new(label);
371 		vbox=gtk_vbox_new(FALSE,FALSE);
372 		gtk_container_add(GTK_CONTAINER(frm),vbox);
373 		gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),frm);
374 	}
375 
376 	/* Frame holds keyname, vbox holds default value */
377 	g_object_set_data_full(G_OBJECT(frm),  TextKey, g_strdup(key), g_free);
378 	g_object_set_data_full(G_OBJECT(vbox), TextKey, g_strdup(value), g_free);
379 	select_radio(vbox,value);
380 }
381 
382 
383 
384 
gsdlg_radio(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr label)385 void gsdlg_radio(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
386 {
387 	GtkWidget *frm=NULL;
388 	GtkWidget *vbox=NULL;
389 	GList *kids=NULL;
390 	GtkWidget *rb=NULL;
391 	gchar *defval;
392 	g_return_if_fail(dlg);
393 	frm=find_widget_by_key(dlg,GTK_TYPE_FRAME,key);
394 	if (frm) {
395 		vbox=gtk_bin_get_child(GTK_BIN(frm));
396 		if (vbox) {
397 		kids=gtk_container_get_children(GTK_CONTAINER(vbox));
398 		}
399 	} else {
400 		gsdlg_group(dlg,key,value,NULL);
401 		frm=find_widget_by_key(dlg,GTK_TYPE_FRAME,key);
402 		vbox=gtk_bin_get_child(GTK_BIN(frm));
403 	}
404 	if (kids) {
405 		rb=gtk_radio_button_new_with_label_from_widget (kids->data,label);
406 		g_list_free(kids);
407 	} else {
408 		rb=gtk_radio_button_new_with_label(NULL, label);
409 	}
410 	g_object_set_data_full(G_OBJECT(rb),TextKey, g_strdup(value), g_free);
411 	gtk_container_add(GTK_CONTAINER(vbox), rb);
412 	defval=g_object_get_data(G_OBJECT(vbox),TextKey);
413 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rb),
414 																value && defval && g_str_equal(defval,value));
415 }
416 
417 
418 
419 
select_combo(GtkWidget * parent,GsDlgStr value)420 static void select_combo(GtkWidget*parent, GsDlgStr value)
421 {
422 	gint n=0;
423 	GSList*values=g_object_get_data(G_OBJECT(parent), DataKey);
424 	GSList*v;
425 	for (v=values; v; v=v->next) {
426 		if (v->data && g_str_equal(v->data, value)) {break;}
427 		n++;
428 	}
429 	gtk_combo_box_set_active(GTK_COMBO_BOX(parent), n);
430 }
431 
432 
433 typedef struct _ComboWidgets {
434 	GtkWidget *label;
435 	GtkWidget *combo;
436 } ComboWidgets;
437 
438 
gsdlg_select(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr label)439 void gsdlg_select(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
440 {
441 	GtkWidget *hbox=NULL;
442 	ComboWidgets*cw=NULL;
443 	g_return_if_fail(dlg);
444 	hbox=find_widget_by_key(dlg,GTK_TYPE_HBOX, key);
445 	if (hbox) {
446 		cw=g_object_get_data(G_OBJECT(hbox), DataKey);
447 		gtk_label_set_text(GTK_LABEL(cw->label), label);
448 	} else {
449 		hbox=gtk_hbox_new(FALSE,FALSE);
450 		cw=g_malloc0(sizeof(ComboWidgets));
451 		g_object_set_data_full(G_OBJECT(hbox),DataKey,cw,g_free);
452 		cw->combo=gtk_combo_box_text_new();
453 		cw->label=gtk_label_new(label);
454 		gtk_box_pack_start(GTK_BOX(hbox), cw->label,FALSE,FALSE,4);
455 		gtk_box_pack_start(GTK_BOX(hbox), cw->combo,TRUE,TRUE,1);
456 		gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),hbox);
457 	}
458 	/* Hbox holds keyname, combo holds default value */
459 	g_object_set_data_full(G_OBJECT(hbox),  TextKey, g_strdup(key), g_free);
460 	g_object_set_data_full(G_OBJECT(cw->combo), TextKey, g_strdup(value), g_free);
461 	select_combo(cw->combo,value);
462 }
463 
464 
465 
gsdlg_option(GtkDialog * dlg,GsDlgStr key,GsDlgStr value,GsDlgStr label)466 void gsdlg_option(GtkDialog *dlg, GsDlgStr key, GsDlgStr value, GsDlgStr label)
467 {
468 	GtkWidget *hbox=NULL;
469 	GSList *values=NULL;
470 	ComboWidgets*cw=NULL;
471 	gchar*defval=NULL;
472 	g_return_if_fail(dlg);
473 
474 	hbox=find_widget_by_key(dlg,GTK_TYPE_HBOX, key);
475 	if (!hbox) {
476 		gsdlg_select(dlg,key,value,NULL);
477 		hbox=find_widget_by_key(dlg,GTK_TYPE_HBOX, key);
478 	}
479 	cw=g_object_get_data(G_OBJECT(hbox), DataKey);
480 	values=g_object_steal_data(G_OBJECT(cw->combo), DataKey);
481 	values=g_slist_append(values, g_strdup(value));
482 	g_object_set_data_full(G_OBJECT(cw->combo), DataKey, values, destroy_slist_and_data);
483 	gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(cw->combo), label);
484 	defval=g_object_get_data(G_OBJECT(cw->combo), TextKey);
485 	if (value && defval && g_str_equal(value,defval)) {
486 		select_combo(cw->combo,value);
487 	}
488 }
489 
490 
491 
492 
gsdlg_label(GtkDialog * dlg,GsDlgStr text)493 void gsdlg_label(GtkDialog *dlg, GsDlgStr text)
494 {
495 	GtkWidget *lab=NULL;
496 	g_return_if_fail(dlg);
497 	lab=gtk_label_new(text);
498 	gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))), lab);
499 	gtk_misc_set_alignment(GTK_MISC(lab), 0.0f, 0.0f);
500 }
501 
502 
503 
gsdlg_hr(GtkDialog * dlg)504 void gsdlg_hr(GtkDialog *dlg)
505 {
506 	g_return_if_fail(dlg);
507 	gtk_container_add(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))), gtk_hseparator_new());
508 }
509 
510 
511 
gsdlg_heading(GtkDialog * dlg,GsDlgStr text)512 void gsdlg_heading(GtkDialog *dlg, GsDlgStr text)
513 {
514 	g_return_if_fail(dlg);
515 	gsdlg_hr(dlg);
516 	gsdlg_label(dlg,text);
517 }
518 
519 GSDLG_API GtkWindow* gsdlg_toplevel=NULL;
520 
521 
522 
gsdlg_new(GsDlgStr title,GsDlgStr * btns)523 GtkDialog *gsdlg_new(GsDlgStr title, GsDlgStr*btns)
524 {
525 	gint i;
526 	GtkDialog *dlg;
527 	dlg=GTK_DIALOG(gtk_dialog_new());
528 	if (gsdlg_toplevel) {
529 		gtk_window_set_destroy_with_parent(GTK_WINDOW(dlg), TRUE);
530 		gtk_window_set_transient_for(GTK_WINDOW(dlg),gsdlg_toplevel);
531 		gtk_window_set_modal(GTK_WINDOW(dlg), TRUE);
532 	}
533 	for (i=0; btns[i]; i++) {
534 		gtk_dialog_add_button(GTK_DIALOG(dlg),btns[i],i);
535 	}
536 	gtk_box_set_spacing(GTK_BOX(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))), 4);
537 	gtk_container_set_border_width(GTK_CONTAINER(dlg), 4);
538 	gtk_window_set_title(GTK_WINDOW(dlg),title);
539 	return dlg;
540 }
541 
542 
543 
widgets_foreach(GtkWidget * w,gpointer p)544 static void widgets_foreach(GtkWidget *w, gpointer p)
545 {
546 	gchar*key=g_object_get_data(G_OBJECT(w),TextKey);
547 	if (key && *key) {
548 		const gchar*value=NULL;
549 		if (GTK_IS_ENTRY(w)) {
550 			value=gtk_entry_get_text(GTK_ENTRY(w));
551 		} else if (GTK_IS_RADIO_BUTTON(w)) {
552 			if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))){
553 				value=key;
554 				key=g_object_get_data(
555 						G_OBJECT(gtk_widget_get_parent(gtk_widget_get_parent(w))), TextKey);
556 			}
557 		} else if (GTK_IS_CHECK_BUTTON(w)) {
558 			value=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w))?"1":"0";
559 		} else if (GTK_IS_COMBO_BOX(w)) {
560 			GSList*values=g_object_get_data(G_OBJECT(w),DataKey);
561 			key=g_object_get_data(G_OBJECT(gtk_widget_get_parent(w)), TextKey);
562 			if (values) {
563 				gint n=gtk_combo_box_get_active(GTK_COMBO_BOX(w));
564 				if (n>=0) { value=g_slist_nth_data(values, n); }
565 			}
566 		} else if (GTK_IS_TEXT_VIEW(w)) {
567 			GtkTextBuffer *tb = gtk_text_view_get_buffer(GTK_TEXT_VIEW(w));
568 			GtkTextIter a,z;
569 			gtk_text_buffer_get_start_iter(tb,&a);
570 			gtk_text_buffer_get_end_iter(tb,&z);
571 			value=gtk_text_buffer_get_text (tb,&a,&z,TRUE);
572 		}
573 		if (value&&*value) {
574 			GHashTable*h=p;
575 			g_hash_table_insert(h,g_strdup(key),g_strdup(value));
576 		}
577 	}
578 	if (GTK_IS_CONTAINER(w)) {
579 		gtk_container_foreach(GTK_CONTAINER(w),widgets_foreach,p);
580 	}
581 }
582 
583 
584 static GsDlgRunHook gsdlg_run_hook=NULL;
585 
586 
587 #ifndef DIALOG_LIB
gsdlg_set_run_hook(GsDlgRunHook cb)588 void gsdlg_set_run_hook(GsDlgRunHook cb)
589 {
590 	gsdlg_run_hook=cb;
591 }
592 #endif
593 
594 
gsdlg_run(GtkDialog * dlg,gint * btn,gpointer user_data)595 GHashTable* gsdlg_run(GtkDialog *dlg, gint *btn, gpointer user_data)
596 {
597 	GHashTable* results=NULL;
598 	gint dummy;
599 	g_return_val_if_fail(dlg, NULL);
600 	gtk_widget_show_all(GTK_WIDGET(dlg));
601 	if (!btn) { btn=&dummy; }
602 	if (gsdlg_run_hook) { gsdlg_run_hook(TRUE,user_data); }
603 	*btn=gtk_dialog_run(GTK_DIALOG(dlg));
604 	if (gsdlg_run_hook) { gsdlg_run_hook(FALSE,user_data); }
605 	if (*btn<0) *btn=-1;
606 	results=g_hash_table_new_full(g_str_hash,g_str_equal,g_free,g_free);
607 	gtk_container_foreach(GTK_CONTAINER(GTK_CONTAINER(gtk_dialog_get_content_area(dlg))),widgets_foreach,results);
608 	gtk_widget_hide(GTK_WIDGET(dlg));
609 	return results;
610 }
611 
612 
613 
614