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