/* * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a * aplicativos mainframe. Registro no INPI sob o nome G3270. * * Copyright (C) <2008> * * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela * Free Software Foundation. * * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para * obter mais detalhes. * * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este * programa; se não, escreva para a Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA, 02111-1307, USA * * Este programa está nomeado como parser.c e possui - linhas de código. * * Contatos: * * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) * licinio@bb.com.br (Licínio Luis Branco) * kraucer@bb.com.br (Kraucer Fernandes Mazuco) * */ #include #include "private.h" /*--[ Globals ]--------------------------------------------------------------------------------------*/ static const struct _element_builders { const gchar * name; enum ui_element id; GObject * (*create)(GtkAction *action,struct parser *info,const gchar **names, const gchar **values, GError **error); void (*end)(GObject *widget,struct parser *info,GError **error); } element_builder[] = { { "menubar", UI_ELEMENT_MENUBAR, ui_create_menubar, ui_end_menubar }, { "menu", UI_ELEMENT_MENU, ui_create_menu, ui_end_menu }, { "menuitem", UI_ELEMENT_MENUITEM, ui_create_menuitem, ui_end_menuitem }, { "separator", UI_ELEMENT_SEPARATOR, ui_create_separator, ui_end_separator }, { "toolbar", UI_ELEMENT_TOOLBAR, ui_create_toolbar, ui_end_toolbar }, { "toolitem", UI_ELEMENT_TOOLITEM, ui_create_toolitem, ui_end_toolitem }, { "accelerator", UI_ELEMENT_ACCELERATOR, ui_create_accelerator, ui_end_accelerator }, { "popup", UI_ELEMENT_POPUP, ui_create_popup, ui_end_popup }, { "script", UI_ELEMENT_SCRIPT, ui_create_script, ui_end_script }, }; /*--[ Implement ]------------------------------------------------------------------------------------*/ const gchar * ui_get_attribute(const gchar *key, const gchar **name, const gchar **value) { int f; for(f=0;name[f];f++) { if(!g_strcasecmp(key,name[f])) return value[f]; } return NULL; } gboolean ui_get_bool_attribute(const gchar *key, const gchar **name, const gchar **value, gboolean def) { const gchar *val = ui_get_attribute(key,name,value); if(!val) return def; if(!g_strcasecmp(val,"yes") || atoi(val)) return TRUE; return FALSE; } GObject * ui_get_element(struct parser *info, GtkAction *action, enum ui_element id, const gchar **names, const gchar **values, GError **error) { GObject * obj; const gchar * name = NULL; gchar * key; if(action) name = gtk_action_get_name(action); if(!name) name = ui_get_attribute("name",names,values); if(!name) { *error = g_error_new(ERROR_DOMAIN,EINVAL,"%s", _( "Can't parse unnamed element")); return NULL; } // trace("%s - %s",__FUNCTION__,name); key = g_utf8_strdown(name,-1); obj = g_hash_table_lookup(info->element_list[id],key); g_free(key); return obj; } GObject * ui_insert_element(struct parser *info, GtkAction *action, enum ui_element id, const gchar **names, const gchar **values, GObject *widget, GError **error) { const gchar * name = NULL; gchar * key; if(action) name = gtk_action_get_name(action); if(!name) name = ui_get_attribute("name",names,values); if(!name) { *error = g_error_new(ERROR_DOMAIN,EINVAL,"%s", _( "Can't parse unnamed element")); g_object_unref(widget); return NULL; } key = g_utf8_strdown(name,-1); gtk_widget_set_name(GTK_WIDGET(widget),key); g_object_ref(G_OBJECT(widget)); g_hash_table_insert(info->element_list[id],key,widget); return widget; } static GtkAction * get_action(const gchar *name, struct parser *info, const gchar **names, const gchar **values, GError **error) { GtkAction *action; if(!g_strcasecmp(name,"quit")) { action = g_hash_table_lookup(info->actions,name); if(!action) { action = gtk_action_new(name,NULL,NULL,GTK_STOCK_QUIT); g_signal_connect(action,"activate",G_CALLBACK(gtk_main_quit), NULL); } } else { action = ui_get_action(info->center_widget,name,info->actions,names,values,error); } if(action) ui_action_set_options(action,info,names,values,error); return action; } static void element_start(GMarkupParseContext *context, const gchar *element_name, const gchar **names,const gchar **values, struct parser *info, GError **error) { enum ui_element id = (enum ui_element) -1; GtkAction * action = NULL; const gchar * name = NULL; GtkWidget * widget = NULL; int f; if(info->disabled) { info->disabled++; trace("%s: <%s> disabled=%d",__FUNCTION__,element_name,info->disabled); return; } for(f=0;felement); info->element = G_OBJECT(widget); gtk_widget_set_visible(widget,ui_get_bool_attribute("visible",names,values,TRUE)); } else { info->disabled++; } } static void element_end(GMarkupParseContext *context, const gchar *element_name, struct parser *info, GError **error) { GtkWidget *widget = GTK_WIDGET(info->element); int f; if(info->disabled) { info->disabled--; // trace("%s: <%s> disabled=%d",__FUNCTION__,element_name,info->disabled); return; } for(f=0;felement,info,error); break; } } if(!widget) return; info->element = G_OBJECT(g_object_get_data(G_OBJECT(widget),"parent")); g_object_set_data(G_OBJECT(widget),"parent",NULL); } int ui_parse_file(struct parser *info, const gchar *filename) { static const GMarkupParser parser = { (void (*)(GMarkupParseContext *, const gchar *, const gchar **, const gchar **, gpointer, GError **)) element_start, (void (*)(GMarkupParseContext *, const gchar *, gpointer, GError **)) element_end, // (void (*)(GMarkupParseContext *, const gchar *, gsize, gpointer, GError **)) NULL, // (void (*)(GMarkupParseContext *context, const gchar *passthrough_text, gsize text_len, gpointer user_data,GError **error)) NULL, // (void (*)(GMarkupParseContext *, GError *, gpointer)) NULL }; int rc = 0; GMarkupParseContext * context; GError * error = NULL; gchar * text = NULL; // Load file if(!g_file_get_contents(filename,&text,NULL,&error)) { GtkWidget * dialog; gchar * name = g_path_get_basename(filename); dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _( "Can't load %s" ), name); g_free(name); gtk_window_set_title(GTK_WINDOW(dialog), _( "Can't parse UI" ) ); if(error && error->message) gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", error->message); g_error_free(error); gtk_dialog_run(GTK_DIALOG (dialog)); gtk_widget_destroy(dialog); return -1; } context = g_markup_parse_context_new(&parser,G_MARKUP_TREAT_CDATA_AS_TEXT|G_MARKUP_PREFIX_ERROR_POSITION,info,NULL); if(!g_markup_parse_context_parse(context,text,strlen(text),&error)) { GtkWidget * dialog; gchar * name = g_path_get_basename(filename); dialog = gtk_message_dialog_new( NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _( "Parse error in %s" ), name); g_free(name); gtk_window_set_title(GTK_WINDOW(dialog), _( "Can't parse UI" ) ); if(error && error->message) gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", error->message); g_error_free(error); gtk_dialog_run(GTK_DIALOG (dialog)); gtk_widget_destroy(dialog); rc = -1; } g_markup_parse_context_free(context); g_free(text); // trace("%s exits with rc=%d",__FUNCTION__,rc); info->disabled = 0; if(info->element) { g_object_set_data(G_OBJECT(info->element),"parent",NULL); info->element = NULL; } return rc; }