/* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */ /* * This file is part of The Croco Library * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2.1 of the GNU Lesser General Public * License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * Author: Dodji Seketeli * See COPYRIGHTS file for copyright information. */ #include #include "cr-utils.h" #include "cr-om-parser.h" /** *@CROMParser: * *The definition of the CSS Object Model Parser. *This parser uses (and sits) the SAC api of libcroco defined *in cr-parser.h and cr-doc-handler.h */ struct _CROMParserPriv { CRParser *parser; }; #define PRIVATE(a_this) ((a_this)->priv) /* *Forward declaration of a type defined later *in this file. */ struct _ParsingContext; typedef struct _ParsingContext ParsingContext; static ParsingContext *new_parsing_context (void); static void destroy_context (ParsingContext * a_ctxt); static void unrecoverable_error (CRDocHandler * a_this); static void error (CRDocHandler * a_this); static void property (CRDocHandler * a_this, CRString * a_name, CRTerm * a_expression, gboolean a_important); static void end_selector (CRDocHandler * a_this, CRSelector * a_selector_list); static void start_selector (CRDocHandler * a_this, CRSelector * a_selector_list); static void start_font_face (CRDocHandler * a_this, CRParsingLocation *a_location); static void end_font_face (CRDocHandler * a_this); static void end_document (CRDocHandler * a_this); static void start_document (CRDocHandler * a_this); static void charset (CRDocHandler * a_this, CRString * a_charset, CRParsingLocation *a_location); static void start_page (CRDocHandler * a_this, CRString * a_page, CRString * a_pseudo_page, CRParsingLocation *a_location); static void end_page (CRDocHandler * a_this, CRString * a_page, CRString * a_pseudo_page); static void start_media (CRDocHandler * a_this, GList * a_media_list, CRParsingLocation *a_location); static void end_media (CRDocHandler * a_this, GList * a_media_list); static void import_style (CRDocHandler * a_this, GList * a_media_list, CRString * a_uri, CRString * a_uri_default_ns, CRParsingLocation *a_location); struct _ParsingContext { CRStyleSheet *stylesheet; CRStatement *cur_stmt; CRStatement *cur_media_stmt; }; /******************************************** *Private methods ********************************************/ static ParsingContext * new_parsing_context (void) { ParsingContext *result = NULL; result = g_try_malloc (sizeof (ParsingContext)); if (!result) { cr_utils_trace_info ("Out of Memory"); return NULL; } memset (result, 0, sizeof (ParsingContext)); return result; } static void destroy_context (ParsingContext * a_ctxt) { g_return_if_fail (a_ctxt); if (a_ctxt->stylesheet) { cr_stylesheet_destroy (a_ctxt->stylesheet); a_ctxt->stylesheet = NULL; } if (a_ctxt->cur_stmt) { cr_statement_destroy (a_ctxt->cur_stmt); a_ctxt->cur_stmt = NULL; } g_free (a_ctxt); } static enum CRStatus cr_om_parser_init_default_sac_handler (CROMParser * a_this) { CRDocHandler *sac_handler = NULL; gboolean created_handler = FALSE; enum CRStatus status = CR_OK; g_return_val_if_fail (a_this && PRIVATE (a_this) && PRIVATE (a_this)->parser, CR_BAD_PARAM_ERROR); status = cr_parser_get_sac_handler (PRIVATE (a_this)->parser, &sac_handler); g_return_val_if_fail (status == CR_OK, status); if (!sac_handler) { sac_handler = cr_doc_handler_new (); created_handler = TRUE; } /* *initialyze here the sac handler. */ sac_handler->start_document = start_document; sac_handler->end_document = end_document; sac_handler->start_selector = start_selector; sac_handler->end_selector = end_selector; sac_handler->property = property; sac_handler->start_font_face = start_font_face; sac_handler->end_font_face = end_font_face; sac_handler->error = error; sac_handler->unrecoverable_error = unrecoverable_error; sac_handler->charset = charset; sac_handler->start_page = start_page; sac_handler->end_page = end_page; sac_handler->start_media = start_media; sac_handler->end_media = end_media; sac_handler->import_style = import_style; if (created_handler) { status = cr_parser_set_sac_handler (PRIVATE (a_this)->parser, sac_handler); cr_doc_handler_unref (sac_handler); } return status; } static void start_document (CRDocHandler * a_this) { ParsingContext *ctxt = NULL; CRStyleSheet *stylesheet = NULL; g_return_if_fail (a_this); ctxt = new_parsing_context (); g_return_if_fail (ctxt); stylesheet = cr_stylesheet_new (NULL); ctxt->stylesheet = stylesheet; cr_doc_handler_set_ctxt (a_this, ctxt); } static void start_font_face (CRDocHandler * a_this, CRParsingLocation *a_location) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; (void) a_location; g_return_if_fail (a_this); g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt->cur_stmt == NULL); ctxt->cur_stmt = cr_statement_new_at_font_face_rule (ctxt->stylesheet, NULL); g_return_if_fail (ctxt->cur_stmt); } static void end_font_face (CRDocHandler * a_this) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; CRStatement *stmts = NULL; g_return_if_fail (a_this); g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt->cur_stmt && ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT && ctxt->stylesheet); stmts = cr_statement_append (ctxt->stylesheet->statements, ctxt->cur_stmt); if (!stmts) goto error; ctxt->stylesheet->statements = stmts; stmts = NULL; ctxt->cur_stmt = NULL; return; error: if (ctxt->cur_stmt) { cr_statement_destroy (ctxt->cur_stmt); ctxt->cur_stmt = NULL; } if (!stmts) { cr_statement_destroy (stmts); stmts = NULL; } } static void end_document (CRDocHandler * a_this) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); if (!ctxt->stylesheet || ctxt->cur_stmt) goto error; status = cr_doc_handler_set_result (a_this, ctxt->stylesheet); g_return_if_fail (status == CR_OK); ctxt->stylesheet = NULL; destroy_context (ctxt); cr_doc_handler_set_ctxt (a_this, NULL); return; error: if (ctxt) { destroy_context (ctxt); } } static void charset (CRDocHandler * a_this, CRString * a_charset, CRParsingLocation *a_location) { enum CRStatus status = CR_OK; CRStatement *stmt = NULL, *stmt2 = NULL; CRString *charset = NULL; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; (void) a_location; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt->stylesheet); charset = cr_string_dup (a_charset) ; stmt = cr_statement_new_at_charset_rule (ctxt->stylesheet, charset); g_return_if_fail (stmt); stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt); if (!stmt2) { if (stmt) { cr_statement_destroy (stmt); stmt = NULL; } if (charset) { cr_string_destroy (charset); } return; } ctxt->stylesheet->statements = stmt2; stmt2 = NULL; } static void start_page (CRDocHandler * a_this, CRString * a_page, CRString * a_pseudo, CRParsingLocation *a_location) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; (void) a_location; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt->cur_stmt == NULL); ctxt->cur_stmt = cr_statement_new_at_page_rule (ctxt->stylesheet, NULL, NULL, NULL); if (a_page) { ctxt->cur_stmt->kind.page_rule->name = cr_string_dup (a_page) ; if (!ctxt->cur_stmt->kind.page_rule->name) { goto error; } } if (a_pseudo) { ctxt->cur_stmt->kind.page_rule->pseudo = cr_string_dup (a_pseudo) ; if (!ctxt->cur_stmt->kind.page_rule->pseudo) { goto error; } } return; error: if (ctxt->cur_stmt) { cr_statement_destroy (ctxt->cur_stmt); ctxt->cur_stmt = NULL; } } static void end_page (CRDocHandler * a_this, CRString * a_page, CRString * a_pseudo_page) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; CRStatement *stmt = NULL; (void) a_page; (void) a_pseudo_page; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt->cur_stmt && ctxt->cur_stmt->type == AT_PAGE_RULE_STMT && ctxt->stylesheet); stmt = cr_statement_append (ctxt->stylesheet->statements, ctxt->cur_stmt); if (stmt) { ctxt->stylesheet->statements = stmt; stmt = NULL; ctxt->cur_stmt = NULL; } if (ctxt->cur_stmt) { cr_statement_destroy (ctxt->cur_stmt); ctxt->cur_stmt = NULL; } a_page = NULL; /*keep compiler happy */ a_pseudo_page = NULL; /*keep compiler happy */ } static void start_media (CRDocHandler * a_this, GList * a_media_list, CRParsingLocation *a_location) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; GList *media_list = NULL; (void) a_location; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt && ctxt->cur_stmt == NULL && ctxt->cur_media_stmt == NULL && ctxt->stylesheet); if (a_media_list) { /*duplicate the media_list */ media_list = cr_utils_dup_glist_of_cr_string (a_media_list); } ctxt->cur_media_stmt = cr_statement_new_at_media_rule (ctxt->stylesheet, NULL, media_list); } static void end_media (CRDocHandler * a_this, GList * a_media_list) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; CRStatement *stmts = NULL; (void) a_media_list; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt && ctxt->cur_media_stmt && ctxt->cur_media_stmt->type == AT_MEDIA_RULE_STMT && ctxt->stylesheet); stmts = cr_statement_append (ctxt->stylesheet->statements, ctxt->cur_media_stmt); if (!stmts) { cr_statement_destroy (ctxt->cur_media_stmt); ctxt->cur_media_stmt = NULL; } ctxt->stylesheet->statements = stmts; stmts = NULL; ctxt->cur_stmt = NULL ; ctxt->cur_media_stmt = NULL ; a_media_list = NULL; } static void import_style (CRDocHandler * a_this, GList * a_media_list, CRString * a_uri, CRString * a_uri_default_ns, CRParsingLocation *a_location) { enum CRStatus status = CR_OK; CRString *uri = NULL; CRStatement *stmt = NULL, *stmt2 = NULL; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; GList *media_list = NULL ; (void) a_uri_default_ns; (void) a_location; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt->stylesheet); uri = cr_string_dup (a_uri) ; if (a_media_list) media_list = cr_utils_dup_glist_of_cr_string (a_media_list) ; stmt = cr_statement_new_at_import_rule (ctxt->stylesheet, uri, media_list, NULL); if (!stmt) goto error; if (ctxt->cur_stmt) { stmt2 = cr_statement_append (ctxt->cur_stmt, stmt); if (!stmt2) goto error; ctxt->cur_stmt = stmt2; stmt2 = NULL; stmt = NULL; } else { stmt2 = cr_statement_append (ctxt->stylesheet->statements, stmt); if (!stmt2) goto error; ctxt->stylesheet->statements = stmt2; stmt2 = NULL; stmt = NULL; } return; error: if (uri) { cr_string_destroy (uri); } if (stmt) { cr_statement_destroy (stmt); stmt = NULL; } a_uri_default_ns = NULL; /*keep compiler happy */ } static void start_selector (CRDocHandler * a_this, CRSelector * a_selector_list) { enum CRStatus status = CR_OK ; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); if (ctxt->cur_stmt) { /*hmm, this should be NULL so free it */ cr_statement_destroy (ctxt->cur_stmt); ctxt->cur_stmt = NULL; } ctxt->cur_stmt = cr_statement_new_ruleset (ctxt->stylesheet, a_selector_list, NULL, NULL); } static void end_selector (CRDocHandler * a_this, CRSelector * a_selector_list) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; (void) a_selector_list; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); g_return_if_fail (ctxt->cur_stmt && ctxt->stylesheet); if (ctxt->cur_stmt) { CRStatement *stmts = NULL; if (ctxt->cur_media_stmt) { CRAtMediaRule *media_rule = NULL; media_rule = ctxt->cur_media_stmt->kind.media_rule; stmts = cr_statement_append (media_rule->rulesets, ctxt->cur_stmt); if (!stmts) { cr_utils_trace_info ("Could not append a new statement"); cr_statement_destroy (media_rule->rulesets); ctxt->cur_media_stmt-> kind.media_rule->rulesets = NULL; return; } media_rule->rulesets = stmts; ctxt->cur_stmt = NULL; } else { stmts = cr_statement_append (ctxt->stylesheet->statements, ctxt->cur_stmt); if (!stmts) { cr_utils_trace_info ("Could not append a new statement"); cr_statement_destroy (ctxt->cur_stmt); ctxt->cur_stmt = NULL; return; } ctxt->stylesheet->statements = stmts; ctxt->cur_stmt = NULL; } } a_selector_list = NULL; /*keep compiler happy */ } static void property (CRDocHandler * a_this, CRString * a_name, CRTerm * a_expression, gboolean a_important) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; CRDeclaration *decl = NULL, *decl2 = NULL; CRString *str = NULL; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); /* *make sure a current ruleset statement has been allocated *already. */ g_return_if_fail (ctxt->cur_stmt && (ctxt->cur_stmt->type == RULESET_STMT || ctxt->cur_stmt->type == AT_FONT_FACE_RULE_STMT || ctxt->cur_stmt->type == AT_PAGE_RULE_STMT)); if (a_name) { str = cr_string_dup (a_name); g_return_if_fail (str); } /*instanciates a new declaration */ decl = cr_declaration_new (ctxt->cur_stmt, str, a_expression); g_return_if_fail (decl); str = NULL; decl->important = a_important; /* *add the new declaration to the current statement *being build. */ switch (ctxt->cur_stmt->type) { case RULESET_STMT: decl2 = cr_declaration_append (ctxt->cur_stmt->kind.ruleset->decl_list, decl); if (!decl2) { cr_declaration_destroy (decl); decl = NULL; cr_utils_trace_info ("Could not append decl to ruleset"); goto error; } ctxt->cur_stmt->kind.ruleset->decl_list = decl2; decl = NULL; decl2 = NULL; break; case AT_FONT_FACE_RULE_STMT: decl2 = cr_declaration_append (ctxt->cur_stmt->kind.font_face_rule->decl_list, decl); if (!decl2) { cr_declaration_destroy (decl); decl = NULL; cr_utils_trace_info ("Could not append decl to ruleset"); goto error; } ctxt->cur_stmt->kind.font_face_rule->decl_list = decl2; decl = NULL; decl2 = NULL; break; case AT_PAGE_RULE_STMT: decl2 = cr_declaration_append (ctxt->cur_stmt->kind.page_rule->decl_list, decl); if (!decl2) { cr_declaration_destroy (decl); decl = NULL; cr_utils_trace_info ("Could not append decl to ruleset"); goto error; } ctxt->cur_stmt->kind.page_rule->decl_list = decl2; decl = NULL; decl2 = NULL; break; default: goto error; break; } return; error: if (str) { g_free (str); str = NULL; } if (decl) { cr_declaration_destroy (decl); decl = NULL; } } static void error (CRDocHandler * a_this) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; g_return_if_fail (a_this); ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK && ctxt); if (ctxt->cur_stmt) { cr_statement_destroy (ctxt->cur_stmt); ctxt->cur_stmt = NULL; } } static void unrecoverable_error (CRDocHandler * a_this) { enum CRStatus status = CR_OK; ParsingContext *ctxt = NULL; ParsingContext **ctxtptr = NULL; ctxtptr = &ctxt; status = cr_doc_handler_get_ctxt (a_this, (gpointer *) ctxtptr); g_return_if_fail (status == CR_OK); if (ctxt) { if (ctxt->stylesheet) { status = cr_doc_handler_set_result (a_this, ctxt->stylesheet); g_return_if_fail (status == CR_OK); } g_free (ctxt); cr_doc_handler_set_ctxt (a_this, NULL); } } /******************************************** *Public methods ********************************************/ /** * cr_om_parser_new: *@a_input: the input stream. * *Constructor of the CROMParser. *Returns the newly built instance of #CROMParser. */ CROMParser * cr_om_parser_new (CRInput * a_input) { CROMParser *result = NULL; enum CRStatus status = CR_OK; result = g_try_malloc (sizeof (CROMParser)); if (!result) { cr_utils_trace_info ("Out of memory"); return NULL; } memset (result, 0, sizeof (CROMParser)); PRIVATE (result) = g_try_malloc (sizeof (CROMParserPriv)); if (!PRIVATE (result)) { cr_utils_trace_info ("Out of memory"); goto error; } memset (PRIVATE (result), 0, sizeof (CROMParserPriv)); PRIVATE (result)->parser = cr_parser_new_from_input (a_input); if (!PRIVATE (result)->parser) { cr_utils_trace_info ("parsing instanciation failed"); goto error; } status = cr_om_parser_init_default_sac_handler (result); if (status != CR_OK) { goto error; } return result; error: if (result) { cr_om_parser_destroy (result); } return NULL; } /** * cr_om_parser_parse_buf: *@a_this: the current instance of #CROMParser. *@a_buf: the in memory buffer to parse. *@a_len: the length of the in memory buffer in number of bytes. *@a_enc: the encoding of the in memory buffer. *@a_result: out parameter the resulting style sheet * *Parses the content of an in memory buffer. * *Returns CR_OK upon successfull completion, an error code otherwise. */ enum CRStatus cr_om_parser_parse_buf (CROMParser * a_this, const guchar * a_buf, gulong a_len, enum CREncoding a_enc, CRStyleSheet ** a_result) { enum CRStatus status = CR_OK; g_return_val_if_fail (a_this && a_result, CR_BAD_PARAM_ERROR); if (!PRIVATE (a_this)->parser) { PRIVATE (a_this)->parser = cr_parser_new (NULL); } status = cr_parser_parse_buf (PRIVATE (a_this)->parser, a_buf, a_len, a_enc); if (status == CR_OK) { CRStyleSheet *result = NULL; CRStyleSheet **resultptr = NULL; CRDocHandler *sac_handler = NULL; cr_parser_get_sac_handler (PRIVATE (a_this)->parser, &sac_handler); g_return_val_if_fail (sac_handler, CR_ERROR); resultptr = &result; status = cr_doc_handler_get_result (sac_handler, (gpointer *) resultptr); g_return_val_if_fail (status == CR_OK, status); if (result) *a_result = result; } return status; } /** * cr_om_parser_simply_parse_buf: *@a_buf: the css2 in memory buffer. *@a_len: the length of the in memory buffer. *@a_enc: the encoding of the in memory buffer. *@a_result: out parameter. The resulting css2 style sheet. * *The simpler way to parse an in memory css2 buffer. * *Returns CR_OK upon successfull completion, an error code otherwise. */ enum CRStatus cr_om_parser_simply_parse_buf (const guchar * a_buf, gulong a_len, enum CREncoding a_enc, CRStyleSheet ** a_result) { CROMParser *parser = NULL; enum CRStatus status = CR_OK; parser = cr_om_parser_new (NULL); if (!parser) { cr_utils_trace_info ("Could not create om parser"); cr_utils_trace_info ("System possibly out of memory"); return CR_ERROR; } status = cr_om_parser_parse_buf (parser, a_buf, a_len, a_enc, a_result); if (parser) { cr_om_parser_destroy (parser); parser = NULL; } return status; } /** * cr_om_parser_parse_file: *@a_this: the current instance of the cssom parser. *@a_file_uri: the uri of the file. *(only local file paths are suppported so far) *@a_enc: the encoding of the file. *@a_result: out parameter. A pointer *the build css object model. * *Parses a css2 stylesheet contained *in a file. * * Returns CR_OK upon succesful completion, an error code otherwise. */ enum CRStatus cr_om_parser_parse_file (CROMParser * a_this, const guchar * a_file_uri, enum CREncoding a_enc, CRStyleSheet ** a_result) { enum CRStatus status = CR_OK; g_return_val_if_fail (a_this && a_file_uri && a_result, CR_BAD_PARAM_ERROR); if (!PRIVATE (a_this)->parser) { PRIVATE (a_this)->parser = cr_parser_new_from_file (a_file_uri, a_enc); } status = cr_parser_parse_file (PRIVATE (a_this)->parser, a_file_uri, a_enc); if (status == CR_OK) { CRStyleSheet *result = NULL; CRStyleSheet **resultptr = NULL; CRDocHandler *sac_handler = NULL; cr_parser_get_sac_handler (PRIVATE (a_this)->parser, &sac_handler); g_return_val_if_fail (sac_handler, CR_ERROR); resultptr = &result; status = cr_doc_handler_get_result (sac_handler, (gpointer *) resultptr); g_return_val_if_fail (status == CR_OK, status); if (result) *a_result = result; } return status; } /** * cr_om_parser_simply_parse_file: *@a_file_path: the css2 local file path. *@a_enc: the file encoding. *@a_result: out parameter. The returned css stylesheet. *Must be freed by the caller using cr_stylesheet_destroy. * *The simpler method to parse a css2 file. * *Returns CR_OK upon successfull completion, an error code otherwise. *Note that this method uses cr_om_parser_parse_file() so both methods *have the same return values. */ enum CRStatus cr_om_parser_simply_parse_file (const guchar * a_file_path, enum CREncoding a_enc, CRStyleSheet ** a_result) { CROMParser *parser = NULL; enum CRStatus status = CR_OK; parser = cr_om_parser_new (NULL); if (!parser) { cr_utils_trace_info ("Could not allocate om parser"); cr_utils_trace_info ("System may be out of memory"); return CR_ERROR; } status = cr_om_parser_parse_file (parser, a_file_path, a_enc, a_result); if (parser) { cr_om_parser_destroy (parser); parser = NULL; } return status; } /** * cr_om_parser_parse_paths_to_cascade: *@a_this: the current instance of #CROMParser *@a_author_path: the path to the author stylesheet *@a_user_path: the path to the user stylesheet *@a_ua_path: the path to the User Agent stylesheet *@a_encoding: the encoding of the sheets. *@a_result: out parameter. The resulting cascade if the parsing *was okay * *Parses three sheets located by their paths and build a cascade * *Returns CR_OK upon successful completion, an error code otherwise */ enum CRStatus cr_om_parser_parse_paths_to_cascade (CROMParser * a_this, const guchar * a_author_path, const guchar * a_user_path, const guchar * a_ua_path, enum CREncoding a_encoding, CRCascade ** a_result) { enum CRStatus status = CR_OK; /*0->author sheet, 1->user sheet, 2->UA sheet */ CRStyleSheet *sheets[3]; guchar *paths[3]; CRCascade *result = NULL; gint i = 0; g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR); memset (sheets, 0, sizeof (CRStyleSheet*) * 3); paths[0] = (guchar *) a_author_path; paths[1] = (guchar *) a_user_path; paths[2] = (guchar *) a_ua_path; for (i = 0; i < 3; i++) { status = cr_om_parser_parse_file (a_this, paths[i], a_encoding, &sheets[i]); if (status != CR_OK) { if (sheets[i]) { cr_stylesheet_unref (sheets[i]); sheets[i] = NULL; } continue; } } result = cr_cascade_new (sheets[0], sheets[1], sheets[2]); if (!result) { for (i = 0; i < 3; i++) { cr_stylesheet_unref (sheets[i]); sheets[i] = 0; } return CR_ERROR; } *a_result = result; return CR_OK; } /** * cr_om_parser_simply_parse_paths_to_cascade: *@a_author_path: the path to the author stylesheet *@a_user_path: the path to the user stylesheet *@a_ua_path: the path to the User Agent stylesheet *@a_encoding: the encoding of the sheets. *@a_result: out parameter. The resulting cascade if the parsing *was okay * *Parses three sheets located by their paths and build a cascade * *Returns CR_OK upon successful completion, an error code otherwise */ enum CRStatus cr_om_parser_simply_parse_paths_to_cascade (const guchar * a_author_path, const guchar * a_user_path, const guchar * a_ua_path, enum CREncoding a_encoding, CRCascade ** a_result) { enum CRStatus status = CR_OK; CROMParser *parser = NULL; parser = cr_om_parser_new (NULL); if (!parser) { cr_utils_trace_info ("could not allocated om parser"); cr_utils_trace_info ("System may be out of memory"); return CR_ERROR; } status = cr_om_parser_parse_paths_to_cascade (parser, a_author_path, a_user_path, a_ua_path, a_encoding, a_result); if (parser) { cr_om_parser_destroy (parser); parser = NULL; } return status; } /** * cr_om_parser_destroy: *@a_this: the current instance of #CROMParser. * *Destructor of the #CROMParser. */ void cr_om_parser_destroy (CROMParser * a_this) { g_return_if_fail (a_this && PRIVATE (a_this)); if (PRIVATE (a_this)->parser) { cr_parser_destroy (PRIVATE (a_this)->parser); PRIVATE (a_this)->parser = NULL; } if (PRIVATE (a_this)) { g_free (PRIVATE (a_this)); PRIVATE (a_this) = NULL; } if (a_this) { g_free (a_this); a_this = NULL; } }