/* xml_news.c Bygfoot Football Manager -- a small and simple GTK2-based football management game. http://bygfoot.sourceforge.net Copyright (C) 2005 Gyözö Both (gyboth@bygfoot.com) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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 General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "free.h" #include "news.h" #include "misc.h" #include "variables.h" #include "xml_news.h" #define TAG_NEWS "news" #define TAG_ARTICLE "news_article" #define TAG_ARTICLE_TYPE "type" #define TAG_ARTICLE_CONDITION "condition" #define TAG_ARTICLE_PRIORITY "priority" #define TAG_ARTICLE_TITLE "title" #define TAG_ARTICLE_SUBTITLE "subtitle" #define ATT_NAME_TEXT_PRIORITY "priority" #define ATT_NAME_TEXT_CONDITION "condition" #define ARTICLE_TYPE_NAME_MATCH "match" #define ARTICLE_TYPE_NAME_FINANCES "finances" #define ARTICLE_TYPE_NAME_STAR_PLAYER_TRANSFER "star_player_transfer" #define ARTICLE_TYPE_NAME_LEAGUE_CHAMPION "league_champion" #define ARTICLE_TYPE_NAME_CUP_QUALIFICATION "cup_qualification" #define ARTICLE_TYPE_NAME_RELEGATION "relegation" enum XmlNewsStates { STATE_NEWS = 0, STATE_ARTICLE, STATE_ARTICLE_TYPE, STATE_ARTICLE_CONDITION, STATE_ARTICLE_PRIORITY, STATE_ARTICLE_TITLE, STATE_ARTICLE_SUBTITLE, STATE_END }; gint state, article_idx, priority; gchar *condition; NewsArticle new_article; NewsText new_title, new_subtitle; /** Return the appropriate enum integer going with the type string. */ gint xml_news_article_type_to_int(const gchar *type_string) { #ifdef DEBUG printf("xml_news_type_to_int\n"); #endif gint return_value = -1; if(strcmp(type_string, ARTICLE_TYPE_NAME_MATCH) == 0) return_value = NEWS_ARTICLE_TYPE_MATCH; else if(strcmp(type_string, ARTICLE_TYPE_NAME_FINANCES) == 0) return_value = NEWS_ARTICLE_TYPE_FINANCES; else if(strcmp(type_string, ARTICLE_TYPE_NAME_STAR_PLAYER_TRANSFER) == 0) return_value = NEWS_ARTICLE_TYPE_STAR_PLAYER_TRANSFER; else if(strcmp(type_string, ARTICLE_TYPE_NAME_LEAGUE_CHAMPION) == 0) return_value = NEWS_ARTICLE_TYPE_LEAGUE_CHAMPION; else if(strcmp(type_string, ARTICLE_TYPE_NAME_CUP_QUALIFICATION) == 0) return_value = NEWS_ARTICLE_TYPE_CUP_QUALIFICATION; else if(strcmp(type_string, ARTICLE_TYPE_NAME_RELEGATION) == 0) return_value = NEWS_ARTICLE_TYPE_RELEGATION; else debug_print_message("xml_news_type_to_int: unknown type name %s \n", type_string); return return_value; } /** * The function called by the parser when an opening tag is read. * The state variable is changed in this function and * sometimes memory allocated for the information that's going to be read. * @see The GLib manual (Simple XML parser). */ void xml_news_read_start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, const gchar **attribute_values, gpointer user_data, GError **error) { #ifdef DEBUG printf("xml_news_read_start_element\n"); #endif gint atidx; atidx = 0; if(strcmp(element_name, TAG_NEWS) == 0) state = STATE_NEWS; else if(strcmp(element_name, TAG_ARTICLE) == 0) { state = STATE_ARTICLE; new_article.titles = g_array_new(FALSE, FALSE, sizeof(NewsText)); new_article.subtitles = g_array_new(FALSE, FALSE, sizeof(NewsText)); new_article.condition = g_strdup("0"); new_article.priority = 1; new_article.id = news_article_id_new; } else if(strcmp(element_name, TAG_ARTICLE_TYPE) == 0) state = STATE_ARTICLE_TYPE; else if(strcmp(element_name, TAG_ARTICLE_CONDITION) == 0) state = STATE_ARTICLE_CONDITION; else if(strcmp(element_name, TAG_ARTICLE_PRIORITY) == 0) state = STATE_ARTICLE_PRIORITY; else if(strcmp(element_name, TAG_ARTICLE_TITLE) == 0) { state = STATE_ARTICLE_TITLE; new_title.id = news_title_id_new; new_title.priority = 1; new_title.condition = g_strdup("1"); while(attribute_names[atidx] != NULL) { if(strcmp(attribute_names[atidx], ATT_NAME_TEXT_PRIORITY) == 0) new_title.priority = (gint)g_ascii_strtod(attribute_values[atidx], NULL); else if(strcmp(attribute_names[atidx], ATT_NAME_TEXT_CONDITION) == 0) misc_string_assign(&new_title.condition, attribute_values[atidx]); atidx++; } } else if(strcmp(element_name, TAG_ARTICLE_SUBTITLE) == 0) { state = STATE_ARTICLE_SUBTITLE; new_subtitle.id = news_subtitle_id_new; new_subtitle.priority = 1; new_subtitle.condition = g_strdup("1"); while(attribute_names[atidx] != NULL) { if(strcmp(attribute_names[atidx], ATT_NAME_TEXT_PRIORITY) == 0) new_subtitle.priority = (gint)g_ascii_strtod(attribute_values[atidx], NULL); else if(strcmp(attribute_names[atidx], ATT_NAME_TEXT_CONDITION) == 0) misc_string_assign(&new_subtitle.condition, attribute_values[atidx]); atidx++; } } else debug_print_message("xml_news_read_start_element: unknown tag: %s; I'm in state %d\n", element_name, state); } /** * The function called by the parser when a closing tag is read. * The state variable is changed in this function. * @see The GLib manual (Simple XML parser). */ void xml_news_read_end_element (GMarkupParseContext *context, const gchar *element_name, gpointer user_data, GError **error) { #ifdef DEBUG printf("xml_news_read_end_element\n"); #endif if(strcmp(element_name, TAG_ARTICLE) == 0) { state = STATE_NEWS; g_array_append_val(news[article_idx], new_article); } else if(strcmp(element_name, TAG_ARTICLE_TYPE) == 0 || strcmp(element_name, TAG_ARTICLE_CONDITION) == 0 || strcmp(element_name, TAG_ARTICLE_PRIORITY) == 0 || strcmp(element_name, TAG_ARTICLE_TITLE) == 0 || strcmp(element_name, TAG_ARTICLE_SUBTITLE) == 0) state = STATE_ARTICLE; else if(strcmp(element_name, TAG_NEWS) != 0) debug_print_message("xml_news_read_end_element: unknown tag: %s; I'm in state %d\n", element_name, state); } /** * The function called by the parser when the text between tags is read. * This function is responsible for filling in the variables (e.g. team names) * when a file gets loaded. * @see The GLib manual (Simple XML parser). */ void xml_news_read_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error) { #ifdef DEBUG printf("xml_news_read_text\n"); #endif gchar buf[text_len + 1]; gint int_value; strncpy(buf, text, text_len); buf[text_len] = '\0'; int_value = (gint)g_ascii_strtod(buf, NULL); if(state == STATE_ARTICLE_TYPE) article_idx = xml_news_article_type_to_int(buf); else if(state == STATE_ARTICLE_CONDITION) misc_string_assign(&new_article.condition, buf); else if(state == STATE_ARTICLE_PRIORITY) new_article.priority = int_value; else if(state == STATE_ARTICLE_TITLE) { new_title.text = g_strdup(buf); g_array_append_val(new_article.titles, new_title); } else if(state == STATE_ARTICLE_SUBTITLE) { new_subtitle.text = g_strdup(buf); g_array_append_val(new_article.subtitles, new_subtitle); } } /** * Function reading an XML file specifying a country. * The variable #country gets freed and overwritten afterwards. * @param news_file Name of the xml file (e.g. 'news_en.xml') * to be read. Full path is not necessary, if the file is located in * one of the suppport directories; neither are the prefix 'news_' * or the suffix '.xml'. */ void xml_news_read(const gchar *news_file) { #ifdef DEBUG printf("xml_news_read\n"); #endif GMarkupParser parser = {xml_news_read_start_element, xml_news_read_end_element, xml_news_read_text, NULL, NULL}; GMarkupParseContext *context; gchar *file_contents; gsize length; GError *error = NULL; context = g_markup_parse_context_new(&parser, 0, NULL, NULL); if(!g_file_get_contents(news_file, &file_contents, &length, &error)) { debug_print_message("xml_news_read: error reading file %s\n", news_file); if(g_str_has_suffix(news_file, "news_en.xml")) misc_print_error(&error, TRUE); else { misc_print_error(&error, FALSE); news_load_news_file("news_en.xml", TRUE); } return; } free_news(TRUE); if(g_markup_parse_context_parse(context, file_contents, length, &error)) { g_markup_parse_context_end_parse(context, NULL); g_markup_parse_context_free(context); g_free(file_contents); } else { debug_print_message("xml_news_read: error parsing file %s\n", news_file); if(g_str_has_suffix(news_file, "news_en.xml")) misc_print_error(&error, TRUE); else { misc_print_error(&error, FALSE); news_load_news_file("news_en.xml", TRUE); } return; } }