/*
    GSK - a library to write servers
    Copyright (C) 2001 Dave Benson

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA

    Contact:
        daveb@ffem.org <Dave Benson>
*/

/* GskXmlProcessor: Streaming GtkArg instantiation from raw XML data. */

#ifndef __GSK_XML_PROCESSOR_H_
#define __GSK_XML_PROCESSOR_H_

#include "../gskgtk.h"

typedef struct _GskXmlProcessor GskXmlProcessor;
typedef struct _GskXmlConfig GskXmlConfig;
typedef struct _GskXmlNamespace GskXmlNamespace;

typedef void (*GskXmlErrorFunc) (const char         *filename,
				 guint               line_no,
				 const char         *message,
				 gpointer            data);

/* Callback to asynchronously return a GtkArg. */
typedef void (*GskXmlArgCallback)(GtkArg          *arg,
				  gpointer         arg_cb_data);

/* Callback to try and get types by name. */
typedef GtkType (*GskXmlGetType) (const char      *name,
			          gpointer         get_type_data);

/* Test whether a configuration should permit instantiation of TYPE. */
typedef gboolean (*GskXmlTypeTestFunc)(GtkType    type,
				       gpointer   test_data);

/* --- GskXmlConfig: xml processor configuration --- */
GskXmlConfig     *gsk_xml_config_new          (GskXmlNamespace   *ns);

/* permit certain types to be instantiated with this GskXmlConfig.  */
void              gsk_xml_config_add_type     (GskXmlConfig      *config,
				               GtkType            type);
void              gsk_xml_config_add_type_test(GskXmlConfig      *config,
					       GskXmlTypeTestFunc type_func,
					       gpointer           test_data,
					       GDestroyNotify     test_destroy);

/* check whether CONFIG permits instantiation of TYPE. */
gboolean          gsk_xml_config_test_type    (GskXmlConfig      *config,
					       GtkType            type);

/* specify a mechanism to load a new type */
void              gsk_xml_config_set_loader   (GskXmlConfig      *config,
					       GskXmlGetType      get_type_func,
					       gpointer           get_type_data,
					       GDestroyNotify     destroy);
GtkType           gsk_xml_config_load_type    (GskXmlConfig      *config,
					       const char        *type_name);

/* A GskXmlGetType-function which scans the current binary for
 * types by named _get_type() function.
 */
GtkType           gsk_xml_loader_introspective(const char        *type_name,
					       gpointer           unused);

/* Obtain the namespace which will be the globals during parsing */
GskXmlNamespace  *gsk_xml_config_peek_globals (GskXmlConfig      *config);

void              gsk_xml_config_ref          (GskXmlConfig      *config);
void              gsk_xml_config_unref        (GskXmlConfig      *config);

/* --- GskXmlProcessor: processing xml, receiving callbacks new objects --- */

GskXmlProcessor * gsk_xml_processor_new       (GskXmlConfig      *config,
					       GtkType            search_type,
					       GskXmlArgCallback  arg_cb,
					       gpointer           arg_cb_data,
					       GDestroyNotify     cb_destroy);
gboolean          gsk_xml_processor_input     (GskXmlProcessor   *processor,
				               const char        *input,
				               int                num_read);
void              gsk_xml_processor_set_pos   (GskXmlProcessor   *processor,
					       const char        *filename,
					       int                lineno);
GskXmlNamespace  *gsk_xml_processor_peek_ns   (GskXmlProcessor   *processor);
void              gsk_xml_processor_destroy   (GskXmlProcessor   *processor);

/* some sort of parse error handling... */
void              gsk_xml_processor_error     (GskXmlProcessor   *processor,
					       const char        *format,
					       ...) G_GNUC_PRINTF(2,3);
void              gsk_xml_processor_errorv    (GskXmlProcessor   *processor,
			                       const char        *format,
			                       va_list            args);
guint             gsk_xml_processor_trap_err  (GskXmlProcessor   *processor,
					       GskXmlErrorFunc    error_handler,
					       gpointer           error_data,
					       GDestroyNotify     destroy);
void              gsk_xml_processor_untrap_err(GskXmlProcessor   *processor,
					       guint              trap_id);
gboolean          gsk_xml_processor_had_error (GskXmlProcessor   *processor);

/* --- GskXmlNamespace: map from names to typed values --- */
GskXmlNamespace  *gsk_xml_namespace_new       (GskXmlNamespace   *parent);
void              gsk_xml_namespace_assign    (GskXmlNamespace   *ns,
					       GtkArg            *value);
gboolean          gsk_xml_namespace_lookup    (GskXmlNamespace   *ns,
					       const char        *name,
					       GtkArg           **value_out);
void              gsk_xml_namespace_ref       (GskXmlNamespace   *ns);
void              gsk_xml_namespace_unref     (GskXmlNamespace   *ns);
/* scopes */                                                     
void              gsk_xml_namespace_push      (GskXmlNamespace   *ns);
void              gsk_xml_namespace_pop       (GskXmlNamespace   *ns);

#endif
