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 <string.h>
24
25 #ifndef WIN32
26 #ifdef DARWIN
27 # include <sys/types.h>
28 #endif
29 # include <unistd.h>
30 # include <sys/mman.h>
31 # include <libgen.h>
32 #endif
33
34 #include "cssedwindow.h"
35 #include "document.h"
36 #include "file-type-manager.h"
37 #include "plugin.h"
38 #include "configdlg-interface.h"
39 #include "cssdialogs-hash.h"
40 #include "cssdialogs-class.h"
41 #include "support.h"
42 #include "utils.h"
43
44 #define CSSED_DYNWIDGETS(obj) ((obj)->dynamic_widgets)
45 #define CSSED_PANES(obj) ((obj)->panes)
46 #define CSSED_FILETYPE_MANAGER(obj) ((obj)->manager)
47
48 typedef struct _CssedWindowPanes {
49 GtkWidget* vpaned_main;
50 GtkWidget* hpaned_up;
51 GtkWidget* vpaned_sidebar;
52 } CssedWindowPanes;
53
54 typedef struct _CssedDynamicWidgets { // those widgets are managed by the app
55 GtkWidget* save_button;
56 GtkWidget* save_main_menu;
57 GtkWidget* undo_button;
58 GtkWidget* undo_main_menu;
59 GtkWidget* undo_pop_menu;
60 GtkWidget* redo_button;
61 GtkWidget* redo_main_menu;
62 GtkWidget* redo_pop_menu;
63 } CssedDynamicWidgets;
64
65 typedef struct _CssedDynamicMenus { // those menus change their state depending on current document
66 GtkWidget *menu_item_line_numbers;
67 GtkWidget *menu_item_endings;
68 GtkWidget *menu_item_white_spaces;
69 GtkWidget *menu_item_lines_wrapped;
70 GtkWidget *menu_item_eol_mode_cr;
71 GtkWidget *menu_item_eol_mode_lf;
72 GtkWidget *menu_item_eol_mode_crlf;
73 GtkWidget *menu_item_autocompletion;
74 GtkWidget *menu_item_folding;
75 } CssedDynamicMenus;
76
77 struct _CssedWindow {
78 GtkWidget* window_widget; // the window widget
79 GtkWidget* notebook_docs; // the documents notebook
80 GtkWidget* notebook_utils; // the output and scratch pad notebook
81 GtkWidget* notebook_sidebar; // the side bar notebook
82 GtkWidget* tree_view_css_properties; // the tree with CSS def from XML parsing
83 GtkWidget* tree_view_css_current; // The current selector ( selector scanner ) properties
84 GtkWidget* tree_view_output; // The program output will be stored here
85 GtkWidget* tree_view_digest; // this is for the document parser
86 GtkWidget* pop_menu; // the editor pop menu
87 GtkWidget* filetypes_menu; // the file types menu
88 gchar* keywords_list; // a space separated string with all def keywords from XML parsing
89 gchar* last_open_dir; // last open directory
90 gchar* last_save_dir; // last saved directory
91 //gchar* last_scan_file; file opened in the "Digest tab" (if any). FIXME move to CSS
92 GList* plugins_list; // all enabled plugins should be here
93 GList* document_list; // the document list
94 GtkTextBuffer* scratch_buffer; // the (static) scratch pad
95 GHashTable* cssdialogs_hash; // a hash containing css dialog classes
96 CssedConfig* config; // configuration data
97 CssedDynamicMenus* dynamic_menus; // the dynamic view menu, must change on a per-document basis
98 CssedDynamicWidgets* dynamic_widgets; // those are changed by the app (not the user)
99 CssedWindowPanes* panes; // the panes that divide the app's UI
100 CssedFileTypeManager* manager; // TESTING here file type manager
101 };
102
103 // prototypes for this module
104 CssedDynamicMenus* cssed_window_dynamic_menus_new (void);
105 CssedDynamicWidgets* cssed_window_dynamic_widgets_new (void);
106 CssedWindowPanes* cssed_window_panes_new (void);
107
108 // to dispose lists memory using g_list_foreach
109 void
free_data_foreach(gpointer data,gpointer user_data)110 free_data_foreach (gpointer data, gpointer user_data)
111 {
112 g_free(data);
113 }
114
115 // to unload plugins using g_list_foreach
116 void
unload_plugins_foreach(gpointer data,gpointer user_data)117 unload_plugins_foreach (gpointer data, gpointer user_data)
118 {
119 cssed_unload_plugin((CssedPlugin*) data);
120 }
121
122 // window functions
123 CssedWindow*
cssed_window_new()124 cssed_window_new()
125 {
126 CssedWindow* window;
127
128 window = g_malloc(sizeof (CssedWindow));
129 window->window_widget = NULL;
130 window->notebook_docs = NULL;
131 window->notebook_utils = NULL;
132 window->notebook_sidebar = NULL;
133 window->tree_view_css_properties = NULL;
134 window->tree_view_css_current = NULL;
135 window->tree_view_output = NULL;
136 window->tree_view_digest = NULL;
137 window->dynamic_menus = cssed_window_dynamic_menus_new();
138 window->document_list = NULL;
139 window->keywords_list = g_strdup("");
140 window->config = cssed_window_config_new();
141 window->cssdialogs_hash = create_and_fill_cssdialogs_hash_table();
142 window->plugins_list = NULL;
143 window->last_open_dir = NULL;
144 window->last_save_dir = NULL;
145 //window->last_scan_file = NULL;
146 window->pop_menu = NULL;
147 window->scratch_buffer = NULL;
148 window->dynamic_widgets = cssed_window_dynamic_widgets_new();
149 window->panes = cssed_window_panes_new();
150 window->manager = cssed_file_type_manager_new();
151
152 return window;
153 }
154 void
cssed_window_destroy(CssedWindow * window)155 cssed_window_destroy (CssedWindow* window)
156 {
157 gtk_widget_hide(window->window_widget);
158 g_free(window->dynamic_menus);
159 g_list_foreach(window->document_list, free_data_foreach , NULL);
160 g_list_free(window->document_list);
161 g_list_foreach(window->plugins_list, unload_plugins_foreach, NULL);
162 g_list_free(window->plugins_list);
163 g_hash_table_destroy (window->cssdialogs_hash);
164 if( window->last_open_dir ) g_free(window->last_open_dir);
165 if( window->last_save_dir ) g_free(window->last_save_dir);
166 if( window->config->browser_command ) g_free(window->config->browser_command);
167 g_free(window->config);
168 g_free(window->dynamic_widgets);
169 g_free(window->panes);
170 cssed_window_free_keyword_list(window);
171 cssed_file_type_manager_free(window->manager);
172 g_free(window);
173 gtk_main_quit ();
174 }
175
176 void
cssed_window_quit(CssedWindow * window)177 cssed_window_quit( CssedWindow* window )
178 {
179 CssedDoc* tmpdoc;
180 GtkWidget* window_widget;
181 GList* doclist;
182 GList* unsaved_docs = NULL;
183 gint ntosave;
184 GtkWidget* dlg;
185 gint response;
186 gint untitled_count = 0;
187 gchar* name = NULL;
188 gchar* filename;
189
190 doclist = g_list_first((GList*) window->document_list);
191 window_widget = cssed_window_get_window_widget(window);
192 while( doclist != NULL ){
193 tmpdoc = (CssedDoc*) doclist->data;
194 if( document_get_modified(tmpdoc) ){
195 unsaved_docs = g_list_append(unsaved_docs, tmpdoc);
196 }
197 doclist = g_list_next(doclist);
198 }
199 ntosave = g_list_length(unsaved_docs);
200 if( ntosave > 0 ){
201 dlg = create_unsaved_files_dialog();
202 response = gtk_dialog_run(GTK_DIALOG(dlg));
203 switch( response ){
204 case GTK_RESPONSE_OK:
205 while( unsaved_docs != NULL ){
206 tmpdoc = (CssedDoc*) unsaved_docs->data;
207 filename = document_get_filename(tmpdoc);
208 if( filename != NULL ){
209 document_save((CssedDoc*) tmpdoc);
210 g_free(filename);
211 }else{
212 name = g_strdup_printf(_("untitled_%d"),untitled_count);
213 document_set_filename(tmpdoc, name);
214 document_save((CssedDoc*) tmpdoc);
215 untitled_count++;
216 g_free(name);
217 }
218 unsaved_docs = g_list_next(unsaved_docs);
219 }
220 break;
221 case GTK_RESPONSE_ACCEPT: // choose files
222 while( unsaved_docs != NULL ){
223 GtkWidget* confirm;
224
225 tmpdoc = (CssedDoc*) unsaved_docs->data;
226 filename = document_get_filename(tmpdoc);
227 if( filename == NULL ){
228 name = g_strdup_printf(_("untitled_%d"),untitled_count);
229 document_set_filename(tmpdoc, name);
230 filename = g_strdup(name);
231 g_free(name);
232 untitled_count++;
233 }
234
235 confirm = create_yes_no_cancel_dialog(_("Do you want to save this file?"), _("File name: %s"), filename);
236 g_free(filename);
237
238 response = gtk_dialog_run(GTK_DIALOG(confirm));
239 gtk_widget_destroy(GTK_WIDGET(confirm));
240
241 if( response == GTK_RESPONSE_YES ){
242 document_save(tmpdoc);
243 unsaved_docs = g_list_next(unsaved_docs);
244 }else if ( response == GTK_RESPONSE_NO ){
245 unsaved_docs = g_list_next(unsaved_docs);
246 }else{ // this is cancel or close so aborting
247 gtk_widget_destroy(dlg);
248 return;
249 }
250 }
251 break;
252 case GTK_RESPONSE_CANCEL: // canceled by user don't quit
253 gtk_widget_destroy(dlg);
254 return;
255 }
256 }
257 save_config_to_file(window);
258 scratch_pad_save_contents(window->scratch_buffer);
259 cssed_window_destroy(window);
260 }
261 // last open dir / last open file
262 void
cssed_window_set_last_open_dir(CssedWindow * window,gchar * dirname)263 cssed_window_set_last_open_dir( CssedWindow* window, gchar* dirname )
264 {
265 g_return_if_fail(dirname != NULL);
266
267 if( window->last_open_dir != NULL ){
268 g_free(window->last_open_dir);
269 }
270 window->last_open_dir = g_strdup(dirname);
271 }
272
273 gint
cssed_window_get_width(CssedWindow * window)274 cssed_window_get_width( CssedWindow* window )
275 {
276 gint width, height;
277 gtk_window_get_size(GTK_WINDOW(window->window_widget), &width, &height);
278 return width;
279 }
280
281 gint
cssed_window_get_height(CssedWindow * window)282 cssed_window_get_height( CssedWindow* window )
283 {
284 gint width, height;
285 gtk_window_get_size(GTK_WINDOW(window->window_widget), &width, &height);
286 return height;
287 }
288
289 gchar*
cssed_window_get_last_open_dir(CssedWindow * window)290 cssed_window_get_last_open_dir( CssedWindow* window )
291 {
292 if( window->last_open_dir != NULL )
293 return g_strdup(window->last_open_dir);
294 else
295 return NULL;
296 }
297
298 void
cssed_window_set_last_save_dir(CssedWindow * window,gchar * dirname)299 cssed_window_set_last_save_dir( CssedWindow* window, gchar* dirname )
300 {
301 g_return_if_fail(dirname != NULL);
302 if( window->last_save_dir != NULL )
303 g_free(window->last_save_dir);
304 window->last_save_dir = g_strdup(dirname);
305 }
306
307 gchar*
cssed_window_get_last_save_dir(CssedWindow * window)308 cssed_window_get_last_save_dir( CssedWindow* window )
309 {
310 if( window->last_save_dir == NULL ) return NULL;
311 return g_strdup(window->last_save_dir);
312
313 }
314 /* This should be moved to the CSS module FIXME
315 void
316 cssed_window_set_last_scan_file( CssedWindow* window, gchar* filename )
317 {
318 if( window->last_scan_file != NULL ){
319 g_free(window->last_scan_file);
320 }
321 if( filename == NULL ){
322 window->last_scan_file = filename;
323 }else{
324 window->last_scan_file = g_strdup(filename);
325 }
326 }
327
328 gchar*
329 cssed_window_get_last_scan_file( CssedWindow* window )
330 {
331 if( window->last_scan_file == NULL ) return NULL;
332 return g_strdup(window->last_scan_file);
333
334 }
335 */
336
337 CssedConfig*
cssed_window_get_config(CssedWindow * window)338 cssed_window_get_config( CssedWindow* window )
339 {
340 return window->config;
341 }
342
343 CssedConfig*
cssed_window_config_new()344 cssed_window_config_new ()
345 {
346 return g_malloc0(sizeof(CssedConfig));
347 }
348
349 // get/set window object fields
350 GtkWidget*
cssed_window_get_window_widget(CssedWindow * window)351 cssed_window_get_window_widget( CssedWindow* window )
352 {
353 return window->window_widget;
354 }
355
356 void
cssed_window_set_window_widget(CssedWindow * window,GtkWidget * widget)357 cssed_window_set_window_widget( CssedWindow* window, GtkWidget* widget )
358 {
359 window->window_widget = widget;
360 }
361 //
362 GtkWidget*
cssed_window_get_document_notebook(CssedWindow * window)363 cssed_window_get_document_notebook ( CssedWindow* window )
364 {
365 return window->notebook_docs;
366 }
367
368 void
cssed_window_set_document_notebook(CssedWindow * window,GtkWidget * widget)369 cssed_window_set_document_notebook ( CssedWindow* window, GtkWidget* widget )
370 {
371 window->notebook_docs = widget;
372 }
373 //
374 GtkWidget*
cssed_window_get_footer_notebook(CssedWindow * window)375 cssed_window_get_footer_notebook ( CssedWindow* window )
376 {
377 return window->notebook_utils;
378 }
379
380 void
cssed_window_set_footer_notebook(CssedWindow * window,GtkWidget * widget)381 cssed_window_set_footer_notebook ( CssedWindow* window, GtkWidget* widget )
382 {
383 window->notebook_utils = widget;
384 }
385 //
386 GtkWidget*
cssed_window_get_sidebar_notebook(CssedWindow * window)387 cssed_window_get_sidebar_notebook ( CssedWindow* window )
388 {
389 return window->notebook_sidebar;
390 }
391
392 void
cssed_window_set_sidebar_notebook(CssedWindow * window,GtkWidget * widget)393 cssed_window_set_sidebar_notebook ( CssedWindow* window, GtkWidget* widget )
394 {
395 window->notebook_sidebar = widget;
396 }
397 //
398 GtkWidget*
cssed_window_get_css_definition_treeview(CssedWindow * window)399 cssed_window_get_css_definition_treeview ( CssedWindow* window )
400 {
401 return window->tree_view_css_properties;
402 }
403
404 void
cssed_window_set_css_definition_treeview(CssedWindow * window,GtkWidget * widget)405 cssed_window_set_css_definition_treeview ( CssedWindow* window, GtkWidget* widget )
406 {
407 window->tree_view_css_properties = widget;
408 }
409 //
410 GtkWidget*
cssed_window_get_selector_scanner_treeview(CssedWindow * window)411 cssed_window_get_selector_scanner_treeview ( CssedWindow* window )
412 {
413 return window->tree_view_css_current;
414 }
415
416 void
cssed_window_set_selector_scanner_treeview(CssedWindow * window,GtkWidget * widget)417 cssed_window_set_selector_scanner_treeview ( CssedWindow* window, GtkWidget* widget )
418 {
419 window->tree_view_css_current = widget;
420 }
421 //
422 GtkWidget*
cssed_window_get_output_treeview(CssedWindow * window)423 cssed_window_get_output_treeview ( CssedWindow* window )
424 {
425 return window->tree_view_output;
426 }
427
428 void
cssed_window_set_output_treeview(CssedWindow * window,GtkWidget * widget)429 cssed_window_set_output_treeview ( CssedWindow* window, GtkWidget* widget )
430 {
431 window->tree_view_output = widget;
432 }
433 //
434 GtkWidget*
cssed_window_get_digest_treeview(CssedWindow * window)435 cssed_window_get_digest_treeview ( CssedWindow* window )
436 {
437 return window->tree_view_digest;
438 }
439
440 void
cssed_window_set_digest_treeview(CssedWindow * window,GtkWidget * widget)441 cssed_window_set_digest_treeview ( CssedWindow* window, GtkWidget* widget )
442 {
443 window->tree_view_digest = widget;
444 }
445 //
446 GtkWidget*
cssed_window_get_pop_menu(CssedWindow * window)447 cssed_window_get_pop_menu ( CssedWindow* window )
448 {
449 return window->pop_menu;
450 }
451
cssed_window_set_pop_menu(CssedWindow * window,GtkWidget * widget)452 void cssed_window_set_pop_menu ( CssedWindow* window, GtkWidget* widget )
453 {
454 window->pop_menu = widget;
455 }
456
457 //
458 GtkTextBuffer*
cssed_window_get_scratch_buffer(CssedWindow * window)459 cssed_window_get_scratch_buffer ( CssedWindow* window )
460 {
461 return window->scratch_buffer;
462 }
463
464 void
cssed_window_set_scratch_buffer(CssedWindow * window,GtkTextBuffer * widget)465 cssed_window_set_scratch_buffer ( CssedWindow* window, GtkTextBuffer* widget )
466 {
467 window->scratch_buffer = widget;
468 }
469 //
470 GtkWidget*
cssed_window_get_filetypes_menu(CssedWindow * window)471 cssed_window_get_filetypes_menu (CssedWindow* window )
472 {
473 return window->filetypes_menu;
474 }
475 void
cssed_window_set_filetypes_menu(CssedWindow * window,GtkWidget * menu)476 cssed_window_set_filetypes_menu (CssedWindow* window, GtkWidget* menu )
477 {
478 window->filetypes_menu = menu;
479 }
480 //
481 void
cssed_window_set_filetype_manager(CssedWindow * window,CssedFileTypeManager * manager)482 cssed_window_set_filetype_manager( CssedWindow* window, CssedFileTypeManager* manager)
483 {
484 window->manager = manager;
485 }
486
487 CssedFileTypeManager*
cssed_window_get_filetype_manager(CssedWindow * window)488 cssed_window_get_filetype_manager( CssedWindow* window)
489 {
490 return window->manager;
491 }
492
493 // dynamic menus
494 CssedDynamicMenus*
cssed_window_dynamic_menus_new(void)495 cssed_window_dynamic_menus_new( void )
496 {
497 CssedDynamicMenus* menus;
498 menus = g_malloc (sizeof (CssedDynamicMenus));
499 return menus;
500 }
501
502 void
cssed_window_dynamic_menus_set_full(CssedWindow * window,GtkWidget * menu_item_line_numbers,GtkWidget * menu_item_endings,GtkWidget * menu_item_white_spaces,GtkWidget * menu_item_lines_wrapped,GtkWidget * menu_item_eol_mode_cr,GtkWidget * menu_item_eol_mode_lf,GtkWidget * menu_item_eol_mode_crlf,GtkWidget * menu_item_autocompletion,GtkWidget * menu_item_folding)503 cssed_window_dynamic_menus_set_full( CssedWindow* window,
504 GtkWidget *menu_item_line_numbers,
505 GtkWidget *menu_item_endings,
506 GtkWidget *menu_item_white_spaces,
507 GtkWidget *menu_item_lines_wrapped,
508 GtkWidget *menu_item_eol_mode_cr,
509 GtkWidget *menu_item_eol_mode_lf,
510 GtkWidget *menu_item_eol_mode_crlf,
511 GtkWidget *menu_item_autocompletion,
512 GtkWidget *menu_item_folding )
513 {
514 CssedDynamicMenus* menus;
515
516 menus = window->dynamic_menus;
517 menus->menu_item_line_numbers = menu_item_line_numbers;
518 menus->menu_item_endings = menu_item_endings;
519 menus->menu_item_white_spaces = menu_item_white_spaces;
520 menus->menu_item_lines_wrapped = menu_item_lines_wrapped;
521 menus->menu_item_eol_mode_cr = menu_item_eol_mode_cr;
522 menus->menu_item_eol_mode_lf = menu_item_eol_mode_lf;
523 menus->menu_item_eol_mode_crlf = menu_item_eol_mode_crlf;
524 menus->menu_item_autocompletion = menu_item_autocompletion;
525 menus->menu_item_folding = menu_item_folding;
526 }
527
528 void
cssed_window_dynamic_menus_set_state(CssedWindow * window,gboolean line_numbers_enabled,gboolean line_endings_enabled,gboolean white_spaces_enabled,gboolean menu_item_lines_wrapped,gboolean autocompletion_enabled,gboolean folding_enabled)529 cssed_window_dynamic_menus_set_state(CssedWindow* window,
530 gboolean line_numbers_enabled,
531 gboolean line_endings_enabled,
532 gboolean white_spaces_enabled,
533 gboolean menu_item_lines_wrapped,
534 gboolean autocompletion_enabled,
535 gboolean folding_enabled )
536 {
537 CssedDynamicMenus* menus;
538
539 menus = window->dynamic_menus;
540
541 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menus->menu_item_line_numbers),
542 line_numbers_enabled);
543 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menus->menu_item_endings),
544 line_endings_enabled);
545 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menus->menu_item_white_spaces),
546 white_spaces_enabled);
547 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menus->menu_item_lines_wrapped),
548 menu_item_lines_wrapped);
549 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menus->menu_item_autocompletion),
550 autocompletion_enabled);
551 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM(menus->menu_item_folding),
552 folding_enabled);
553
554 }
555
556 void
cssed_window_dynamic_menus_set_eols_state(CssedWindow * window,CssedEolMode eols)557 cssed_window_dynamic_menus_set_eols_state( CssedWindow* window, CssedEolMode eols )
558 {
559 CssedDynamicMenus* menus;
560
561 menus = window->dynamic_menus;
562
563 switch( eols ){
564 case EOL_MODE_CR:
565 gtk_check_menu_item_set_active (
566 GTK_CHECK_MENU_ITEM(menus->menu_item_eol_mode_cr),
567 TRUE);
568 break;
569 case EOL_MODE_LF:
570 gtk_check_menu_item_set_active (
571 GTK_CHECK_MENU_ITEM(menus->menu_item_eol_mode_lf),
572 TRUE);
573 break;
574 case EOL_MODE_CRLF:
575 gtk_check_menu_item_set_active (
576 GTK_CHECK_MENU_ITEM(menus->menu_item_eol_mode_crlf),
577 TRUE);
578 break;
579 default:
580 break;
581 }
582 }
583
584 // dynamic widgets
585 CssedDynamicWidgets*
cssed_window_dynamic_widgets_new()586 cssed_window_dynamic_widgets_new()
587 {
588 return g_malloc(sizeof(CssedDynamicWidgets));
589 }
590
591 void
cssed_window_dynamic_widgets_set(CssedWindow * window,GtkWidget * save_button,GtkWidget * save_main_menu,GtkWidget * undo_button,GtkWidget * undo_main_menu,GtkWidget * undo_pop_menu,GtkWidget * redo_button,GtkWidget * redo_main_menu,GtkWidget * redo_pop_menu)592 cssed_window_dynamic_widgets_set( CssedWindow* window,
593 GtkWidget* save_button,
594 GtkWidget* save_main_menu,
595 GtkWidget* undo_button,
596 GtkWidget* undo_main_menu,
597 GtkWidget* undo_pop_menu,
598 GtkWidget* redo_button,
599 GtkWidget* redo_main_menu,
600 GtkWidget* redo_pop_menu )
601 {
602 CSSED_DYNWIDGETS(window)->save_button = save_button;
603 CSSED_DYNWIDGETS(window)->save_main_menu = save_main_menu;
604 CSSED_DYNWIDGETS(window)->undo_button = undo_button;
605 CSSED_DYNWIDGETS(window)->undo_main_menu = undo_main_menu;
606 CSSED_DYNWIDGETS(window)->undo_pop_menu = undo_pop_menu;
607 CSSED_DYNWIDGETS(window)->redo_button = redo_button;
608 CSSED_DYNWIDGETS(window)->redo_main_menu = redo_main_menu;
609 CSSED_DYNWIDGETS(window)->redo_pop_menu = redo_pop_menu;
610 }
611
612 void
cssed_window_enable_save(CssedWindow * window)613 cssed_window_enable_save ( CssedWindow* window )
614 {
615 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->save_button, TRUE);
616 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->save_main_menu, TRUE);
617 }
618
619 void
cssed_window_disable_save(CssedWindow * window)620 cssed_window_disable_save(CssedWindow* window )
621 {
622 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->save_button, FALSE);
623 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->save_main_menu, FALSE);
624 }
625
626 void
cssed_window_enable_undo(CssedWindow * window)627 cssed_window_enable_undo (CssedWindow* window )
628 {
629 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->undo_button, TRUE);
630 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->undo_main_menu, TRUE);
631 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->undo_pop_menu, TRUE);
632 }
633
634 void
cssed_window_disable_undo(CssedWindow * window)635 cssed_window_disable_undo(CssedWindow* window )
636 {
637 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->undo_button, FALSE);
638 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->undo_main_menu, FALSE);
639 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->undo_pop_menu, FALSE);
640 }
641
642 void
cssed_window_enable_redo(CssedWindow * window)643 cssed_window_enable_redo (CssedWindow* window )
644 {
645 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->redo_button, TRUE);
646 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->redo_main_menu, TRUE);
647 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->redo_pop_menu, TRUE);
648 }
649
650 void
cssed_window_disable_redo(CssedWindow * window)651 cssed_window_disable_redo(CssedWindow* window )
652 {
653 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->redo_button, FALSE);
654 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->redo_main_menu, FALSE);
655 gtk_widget_set_sensitive(CSSED_DYNWIDGETS(window)->redo_pop_menu, FALSE);
656 }
657
658
659 // window panes
660 CssedWindowPanes*
cssed_window_panes_new()661 cssed_window_panes_new()
662 {
663 return g_malloc0(sizeof(CssedWindowPanes));
664 }
665
666 void
cssed_window_panes_set(CssedWindow * window,GtkWidget * vpaned_main,GtkWidget * hpaned_up,GtkWidget * vpaned_sidebar)667 cssed_window_panes_set( CssedWindow* window,
668 GtkWidget* vpaned_main,
669 GtkWidget* hpaned_up,
670 GtkWidget* vpaned_sidebar )
671 {
672 CSSED_PANES(window)->vpaned_main = vpaned_main;
673 CSSED_PANES(window)->hpaned_up = hpaned_up;
674 CSSED_PANES(window)->vpaned_sidebar = vpaned_sidebar;
675 }
676 void
cssed_window_ensure_output_visible(CssedWindow * window)677 cssed_window_ensure_output_visible( CssedWindow* window )
678 {
679 GtkWidget* notebook;
680 GtkWidget* vpaned;
681 gint pos;
682 gint height;
683 gint width;
684
685 notebook = cssed_window_get_footer_notebook(window);
686 vpaned = CSSED_PANES(window)->vpaned_main;
687
688 gtk_window_get_size(GTK_WINDOW(window->window_widget), &width, &height);
689 pos = gtk_paned_get_position(GTK_PANED(vpaned));
690 gtk_notebook_set_current_page (GTK_NOTEBOOK(notebook), 0);
691
692 if( pos > height-(height/3) )
693 gtk_paned_set_position(GTK_PANED(vpaned) ,height-(height/3));
694 }
695
696 void
cssed_window_ensure_selector_scanner_visible(CssedWindow * window)697 cssed_window_ensure_selector_scanner_visible( CssedWindow* window )
698 {
699 GtkWidget* notebook;
700 GtkWidget* hpaned;
701 GtkWidget* vpaned;
702 GtkWidget* vpaned_css;
703 gint pos;
704 gint height;
705 gint width;
706
707 notebook = cssed_window_get_sidebar_notebook(window);
708 vpaned = CSSED_PANES(window)->vpaned_main;
709 vpaned_css = CSSED_PANES(window)->vpaned_sidebar;
710 hpaned = CSSED_PANES(window)->hpaned_up;
711
712 gtk_window_get_size(GTK_WINDOW(window->window_widget), &width, &height);
713 pos = gtk_paned_get_position(GTK_PANED(hpaned));
714
715 gtk_notebook_set_current_page (GTK_NOTEBOOK(notebook), 0);
716 if( pos < width/3 ){
717 gtk_paned_set_position(GTK_PANED(hpaned), width/3);
718 }
719 pos = gtk_paned_get_position(GTK_PANED(vpaned_css));
720
721 if( pos < height/3 ){
722 gtk_paned_set_position(GTK_PANED(vpaned_css), height/3);
723 }
724 }
725
726 // window functions
727 void
cssed_window_output_write(CssedWindow * window,gchar * format,...)728 cssed_window_output_write( CssedWindow* window, gchar* format, ... )
729 {
730 GtkTreeView* view;
731 GtkListStore* store;
732 GtkTreeIter iter;
733 GtkTreePath* path;
734 gchar* message;
735 va_list args;
736
737 va_start(args, format);
738 message = g_strdup_vprintf(format, args);
739 va_end(args);
740
741 view = GTK_TREE_VIEW(window->tree_view_output);
742 store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
743 gtk_list_store_append (store, &iter);
744 gtk_list_store_set (store, &iter, 0, message, -1);
745 g_free(message);
746
747 path = gtk_tree_model_get_path (GTK_TREE_MODEL(store), &iter);
748 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), path, NULL, FALSE, 0, 0);
749 cssed_window_ensure_output_visible (window);
750 gtk_tree_path_free(path);
751 }
752
753 void
cssed_window_output_clear(CssedWindow * window)754 cssed_window_output_clear( CssedWindow* window )
755 {
756 GtkTreeView* view;
757 GtkListStore* store;
758
759 view = GTK_TREE_VIEW(window->tree_view_output);
760 store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
761 gtk_list_store_clear(store);
762 }
763
764 // flagged to be skiped FIXME
765 void
cssed_window_digest_write(CssedWindow * window,gchar * first_col,gchar * second_col)766 cssed_window_digest_write( CssedWindow* window, gchar* first_col, gchar* second_col )
767 {
768 GtkTreeView* view;
769 GtkListStore* store;
770 GtkTreeIter iter;
771 GtkTreePath* path;
772
773 view = GTK_TREE_VIEW(window->tree_view_digest);
774 store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
775 gtk_list_store_append (store, &iter);
776 gtk_list_store_set (store, &iter, 0, first_col, 1, second_col, -1);
777
778 path = gtk_tree_model_get_path (GTK_TREE_MODEL(store),&iter);
779 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), path, NULL, FALSE, 0, 0);
780 gtk_tree_path_free(path);
781 }
782
783 void
cssed_window_digest_clear(CssedWindow * window)784 cssed_window_digest_clear( CssedWindow* window )
785 {
786 GtkTreeView* view;
787 GtkListStore* store;
788
789 view = GTK_TREE_VIEW(window->tree_view_digest);
790 store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
791 gtk_list_store_clear(store);
792 }
793
794 // This may be moved to a future CSS support implementation
795 // FIXME
796 void
cssed_window_selector_scanner_write(CssedWindow * window,gchar * first_col,gchar * second_col)797 cssed_window_selector_scanner_write(CssedWindow* window, gchar* first_col,
798 gchar* second_col)
799 {
800 GtkTreeView* view;
801 GtkListStore* store;
802 GtkTreeIter iter;
803 GtkTreePath* path;
804 GdkPixbuf* arrow;
805
806 view = GTK_TREE_VIEW(window->tree_view_css_current);
807 store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
808 arrow= create_pixbuf ("arrow.png");
809
810 gtk_list_store_append (store, &iter);
811 gtk_list_store_set (store, &iter, 0, first_col, 1, second_col, 2, arrow, -1);
812
813 path = gtk_tree_model_get_path (GTK_TREE_MODEL(store),&iter);
814 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW(view), path, NULL, FALSE, 0, 0);
815 gtk_tree_path_free(path);
816 }
817
818 // This may be moved to a future CSS support implementation
819 // FIXME
820 void
cssed_window_selector_scanner_clear(CssedWindow * window)821 cssed_window_selector_scanner_clear(CssedWindow* window )
822 {
823 GtkTreeView* view;
824 GtkListStore* store;
825
826 view = GTK_TREE_VIEW(window->tree_view_css_current);
827 store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
828 gtk_list_store_clear(store);
829 }
830
831 // This may be moved to a future CSS support implementation
832 // FIXME
833 void
cssed_window_selector_scanner_edited(CssedWindow * window,gchar * path_string,gchar * new_text)834 cssed_window_selector_scanner_edited ( CssedWindow* window,
835 gchar *path_string,
836 gchar *new_text )
837 {
838 CssedDoc* doc;
839 GtkTreeView* view;
840 GtkTreePath *path;
841 GtkTreeIter iter;
842 GtkListStore *store;
843 gint start_pos;
844 gint end_pos;
845 gboolean valid;
846 gchar* property;
847 gchar* value;
848 gchar* selector_contents;
849 gchar* declaration;
850
851 path = gtk_tree_path_new_from_string (path_string);
852
853 view = GTK_TREE_VIEW(window->tree_view_css_current);
854 store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
855 doc = document_get_current(window);
856
857 start_pos = document_get_selection_start(doc);
858 end_pos = document_get_selection_end(doc);
859
860 gtk_tree_model_get_iter (GTK_TREE_MODEL(store), &iter, path);
861 gtk_tree_path_free (path);
862 gtk_list_store_set (store, &iter, 1, new_text, -1);
863
864 if( start_pos == end_pos ){ // selection out
865 return;
866 }
867 selector_contents = g_strdup(""); // empty but not NULL string must be allocated in memory
868 // as will be disposed in allocated_buffer_add_string()
869
870 valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL(store), &iter);
871 selector_contents = allocated_buffer_add_string(selector_contents, "\n\t");
872 while( valid){
873 gtk_tree_model_get (GTK_TREE_MODEL(store), &iter,
874 0, &property,
875 1, &value, -1);
876
877 if( (property != NULL) || (value != NULL)){ // avoid NULL values
878 declaration = g_strdup_printf("%s: %s;",property,value);
879 selector_contents = allocated_buffer_add_string(selector_contents, declaration);
880 g_free(declaration);
881 g_free(property);
882 g_free(value);
883 }
884 valid = gtk_tree_model_iter_next (GTK_TREE_MODEL(store), &iter);
885 if( valid){
886 selector_contents = allocated_buffer_add_string(selector_contents, "\n\t");
887 }else{
888 selector_contents = allocated_buffer_add_string(selector_contents, "\n");
889 }
890 }
891 document_replace_sel(doc,selector_contents);
892 g_free(selector_contents);
893 }
894
895 //
896 void
cssed_window_show_preferences_dialog(CssedWindow * window)897 cssed_window_show_preferences_dialog( CssedWindow* window)
898 {
899 GtkWidget* dialog;
900 gint response;
901 GList* doclist;
902 CssedConfig* tmpcfg;
903 CssedConfig* cfg;
904 CssedDoc* tmpdoc;
905 CssedFileType* filetype;
906 // here will be copied the old configuration
907 // to be restored if the user click on cancel
908 // as changes are made directly to the window->config structure
909 tmpcfg = cssed_window_config_new ();
910 cfg = cssed_window_get_config (window );
911
912 dialog = create_preferences_dialog (window, tmpcfg );
913
914 response = gtk_dialog_run(GTK_DIALOG(dialog));
915 switch( response){
916 case GTK_RESPONSE_OK:
917 if( GTK_IS_WIDGET(dialog ) )
918 gtk_widget_destroy(dialog );
919 // colourise all
920 doclist = g_list_first((GList*) window->document_list );
921 if( doclist != NULL){
922 while( doclist != NULL){
923 tmpdoc = (CssedDoc*) doclist->data;
924 // the higlighting may have changed
925 if( (filetype = document_get_filetype(tmpdoc)) != NULL ){
926 filetype->apply_style(tmpdoc);
927 document_colourise_all(tmpdoc);
928 }
929 document_set_font(tmpdoc);
930 document_set_current_font_size(tmpdoc);
931 doclist = g_list_next(doclist);
932 }
933 }
934 break;
935 default:
936 // restore old configuration
937 if( GTK_IS_WIDGET(dialog) )
938 gtk_widget_destroy(dialog);
939 cssed_config_copy_style_and_defaults (tmpcfg, cssed_window_get_config(window));
940 break;
941 }
942 g_free(tmpcfg);
943 }
944 // document list
945 void
cssed_window_add_document_to_list(CssedWindow * window,CssedDoc * doc)946 cssed_window_add_document_to_list(CssedWindow* window, CssedDoc* doc )
947 {
948 window->document_list = g_list_append(window->document_list, doc);
949 }
950
951 void
cssed_window_delete_document_from_list(CssedWindow * window,CssedDoc * doc)952 cssed_window_delete_document_from_list(CssedWindow* window, CssedDoc* doc )
953 {
954 window->document_list = g_list_remove(window->document_list, doc);
955 }
956
957 gint
cssed_window_get_document_list_length(CssedWindow * window)958 cssed_window_get_document_list_length(CssedWindow* window )
959 {
960 return g_list_length(window->document_list);
961 }
962
963 GList*
cssed_window_get_document_list_first(CssedWindow * window)964 cssed_window_get_document_list_first(CssedWindow* window )
965 {
966 return g_list_first(window->document_list);
967 }
968
969 // returns -1 if not found
970 gint
cssed_window_get_document_list_index(CssedWindow * window,CssedDoc * doc)971 cssed_window_get_document_list_index(CssedWindow* window, CssedDoc* doc )
972 {
973 return g_list_index(window->document_list, doc);
974 }
975
976 // TRUE if document is moved, false otherwise
977 gboolean
cssed_window_set_document_list_index(CssedWindow * window,CssedDoc * doc,gint index)978 cssed_window_set_document_list_index(CssedWindow* window, CssedDoc* doc, gint index )
979 {
980 gint old_index, size, cur_page=0;
981 GList* old_list, *new_list=NULL;
982 CssedDoc* cur_doc;
983
984 old_index = g_list_index(window->document_list, doc);
985
986 if( old_index == -1 || index == -1 || old_index == index )
987 return FALSE;
988
989 size = gtk_notebook_get_n_pages(GTK_NOTEBOOK(window->notebook_docs));
990 while(cur_page < size){
991 cur_doc = document_get_from_notebook_page_num(window, cur_page);
992 if(cur_doc != doc){
993 new_list = g_list_append(new_list, (gpointer) cur_doc);
994 }
995 cur_page++;
996 }
997 new_list = g_list_insert(new_list, doc, index);
998
999 gtk_notebook_reorder_child (GTK_NOTEBOOK(window->notebook_docs),
1000 document_get_scintilla_widget(doc),
1001 index);
1002
1003 old_list = window->document_list;
1004 window->document_list = new_list;
1005 g_list_free(old_list);
1006 return TRUE;
1007 }
1008
1009 // plugins list
1010 void
cssed_window_add_plugin_to_list(CssedWindow * window,gpointer plugin)1011 cssed_window_add_plugin_to_list( CssedWindow* window, gpointer plugin )
1012 {
1013 window->plugins_list = g_list_append(window->plugins_list, plugin);
1014 }
1015
1016 void
cssed_window_delete_plugin_from_list(CssedWindow * window,gpointer plugin)1017 cssed_window_delete_plugin_from_list( CssedWindow* window, gpointer plugin )
1018 {
1019 window->plugins_list = g_list_remove(window->plugins_list, plugin);
1020 }
1021
1022 gint
cssed_window_get_plugin_list_length(CssedWindow * window)1023 cssed_window_get_plugin_list_length( CssedWindow* window )
1024 {
1025 return g_list_length(window->plugins_list);
1026 }
1027
1028 GList*
cssed_window_get_plugin_list_first(CssedWindow * window)1029 cssed_window_get_plugin_list_first( CssedWindow* window )
1030 {
1031 return g_list_first(window->plugins_list);
1032 }
1033
1034 // keywords list FIXME: this should go to a DocumentTypeManager struct
1035 gchar*
cssed_window_get_keyword_list(CssedWindow * window)1036 cssed_window_get_keyword_list( CssedWindow* window )
1037 {
1038 g_return_val_if_fail(window->keywords_list != NULL, NULL);
1039 return window->keywords_list;
1040 }
1041
1042 void
cssed_window_set_keyword_list(CssedWindow * window,gchar * keywords)1043 cssed_window_set_keyword_list(CssedWindow* window, gchar* keywords )
1044 {
1045 if( window->keywords_list != NULL )
1046 g_free(window->keywords_list);
1047 window->keywords_list = keywords;
1048 }
1049
1050 void
cssed_window_free_keyword_list(CssedWindow * window)1051 cssed_window_free_keyword_list( CssedWindow* window )
1052 {
1053 if(window->keywords_list != NULL)
1054 g_free(window->keywords_list);
1055 }
1056 // css dialogs hash table
1057 void
cssed_window_css_dialog_insert(CssedWindow * window,gchar * key,gpointer klass)1058 cssed_window_css_dialog_insert(CssedWindow* window, gchar* key, gpointer klass )
1059 {
1060 g_hash_table_insert(window->cssdialogs_hash, (gpointer) key, klass);
1061 }
1062
1063
1064 void
cssed_window_css_dialog_remove_by_keyword(CssedWindow * window,gchar * key)1065 cssed_window_css_dialog_remove_by_keyword( CssedWindow* window, gchar* key )
1066 {
1067 g_hash_table_remove(window->cssdialogs_hash, (gpointer) key);
1068 }
1069
1070 gpointer
cssed_window_css_dialog_lookup_by_keyword(CssedWindow * window,gchar * key)1071 cssed_window_css_dialog_lookup_by_keyword( CssedWindow* window, gchar* key )
1072 {
1073 return g_hash_table_lookup (window->cssdialogs_hash, (gpointer) key);
1074 }
1075
1076 gboolean
cssed_window_css_dialog_keyword_in_use(CssedWindow * window,gchar * key)1077 cssed_window_css_dialog_keyword_in_use( CssedWindow* window, gchar* key )
1078 {
1079 gpointer klass;
1080
1081 klass = g_hash_table_lookup (window->cssdialogs_hash, (gpointer) key);
1082 if(klass == NULL)
1083 return FALSE;
1084 else
1085 return TRUE;
1086 }
1087
1088 // check for an opened file and select it if exists (use only full path)
1089 gboolean
cssed_window_is_file_opened(CssedWindow * window,gchar * file)1090 cssed_window_is_file_opened( CssedWindow* window, gchar* file )
1091 {
1092 GList* docs;
1093 CssedDoc* doc;
1094 gchar* filename;
1095 gint page = 0;
1096
1097 g_return_val_if_fail(file != NULL, FALSE);
1098
1099 docs = g_list_first(window->document_list);
1100 while( docs != NULL ){
1101 doc = (CssedDoc*) docs->data;
1102 filename = document_get_filename(doc);
1103
1104 if( filename != NULL ){
1105 if( strcmp(filename, file) == 0 ){
1106 gtk_notebook_set_current_page(
1107 GTK_NOTEBOOK(window->notebook_docs), page);
1108 return TRUE;
1109 }
1110 g_free(filename);
1111 }
1112 page++;
1113 docs = g_list_next(docs);
1114 }
1115 return FALSE;
1116 }
1117 //
1118 gint
cssed_window_get_num_docs(CssedWindow * window)1119 cssed_window_get_num_docs( CssedWindow* window )
1120 {
1121 return g_list_length(window->document_list);
1122 }
1123
1124 void
cssed_window_set_ndoc_active(CssedWindow * window,gint doc_number)1125 cssed_window_set_ndoc_active( CssedWindow* window, gint doc_number )
1126 {
1127 gtk_notebook_set_current_page(GTK_NOTEBOOK(window->notebook_docs), doc_number);
1128 }
1129
1130
1131 void
cssed_window_add_filetype(CssedWindow * window,CssedFileType * filetype,gboolean free_previous)1132 cssed_window_add_filetype (CssedWindow* window, CssedFileType* filetype, gboolean free_previous)
1133 {
1134 GSList* list;
1135
1136 g_return_if_fail( window != NULL );
1137 g_return_if_fail( filetype != NULL );
1138 g_return_if_fail( window->manager != NULL );
1139
1140 if( free_previous && (CSSED_FILETYPE_MANAGER(window)->filetype[filetype->id] != NULL) ){
1141 cssed_file_type_free( CSSED_FILETYPE_MANAGER(window)->filetype[filetype->id] );
1142 }
1143
1144 CSSED_FILETYPE_MANAGER(window)->filetype[filetype->id] = filetype;
1145
1146 // add the patterns
1147 for ( list = g_slist_nth (filetype->patterns, 0);list != NULL; list = g_slist_next(list) ) {
1148 cssed_file_type_manager_add_pattern( window->manager, list->data, filetype->id );
1149 }
1150
1151 if( filetype->menu_item != NULL ){
1152 gtk_widget_show (filetype->menu_item);
1153 gtk_container_add (GTK_CONTAINER (window->filetypes_menu), filetype->menu_item);
1154 }
1155 }
1156
1157 // read cssdwindow.h for an explanation about this function
1158 void
cssed_window_apply_stored_size_and_position(CssedWindow * window)1159 cssed_window_apply_stored_size_and_position( CssedWindow* window )
1160 {
1161 gtk_window_move(GTK_WINDOW(window->window_widget), window->config->window_x, window->config->window_y );
1162 gtk_window_resize (GTK_WINDOW(window->window_widget),window->config->window_width, window->config->window_height);
1163 if( window->config->initiall_state_maximized ) gtk_window_maximize (GTK_WINDOW(window->window_widget));// PANEDBUG
1164 }
1165
1166 void
cssed_window_apply_stored_paned_positions(CssedWindow * window)1167 cssed_window_apply_stored_paned_positions( CssedWindow* window )
1168 {
1169
1170 // PANEDBUG - this is not working when the window is maximized
1171 // so it's temporarly disabled in such case FIXME
1172 //if( !window->config->initiall_state_maximized ){
1173 gtk_paned_set_position(GTK_PANED (window->panes->hpaned_up), window->config->sidebar_pos);
1174 gtk_paned_set_position(GTK_PANED (window->panes->vpaned_main), window->config->footer_pos);
1175 //}
1176
1177 gtk_paned_set_position(GTK_PANED (window->panes->vpaned_sidebar), window->config->css_treeview_pos);
1178 }
1179
1180 // to show help in a system HTML browser
1181 void
cssed_window_show_in_default_browser(CssedWindow * window,gchar * uri)1182 cssed_window_show_in_default_browser ( CssedWindow* window, gchar* uri )
1183 {
1184 gchar *command;
1185 GError *error = NULL;
1186 gchar* browser_command;
1187
1188 browser_command = window->config->browser_command;
1189
1190 if( browser_command == NULL ){
1191 cssed_error_message( _("Browser command not set"), _("You must set the default browser command on the\n\"Other\" tab in the preferences dialog before to use this command."));
1192 return;
1193 }
1194
1195 if( strstr(browser_command, "%u") == NULL ){
1196 command = g_strdup_printf("%s %s", browser_command, uri );
1197 }else{
1198 command = cssed_string_replace_all(browser_command, "%u", uri);
1199 }
1200
1201 if( command == NULL ){
1202 cssed_error_message( _("Internall error while creating browser command"), _("It may indicate a programming error.\nPlease comunicate it in the cssed-devel list or send a mail to iagorubio@users.sourceforge.net."));
1203 return;
1204 }
1205
1206 if( !g_spawn_command_line_async (command, &error) ){
1207 cssed_error_message( _("Unable to show the browser, command failed."), error->message);
1208 }
1209 g_free(command);
1210 }
1211
1212
1213