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 /*
19 This parser is implemented using a subset of the libcroco (the parser)
20 and using just it's SAC handler. Don't use it as a libcroco example as
21 the libcroco used IS MODIFIED. Some functions doesn't exists or are private
22 in the original libcroco.
23
24 Download the original libcroco from http://www.freespiders.org/
25 */
26
27 #ifdef HAVE_CONFIG_H
28 # include <config.h>
29 #endif
30
31 #define PLAT_GTK 1
32
33 #include <stdio.h>
34 #include <gtk/gtk.h>
35
36 #include "cssedwindow.h"
37 #include "document.h"
38 #include "callbacks.h"
39 #include "interface.h"
40 #include "support.h"
41 #include "utils.h"
42
43 #include <libcroco.h>
44 #include <string.h>
45
46 #define OUT_COLOR "navy"
47 #define ERR_COLOR "red"
48 #define SEL_COLOR "blue"
49 #define PRO_COLOR "maroon"
50 #define MED_COLOR "dark green"
51
52 typedef struct _CssedCssParserData {
53 CssedDoc *doc;
54 gchar *current_selector;
55 gboolean in_media;
56 gint err_count;
57 gchar *filename;
58 } CssedCssParserData;
59
60 /* *** UTILS *** */
61 CssedWindow *
get_window_fom_sac_handler_data(CRDocHandler * a_handler)62 get_window_fom_sac_handler_data (CRDocHandler * a_handler)
63 {
64 CssedCssParserData* data;
65 CssedDoc *document;
66 CssedWindow *win;
67
68 data = (CssedCssParserData*) a_handler->app_data;
69 document = (CssedDoc *) data->doc;
70 win = document_get_window (document);
71
72 return win;
73 }
74
75 void
change_current_sac_handler_selector(CRDocHandler * a_handler,gchar * selector)76 change_current_sac_handler_selector(CRDocHandler * a_handler,gchar* selector)
77 {
78 CssedCssParserData* data;
79 data = (CssedCssParserData*) a_handler->app_data;
80
81 if( data->current_selector )
82 g_free(data->current_selector);
83
84 data->current_selector = g_strdup(selector);
85 }
86
87 /* *** SAC HANDLERS START *** */
88 void
sac_handler_start_document(CRDocHandler * a_handler)89 sac_handler_start_document (CRDocHandler * a_handler)
90 {
91 CssedWindow* window;
92 g_return_if_fail (a_handler);
93
94 window = get_window_fom_sac_handler_data (a_handler);
95 cssed_window_output_clear(window);
96 }
97
98 void
sac_handler_end_document(CRDocHandler * a_handler)99 sac_handler_end_document (CRDocHandler * a_handler)
100 {
101 g_return_if_fail (a_handler);
102 }
103
104 void
sac_handler_import_style(CRDocHandler * a_handler,GList * a_media_list,CRString * ar_uri,CRString * ar_uri_default_ns,CRParsingLocation * a_location)105 sac_handler_import_style (CRDocHandler *a_handler,
106 GList *a_media_list,
107 CRString *ar_uri,
108 CRString *ar_uri_default_ns,
109 CRParsingLocation *a_location)
110 {
111 GList *cur = NULL;
112 guchar *str;
113 guchar *out;
114 CssedCssParserData* data;
115 GString *a_uri, *a_uri_default_ns;
116
117
118 g_return_if_fail (ar_uri);
119 g_return_if_fail (ar_uri_default_ns);
120 g_return_if_fail (a_handler);
121
122 a_uri = ar_uri->stryng;
123 a_uri_default_ns = ar_uri_default_ns->stryng;
124
125 data = (CssedCssParserData*) a_handler->app_data;
126
127 document_write_error_to_program_output ((CssedDoc *) data->doc,
128 _("Input style from import found."),
129 OUT_COLOR);
130
131 if (a_media_list)
132 {
133 document_write_error_to_program_output ((CssedDoc *) data->doc,
134 _("\tMedia list"),
135 OUT_COLOR);
136
137 for (cur = a_media_list; cur; cur = cur->next)
138 {
139 if (cur->data)
140 {
141 str = g_strndup
142 (((GString *) cur->data)->str,
143 ((GString *) cur->data)->len);
144
145 if (str)
146 {
147 out = g_strdup_printf ("\t\t%s", str);
148 document_write_error_to_program_output((CssedDoc *) data->doc, out, OUT_COLOR);
149 g_free (str);
150 g_free (out);
151 str = NULL;
152 out = NULL;
153 }
154 }
155 }
156
157 document_write_error_to_program_output ((CssedDoc *)data->doc, _("\tDefault namespace"), OUT_COLOR);
158 if (a_uri_default_ns && a_uri_default_ns->str)
159 {
160 str = g_strndup (a_uri_default_ns->str, a_uri_default_ns->len);
161 if (str)
162 {
163 out = g_strdup_printf ("\t\t%s", str);
164 document_write_error_to_program_output ((CssedDoc *) data->doc, out, OUT_COLOR);
165 g_free (str);
166 g_free (out);
167 }
168 }
169 }
170 }
171
172
173 void
sac_handler_namespace_declaration(CRDocHandler * a_handler,CRString * ar_prefix,CRString * ar_uri,CRParsingLocation * a_location)174 sac_handler_namespace_declaration (CRDocHandler *a_handler,
175 CRString *ar_prefix,
176 CRString *ar_uri,
177 CRParsingLocation *a_location)
178
179 {
180 GString *a_prefix, *a_uri;
181 guchar *prefix = NULL;
182 guchar *uri = NULL;
183 guchar *out = NULL;
184 CssedCssParserData* data;
185
186
187 g_return_if_fail (ar_uri);
188 g_return_if_fail (ar_prefix);
189 g_return_if_fail (a_handler);
190
191 data = (CssedCssParserData*) a_handler->app_data;
192 a_prefix = ar_prefix->stryng;
193 a_uri = ar_uri->stryng;
194
195 document_write_error_to_program_output ((CssedDoc *) data->doc,
196 _("parser: Namespace declaration"), OUT_COLOR);
197
198 if (a_prefix && a_prefix->str)
199 {
200 prefix = g_strndup (a_prefix->str, a_prefix->len);
201
202 if (prefix)
203 {
204 out = g_strdup_printf (_("\t\tprefix: %s"), prefix);
205 document_write_error_to_program_output ((CssedDoc *)
206 data->
207 doc, out,
208 OUT_COLOR);
209 g_free (prefix);
210 g_free (out);
211 }
212 }
213
214 if (a_uri && a_uri->str)
215 {
216
217 uri = g_strndup (a_uri->str, a_uri->len);
218
219 if (uri)
220 {
221 out = g_strdup_printf (_("\t\turi: %s"), uri);
222 document_write_error_to_program_output ((CssedDoc *)
223 data->
224 doc, out,
225 OUT_COLOR);
226 g_free (prefix);
227 g_free (out);
228 }
229 }
230 }
231
232
233 void
sac_handler_comment(CRDocHandler * a_handler,CRString * ar_comment)234 sac_handler_comment (CRDocHandler *a_handler,
235 CRString *ar_comment)
236 {
237 gchar *out = NULL;
238 guchar *comment = NULL;
239 CssedCssParserData* data;
240 GString * a_comment;
241
242 g_return_if_fail (ar_comment);
243 g_return_if_fail (a_handler);
244
245 data = (CssedCssParserData*) a_handler->app_data;
246 a_comment = ar_comment->stryng;
247 if (a_comment && a_comment->str)
248 {
249 comment = g_strndup (a_comment->str, a_comment->len);
250
251 if (comment)
252 {
253 out = g_strdup_printf (_("comment -> %s"), comment);
254 document_write_error_to_program_output ((CssedDoc*) data->doc, out, OUT_COLOR);
255 g_free (comment);
256 g_free (out);
257 out = NULL;
258 comment = NULL;
259 }
260 }
261 }
262
263
264 void
sac_handler_start_selector(CRDocHandler * a_handler,CRSelector * a_selector_list)265 sac_handler_start_selector (CRDocHandler * a_handler,
266 CRSelector * a_selector_list)
267 {
268 guchar *tmp_buf = NULL;
269 gchar *out = NULL;
270 CssedCssParserData* data;
271
272
273 g_return_if_fail (a_selector_list);
274 g_return_if_fail (a_handler);
275
276 data = (CssedCssParserData*) a_handler->app_data;
277
278 if (a_selector_list)
279 {
280 tmp_buf = cr_selector_to_string (a_selector_list);
281 if (tmp_buf)
282 {
283 data->current_selector = g_strdup(tmp_buf);
284 out = g_strdup_printf (_("<span color='black'>%s</span>:<span color='dark green'>%d</span>:\n%s"),
285 data->filename,
286 a_selector_list->location.line,
287 tmp_buf);
288 document_write_error_to_program_output ((CssedDoc*) data->doc, out, SEL_COLOR);
289 g_free (out);
290 g_free (tmp_buf);
291 }
292 }
293 }
294
295
296 void
sac_handler_end_selector(CRDocHandler * a_handler,CRSelector * a_selector_list)297 sac_handler_end_selector (CRDocHandler * a_handler,
298 CRSelector * a_selector_list)
299 {
300 guchar *tmp_buf = NULL;
301 gchar *out = NULL;
302 CssedCssParserData* data;
303
304 g_return_if_fail (a_selector_list);
305 g_return_if_fail (a_handler);
306
307 data = (CssedCssParserData*) a_handler->app_data;
308
309 if (a_selector_list)
310 {
311 tmp_buf = cr_selector_to_string (a_selector_list);
312 if (tmp_buf)
313 {
314 out = g_strdup_printf (_("%s end"), tmp_buf);
315 document_write_error_to_program_output ((CssedDoc*) data-> doc, out, SEL_COLOR);
316 g_free (out);
317 g_free (tmp_buf);
318 tmp_buf = NULL;
319 out = NULL;
320 }
321 }
322 }
323
324 void
sac_handler_property(CRDocHandler * a_handler,CRString * ar_name,CRTerm * a_expr,gboolean a_is_important)325 sac_handler_property (CRDocHandler *a_handler,
326 CRString *ar_name,
327 CRTerm *a_expr,
328 gboolean a_is_important)
329 {
330 gchar *out = NULL;
331 guchar* val;
332 guchar *name ;
333 CssedCssParserData* data;
334 GString * a_name;
335
336 g_return_if_fail (ar_name);
337 g_return_if_fail (a_expr);
338 g_return_if_fail (a_handler);
339
340 data = (CssedCssParserData*) a_handler->app_data;
341 a_name = ar_name->stryng;
342
343 if (a_name && a_name->str)
344 {
345 name = g_strndup (a_name->str, a_name->len);
346
347 if (name && a_expr)
348 {
349 val = cr_term_to_string (a_expr) ;
350 out=g_strdup_printf(_("\t%s: %s"), name, val);
351 document_write_error_to_program_output ((CssedDoc *) data->doc, out, PRO_COLOR);
352 g_free(out);
353 g_free(val);
354 }
355 else
356 {
357 if( name ){
358 out=g_strdup_printf(_("\tempty property -> %s"),name);
359 document_write_error_to_program_output ((CssedDoc *) data->doc, out, ERR_COLOR);
360 g_free( out );
361
362 }
363 if( a_expr ){
364 val=g_strdup_printf(_("\tempty value -> %s"),name);
365 document_write_error_to_program_output ((CssedDoc *) data->doc, val, ERR_COLOR);
366 g_free( val );
367 }
368 }
369
370 if (name)
371 g_free (name);
372 }
373 }
374
375 void
sac_handler_start_font_face(CRDocHandler * a_handler,CRParsingLocation * a_location)376 sac_handler_start_font_face (CRDocHandler * a_handler, CRParsingLocation *a_location)
377 {
378 CssedCssParserData* data;
379 g_return_if_fail (a_handler);
380
381 data = (CssedCssParserData*) a_handler->app_data;
382 document_write_error_to_program_output ((CssedDoc *)
383 data->doc, _("Start font face"),
384 OUT_COLOR);
385 }
386
387
388 void
sac_handler_end_font_face(CRDocHandler * a_handler)389 sac_handler_end_font_face (CRDocHandler * a_handler)
390 {
391 CssedCssParserData* data;
392 g_return_if_fail (a_handler);
393
394 data = (CssedCssParserData*) a_handler->app_data;
395 document_write_error_to_program_output ((CssedDoc *)
396 data->doc, _("End font face"),
397 OUT_COLOR);
398 }
399
400 void
sac_handler_start_media(CRDocHandler * a_handler,GList * a_media_list,CRParsingLocation * a_location)401 sac_handler_start_media (CRDocHandler * a_handler, GList * a_media_list, CRParsingLocation *a_location)
402 {
403 CssedCssParserData* data;
404 gchar *out;
405
406 g_return_if_fail (a_handler);
407 g_return_if_fail (a_location);
408
409 data = (CssedCssParserData*) a_handler->app_data ;
410
411 out = g_strdup_printf (_("<span color='black'>%s</span>:<span color='dark green'>%d</span>:\nMedia"),
412 data->filename,
413 a_location->line);
414 document_write_error_to_program_output ((CssedDoc *) data->doc, out, MED_COLOR);
415 g_free(out);
416 }
417
418
419 void
sac_handler_end_media(CRDocHandler * a_handler,GList * a_media_list)420 sac_handler_end_media (CRDocHandler * a_handler, GList * a_media_list)
421 {
422 CssedCssParserData* data;
423
424 g_return_if_fail (a_handler);
425 data = (CssedCssParserData*) a_handler->app_data;
426
427 document_write_error_to_program_output ((CssedDoc *) data->doc,
428 _("End Media"), MED_COLOR);
429
430 }
431
432 void
sac_handler_start_page(CRDocHandler * a_handler,CRString * ar_name,CRString * ar_pseudo_page,CRParsingLocation * a_location)433 sac_handler_start_page (CRDocHandler *a_handler,
434 CRString *ar_name,
435 CRString *ar_pseudo_page,
436 CRParsingLocation *a_location)
437
438 {
439 CssedCssParserData* data;
440 gchar *out;
441
442 g_return_if_fail (a_handler);
443 data = (CssedCssParserData*) a_handler->app_data;
444 out = g_strdup_printf (_("<span color='black'>%s</span>:<span color='dark green'>%d</span>:\nPage"),
445 data->filename,
446 a_location->line);
447 document_write_error_to_program_output ((CssedDoc*) data->doc, out, MED_COLOR);
448 g_free(out);
449 }
450
451 void
sac_handler_end_page(CRDocHandler * a_handler,CRString * ar_name,CRString * ar_pseudo_page)452 sac_handler_end_page (CRDocHandler *a_handler,
453 CRString *ar_name,
454 CRString *ar_pseudo_page)
455 {
456 CssedCssParserData* data;
457
458 g_return_if_fail (a_handler);
459 data = (CssedCssParserData*) a_handler->app_data;
460 document_write_error_to_program_output ((CssedDoc*) data->doc, _("End Page"), MED_COLOR);
461 }
462
463
464 void
sac_handler_ignorable_at_rule(CRDocHandler * a_handler,CRString * ar_name)465 sac_handler_ignorable_at_rule (CRDocHandler * a_handler, CRString *ar_name)
466 {
467 guchar *name = NULL;
468 GString * a_name;
469
470 g_return_if_fail (a_handler);
471 g_return_if_fail (ar_name);
472
473 a_name = ar_name->stryng;
474
475 fprintf (stdout, "*********************\n");
476 fprintf (stdout, "ignorable_at_rule\n");
477
478 if (a_name && a_name->str)
479 {
480 name = g_strndup (a_name->str, a_name->len);
481 }
482
483 if (name)
484 {
485 fprintf (stdout, "%s\n", name);
486 g_free(name);
487 }
488
489 fprintf (stdout, "*********************\n\n");
490 }
491
492 void
sac_handler_parse_error(CRDocHandler * a_handler,gint line)493 sac_handler_parse_error (CRDocHandler * a_handler, gint line)
494 {
495 CssedCssParserData* data;
496 gchar* err;
497
498 data = (CssedCssParserData*) a_handler->app_data ;
499 data->err_count++;
500 err = g_strdup_printf(_("%s:%d: syntax error (%d)"), data->filename, line+1, data->err_count);
501 document_write_error_to_program_output ((CssedDoc *) data->doc, err, ERR_COLOR);
502 g_free(err);
503 }
504
505 void
sac_handler_fatal_error(CRDocHandler * a_handler)506 sac_handler_fatal_error (CRDocHandler * a_handler)
507 {
508 CssedCssParserData* data;
509 data = (CssedCssParserData*) a_handler->app_data ;
510
511 document_write_error_to_program_output ((CssedDoc *) data->doc, _("FATAL error"), ERR_COLOR);
512 }
513
514 void
init_sac_handler(CRDocHandler * a_handler)515 init_sac_handler (CRDocHandler * a_handler)
516 {
517 a_handler->start_document = sac_handler_start_document;
518 a_handler->end_document = sac_handler_end_document;
519 a_handler->import_style = sac_handler_import_style;
520 a_handler->namespace_declaration = sac_handler_namespace_declaration;
521 a_handler->comment = sac_handler_comment;
522 a_handler->start_selector = sac_handler_start_selector;
523 a_handler->end_selector = sac_handler_end_selector;
524 a_handler->property = sac_handler_property;
525 a_handler->start_font_face = sac_handler_start_font_face;
526 a_handler->end_font_face = sac_handler_end_font_face;
527 a_handler->start_media = sac_handler_start_media;
528 a_handler->end_media = sac_handler_end_media;
529 a_handler->start_page = sac_handler_start_page;
530 a_handler->end_page = sac_handler_end_page;
531 a_handler->ignorable_at_rule = sac_handler_ignorable_at_rule;
532 a_handler->error = sac_handler_parse_error;
533 a_handler->unrecoverable_error = sac_handler_fatal_error;
534 }
535
536 void
init_no_dump_sac_handler(CRDocHandler * a_handler)537 init_no_dump_sac_handler (CRDocHandler * a_handler)
538 {
539 a_handler->start_document = sac_handler_start_document; // clean previous output
540 a_handler->end_document = NULL;
541 a_handler->import_style = NULL;
542 a_handler->namespace_declaration = NULL;
543 a_handler->comment = NULL;
544 a_handler->start_selector = NULL;
545 a_handler->end_selector = NULL;
546 a_handler->property = NULL;
547 a_handler->start_font_face = NULL;
548 a_handler->end_font_face = NULL;
549 a_handler->start_media = NULL;
550 a_handler->end_media = NULL;
551 a_handler->start_page = NULL;
552 a_handler->end_page = NULL;
553 a_handler->ignorable_at_rule = NULL;
554 a_handler->error = sac_handler_parse_error;
555 a_handler->unrecoverable_error = NULL;
556 }
557 /* *** SAC HANDLERS END *** */
558
559
560
561
562 void
cssed_cr_parser_parse_buffer(CssedDoc * doc,gchar * buffer,gint len,gboolean dump)563 cssed_cr_parser_parse_buffer (CssedDoc * doc, gchar * buffer, gint len, gboolean dump)
564 {
565 enum CRStatus status = CR_OK;
566 CRDocHandler *handler = { 0 };
567 CRParser *parser = NULL;
568 CssedCssParserData* data;
569 gchar* val_buf;
570 gchar *filename;
571 GList* err_list;
572 CRParserError* cr_err;
573 CssedCodePage codepage;
574
575 data = g_malloc(sizeof(CssedCssParserData));
576 data->doc = doc;
577 data->err_count = 0;
578 data->current_selector = NULL;
579 data->in_media = FALSE;
580
581 filename = document_get_filename(doc);
582 if( !filename )
583 filename = g_strdup(_("Untitled"));
584 data->filename = filename;
585
586 codepage = document_get_codepage(doc);
587
588 switch( codepage ){
589 case CSSED_CODEPAGE_DEFAULT:
590 parser = cr_parser_new_from_buf (buffer, len, CR_ISO_8859_1, FALSE);
591 break;
592 case CSSED_CODEPAGE_UTF8:
593 parser = cr_parser_new_from_buf (buffer, len, CR_UTF_8, FALSE);
594 break;
595 case CSSED_CODEPAGE_DBCS:
596 parser = cr_parser_new_from_buf (buffer, len, CR_UCS_4, FALSE);
597 break;
598 default:
599 parser = cr_parser_new_from_buf (buffer, len, CR_AUTO, FALSE);
600 }
601
602 handler = cr_doc_handler_new ();
603
604 if( dump )
605 init_sac_handler (handler);
606 else
607 init_no_dump_sac_handler (handler);
608
609 handler->app_data = data;
610 status = cr_parser_set_sac_handler (parser, handler);
611
612 if (status != CR_OK)
613 {//FIXME say somethig to user
614 cr_parser_destroy (parser);
615 g_free(data);
616 g_free(filename);
617 return;
618 }
619
620 //g_print("validating buffer: %s\n", buffer);
621 status = cr_parser_parse (parser);
622 switch( status ){
623 case CR_OK:
624 if( data->err_count > 0 ){
625 cssed_error_message(_("Validation result ok with errors"),
626 _("The CSS document can be parsed, but has syntax errors (%d).\nCheck the program output window."),
627 data->err_count);
628 }else{
629 cssed_error_message(_("Validation result ok"),
630 _("The CSS document is well formed and\ncan be parsed by a browser."));
631 }
632 break;
633 case CR_ERROR:
634 cssed_error_message(_("Validation fails"), _("The CSS document is not well formed"));
635 break;
636 case CR_BAD_PARAM_ERROR:
637 case CR_INSTANCIATION_FAILED_ERROR:
638 case CR_EMPTY_PARSER_INPUT_ERROR:
639 case CR_ENCODING_ERROR:
640 case CR_ENCODING_NOT_FOUND_ERROR:
641 cssed_error_message(_("Validation fails"),
642 _("The validator found an internal error\nand is unable to continue."));
643 break;
644 default:
645 cssed_error_message(_("Validation fails"),
646 _("The CSS document is not well formed"));
647 break;
648 }
649
650 err_list = cr_parser_get_error_stack(parser);
651
652 for ( ;err_list;err_list = err_list->next )
653 {
654 cr_err = (CRParserError*) err_list->data;
655 if ( cr_err != NULL ){
656 val_buf = g_strdup_printf("%s:%d: %s ", filename, ((int) cr_err->line + 1) ,cr_err->msg );
657 document_write_error_to_program_output(doc,val_buf,ERR_COLOR);
658 g_free(val_buf);
659 }
660 }
661
662 if( err_list ) g_list_free( err_list );
663 cr_parser_destroy (parser);
664
665 if( data->current_selector ) g_free(data->current_selector);
666 g_free(data);
667 g_free(filename);
668 }
669
670