1 /*  cssed (c) Iago Rubio 2003, 2005 - A tiny CSS editor.
2  *
3  *  This program is free software; you can redistribute it and/or modify
4  *  it under the terms of the GNU General Public License as published by
5  *  the Free Software Foundation; either version 2 of the License, or
6  *  (at your option) any later version.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU Library General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program; if not, write to the Free Software
15  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16  */
17 
18 #ifdef HAVE_CONFIG_H
19 #  include <config.h>
20 #endif
21 
22 #include <gtk/gtk.h>
23 #include <glib.h>
24 
25 #include <stdlib.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <stdarg.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <stdio.h>
32 #include <ctype.h>
33 
34 #ifdef WIN32
35 # include <direct.h>
36 # include  <io.h>
37 #else
38 # include <unistd.h>
39 # include <libgen.h>
40 #endif
41 
42 #include "cssedwindow.h"
43 #include "interface.h"
44 #include "support.h"
45 #include "document.h"
46 #include "plugin.h"
47 #include "debug.h"
48 #include "utils.h"
49 
50 void
cssed_error_message(gchar * title,gchar * message,...)51 cssed_error_message (gchar * title, gchar * message, ... )
52 {
53 	va_list args;
54 	GtkWidget* error_box;
55 	GtkWidget* label;
56 	GtkWidget* label_detail;
57 	gchar* error_message;
58 
59 	error_box = create_error_dialog ();
60 	gtk_window_set_title ((GtkWindow *) error_box, "");
61 
62 	label = lookup_widget (error_box, "label_msg");
63 	label_detail = lookup_widget (error_box, "label_detail");
64 
65 	error_message = g_strdup_printf("<span weight='bold' size='larger'>%s</span>", title);
66 	gtk_label_set_text (GTK_LABEL(label), error_message);
67 	gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
68 	g_free(error_message);
69 
70     va_start(args, message);
71     error_message = g_strdup_vprintf(message, args);
72     va_end(args);
73 
74 	gtk_label_set_text (GTK_LABEL(label_detail), error_message);
75 	gtk_widget_show_all(error_box);
76 	g_free(error_message);
77 }
78 
79 /* modal dialogs call with gtk_dialog_run and get the response */
80 GtkWidget*
create_ok_cancel_dialog(gchar * title,gchar * format,...)81 create_ok_cancel_dialog (gchar* title, gchar* format, ...)
82 {
83 	GtkWidget *ok_cancel_dialog;
84 	GtkWidget *dialog_vbox;
85 	GtkWidget *hbox;
86 	GtkWidget *image;
87 	GtkWidget *vbox;
88 	GtkWidget *label_header;
89 	GtkWidget *label_message;
90 	GtkWidget *dialog_action_area;
91 	GtkWidget *cancelbutton;
92 	GtkWidget *okbutton;
93 	gchar* message;
94 	gchar* markup_title;
95  	va_list args;
96 
97 	markup_title = g_strconcat("<span size='larger'>",title,"</span>",NULL);
98 
99     va_start(args, format);
100     message = g_strdup_vprintf(format, args);
101     va_end(args);
102 
103 	ok_cancel_dialog = gtk_dialog_new ();
104 	gtk_window_set_position (GTK_WINDOW (ok_cancel_dialog), GTK_WIN_POS_CENTER);
105 
106 	dialog_vbox = GTK_DIALOG (ok_cancel_dialog)->vbox;
107 	gtk_widget_show (dialog_vbox);
108 
109 	hbox = gtk_hbox_new (FALSE, 0);
110 	gtk_widget_show (hbox);
111 	gtk_box_pack_start (GTK_BOX (dialog_vbox), hbox, TRUE, TRUE, 0);
112 
113 	image = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_DIALOG);
114 	gtk_widget_show (image);
115 	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 20);
116 
117 	vbox = gtk_vbox_new (FALSE, 0);
118 	gtk_widget_show (vbox);
119 	gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
120 
121 
122 	label_header = gtk_label_new (markup_title);
123 	gtk_widget_show (label_header);
124 	gtk_box_pack_start (GTK_BOX (vbox), label_header, FALSE, TRUE, 20);
125 	gtk_label_set_use_markup (GTK_LABEL (label_header), TRUE);
126 	gtk_label_set_justify (GTK_LABEL (label_header), GTK_JUSTIFY_LEFT);
127 
128 	label_message = gtk_label_new (message);
129 	gtk_widget_show (label_message);
130 	gtk_box_pack_start (GTK_BOX (vbox), label_message, TRUE, TRUE, 0);
131 	gtk_label_set_use_markup (GTK_LABEL (label_message), TRUE);
132 	gtk_label_set_justify (GTK_LABEL (label_message), GTK_JUSTIFY_LEFT);
133 	gtk_label_set_line_wrap (GTK_LABEL (label_message), TRUE);
134 
135 	dialog_action_area = GTK_DIALOG (ok_cancel_dialog)->action_area;
136 	gtk_widget_show (dialog_action_area);
137 	gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END);
138 
139 	okbutton = gtk_button_new_from_stock ("gtk-ok");
140 	gtk_widget_show (okbutton);
141 	gtk_dialog_add_action_widget (GTK_DIALOG (ok_cancel_dialog), okbutton, GTK_RESPONSE_OK);
142 	GTK_WIDGET_SET_FLAGS (okbutton, GTK_CAN_DEFAULT);
143 
144 	cancelbutton = gtk_button_new_from_stock ("gtk-cancel");
145 	gtk_widget_show (cancelbutton);
146 	gtk_dialog_add_action_widget (GTK_DIALOG (ok_cancel_dialog), cancelbutton, GTK_RESPONSE_CANCEL);
147 	GTK_WIDGET_SET_FLAGS (cancelbutton, GTK_CAN_DEFAULT);
148 
149 	gtk_widget_grab_default (okbutton);
150 	g_free(markup_title);
151 	g_free(message);
152 
153 	return ok_cancel_dialog;
154 }
155 
156 GtkWidget*
create_yes_no_cancel_dialog(gchar * title,gchar * format,...)157 create_yes_no_cancel_dialog (gchar* title, gchar* format, ...)
158 {
159 	GtkWidget *yes_no_cancel_dialog;
160 	GtkWidget *dialog_vbox;
161 	GtkWidget *hbox;
162 	GtkWidget *image;
163 	GtkWidget *vbox;
164 	GtkWidget *label_header;
165 	GtkWidget *label_message;
166 	GtkWidget *dialog_action_area;
167 	GtkWidget *cancelbutton;
168 	GtkWidget *nobutton;
169 	GtkWidget* yesbutton;
170 	gchar* markup_title;
171 	gchar* message;
172  	va_list args;
173 
174 	markup_title = g_strconcat("<span size='larger'>",title,"</span>",NULL);
175 
176     va_start(args, format);
177     message = g_strdup_vprintf(format, args);
178     va_end(args);
179 
180 	yes_no_cancel_dialog = gtk_dialog_new ();
181 	gtk_window_set_position (GTK_WINDOW (yes_no_cancel_dialog), GTK_WIN_POS_CENTER);
182 
183 	dialog_vbox = GTK_DIALOG (yes_no_cancel_dialog)->vbox;
184 	gtk_widget_show (dialog_vbox);
185 
186 	hbox = gtk_hbox_new (FALSE, 0);
187 	gtk_widget_show (hbox);
188 	gtk_box_pack_start (GTK_BOX (dialog_vbox), hbox, TRUE, TRUE, 0);
189 
190 	image = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_DIALOG);
191 	gtk_widget_show (image);
192 	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 20);
193 
194 	vbox = gtk_vbox_new (FALSE, 0);
195 	gtk_widget_show (vbox);
196 	gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
197 
198 
199 	label_header = gtk_label_new (markup_title);
200 	gtk_widget_show (label_header);
201 	gtk_box_pack_start (GTK_BOX (vbox), label_header, FALSE, TRUE, 20);
202 	gtk_label_set_use_markup (GTK_LABEL (label_header), TRUE);
203 	gtk_label_set_justify (GTK_LABEL (label_header), GTK_JUSTIFY_LEFT);
204 
205 	label_message = gtk_label_new (message);
206 	gtk_widget_show (label_message);
207 	gtk_box_pack_start (GTK_BOX (vbox), label_message, TRUE, TRUE, 0);
208 	gtk_label_set_use_markup (GTK_LABEL (label_message), TRUE);
209 	gtk_label_set_justify (GTK_LABEL (label_message), GTK_JUSTIFY_LEFT);
210 	gtk_label_set_line_wrap (GTK_LABEL (label_message), TRUE);
211 
212 	dialog_action_area = GTK_DIALOG (yes_no_cancel_dialog)->action_area;
213 	gtk_widget_show (dialog_action_area);
214 	gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END);
215 
216 	yesbutton = gtk_button_new_from_stock ("gtk-yes");
217 	gtk_widget_show (yesbutton);
218 	gtk_dialog_add_action_widget (GTK_DIALOG (yes_no_cancel_dialog), yesbutton, GTK_RESPONSE_YES);
219 	GTK_WIDGET_SET_FLAGS (yesbutton, GTK_CAN_DEFAULT);
220 
221 	nobutton = gtk_button_new_from_stock ("gtk-no");
222 	gtk_widget_show (nobutton);
223 	gtk_dialog_add_action_widget (GTK_DIALOG (yes_no_cancel_dialog), nobutton, GTK_RESPONSE_NO);
224 	GTK_WIDGET_SET_FLAGS (nobutton, GTK_CAN_DEFAULT);
225 
226 	cancelbutton = gtk_button_new_from_stock ("gtk-cancel");
227 	gtk_widget_show (cancelbutton);
228 	gtk_dialog_add_action_widget (GTK_DIALOG (yes_no_cancel_dialog), cancelbutton, GTK_RESPONSE_CANCEL);
229 	GTK_WIDGET_SET_FLAGS (cancelbutton, GTK_CAN_DEFAULT);
230 
231 	gtk_widget_grab_default (yesbutton);
232 
233 	g_free(markup_title);
234 	g_free(message);
235 
236 	return yes_no_cancel_dialog;
237 }
238 
239 GtkWidget*
create_yes_no_save_dialog(gchar * title,gchar * format,...)240 create_yes_no_save_dialog (gchar* title, gchar* format, ...)
241 {
242 	GtkWidget *yes_no_save_dialog;
243 	GtkWidget *dialog_vbox;
244 	GtkWidget *hbox;
245 	GtkWidget *image;
246 	GtkWidget *vbox;
247 	GtkWidget *label_header;
248 	GtkWidget *label_message;
249 	GtkWidget *dialog_action_area;
250 	GtkWidget *savebutton;
251 	GtkWidget *nobutton;
252 	GtkWidget* yesbutton;
253 	gchar* markup_title;
254 	gchar* message;
255  	va_list args;
256 
257 	markup_title = g_strconcat("<span size='larger'>",title,"</span>",NULL);
258 
259     va_start(args, format);
260     message = g_strdup_vprintf(format, args);
261     va_end(args);
262 
263 	yes_no_save_dialog = gtk_dialog_new ();
264 	gtk_window_set_position (GTK_WINDOW (yes_no_save_dialog), GTK_WIN_POS_CENTER);
265 
266 	dialog_vbox = GTK_DIALOG (yes_no_save_dialog)->vbox;
267 	gtk_widget_show (dialog_vbox);
268 
269 	hbox = gtk_hbox_new (FALSE, 0);
270 	gtk_widget_show (hbox);
271 	gtk_box_pack_start (GTK_BOX (dialog_vbox), hbox, TRUE, TRUE, 0);
272 
273 	image = gtk_image_new_from_stock ("gtk-dialog-question", GTK_ICON_SIZE_DIALOG);
274 	gtk_widget_show (image);
275 	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 20);
276 
277 	vbox = gtk_vbox_new (FALSE, 0);
278 	gtk_widget_show (vbox);
279 	gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
280 
281 	label_header = gtk_label_new (markup_title);
282 	gtk_widget_show (label_header);
283 	gtk_box_pack_start (GTK_BOX (vbox), label_header, FALSE, TRUE, 20);
284 	gtk_label_set_use_markup (GTK_LABEL (label_header), TRUE);
285 	gtk_label_set_justify (GTK_LABEL (label_header), GTK_JUSTIFY_LEFT);
286 
287 	label_message = gtk_label_new (message);
288 	gtk_widget_show (label_message);
289 	gtk_box_pack_start (GTK_BOX (vbox), label_message, TRUE, TRUE, 0);
290 	gtk_label_set_use_markup (GTK_LABEL (label_message), TRUE);
291 	gtk_label_set_justify (GTK_LABEL (label_message), GTK_JUSTIFY_LEFT);
292 	gtk_label_set_line_wrap (GTK_LABEL (label_message), TRUE);
293 
294 	dialog_action_area = GTK_DIALOG (yes_no_save_dialog)->action_area;
295 	gtk_widget_show (dialog_action_area);
296 	gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END);
297 
298 	yesbutton = gtk_button_new_from_stock ("gtk-yes");
299 	gtk_widget_show (yesbutton);
300 	gtk_dialog_add_action_widget (GTK_DIALOG (yes_no_save_dialog), yesbutton, GTK_RESPONSE_YES);
301 	GTK_WIDGET_SET_FLAGS (yesbutton, GTK_CAN_DEFAULT);
302 
303 	nobutton = gtk_button_new_from_stock ("gtk-no");
304 	gtk_widget_show (nobutton);
305 	gtk_dialog_add_action_widget (GTK_DIALOG (yes_no_save_dialog), nobutton, GTK_RESPONSE_NO);
306 	GTK_WIDGET_SET_FLAGS (nobutton, GTK_CAN_DEFAULT);
307 
308 	savebutton = gtk_button_new_from_stock ("gtk-save");
309 	gtk_widget_show (savebutton);
310 	gtk_dialog_add_action_widget (GTK_DIALOG (yes_no_save_dialog), savebutton, GTK_RESPONSE_OK);
311 	GTK_WIDGET_SET_FLAGS (savebutton, GTK_CAN_DEFAULT);
312 
313 	gtk_widget_grab_default (savebutton);
314 
315 	g_free(markup_title);
316 	g_free(message);
317 
318 	return yes_no_save_dialog;
319 }
320 
321 GtkWidget*
create_unsaved_files_dialog(void)322 create_unsaved_files_dialog (void)
323 {
324 	GtkWidget *unsaved_files_dialog;
325 	GtkWidget *dialog_vbox;
326 	GtkWidget *hbox;
327 	GtkWidget *image;
328 	GtkWidget *vbox;
329 	GtkWidget *label_msg;
330 	GtkWidget *label_detail;
331 	GtkWidget *dialog_action_area;
332 	GtkWidget *button_save_all;
333 	GtkWidget *button_choose_files;
334 	GtkWidget *button_dont_save;
335 	GtkWidget *button_cancel;
336 
337 	unsaved_files_dialog = gtk_dialog_new ();
338 
339 	dialog_vbox = GTK_DIALOG (unsaved_files_dialog)->vbox;
340 	gtk_widget_show (dialog_vbox);
341 
342 	hbox = gtk_hbox_new (FALSE, 0);
343 	gtk_widget_show (hbox);
344 	gtk_box_pack_start (GTK_BOX (dialog_vbox), hbox, TRUE, TRUE, 0);
345 
346 	image = gtk_image_new_from_stock ("gtk-dialog-warning", GTK_ICON_SIZE_DIALOG);
347 	gtk_widget_show (image);
348 	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 20);
349 
350 	vbox = gtk_vbox_new (FALSE, 0);
351 	gtk_widget_show (vbox);
352 	gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
353 
354 	label_msg = gtk_label_new (_("<span size='larger'><b>There are documents not saved.  Changes will be lost.</b></span>"));
355 	gtk_widget_show (label_msg);
356 	gtk_box_pack_start (GTK_BOX (vbox), label_msg, FALSE, FALSE, 15);
357 	gtk_label_set_use_markup (GTK_LABEL (label_msg), TRUE);
358 	gtk_label_set_justify (GTK_LABEL (label_msg), GTK_JUSTIFY_LEFT);
359 
360 	label_detail = gtk_label_new (_("<span>Please choose an action to be taken:\n\n\t<b>\"Save all\"</b> - will save all unsaved files.\n\t<b>\"Choose files\"</b> - will ask you to save each file.\n\t<b>\"Don't save\"</b> - will close cssed without saving any file.\n\t<b>\"Cancel\"</b> - will close this dialog but won't close cssed.</span>\n"));
361 	gtk_widget_show (label_detail);
362 	gtk_box_pack_start (GTK_BOX (vbox), label_detail, TRUE, TRUE, 0);
363 	gtk_label_set_use_markup (GTK_LABEL (label_detail), TRUE);
364 	gtk_label_set_justify (GTK_LABEL (label_detail), GTK_JUSTIFY_LEFT);
365 	gtk_label_set_line_wrap (GTK_LABEL (label_detail), TRUE);
366 
367 	dialog_action_area = GTK_DIALOG (unsaved_files_dialog)->action_area;
368 	gtk_widget_show (dialog_action_area);
369 	gtk_button_box_set_layout (GTK_BUTTON_BOX (dialog_action_area), GTK_BUTTONBOX_END);
370 
371 	button_save_all = gtk_button_new_with_mnemonic (_("_Save all"));
372 	gtk_widget_show (button_save_all);
373 	gtk_dialog_add_action_widget (GTK_DIALOG (unsaved_files_dialog), button_save_all, GTK_RESPONSE_OK);
374 	GTK_WIDGET_SET_FLAGS (button_save_all, GTK_CAN_DEFAULT);
375 
376 	button_choose_files = gtk_button_new_with_mnemonic (_("_Choose files"));
377 	gtk_widget_show (button_choose_files);
378 	gtk_dialog_add_action_widget (GTK_DIALOG (unsaved_files_dialog), button_choose_files, GTK_RESPONSE_ACCEPT);
379 	GTK_WIDGET_SET_FLAGS (button_choose_files, GTK_CAN_DEFAULT);
380 
381 	button_dont_save = gtk_button_new_with_mnemonic (_("_Don't save"));
382 	gtk_widget_show (button_dont_save);
383 	gtk_dialog_add_action_widget (GTK_DIALOG (unsaved_files_dialog), button_dont_save, GTK_RESPONSE_NO);
384 	GTK_WIDGET_SET_FLAGS (button_choose_files, GTK_CAN_DEFAULT);
385 
386 
387 	button_cancel = gtk_button_new_from_stock ("gtk-cancel");
388 	gtk_widget_show (button_cancel);
389 	gtk_dialog_add_action_widget (GTK_DIALOG (unsaved_files_dialog), button_cancel, GTK_RESPONSE_CANCEL);
390 	GTK_WIDGET_SET_FLAGS (button_cancel, GTK_CAN_DEFAULT);
391 
392 	gtk_widget_grab_default (button_save_all);
393 	return unsaved_files_dialog;
394 }
395 
396 /* Converts a GdkColor to a triplet #RRGGBB string
397    the returned string must be freed by caller  */
398 gchar*
gdk_color_to_rgb_triplet_string(GdkColor * color)399 gdk_color_to_rgb_triplet_string(GdkColor* color)
400 {
401 	gchar* rgb;
402     rgb = g_strdup_printf("#%02x%02x%02x",
403                          color->red >> 8,
404                          color->green >> 8,
405                          color->blue >> 8);
406 	return rgb;
407 }
408 
409 /* converts a GdkColor to scintilla rgb integer color */
410 gint
gdk_color_to_scintilla_integer_color(GdkColor * color)411 gdk_color_to_scintilla_integer_color( GdkColor* color )
412 {
413 
414 	guint16 red;
415 	guint16 green;
416 	guint16 blue;
417 	gint scicolor;
418 
419 	red =   (color->red/65535)*255;
420 	green = (color->green/65535)*255;
421 	blue =  (color->blue/65535)*255;
422 
423 	scicolor = red | (green << 8) | (blue << 16);
424 	DBGMSG (__FILE__,__LINE__,"\tscicolor %d %x", scicolor, scicolor);
425 
426 	return scicolor;
427 }
428 
429 /*  */
430 GtkWidget*
create_custom_button_from_stock(gchar * label_text,gchar * stock_id)431 create_custom_button_from_stock(gchar* label_text,gchar *stock_id)
432 {
433   GtkWidget* button;
434   GtkWidget* image;
435   GtkWidget* box;
436   GtkWidget* label;
437 
438   button = gtk_button_new();
439   box = gtk_hbox_new(FALSE,0);
440 
441   image = gtk_image_new_from_stock(stock_id,GTK_ICON_SIZE_BUTTON);
442   label = gtk_label_new(label_text);
443 
444   gtk_box_pack_start((GtkBox*)box, image, TRUE, TRUE, 0);
445   gtk_box_pack_end  ((GtkBox*)box, label, TRUE, TRUE, 0);
446   gtk_widget_show_all(box);
447   gtk_container_add(GTK_CONTAINER(button),box);
448 
449   return button;
450 }
451 /* returned buffer must be freed by caller, input buffer must be allocated
452 	in memory and it will be disposed */
453 gchar*
allocated_buffer_add_string(gchar * buffer,const gchar * string)454 allocated_buffer_add_string(gchar* buffer, const gchar* string)
455 {
456 	gchar* newstring;
457 	newstring = g_strconcat(buffer, string, NULL);
458 	g_free(buffer);
459 	return newstring;
460 }
461 
462 /* FIXME must be moved to a window function */
463 void
init_default_config(CssedWindow * window)464 init_default_config( CssedWindow *window )
465 {
466 	CssedConfig* cfg;
467 
468 	cfg = cssed_window_get_config( window );
469 
470 	cfg->window_x = 100;
471 	cfg->window_y = 100;
472 	cfg->window_width = 600;
473 	cfg->window_height = 400;
474 	cfg->initiall_state_maximized = FALSE;
475 	cfg->footer_pos = 200;
476 	cfg->sidebar_pos = 400;
477 	cfg->linenumbers = FALSE;
478 	cfg->autocompletion = FALSE;
479 	cfg->lineendings = FALSE;
480 	cfg->whitespaces = FALSE;
481 	cfg->folding = FALSE;
482 	cfg->lineswraped = FALSE;
483 	cfg->font = NULL;
484 	cfg->font_size = 10; //start with a visible font size by default
485 	cfg->opened_docs = NULL;
486 	cfg->DEFAULT_fore_color = 0x000077;
487 	cfg->DEFAULT_back_color = 0xffffff;
488 	cfg->DEFAULT_bold = FALSE;
489 	cfg->TAG_fore_color = 0xA46621;
490 	cfg->TAG_back_color = 0xffffff;
491 	cfg->TAG_bold = TRUE;
492 	cfg->PSEUDOCLASS_fore_color = 0x990066;
493 	cfg->PSEUDOCLASS_back_color = 0xffffff;
494 	cfg->PSEUDOCLASS_bold = FALSE;
495 	cfg->UNKNOWN_PSEUDOCLASS_fore_color = 0x0000ff;
496 	cfg->UNKNOWN_PSEUDOCLASS_back_color = 0xffffff;
497 	cfg->UNKNOWN_PSEUDOCLASS_bold = FALSE;
498 	cfg->OPERATOR_fore_color = 0x000099;
499 	cfg->OPERATOR_back_color = 0xffffff;
500 	cfg->OPERATOR_bold = FALSE;
501 	cfg->IDENTIFIER_fore_color = 0x990000;
502 	cfg->IDENTIFIER_back_color = 0xffffff;
503 	cfg->IDENTIFIER_bold = TRUE;
504 	cfg->UNKNOWN_IDENTIFIER_fore_color = 0x0000ff;
505 	cfg->UNKNOWN_IDENTIFIER_back_color = 0xffffff;
506 	cfg->UNKNOWN_IDENTIFIER_bold = FALSE;
507 	cfg->VALUE_fore_color = 0x222222;
508 	cfg->VALUE_back_color = 0xffffff;
509 	cfg->VALUE_bold = FALSE;
510 	cfg->COMMENT_fore_color = 0x666666;
511 	cfg->COMMENT_back_color = 0xffffff;
512 	cfg->COMMENT_bold = FALSE;
513 	cfg->IMPORTANT_fore_color = 0x000099;
514 	cfg->IMPORTANT_back_color = 0xffffff;
515 	cfg->IMPORTANT_bold = TRUE;
516 	cfg->DIRECTIVE_fore_color = 0x660066;
517 	cfg->DIRECTIVE_back_color = 0xffffff;
518 	cfg->DIRECTIVE_bold = FALSE;
519 	cfg->DOUBLESTRING_fore_color = 0x660033;
520 	cfg->DOUBLESTRING_back_color = 0xffffff;
521 	cfg->DOUBLESTRING_bold = FALSE;
522 	cfg->SINGLESTRING_fore_color = 0x660033;
523 	cfg->SINGLESTRING_back_color = 0xffffff;
524 	cfg->SINGLESTRING_bold = FALSE;
525 	cfg->CLASS_fore_color = 0x004400;
526 	cfg->CLASS_back_color = 0xffffff;
527 	cfg->CLASS_bold = TRUE;
528 	cfg->ID_fore_color = 0x004400;
529 	cfg->ID_back_color = 0xffffff;
530 	cfg->ID_bold = TRUE;
531 	cfg->VALID_VALUE_fore_color = 0x003399;
532 	cfg->VALID_VALUE_back_color = 0xffffff;
533 	cfg->VALID_VALUE_bold = FALSE;
534 	cfg->FUNCTION_fore_color = 0x993300;
535 	cfg->FUNCTION_back_color = 0xffffff;
536 	cfg->FUNCTION_bold = FALSE;
537 	cfg->NUMBER_fore_color = 0x330099;
538 	cfg->NUMBER_back_color = 0xffffff;
539 	cfg->NUMBER_bold = FALSE;
540 	cfg->UNIT_fore_color = 0x990000;
541 	cfg->UNIT_back_color = 0xffffff;
542 	cfg->UNIT_bold = FALSE;
543 	cfg->COLOR_fore_color = 0x006600;
544 	cfg->COLOR_back_color = 0xffffff;
545 	cfg->COLOR_bold = FALSE;
546 	cfg->HEXACOLOR_fore_color = 0x006600;
547 	cfg->HEXACOLOR_back_color = 0xffffff;
548 	cfg->HEXACOLOR_bold = FALSE;
549 	cfg->ATTR_MATCH_fore_color = 0x004444;
550 	cfg->ATTR_MATCH_back_color = 0xffffff;
551 	cfg->ATTR_MATCH_bold = FALSE;
552 	cfg->LANGUAGE_fore_color = 0x990000;
553 	cfg->LANGUAGE_back_color = 0xffffff;
554 	cfg->LANGUAGE_bold = FALSE;
555 }
556 
557 /* FIXME must be moved to a window function */
558 void
save_config_to_file(CssedWindow * window)559 save_config_to_file(CssedWindow* window)
560 {
561 	CssedConfig* cfg;
562 	CssedPlugin* plugin;
563 	gint nplugins;
564 	GList* plugins;
565 	//GString *configstr;
566 
567 	gchar* pluginstr;
568 	gchar* csseddir;
569 	gchar* cssedcfg_file;
570 	gchar* outstr;
571 	gchar* stylestr;
572 	gchar* styleout;
573 
574 	gint wx, wy, ww, wh; // window: x y width height.
575 	GdkWindow* gdw;
576 	GtkWidget* window_widget;
577 	GtkWidget* panned_footer;
578 	GtkWidget* panned_tree;
579 	GtkWidget* panned_sidebar;
580 	gint footer_pos;
581 	gint tree_pos;
582 	gint sidebar_pos;
583 	int fd;
584 #ifdef WIN32
585 	int written;
586 	gchar* tmp;
587 	gchar* line;
588 #else
589 	ssize_t written;
590 #endif
591 
592 	cfg = cssed_window_get_config( window );
593 	window_widget = cssed_window_get_window_widget( window );
594 	csseddir = g_strconcat(g_get_home_dir(), G_DIR_SEPARATOR_S, ".cssed", NULL);
595 
596 	if( !g_file_test(csseddir,G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) ){
597 #ifdef WIN32
598 		if( mkdir(csseddir) == -1 ){
599 #else
600 		if( mkdir(csseddir, S_IRWXU) == -1 ){
601 #endif
602 			g_free(csseddir);
603 			return;
604 		}
605 	}
606 
607 	cssedcfg_file = g_strconcat(csseddir, G_DIR_SEPARATOR_S, "cssed-cfg.xml",NULL);
608 	if( g_file_test(cssedcfg_file, G_FILE_TEST_IS_REGULAR| G_FILE_TEST_EXISTS) )
609 		unlink(cssedcfg_file); // we're deleting the file, if anything goes wrong ... Lost configuration ! FIXME
610 
611 	gdw = gtk_widget_get_parent_window(cssed_window_get_document_notebook(window));
612 
613 	panned_footer = lookup_widget( window_widget, "vpaned_main" ); //
614 	panned_sidebar = lookup_widget( window_widget, "hpaned_main" );
615 	panned_tree = lookup_widget( window_widget, "vpaned_css" );
616 
617 	if(gdk_window_get_state (gdw) == GDK_WINDOW_STATE_MAXIMIZED){
618 		ww = cfg->window_width;
619 		wh = cfg->window_height;
620 		wx = cfg->window_x;
621 		wy = cfg->window_y;
622 		cfg->initiall_state_maximized = TRUE;
623 	}else{ // get x & y pos to write to config
624 		ww = window_widget->allocation.width;
625 		wh = window_widget->allocation.height;
626 		gdk_window_get_root_origin(gdw, &wx, &wy);
627 		cfg->initiall_state_maximized = FALSE;
628 	}
629 	// get panned positions
630 	footer_pos = gtk_paned_get_position(GTK_PANED(panned_footer));
631 	sidebar_pos =  gtk_paned_get_position(GTK_PANED(panned_sidebar));
632 	tree_pos =  gtk_paned_get_position(GTK_PANED(panned_tree));
633 
634 #ifdef WIN32
635 	fd = _open(cssedcfg_file, _O_WRONLY|_O_CREAT, _S_IREAD|_S_IWRITE);
636 #else
637 	fd = open(cssedcfg_file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR);
638 #endif
639 
640 	if( fd == -1 ){
641 		g_free(cssedcfg_file);
642 		g_free(csseddir);
643 		return;
644 	}
645 
646 	if( cfg->browser_command ){
647 		outstr = g_strdup_printf("<cssed-conf>\n\t<browser command='%s' />\n\t", cfg->browser_command);
648 	}else{
649 		outstr = g_strdup("<cssed-conf>\n\t");
650 	}
651 
652 	written = write(fd, outstr, strlen(outstr) * sizeof(gchar));
653 	g_free(outstr);
654 	outstr = NULL;
655 
656 	if( written == -1 ){
657 		DBGMSG (__FILE__,__LINE__,"Can't write to file descriptor %d", fd);
658 		cssed_error_message(_("Cannot write to configuration file"),
659 							_("I'm unable to write to the configuration file,\nsettings will not be saved.")
660 							);
661 		return;
662 	}
663 
664 	if( cfg->font == NULL ){
665 		outstr = g_strdup_printf(
666 		//g_string_append_printf (configstr,
667 "<document>\n\t\t \
668 <linenumbers show=\"%s\" />\n\t\t \
669 <autocompletion enabled=\"%s\" />\n\t\t \
670 <lineendings show=\"%s\" /> \n\t\t \
671 <whitespaces show=\"%s\" /> \n\t\t \
672 <folding enabled=\"%s\" /> \n\t\t \
673 <lineswraped show=\"%s\" />\n\t  \
674 </document>\n\t  \
675 <window x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" maximized=\"%s\">\n\t\t  \
676 <footer position=\"%d\" />\n\t\t\
677 <sidebar position=\"%d\" />\n\t\t\
678 <csstreeview position=\"%d\" />\n\t\
679 </window>\n",
680 		cfg->linenumbers?"true":"false",
681 		cfg->autocompletion?"true":"false",
682 		cfg->lineendings?"true":"false",
683 		cfg->whitespaces?"true":"false",
684 		cfg->folding?"true":"false",
685 		cfg->lineswraped?"true":"false",
686 		wx>0?wx:0,
687 		wy>0?wy:0,
688 		ww,
689 		wh,
690 		cfg->initiall_state_maximized?"true":"false",
691 		footer_pos,
692 		sidebar_pos,
693 		tree_pos
694 		);
695 	}else{
696 		outstr = g_strdup_printf(
697 		//g_string_append_printf (configstr,
698 "<document>\n\t\t \
699 <linenumbers show=\"%s\" />\n\t\t \
700 <autocompletion enabled=\"%s\" />\n\t\t \
701 <lineendings show=\"%s\" /> \n\t\t \
702 <whitespaces show=\"%s\" /> \n\t\t \
703 <folding enabled=\"%s\" /> \n\t\t \
704 <lineswraped show=\"%s\" />\n\t \t \
705 <font name=\"%s\" size=\"%d\" />\n\t \
706 </document>\n\t  \
707 <window x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" maximized=\"%s\">\n\t\t  \
708 <footer position=\"%d\" />\n\t\t\
709 <sidebar position=\"%d\" />\n\t\t\
710 <csstreeview position=\"%d\" />\n\t\
711 </window>\n",
712 		cfg->linenumbers?"true":"false",
713 		cfg->autocompletion?"true":"false",
714 		cfg->lineendings?"true":"false",
715 		cfg->whitespaces?"true":"false",
716 		cfg->folding?"true":"false",
717 		cfg->lineswraped?"true":"false",
718 		cfg->font,
719 		cfg->font_size,
720 		wx>0?wx:0,
721 		wy>0?wy:0,
722 		ww,
723 		wh,
724 		cfg->initiall_state_maximized?"true":"false",
725 		footer_pos,
726 		sidebar_pos,
727 		tree_pos
728 		);
729 	}
730 
731 	written = write(fd, outstr, strlen(outstr) * sizeof(gchar));
732 	g_free(outstr);
733 	outstr = NULL;
734 
735 	if( written == -1 ){
736 		DBGMSG (__FILE__,__LINE__,"Can't write to file descriptor %d", fd);
737 		cssed_error_message(_("Cannot write to configuration file"),
738 							_("I'm unable to write to the configuration file,\nsettings will not be saved.")
739 							);
740 		return;
741 	}
742 	/* *********************** loaded plugins ************************ */
743 
744 	nplugins = cssed_window_get_plugin_list_length( window );
745 	if( nplugins > 0 ){
746 		pluginstr = g_strdup("\t<plugins>\n\t\t");
747 		plugins = cssed_window_get_plugin_list_first( window );
748 		while( plugins ){
749 			plugin = plugins->data;
750 			pluginstr = allocated_buffer_add_string(pluginstr, "<plugin file=\"" );
751 			pluginstr = allocated_buffer_add_string(pluginstr, cssed_plugin_get_filename(plugin));
752 			pluginstr = allocated_buffer_add_string(pluginstr, "\" />\n\t" );
753 
754 			plugins = g_list_next( plugins );
755 			if( plugins ) pluginstr = allocated_buffer_add_string( pluginstr, "\t" );
756 		}
757 		pluginstr = allocated_buffer_add_string( pluginstr, "</plugins>\n\t" );
758 		written = write( fd, pluginstr, strlen(pluginstr) * sizeof(gchar));
759 		g_free( pluginstr );
760 		pluginstr = NULL;
761 		if( written == -1 ){
762 			DBGMSG (__FILE__,__LINE__,"Can't write to file descriptor %d", fd);
763 			cssed_error_message(_("Cannot write to configuration file"),
764 								_("I'm unable to write to the configuration file,\nsettings will not be saved."));
765 			return;
766 		}
767 	}
768 
769 #ifdef WIN32
770 	/* I have to strip the g_strdup call in two pieces as it seems
771 	that glib (Win32) have problems with long va_args */
772 	stylestr = g_strdup_printf(
773 "<style name=\"DEFAULT\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\"	/>\n\t\t \
774 <style name=\"TAG\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
775 <style name=\"PSEUDOCLASS\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
776 <style name=\"UNKNOWN_PSEUDOCLASS\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
777 <style name=\"OPERATOR\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
778 <style name=\"IDENTIFIER\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
779 <style name=\"UNKNOWN_IDENTIFIER\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
780 <style name=\"VALUE\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
781 <style name=\"COMMENT\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
782 <style name=\"IMPORTANT\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
783 <style name=\"DIRECTIVE\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
784 <style name=\"DOUBLESTRING\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t ",
785 	cfg->DEFAULT_fore_color, cfg->DEFAULT_back_color, cfg->DEFAULT_bold?"true":"false",
786 		cfg->TAG_fore_color, cfg->TAG_back_color, cfg->TAG_bold?"true":"false",
787 		cfg->PSEUDOCLASS_fore_color, cfg->PSEUDOCLASS_back_color, cfg->PSEUDOCLASS_bold?"true":"false",
788 		cfg->UNKNOWN_PSEUDOCLASS_fore_color, cfg->UNKNOWN_PSEUDOCLASS_back_color, cfg->UNKNOWN_PSEUDOCLASS_bold?"true":"false",
789 		cfg->OPERATOR_fore_color, cfg->OPERATOR_back_color, cfg->OPERATOR_bold?"true":"false",
790 		cfg->IDENTIFIER_fore_color, cfg->IDENTIFIER_back_color, cfg->IDENTIFIER_bold?"true":"false",
791 		cfg->UNKNOWN_IDENTIFIER_fore_color, cfg->UNKNOWN_IDENTIFIER_back_color, cfg->UNKNOWN_IDENTIFIER_bold?"true":"false",
792 		cfg->VALUE_fore_color, cfg->VALUE_back_color, cfg->VALUE_bold?"true":"false",
793 		cfg->COMMENT_fore_color, cfg->COMMENT_back_color, cfg->COMMENT_bold?"true":"false",
794 		cfg->IMPORTANT_fore_color, cfg->IMPORTANT_back_color, cfg->IMPORTANT_bold?"true":"false",
795 		cfg->DIRECTIVE_fore_color, cfg->DIRECTIVE_back_color, cfg->DIRECTIVE_bold?"true":"false",
796 		cfg->DOUBLESTRING_fore_color, cfg->DOUBLESTRING_back_color, cfg->DOUBLESTRING_bold?"true":"false"
797 		);
798 
799 	line = g_strdup_printf(
800 		"<style name=\"SINGLESTRING\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
801 <style name=\"CLASS\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
802 <style name=\"ID\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
803 <style name=\"VALID_VALUE\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
804 <style name=\"FUNCTION\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
805 <style name=\"NUMBER\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
806 <style name=\"UNIT\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
807 <style name=\"COLOR\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
808 <style name=\"HEXACOLOR\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
809 <style name=\"ATTR_MATCH\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
810 <style name=\"LANGUAGE\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t",
811 		cfg->SINGLESTRING_fore_color, cfg->SINGLESTRING_back_color, cfg->SINGLESTRING_bold?"true":"false",
812 		cfg->CLASS_fore_color, cfg->CLASS_back_color, cfg->CLASS_bold?"true":"false",
813 		cfg->ID_fore_color, cfg->ID_back_color, cfg->ID_bold?"true":"false",
814 		cfg->VALID_VALUE_fore_color, cfg->VALID_VALUE_back_color, cfg->VALID_VALUE_bold?"true":"false",
815 		cfg->FUNCTION_fore_color, cfg->FUNCTION_back_color, cfg->FUNCTION_bold?"true":"false",
816 		cfg->NUMBER_fore_color, cfg->NUMBER_back_color, cfg->NUMBER_bold?"true":"false",
817 		cfg->UNIT_fore_color, cfg->UNIT_back_color, cfg->UNIT_bold?"true":"false",
818 		cfg->COLOR_fore_color, cfg->COLOR_back_color, cfg->COLOR_bold?"true":"false",
819 		cfg->HEXACOLOR_fore_color, cfg->HEXACOLOR_back_color, cfg->HEXACOLOR_bold?"true":"false",
820 		cfg->ATTR_MATCH_fore_color, cfg->ATTR_MATCH_back_color, cfg->ATTR_MATCH_bold?"true":"false",
821 		cfg->LANGUAGE_fore_color, cfg->LANGUAGE_back_color, cfg->LANGUAGE_bold?"true":"false"
822 	);
823 	tmp = stylestr;
824 	stylestr = g_strconcat(tmp, line, NULL);
825 	g_free(tmp);
826 	g_free(line);
827 #else
828 	stylestr = g_strdup_printf(
829 "<style name=\"DEFAULT\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\"	/>\n\t\t \
830 <style name=\"TAG\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
831 <style name=\"PSEUDOCLASS\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
832 <style name=\"UNKNOWN_PSEUDOCLASS\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
833 <style name=\"OPERATOR\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
834 <style name=\"IDENTIFIER\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
835 <style name=\"UNKNOWN_IDENTIFIER\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
836 <style name=\"VALUE\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
837 <style name=\"COMMENT\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
838 <style name=\"IMPORTANT\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
839 <style name=\"DIRECTIVE\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
840 <style name=\"DOUBLESTRING\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
841 <style name=\"SINGLESTRING\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
842 <style name=\"CLASS\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
843 <style name=\"ID\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
844 <style name=\"VALID_VALUE\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
845 <style name=\"FUNCTION\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
846 <style name=\"NUMBER\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
847 <style name=\"UNIT\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
848 <style name=\"COLOR\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
849 <style name=\"HEXACOLOR\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
850 <style name=\"ATTR_MATCH\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t\t \
851 <style name=\"LANGUAGE\" fore=\"%#06x\" back=\"%#06x\" bold=\"%s\" />\n\t",
852 		cfg->DEFAULT_fore_color, cfg->DEFAULT_back_color, cfg->DEFAULT_bold?"true":"false",
853 		cfg->TAG_fore_color, cfg->TAG_back_color, cfg->TAG_bold?"true":"false",
854 		cfg->PSEUDOCLASS_fore_color, cfg->PSEUDOCLASS_back_color, cfg->PSEUDOCLASS_bold?"true":"false",
855 		cfg->UNKNOWN_PSEUDOCLASS_fore_color, cfg->UNKNOWN_PSEUDOCLASS_back_color, cfg->UNKNOWN_PSEUDOCLASS_bold?"true":"false",
856 		cfg->OPERATOR_fore_color, cfg->OPERATOR_back_color, cfg->OPERATOR_bold?"true":"false",
857 		cfg->IDENTIFIER_fore_color, cfg->IDENTIFIER_back_color, cfg->IDENTIFIER_bold?"true":"false",
858 		cfg->UNKNOWN_IDENTIFIER_fore_color, cfg->UNKNOWN_IDENTIFIER_back_color, cfg->UNKNOWN_IDENTIFIER_bold?"true":"false",
859 		cfg->VALUE_fore_color, cfg->VALUE_back_color, cfg->VALUE_bold?"true":"false",
860 		cfg->COMMENT_fore_color, cfg->COMMENT_back_color, cfg->COMMENT_bold?"true":"false",
861 		cfg->IMPORTANT_fore_color, cfg->IMPORTANT_back_color, cfg->IMPORTANT_bold?"true":"false",
862 		cfg->DIRECTIVE_fore_color, cfg->DIRECTIVE_back_color, cfg->DIRECTIVE_bold?"true":"false",
863 		cfg->DOUBLESTRING_fore_color, cfg->DOUBLESTRING_back_color, cfg->DOUBLESTRING_bold?"true":"false",
864 		cfg->SINGLESTRING_fore_color, cfg->SINGLESTRING_back_color, cfg->SINGLESTRING_bold?"true":"false",
865 		cfg->CLASS_fore_color, cfg->CLASS_back_color, cfg->CLASS_bold?"true":"false",
866 		cfg->ID_fore_color, cfg->ID_back_color, cfg->ID_bold?"true":"false",
867 		cfg->VALID_VALUE_fore_color, cfg->VALID_VALUE_back_color, cfg->VALID_VALUE_bold?"true":"false",
868 		cfg->FUNCTION_fore_color, cfg->FUNCTION_back_color, cfg->FUNCTION_bold?"true":"false",
869 		cfg->NUMBER_fore_color, cfg->NUMBER_back_color, cfg->NUMBER_bold?"true":"false",
870 		cfg->UNIT_fore_color, cfg->UNIT_back_color, cfg->UNIT_bold?"true":"false",
871 		cfg->COLOR_fore_color, cfg->COLOR_back_color, cfg->COLOR_bold?"true":"false",
872 		cfg->HEXACOLOR_fore_color, cfg->HEXACOLOR_back_color, cfg->HEXACOLOR_bold?"true":"false",
873 		cfg->ATTR_MATCH_fore_color, cfg->ATTR_MATCH_back_color, cfg->ATTR_MATCH_bold?"true":"false",
874 		cfg->LANGUAGE_fore_color, cfg->LANGUAGE_back_color, cfg->LANGUAGE_bold?"true":"false"
875 	);
876 #endif
877 	styleout = g_strconcat("<highlighting> \n\t\t",stylestr,"</highlighting>\n</cssed-conf>",NULL);
878 	g_free(stylestr);
879 
880 	written = write(fd, styleout, strlen(styleout) * sizeof(gchar));
881 	DBGMSG (__FILE__,__LINE__,"Config written %d chars",written);
882 
883 	g_free( styleout );
884 	g_free( cssedcfg_file );
885 	g_free( csseddir );
886 
887 #ifdef WIN32
888 	_close(fd);
889 #else
890 	close( fd );
891 #endif
892 }
893 
894 
895 void
896 cssed_config_copy_style_and_defaults( CssedConfig* source, CssedConfig* target )
897 {
898 
899 	target->linenumbers  = source->linenumbers ;
900 	target->autocompletion  = source->autocompletion ;
901 	target->lineendings  = source->lineendings ;
902 	target->whitespaces  = source->whitespaces ;
903 	target->folding = source->folding ;
904 	target->lineswraped = source->lineswraped ;
905 	target->font = source->font ;
906 	target->font_size = source->font_size ;
907 	target->opened_docs = source->opened_docs ;
908 	target->browser_command  = source->browser_command;
909 	target->DEFAULT_fore_color = source->DEFAULT_fore_color ;
910 	target->DEFAULT_back_color = source->DEFAULT_back_color ;
911 	target->DEFAULT_bold = source->DEFAULT_bold ;
912 	target->TAG_fore_color = source->TAG_fore_color ;
913 	target->TAG_back_color = source->TAG_back_color ;
914 	target->TAG_bold = source->TAG_bold ;
915 	target->PSEUDOCLASS_fore_color = source->PSEUDOCLASS_fore_color ;
916 	target->PSEUDOCLASS_back_color = source->PSEUDOCLASS_back_color ;
917 	target->PSEUDOCLASS_bold = source->PSEUDOCLASS_bold ;
918 	target->UNKNOWN_PSEUDOCLASS_fore_color = source->UNKNOWN_PSEUDOCLASS_fore_color ;
919 	target->UNKNOWN_PSEUDOCLASS_back_color = source->UNKNOWN_PSEUDOCLASS_back_color ;
920 	target->UNKNOWN_PSEUDOCLASS_bold = source->UNKNOWN_PSEUDOCLASS_bold ;
921 	target->OPERATOR_fore_color = source->OPERATOR_fore_color ;
922 	target->OPERATOR_back_color = source->OPERATOR_back_color ;
923 	target->OPERATOR_bold = source->OPERATOR_bold ;
924 	target->IDENTIFIER_fore_color = source->IDENTIFIER_fore_color ;
925 	target->IDENTIFIER_back_color = source->IDENTIFIER_back_color ;
926 	target->IDENTIFIER_bold = source->IDENTIFIER_bold ;
927 	target->UNKNOWN_IDENTIFIER_fore_color = source->UNKNOWN_IDENTIFIER_fore_color ;
928 	target->UNKNOWN_IDENTIFIER_back_color = source->UNKNOWN_IDENTIFIER_back_color ;
929 	target->UNKNOWN_IDENTIFIER_bold = source->UNKNOWN_IDENTIFIER_bold ;
930 	target->VALUE_fore_color = source->VALUE_fore_color ;
931 	target->VALUE_back_color = source->VALUE_back_color ;
932 	target->VALUE_bold = source->VALUE_bold ;
933 	target->COMMENT_fore_color = source->COMMENT_fore_color ;
934 	target->COMMENT_back_color = source->COMMENT_back_color ;
935 	target->COMMENT_bold = source->COMMENT_bold ;
936 	target->IMPORTANT_fore_color = source->IMPORTANT_fore_color ;
937 	target->IMPORTANT_back_color = source->IMPORTANT_back_color ;
938 	target->IMPORTANT_bold = source->IMPORTANT_bold ;
939 	target->DIRECTIVE_fore_color = source->DIRECTIVE_fore_color ;
940 	target->DIRECTIVE_back_color = source->DIRECTIVE_back_color ;
941 	target->DIRECTIVE_bold = source->DIRECTIVE_bold ;
942 	target->DOUBLESTRING_fore_color = source->DOUBLESTRING_fore_color ;
943 	target->DOUBLESTRING_back_color = source->DOUBLESTRING_back_color ;
944 	target->DOUBLESTRING_bold = source->DOUBLESTRING_bold ;
945 	target->SINGLESTRING_fore_color = source->SINGLESTRING_fore_color ;
946 	target->SINGLESTRING_back_color = source->SINGLESTRING_back_color ;
947 	target->SINGLESTRING_bold = source->SINGLESTRING_bold ;
948 	target->CLASS_fore_color = source->CLASS_fore_color ;
949 	target->CLASS_back_color = source->CLASS_back_color ;
950 	target->CLASS_bold = source->CLASS_bold ;
951 	target->ID_fore_color = source->ID_fore_color ;
952 	target->ID_back_color = source->ID_back_color ;
953 	target->ID_bold = source->ID_bold ;
954 	target->VALID_VALUE_fore_color = source->VALID_VALUE_fore_color ;
955 	target->VALID_VALUE_back_color = source->VALID_VALUE_back_color ;
956 	target->VALID_VALUE_bold = source->VALID_VALUE_bold ;
957 	target->FUNCTION_fore_color = source->FUNCTION_fore_color ;
958 	target->FUNCTION_back_color = source->FUNCTION_back_color ;
959 	target->FUNCTION_bold = source->FUNCTION_bold ;
960 	target->NUMBER_fore_color = source->NUMBER_fore_color ;
961 	target->NUMBER_back_color = source->NUMBER_back_color ;
962 	target->NUMBER_bold = source->NUMBER_bold ;
963 	target->UNIT_fore_color = source->UNIT_fore_color ;
964 	target->UNIT_back_color = source->UNIT_back_color ;
965 	target->UNIT_bold = source->UNIT_bold ;
966 	target->COLOR_fore_color = source->COLOR_fore_color ;
967 	target->COLOR_back_color = source->COLOR_back_color ;
968 	target->COLOR_bold = source->COLOR_bold ;
969 	target->HEXACOLOR_fore_color = source->HEXACOLOR_fore_color ;
970 	target->HEXACOLOR_back_color = source->HEXACOLOR_back_color ;
971 	target->HEXACOLOR_bold = source->HEXACOLOR_bold ;
972 	target->ATTR_MATCH_fore_color = source->ATTR_MATCH_fore_color ;
973 	target->ATTR_MATCH_back_color = source->ATTR_MATCH_back_color ;
974 	target->ATTR_MATCH_bold = source->ATTR_MATCH_bold ;
975 	target->LANGUAGE_fore_color = source->LANGUAGE_fore_color ;
976 	target->LANGUAGE_back_color = source->LANGUAGE_back_color ;
977 	target->LANGUAGE_bold = source->LANGUAGE_bold ;
978 }
979 
980 /* FIXME this shoud be window function */
981 void
982 load_all_plugins( CssedWindow* cssedwin, GList* plugins_to_load )
983 {
984 	GList* plugins;
985 	CssedPlugin* plugin;
986 
987 	g_return_if_fail( plugins_to_load != NULL );
988 	plugins = g_list_first(plugins_to_load);
989 
990 	while( plugins ){
991 		plugin = cssed_init_plugin(cssedwin, plugins->data);
992 		if( plugin ){
993 			cssed_load_plugin(plugin);
994 		}
995 		plugin = NULL;
996 		plugins = g_list_next(plugins);
997 	}
998 	g_list_free(plugins);
999 }
1000 
1001 /* used by the xml parsers FIXME */
1002 gboolean
1003 char_ptr_is_decimal_num(const gchar* ptr)
1004 {
1005 	gint len, i;
1006 	len = strlen(ptr);
1007 
1008 	if( len <= 0 )
1009 		return FALSE;
1010 
1011 	for(i=0;i<len;i++){
1012 		if( !isdigit( ptr[i] ) )
1013 				return FALSE;
1014 	}
1015 	return TRUE;
1016 }
1017 
1018 /* 	This should go to the - future - css support code FIXME
1019 */
1020 gint
1021 tree_iter_doc_scanner_compare_string   (GtkTreeModel *model,
1022 										GtkTreeIter *a,
1023 										GtkTreeIter *b,
1024 										gpointer user_data)
1025 {
1026 	gchar* first_string;
1027 	gchar* second_string;
1028 	gchar* cleaned_first;
1029 	gchar* cleaned_second;
1030 	gint len_first;
1031 	gint len_second;
1032 	gint first;
1033 	gint second;
1034 	gint col = GPOINTER_TO_INT(user_data);
1035 
1036 	gtk_tree_model_get(model, a, col, &first_string, -1);
1037     gtk_tree_model_get(model, b, col, &second_string, -1);
1038 
1039 	if((first_string==NULL) && (second_string==NULL))	return 0;
1040 	if((first_string==NULL) && (second_string!=NULL))	return 1;
1041 	if((first_string!=NULL) && (second_string==NULL))	return -1;
1042 
1043 	//clean first
1044 	pango_parse_markup (first_string, strlen(first_string), 0, NULL, &cleaned_first, NULL, NULL);
1045 	pango_parse_markup (second_string, strlen(second_string), 0, NULL, &cleaned_second, NULL, NULL);
1046 
1047 	switch( col ){
1048 		case 0: // clean the number in the form <span>[111]</span> and convert to int
1049 			len_first = strlen(cleaned_first);
1050 			len_second = strlen(cleaned_second);
1051 			return g_ascii_strncasecmp(cleaned_first, cleaned_second, len_first>len_second?len_first:len_second);
1052 		break;
1053 
1054 		case 1: // clean the number in the form <span>[111]</span> and convert to int
1055 			first = atoi(cleaned_first);
1056 			second = atoi(cleaned_second);
1057 			if( first == second ) return 0;
1058 			else return first>second?1:-1;
1059 		break;
1060 		case 2:
1061 		case 3:
1062 			len_first = strlen(cleaned_first);
1063 			len_second = strlen(cleaned_second);
1064 			return g_ascii_strncasecmp(cleaned_first, cleaned_second, len_first>len_second?len_first:len_second);
1065 		break;
1066 	}
1067 	g_free( cleaned_first );
1068 	g_free( cleaned_second );
1069 	g_free( first_string );
1070 	g_free( second_string );
1071 
1072 	return 0;
1073 }
1074 
1075 /* THOSE SHOULD GO TO CALLBACKS */
1076 /* load save text buffer */
1077 void
1078 text_buffer_save_contents( GtkTextBuffer* buffer, gchar* filename )
1079 {
1080 	GtkTextIter iter_start;
1081 	GtkTextIter iter_end;
1082 	gchar* text;
1083 	FILE* f;
1084 
1085 	gtk_text_buffer_get_start_iter(buffer,&iter_start);
1086 	gtk_text_buffer_get_end_iter(buffer,&iter_end);
1087 
1088 	text = gtk_text_buffer_get_text(buffer, &iter_start, &iter_end, FALSE);
1089 
1090 	f = fopen (filename, "w");
1091 	if (f == NULL)
1092 	{
1093 		g_free (text);
1094 	}
1095 	else
1096 	{
1097 		fwrite (text, sizeof (gchar), strlen(text), f);
1098 		g_free (text);
1099 		fclose (f);
1100 	}
1101 }
1102 
1103 void
1104 text_buffer_load_contents( GtkTextBuffer* buffer, gchar* filename )
1105 {
1106 	gchar* text;
1107 
1108 	if ( g_file_get_contents( filename, &text, NULL, NULL ) ){
1109 		gtk_text_buffer_set_text(buffer, text,  -1);
1110 		g_free(text);
1111 	}
1112 }
1113 /* load save scratch pad */
1114 void
1115 scratch_pad_load_contents( GtkTextBuffer* scratch_pad_buffer )
1116 {
1117 	gchar* file;
1118 
1119 #ifdef WIN32
1120 	file = g_strconcat( g_get_home_dir(), "\\cssed\\scratch", NULL );
1121 #else
1122 	file = g_strconcat( g_get_home_dir(), "/.cssed/scratch", NULL );
1123 #endif
1124 
1125 	text_buffer_load_contents(scratch_pad_buffer, file);
1126 	g_free(file);
1127 }
1128 void
1129 scratch_pad_save_contents( GtkTextBuffer* scratch_pad_buffer )
1130 {
1131 	gchar* file;
1132 
1133 #ifdef WIN32
1134 	file = g_strconcat( g_get_home_dir(), "\\cssed\\scratch", NULL );
1135 #else
1136 	file = g_strconcat( g_get_home_dir(), "/.cssed/scratch", NULL );
1137 #endif
1138 	text_buffer_save_contents(scratch_pad_buffer, file);
1139 	g_free(file);
1140 }
1141 
1142 CssedEolMode
1143 buffer_get_first_eol( gchar* buffer_start, gchar* buffer_end )
1144 {
1145 	gchar* iterator;
1146 
1147 #ifdef WIN32
1148 	g_return_val_if_fail( buffer_start != NULL, EOL_MODE_CRLF ); // default
1149 #else
1150 	g_return_val_if_fail( buffer_start != NULL, EOL_MODE_LF ); // default
1151 #endif
1152 
1153 	iterator = buffer_start;
1154 
1155 	if( buffer_end == NULL ){
1156 		while( *iterator != '\0' ){
1157 			if( *iterator == '\r' ){
1158 				if( *(iterator + 1) == '\n' )
1159 					return EOL_MODE_CRLF;
1160 				else
1161 					return EOL_MODE_CR;
1162 			}else if( *iterator == '\n' ){
1163 				return EOL_MODE_LF;
1164 			}
1165 			++iterator;
1166 		}
1167 	} else {
1168 		if( !(buffer_end > buffer_start)){ // empty buffer
1169 #ifdef WIN32
1170 			return EOL_MODE_CRLF; // default
1171 #else
1172 			return EOL_MODE_LF; // default
1173 #endif
1174 		}
1175 		while( *iterator != '\0' && iterator != buffer_end ){
1176 			if( *iterator == '\r' ){
1177 				if( *(iterator + 1) == '\n' )
1178 					return EOL_MODE_CRLF;
1179 				else
1180 					return EOL_MODE_CR;
1181 			}else if( *iterator == '\n' ){
1182 				return EOL_MODE_LF;
1183 			}
1184 			++iterator;
1185 		}
1186 	}
1187 
1188 #ifdef WIN32
1189 	return EOL_MODE_CRLF; // default
1190 #else
1191 	return EOL_MODE_LF; // default
1192 #endif
1193 
1194 }
1195 
1196 // This is to be used with both Gtk2.2 and Gtk2.4
1197 // FIXME: there're around a big bunch of different
1198 // file open - save funtions, that should be deleted
1199 // and changed for a generic one.
1200 // This is the seed for this generic function but right now
1201 // it's only used in newly written code.
1202 
1203 gchar*
1204 cssed_prompt_for_file (CssedWindow* window, gchar *title, gchar* path, CssedFileSelectorType type)
1205 {
1206 	GtkWidget *opensel = NULL; // keep compiler happy
1207 	GtkWindow *window_widget;
1208 	gchar *last_dir;
1209 	gchar *filename, *basename;
1210 #ifndef GTK_ATLEAST_2_4
1211 	G_CONST_RETURN  gchar* sel_filename = NULL;
1212 	gchar *fullname;
1213 #endif
1214 
1215 	if( window != NULL )
1216 		window_widget = GTK_WINDOW(cssed_window_get_window_widget(window));
1217 	else
1218 		window_widget = NULL;
1219 
1220 #ifndef GTK_ATLEAST_2_4
1221 	opensel = gtk_file_selection_new (title);
1222 	switch( type ){
1223 		case CSSED_FILESELECTOR_SAVE:
1224 		case CSSED_FILESELECTOR_SELECT_FOLDER:
1225 			if( window ){
1226 				if( path == NULL ){
1227 					last_dir = cssed_window_get_last_save_dir( window );
1228 					if( last_dir != NULL ){
1229 						fullname = g_strconcat( last_dir, G_DIR_SEPARATOR_S, NULL);
1230 						gtk_file_selection_set_filename( GTK_FILE_SELECTION (opensel), fullname );
1231 						g_free(last_dir);
1232 						g_free(fullname);
1233 					}
1234 				}else{
1235 					gtk_file_selection_set_filename( GTK_FILE_SELECTION (opensel), path );
1236 				}
1237 			}
1238 			break;
1239 		case CSSED_FILESELECTOR_OPEN:
1240 		case CSSED_FILESELECTOR_CREATE_FOLDER:
1241 			if( window ){
1242 				if( path == NULL ){
1243 					last_dir = cssed_window_get_last_open_dir( window );
1244 					if( last_dir != NULL ){
1245 						fullname = g_strconcat( last_dir, G_DIR_SEPARATOR_S, NULL);
1246 						gtk_file_selection_set_filename( GTK_FILE_SELECTION (opensel), fullname );
1247 						g_free(last_dir);
1248 						g_free(fullname);
1249 					}
1250 				}else{
1251 					gtk_file_selection_set_filename( GTK_FILE_SELECTION (opensel), path );
1252 				}
1253 			}
1254 			break;
1255 	}
1256 #else // defined GTK_ATLEAST_2_4
1257 	switch( type ){
1258 		case CSSED_FILESELECTOR_OPEN:
1259 			opensel = gtk_file_chooser_dialog_new(title, window_widget, type,
1260 												GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1261 												GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
1262 			if( window ){
1263 				if( path == NULL ){
1264 					last_dir = cssed_window_get_last_open_dir( window );
1265 					if( last_dir != NULL ){
1266 						gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER (opensel), last_dir );
1267 						g_free(last_dir);
1268 					}
1269 				}else{
1270 					if( g_file_test(path, G_FILE_TEST_IS_DIR) ) {
1271 						gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (opensel), path);
1272 					}else{
1273 						//basename = 	g_path_get_basename (path);
1274 						gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (opensel), path);
1275 						//gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (opensel), basename);
1276 						//g_free( basename );
1277 					}
1278 				}
1279 			}
1280 			break;
1281 		case CSSED_FILESELECTOR_SAVE:
1282 			opensel = gtk_file_chooser_dialog_new(title, window_widget, type,
1283 												GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1284 												GTK_STOCK_SAVE, GTK_RESPONSE_OK, NULL);
1285 			if( window ){
1286 				if( path == NULL ){
1287 					last_dir = cssed_window_get_last_save_dir( window );
1288 					if( last_dir != NULL ){
1289 						gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER (opensel), last_dir );
1290 						g_free(last_dir);
1291 					}
1292 				}else{
1293 					if( g_file_test(path, G_FILE_TEST_IS_DIR) ) {
1294 						gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (opensel), path);
1295 					}else{
1296 						gchar *dirname = g_path_get_dirname(path);
1297 						if( dirname ){
1298 							gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (opensel), dirname);
1299 							g_free(dirname);
1300 						}
1301 						basename = 	g_path_get_basename (path);
1302 						gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER (opensel), basename);
1303 						g_free( basename );
1304 					}
1305 				}
1306 			}
1307 			break;
1308 		case CSSED_FILESELECTOR_SELECT_FOLDER:
1309 			opensel = gtk_file_chooser_dialog_new(title, window_widget, type,
1310 												GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1311 												GTK_STOCK_OPEN, GTK_RESPONSE_OK, NULL);
1312 			if( window ){
1313 				if( path == NULL ){
1314 					last_dir = cssed_window_get_last_open_dir( window );
1315 					if( last_dir != NULL ){
1316 						gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER (opensel), last_dir );
1317 						g_free(last_dir);
1318 					}
1319 				}else{
1320 					 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (opensel), path);
1321 				}
1322 			}
1323 			break;
1324 		case CSSED_FILESELECTOR_CREATE_FOLDER:
1325 			opensel = gtk_file_chooser_dialog_new(title, window_widget, type,
1326 												GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
1327 												GTK_STOCK_NEW, GTK_RESPONSE_OK, NULL);
1328 			if( window ){
1329 				if( path == NULL ){
1330 					last_dir = cssed_window_get_last_save_dir( window );
1331 					if( last_dir != NULL ){
1332 						gtk_file_chooser_set_current_folder( GTK_FILE_CHOOSER (opensel), last_dir );
1333 						g_free(last_dir);
1334 					}
1335 				}else{
1336 					gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (opensel), path);
1337 				}
1338 			}
1339 			break;
1340 	}
1341 #endif
1342 	if( gtk_dialog_run(GTK_DIALOG(opensel)) == GTK_RESPONSE_OK ){
1343 #ifndef GTK_ATLEAST_2_4
1344 		sel_filename = gtk_file_selection_get_filename( GTK_FILE_SELECTION(opensel) );
1345 		filename = g_strdup(sel_filename);
1346 #else
1347 		filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(opensel) );
1348 #endif
1349 		gtk_widget_destroy(opensel);
1350 		return filename;
1351 	}else{
1352 		gtk_widget_destroy(opensel);
1353 		return NULL;
1354 	}
1355 }
1356 
1357 // shows an error message from GError, see document.h for error codes
1358 void
1359 cssed_show_message_from_error (GError *error, gchar *title, gboolean free_error)
1360 {
1361 	g_return_if_fail( error != NULL );
1362 
1363 	switch(error->code){
1364 		case CSSED_FILE_ERROR_LAST:
1365 		case CSSED_ERROR_FILE_IS_OPENED:
1366 			break;// those should be ignored
1367 		default:
1368 			cssed_error_message (title, error->message);
1369 			break;
1370 	}
1371 	if( free_error ) g_error_free (error);
1372 }
1373 
1374 // for variable substitution, don't use it with large text as it uses a copy - so it doubles the
1375 // memory needed for the string substitution.
1376 gchar* cssed_string_replace_all(gchar *string, gchar *replaced_str, gchar *replacement_str)
1377 {
1378 	gchar* string_copy; // we'll manipulate it so we need a copy
1379 	gchar *iterator, *match, *endstr; // catch position pointers
1380 	GString *newstring;
1381 
1382 	g_return_val_if_fail(string != NULL, NULL);
1383 	g_return_val_if_fail(replaced_str != NULL, NULL);
1384 	g_return_val_if_fail(replacement_str != NULL, NULL);
1385 
1386 	newstring = g_string_new("");
1387 	string_copy = g_strdup(string);
1388 	endstr = string_copy + strlen(string_copy);
1389 	iterator = string_copy;
1390 
1391 	while( (match = strstr (iterator, replaced_str)) != NULL ){
1392 		*match = '\0';
1393 		newstring = g_string_append(newstring, iterator);
1394 		newstring = g_string_append(newstring, replacement_str);
1395 		iterator = match + strlen(replaced_str);
1396 	}
1397 
1398 	// if no match it'll copy the whole string, if there's something
1399 	// before last match will append the leading text.
1400 	if( iterator != endstr )
1401 		newstring = g_string_append(newstring, iterator);
1402 
1403 	g_free(string_copy);
1404 	string_copy = g_strdup(newstring->str);
1405 	g_string_free(newstring, TRUE);
1406 
1407 	return string_copy;
1408 }
1409 
1410 gint
1411 cssed_string_unescape_uri( const gchar *source, gchar **retval )
1412 
1413  {
1414 	gint pos, value, len, i=0;
1415 	gchar dummy[] = " ";
1416 	const gchar hex_digits[] = "0123456789ABCDEF";
1417 	gchar *dest;
1418 
1419 	g_return_val_if_fail(source, -1);
1420 	len = strlen(source);
1421 	*retval =  g_malloc0(len*sizeof(gchar));
1422 	dest = *retval;
1423 
1424 	while( i < len )
1425     {
1426 		if( '\0' == *source ){
1427 			dest[i] = '\0';
1428 			return( i );
1429 		}
1430 		if( '%' != *source ){
1431 			dest[i] = *source;
1432 			source++;
1433 		}else{
1434 			*dummy = toupper( *(++source) );
1435 			pos = (int)strcspn( hex_digits, dummy );
1436 
1437 			if( pos < 16 )
1438 			{
1439 				value = pos;
1440 				*dummy = toupper( *(++source) );
1441 				pos = (int)strcspn( hex_digits, dummy );
1442 				if( pos < 16 )
1443 				{
1444 					value = (value * 16) + pos;
1445 					source++;
1446 				}
1447 				dest[i] = (char)value;
1448 			} else {
1449 				dest[i] = '%';
1450 			}
1451 		}
1452 		i++;
1453 	}
1454 
1455 	dest[len-1] = '\0';
1456 	return( -1 );
1457 }
1458 
1459