mirror of
https://github.com/aseprite/aseprite.git
synced 2025-01-26 03:35:23 +00:00
Added ultra-basic XML support in Jinete
This commit is contained in:
parent
a68a9e2e56
commit
f7657bb2dd
30
docs/licenses/BSD.txt
Normal file
30
docs/licenses/BSD.txt
Normal file
@ -0,0 +1,30 @@
|
||||
Jinete - a GUI library
|
||||
Copyright (c) 2003, 2004, 2005, 2007, David A. Capello
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of the Jinete nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
18
docs/licenses/ZLIB.txt
Normal file
18
docs/licenses/ZLIB.txt
Normal file
@ -0,0 +1,18 @@
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
129
jinete/examples/22xml.c
Normal file
129
jinete/examples/22xml.c
Normal file
@ -0,0 +1,129 @@
|
||||
/* jinete - a GUI library
|
||||
* Copyright (C) 2003-2005, 2007 by David A. Capello
|
||||
*
|
||||
* Jinete is gift-ware.
|
||||
*/
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
#include "jinete.h"
|
||||
|
||||
static char *xml_src =
|
||||
"<root>" "\n"
|
||||
" <item>" "\n"
|
||||
" <value1>text" "\n"
|
||||
" </value1>" "\n"
|
||||
" more text" "\n"
|
||||
" </item>" "\n"
|
||||
"</root>";
|
||||
|
||||
static JWidget textsrc, textdst;
|
||||
|
||||
static void read_xml(JWidget widget);
|
||||
static void prt_xmlnode(JXmlNode node, int indent);
|
||||
static void prt(const char *format, ...);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
JWidget manager, window, hbox, vbox, button;
|
||||
|
||||
allegro_init();
|
||||
if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0) < 0) {
|
||||
if (set_gfx_mode(GFX_AUTODETECT, 640, 480, 0, 0) < 0) {
|
||||
allegro_message("%s\n", allegro_error);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
install_timer();
|
||||
install_keyboard();
|
||||
install_mouse();
|
||||
|
||||
manager = jmanager_new();
|
||||
ji_set_standard_theme();
|
||||
|
||||
window = jwindow_new("XML");
|
||||
hbox = jpanel_new(JI_VERTICAL);
|
||||
vbox = jbox_new(JI_VERTICAL);
|
||||
textsrc = jtextbox_new(xml_src, JI_WORDWRAP);
|
||||
textdst = jtextbox_new("", JI_WORDWRAP);
|
||||
button = jbutton_new("Read XML");
|
||||
|
||||
jbutton_add_command(button, read_xml);
|
||||
|
||||
jwidget_expansive(hbox, TRUE);
|
||||
jwidget_expansive(textsrc, TRUE);
|
||||
jwidget_expansive(textdst, TRUE);
|
||||
jwidget_set_static_size(textsrc, 600, 200);
|
||||
jwidget_set_static_size(textdst, 600, 200);
|
||||
|
||||
jwidget_add_child(hbox, textsrc);
|
||||
jwidget_add_child(hbox, textdst);
|
||||
jwidget_add_child(vbox, hbox);
|
||||
jwidget_add_child(vbox, button);
|
||||
jwidget_add_child(window, vbox);
|
||||
|
||||
jwindow_open_bg(window);
|
||||
|
||||
jmanager_run(manager);
|
||||
jmanager_free(manager);
|
||||
return 0;
|
||||
}
|
||||
|
||||
END_OF_MAIN();
|
||||
|
||||
static void read_xml(JWidget widget)
|
||||
{
|
||||
JXml xml;
|
||||
|
||||
prt("Processing XML...\n\n");
|
||||
|
||||
xml = jxml_new_from_string(jwidget_get_text(textsrc));
|
||||
if (!xml) {
|
||||
prt("ERROR\n");
|
||||
return;
|
||||
}
|
||||
|
||||
prt_xmlnode((JXmlNode)xml->root, 0);
|
||||
|
||||
jxml_free(xml);
|
||||
}
|
||||
|
||||
static void prt_xmlnode(JXmlNode node, int indent)
|
||||
{
|
||||
JLink link;
|
||||
int c;
|
||||
|
||||
for (c=0; c<indent; c++)
|
||||
prt(" ");
|
||||
prt("JXmlNode->value = %s\n", node->value);
|
||||
|
||||
JI_LIST_FOR_EACH(node->children, link)
|
||||
prt_xmlnode(link->data, indent+1);
|
||||
}
|
||||
|
||||
static void prt(const char *format, ...)
|
||||
{
|
||||
const char *text;
|
||||
char buf[1024];
|
||||
char *final;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
uvsprintf(buf, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
text = jwidget_get_text(textdst);
|
||||
if (!text)
|
||||
final = jstrdup(buf);
|
||||
else {
|
||||
final = jmalloc(ustrlen(text) + ustrlen(buf) + 1);
|
||||
|
||||
ustrcpy(final, empty_string);
|
||||
ustrcat(final, text);
|
||||
ustrcat(final, buf);
|
||||
}
|
||||
|
||||
jwidget_set_text(textdst, final);
|
||||
jfree(final);
|
||||
}
|
||||
|
70
jinete/include/jinete/stream.h
Normal file
70
jinete/include/jinete/stream.h
Normal file
@ -0,0 +1,70 @@
|
||||
/* Jinete - a GUI library
|
||||
* Copyright (c) 2007 David A. Capello
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the Jinete nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef JINETE_STREAM_H
|
||||
#define JINETE_STREAM_H
|
||||
|
||||
#include "jinete/base.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
JI_BEGIN_DECLS
|
||||
|
||||
struct jstream
|
||||
{
|
||||
void (*close)(JStream stream);
|
||||
bool (*eof)(JStream stream);
|
||||
void (*flush)(JStream stream);
|
||||
int (*getc)(JStream stream);
|
||||
char *(*gets)(JStream stream, char *s, int size);
|
||||
int (*putc)(JStream stream, int ch);
|
||||
int (*seek)(JStream stream, int offset, int whence);
|
||||
int (*tell)(JStream stream);
|
||||
/* void (*error)(JStream stream, const char *err); */
|
||||
};
|
||||
|
||||
JStream jstream_new(int size);
|
||||
JStream jstream_new_for_file(FILE *f);
|
||||
JStream jstream_new_for_string(const char *string);
|
||||
void jstream_free(JStream stream);
|
||||
|
||||
bool jstream_eof(JStream stream);
|
||||
void jstream_flush(JStream stream);
|
||||
int jstream_getc(JStream stream);
|
||||
char *jstream_gets(JStream stream, char *s, int size);
|
||||
int jstream_putc(JStream stream, int ch);
|
||||
/* int jstream_puts(JStream stream, const char *s); */
|
||||
int jstream_seek(JStream stream, int offset, int whence);
|
||||
int jstream_tell(JStream stream);
|
||||
|
||||
JI_END_DECLS
|
||||
|
||||
#endif /* JINETE_STREAM_H */
|
127
jinete/include/jinete/xml.h
Normal file
127
jinete/include/jinete/xml.h
Normal file
@ -0,0 +1,127 @@
|
||||
/* Jinete - a GUI library
|
||||
* Copyright (c) 2007 David A. Capello
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the Jinete nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef JINETE_XML_H
|
||||
#define JINETE_XML_H
|
||||
|
||||
#include "jinete/base.h"
|
||||
|
||||
JI_BEGIN_DECLS
|
||||
|
||||
enum { JI_XML_ELEM, JI_XML_TEXT };
|
||||
|
||||
struct jxml
|
||||
{
|
||||
JXmlElem root;
|
||||
};
|
||||
|
||||
struct jxmlattr
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct jxmlnode
|
||||
{
|
||||
int type;
|
||||
char *value;
|
||||
JXmlNode parent;
|
||||
JList children;
|
||||
};
|
||||
|
||||
struct jxmlelem
|
||||
{
|
||||
struct jxmlnode head;
|
||||
JList attributes;
|
||||
};
|
||||
|
||||
struct jxmltext
|
||||
{
|
||||
struct jxmlnode head;
|
||||
};
|
||||
|
||||
/* JXml **********************************************/
|
||||
|
||||
JXml jxml_new(void);
|
||||
JXml jxml_new_from_file(const char *filename);
|
||||
JXml jxml_new_from_string(const char *buffer);
|
||||
JXml jxml_new_from_stream(JStream stream);
|
||||
void jxml_free(JXml xml);
|
||||
|
||||
JXmlElem jxml_get_root(JXml xml);
|
||||
JXmlElem jxml_get_elem_by_id(JXml xml, const char *id);
|
||||
|
||||
/* JXmlAttr ******************************************/
|
||||
|
||||
JXmlAttr jxmlattr_new(const char *name, const char *value);
|
||||
void jxmlattr_free(JXmlAttr attr);
|
||||
|
||||
const char *jxmlattr_get_name(JXmlAttr attr);
|
||||
const char *jxmlattr_get_value(JXmlAttr attr);
|
||||
void jxmlattr_set_name(JXmlAttr attr, const char *name);
|
||||
void jxmlattr_set_value(JXmlAttr attr, const char *value);
|
||||
|
||||
/* JXmlNode ******************************************/
|
||||
|
||||
JXmlNode jxmlnode_new(int type, const char *value);
|
||||
void jxmlnode_free(JXmlNode node);
|
||||
|
||||
const char *jxmlnode_get_value(JXmlNode node);
|
||||
void jxmlnode_set_value(JXmlNode node, const char *value);
|
||||
|
||||
void jxmlnode_add_child(JXmlNode node, JXmlNode child);
|
||||
void jxmlnode_remove_child(JXmlNode node, JXmlNode child);
|
||||
|
||||
/* JXmlElem ******************************************/
|
||||
|
||||
JXmlElem jxmlelem_new(const char *name);
|
||||
void jxmlelem_free(JXmlElem elem);
|
||||
|
||||
const char *jxmlelem_get_name(JXmlElem elem);
|
||||
void jxmlelem_set_name(JXmlElem elem, const char *name);
|
||||
|
||||
bool jxmlelem_has_attr(JXmlElem elem, const char *name);
|
||||
const char *jxmlelem_get_attr(JXmlElem elem, const char *name);
|
||||
void jxmlelem_set_attr(JXmlElem elem, const char *name, const char *value);
|
||||
|
||||
JXmlElem jxmlelem_get_elem_by_id(JXmlElem elem, const char *id);
|
||||
|
||||
/* JXmlText ******************************************/
|
||||
|
||||
JXmlText jxmltext_new(const char *value);
|
||||
void jxmltext_free(JXmlText text);
|
||||
|
||||
const char *jxmltext_get_text(JXmlText text);
|
||||
void jxmltext_set_text(JXmlText text, const char *value);
|
||||
|
||||
JI_END_DECLS
|
||||
|
||||
#endif /* JINETE_XML_H */
|
346
jinete/src/jstream.c
Normal file
346
jinete/src/jstream.c
Normal file
@ -0,0 +1,346 @@
|
||||
/* Jinete - a GUI library
|
||||
* Copyright (c) 2007 David A. Capello
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the Jinete nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* jstream_string is based on streams of HTMLEX */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jinete.h"
|
||||
|
||||
/* jinete stream file/string */
|
||||
#define JSF ((struct jstream_file *)(stream))
|
||||
#define JSS ((struct jstream_string *)(stream))
|
||||
|
||||
/* size of chunks to add to the buffer for jstream_strings */
|
||||
#define BLOCKSIZE 1024
|
||||
|
||||
struct jstream_file
|
||||
{
|
||||
struct jstream head;
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
struct jstream_string
|
||||
{
|
||||
struct jstream head;
|
||||
char *buf; /* buffer for the characters */
|
||||
int size; /* real size of the buffer */
|
||||
int end; /* index of the last character used in the buffer */
|
||||
int pos; /* the position for read data */
|
||||
};
|
||||
|
||||
static void stream_file_close(JStream stream);
|
||||
static bool stream_file_eof(JStream stream);
|
||||
static void stream_file_flush(JStream stream);
|
||||
static int stream_file_getc(JStream stream);
|
||||
static char *stream_file_gets(JStream stream, char *s, int size);
|
||||
static int stream_file_putc(JStream stream, int ch);
|
||||
static int stream_file_seek(JStream stream, int offset, int whence);
|
||||
static int stream_file_tell(JStream stream);
|
||||
|
||||
static void stream_string_close(JStream stream);
|
||||
static bool stream_string_eof(JStream stream);
|
||||
static void stream_string_flush(JStream stream);
|
||||
static int stream_string_getc(JStream stream);
|
||||
static char *stream_string_gets(JStream stream, char *s, int size);
|
||||
static int stream_string_putc(JStream stream, int ch);
|
||||
static int stream_string_seek(JStream stream, int offset, int whence);
|
||||
static int stream_string_tell(JStream stream);
|
||||
|
||||
JStream jstream_new(int size)
|
||||
{
|
||||
JStream stream = jmalloc0(MAX(size, sizeof(struct jstream)));
|
||||
if (!stream)
|
||||
return NULL;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
JStream jstream_new_for_file(FILE *f)
|
||||
{
|
||||
JStream stream = jstream_new(sizeof(struct jstream_file));
|
||||
if (!stream)
|
||||
return NULL;
|
||||
|
||||
stream->close = stream_file_close;
|
||||
stream->eof = stream_file_eof;
|
||||
stream->flush = stream_file_flush;
|
||||
stream->getc = stream_file_getc;
|
||||
stream->gets = stream_file_gets;
|
||||
stream->putc = stream_file_putc;
|
||||
stream->seek = stream_file_seek;
|
||||
stream->tell = stream_file_tell;
|
||||
|
||||
JSF->file = f;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
JStream jstream_new_for_string(const char *buffer)
|
||||
{
|
||||
JStream stream = jstream_new(sizeof(struct jstream_string));
|
||||
if (!stream)
|
||||
return NULL;
|
||||
|
||||
stream->close = stream_string_close;
|
||||
stream->eof = stream_string_eof;
|
||||
stream->flush = stream_string_flush;
|
||||
stream->getc = stream_string_getc;
|
||||
stream->gets = stream_string_gets;
|
||||
stream->putc = stream_string_putc;
|
||||
stream->seek = stream_string_seek;
|
||||
stream->tell = stream_string_tell;
|
||||
|
||||
JSS->buf = buffer ? jstrdup(buffer): NULL;
|
||||
if (buffer && !JSS->buf) {
|
||||
jfree(stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSS->end = buffer ? strlen(buffer): 0;
|
||||
JSS->size = buffer ? ((JSS->end / BLOCKSIZE) +
|
||||
((JSS->end % BLOCKSIZE) > 0 ? 1: 0)): 0;
|
||||
JSS->pos = 0;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
void jstream_free(JStream stream)
|
||||
{
|
||||
if (stream->close)
|
||||
(*stream->close)(stream);
|
||||
|
||||
jfree(stream);
|
||||
}
|
||||
|
||||
bool jstream_eof(JStream stream)
|
||||
{
|
||||
if (stream->eof)
|
||||
return (*stream->eof)(stream);
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void jstream_flush(JStream stream)
|
||||
{
|
||||
if (stream->flush)
|
||||
(*stream->flush)(stream);
|
||||
}
|
||||
|
||||
int jstream_getc(JStream stream)
|
||||
{
|
||||
if (stream->getc)
|
||||
return (*stream->getc)(stream);
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
char *jstream_gets(JStream stream, char *s, int size)
|
||||
{
|
||||
if (stream->gets)
|
||||
return (*stream->gets)(stream, s, size);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int jstream_putc(JStream stream, int ch)
|
||||
{
|
||||
if (stream->putc)
|
||||
return (*stream->putc)(stream, ch);
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* int jstream_puts(JStream stream, const char *s) */
|
||||
/* { */
|
||||
/* return 0; */
|
||||
/* } */
|
||||
|
||||
int jstream_seek(JStream stream, int offset, int whence)
|
||||
{
|
||||
if (stream->seek)
|
||||
return (*stream->seek)(stream, offset, whence);
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
int jstream_tell(JStream stream)
|
||||
{
|
||||
if (stream->tell)
|
||||
return (*stream->tell)(stream);
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* jstream_file */
|
||||
|
||||
static void stream_file_close(JStream stream)
|
||||
{
|
||||
FILE *f = JSF->file;
|
||||
if ((f != stdin) && (f != stdout) && (f != stderr))
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
static bool stream_file_eof(JStream stream)
|
||||
{
|
||||
return feof(JSF->file) != 0;
|
||||
}
|
||||
|
||||
static void stream_file_flush(JStream stream)
|
||||
{
|
||||
fflush(JSF->file);
|
||||
}
|
||||
|
||||
static int stream_file_getc(JStream stream)
|
||||
{
|
||||
return fgetc(JSF->file);
|
||||
}
|
||||
|
||||
static char *stream_file_gets(JStream stream, char *s, int size)
|
||||
{
|
||||
return fgets(s, size, JSF->file);
|
||||
}
|
||||
|
||||
static int stream_file_putc(JStream stream, int ch)
|
||||
{
|
||||
return fputc(ch, JSF->file);
|
||||
}
|
||||
|
||||
static int stream_file_seek(JStream stream, int offset, int whence)
|
||||
{
|
||||
return fseek(JSF->file, offset, whence);
|
||||
}
|
||||
|
||||
static int stream_file_tell(JStream stream)
|
||||
{
|
||||
return ftell(JSF->file);
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* jstream_string */
|
||||
|
||||
static void stream_string_close(JStream stream)
|
||||
{
|
||||
if (JSS->buf)
|
||||
jfree(JSS->buf);
|
||||
}
|
||||
|
||||
static bool stream_string_eof(JStream stream)
|
||||
{
|
||||
return (JSS->pos == JSS->end);
|
||||
}
|
||||
|
||||
static void stream_string_flush(JStream stream)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static int stream_string_getc(JStream stream)
|
||||
{
|
||||
if (JSS->pos < JSS->end)
|
||||
return JSS->buf[JSS->pos++];
|
||||
else
|
||||
return EOF;
|
||||
}
|
||||
|
||||
static char *stream_string_gets(JStream stream, char *s, int size)
|
||||
{
|
||||
if (JSS->pos == JSS->end)
|
||||
return NULL;
|
||||
else {
|
||||
char *r = s;
|
||||
int c, i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (JSS->pos < JSS->end) {
|
||||
c = JSS->buf[JSS->pos++];
|
||||
*(s++) = c;
|
||||
if (c == '\n')
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
*s = 0;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
static int stream_string_putc(JStream stream, int ch)
|
||||
{
|
||||
if (JSS->end >= JSS->size) {
|
||||
JSS->size += BLOCKSIZE;
|
||||
JSS->buf = jrealloc(JSS->buf, JSS->size);
|
||||
if (!JSS->buf) {
|
||||
JSS->size = 0;
|
||||
JSS->end = 0;
|
||||
JSS->pos = 0;
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
|
||||
if (JSS->pos < JSS->end)
|
||||
memmove(JSS->buf + JSS->pos + 1,
|
||||
JSS->buf + JSS->pos,
|
||||
JSS->end - JSS->pos);
|
||||
|
||||
JSS->end++;
|
||||
return JSS->buf[JSS->pos++] = ch;
|
||||
}
|
||||
|
||||
static int stream_string_seek(JStream stream, int offset, int whence)
|
||||
{
|
||||
switch (whence) {
|
||||
case SEEK_SET:
|
||||
JSS->pos = offset;
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
JSS->pos += offset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
JSS->pos = JSS->end + offset;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
if (JSS->pos < 0)
|
||||
JSS->pos = 0;
|
||||
else if (JSS->pos > JSS->end)
|
||||
JSS->pos = JSS->end;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stream_string_tell(JStream stream)
|
||||
{
|
||||
return JSS->pos;
|
||||
}
|
615
jinete/src/jxml.c
Normal file
615
jinete/src/jxml.c
Normal file
@ -0,0 +1,615 @@
|
||||
/* Jinete - a GUI library
|
||||
* Copyright (c) 2007 David A. Capello
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of the Jinete nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "jinete.h"
|
||||
|
||||
/* determine is the characer is a blank space */
|
||||
#define IS_BLANK(chr) (((chr) == ' ') || \
|
||||
((chr) == '\t') || \
|
||||
((chr) == '\n') || \
|
||||
((chr) == '\r'))
|
||||
|
||||
static JList read_nodes(JStream stream);
|
||||
static JXmlElem read_elem(char *elem_string);
|
||||
|
||||
/**********************************************************************/
|
||||
/* JXml */
|
||||
/**********************************************************************/
|
||||
|
||||
JXml jxml_new(void)
|
||||
{
|
||||
JXml xml= jnew(struct jxml, 1);
|
||||
if (!xml)
|
||||
return NULL;
|
||||
|
||||
xml->root = NULL;
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
JXml jxml_new_from_file(const char *filename)
|
||||
{
|
||||
JStream stream;
|
||||
JXml xml;
|
||||
FILE *f;
|
||||
|
||||
/* open the file */
|
||||
f = fopen(filename, "rt");
|
||||
if (!f)
|
||||
return NULL;
|
||||
|
||||
/* read the xml */
|
||||
stream = jstream_new_for_file(f);
|
||||
xml = jxml_new_from_stream(stream);
|
||||
jstream_free(stream);
|
||||
|
||||
/* and close it */
|
||||
fclose(f);
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
JXml jxml_new_from_string(const char *buffer)
|
||||
{
|
||||
JStream stream;
|
||||
JXml xml;
|
||||
|
||||
stream = jstream_new_for_string(buffer);
|
||||
xml = jxml_new_from_stream(stream);
|
||||
jstream_free(stream);
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
JXml jxml_new_from_stream(JStream stream)
|
||||
{
|
||||
JList nodes = read_nodes(stream);
|
||||
JXml xml = NULL;
|
||||
|
||||
if (!nodes)
|
||||
return NULL;
|
||||
|
||||
if (jlist_length(nodes) != 1) {
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(nodes, link) {
|
||||
JXmlNode node = (JXmlNode)link->data;
|
||||
jxmlnode_free(node);
|
||||
}
|
||||
|
||||
/* xml_error("More than one tag in root"); */
|
||||
}
|
||||
else {
|
||||
xml = jxml_new();
|
||||
xml->root = jlist_first_data(nodes);
|
||||
}
|
||||
|
||||
jlist_free(nodes);
|
||||
return xml;
|
||||
}
|
||||
|
||||
void jxml_free(JXml xml)
|
||||
{
|
||||
if (xml->root)
|
||||
jxmlelem_free(xml->root);
|
||||
|
||||
jfree(xml);
|
||||
}
|
||||
|
||||
JXmlElem jxml_get_root(JXml xml)
|
||||
{
|
||||
return xml->root;
|
||||
}
|
||||
|
||||
JXmlElem jxml_get_elem_by_id(JXml xml, const char *id)
|
||||
{
|
||||
if (xml->root)
|
||||
return jxmlelem_get_elem_by_id(xml->root, id);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* JXmlAttr */
|
||||
/**********************************************************************/
|
||||
|
||||
JXmlAttr jxmlattr_new(const char *name, const char *value)
|
||||
{
|
||||
JXmlAttr attr = jnew(struct jxmlattr, 1);
|
||||
attr->name = name ? jstrdup(name): NULL;
|
||||
attr->value = value ? jstrdup(value): NULL;
|
||||
return attr;
|
||||
}
|
||||
|
||||
void jxmlattr_free(JXmlAttr attr)
|
||||
{
|
||||
if (attr->name)
|
||||
jfree(attr->name);
|
||||
|
||||
if (attr->value)
|
||||
jfree(attr->value);
|
||||
|
||||
jfree(attr);
|
||||
}
|
||||
|
||||
const char *jxmlattr_get_name(JXmlAttr attr)
|
||||
{
|
||||
return attr->name;
|
||||
}
|
||||
|
||||
const char *jxmlattr_get_value(JXmlAttr attr)
|
||||
{
|
||||
return attr->value;
|
||||
}
|
||||
|
||||
void jxmlattr_set_name(JXmlAttr attr, const char *name)
|
||||
{
|
||||
if (attr->name)
|
||||
jfree(attr->name);
|
||||
|
||||
attr->name = name ? jstrdup(name): NULL;
|
||||
}
|
||||
|
||||
void jxmlattr_set_value(JXmlAttr attr, const char *value)
|
||||
{
|
||||
if (attr->value)
|
||||
jfree(attr->value);
|
||||
|
||||
attr->value = value ? jstrdup(value): NULL;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* JXmlNode */
|
||||
/**********************************************************************/
|
||||
|
||||
JXmlNode jxmlnode_new(int type, const char *value)
|
||||
{
|
||||
JXmlNode node = NULL;
|
||||
|
||||
switch (type) {
|
||||
case JI_XML_ELEM:
|
||||
node = (JXmlNode)jnew(struct jxmlelem, 1);
|
||||
if (node) {
|
||||
((JXmlElem)node)->attributes = jlist_new();
|
||||
}
|
||||
break;
|
||||
case JI_XML_TEXT:
|
||||
node = (JXmlNode)jnew(struct jxmltext, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (node) {
|
||||
node->type = type;
|
||||
node->value = value ? jstrdup(value): NULL;
|
||||
node->parent = NULL;
|
||||
node->children = jlist_new();
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void jxmlnode_free(JXmlNode node)
|
||||
{
|
||||
JLink link;
|
||||
|
||||
switch (node->type) {
|
||||
case JI_XML_ELEM:
|
||||
JI_LIST_FOR_EACH(((JXmlElem)node)->attributes, link) {
|
||||
JXmlAttr child = (JXmlAttr)link->data;
|
||||
jxmlattr_free(child);
|
||||
}
|
||||
jlist_free(((JXmlElem)node)->attributes);
|
||||
break;
|
||||
case JI_XML_TEXT:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
|
||||
if (node->value)
|
||||
jfree(node->value);
|
||||
|
||||
JI_LIST_FOR_EACH(node->children, link) {
|
||||
JXmlNode child = (JXmlNode)link->data;
|
||||
jxmlnode_free(child);
|
||||
}
|
||||
jlist_free(node->children);
|
||||
|
||||
jfree(node);
|
||||
}
|
||||
|
||||
const char *jxmlnode_get_value(JXmlNode node)
|
||||
{
|
||||
return node->value;
|
||||
}
|
||||
|
||||
void jxmlnode_set_value(JXmlNode node, const char *value)
|
||||
{
|
||||
if (node->value)
|
||||
jfree(node->value);
|
||||
|
||||
node->value = value ? jstrdup(value): NULL;
|
||||
}
|
||||
|
||||
void jxmlnode_add_child(JXmlNode node, JXmlNode child)
|
||||
{
|
||||
jlist_append(node->children, child);
|
||||
child->parent = node;
|
||||
}
|
||||
|
||||
void jxmlnode_remove_child(JXmlNode node, JXmlNode child)
|
||||
{
|
||||
jlist_remove(node->children, child);
|
||||
child->parent = NULL;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* JXmlElem */
|
||||
/**********************************************************************/
|
||||
|
||||
JXmlElem jxmlelem_new(const char *name)
|
||||
{
|
||||
return (JXmlElem)jxmlnode_new(JI_XML_ELEM, name);
|
||||
}
|
||||
|
||||
void jxmlelem_free(JXmlElem elem)
|
||||
{
|
||||
jxmlnode_free((JXmlNode)elem);
|
||||
}
|
||||
|
||||
const char *jxmlelem_get_name(JXmlElem elem)
|
||||
{
|
||||
return jxmlnode_get_value((JXmlNode)elem);
|
||||
}
|
||||
|
||||
void jxmlelem_set_name(JXmlElem elem, const char *name)
|
||||
{
|
||||
jxmlnode_set_value((JXmlNode)elem, name);
|
||||
}
|
||||
|
||||
bool jxmlelem_has_attr(JXmlElem elem, const char *name)
|
||||
{
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(elem->attributes, link) {
|
||||
JXmlAttr attr = (JXmlAttr)link->data;
|
||||
if (strcmp(name, jxmlattr_get_name(attr)) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const char *jxmlelem_get_attr(JXmlElem elem, const char *name)
|
||||
{
|
||||
JLink link;
|
||||
|
||||
JI_LIST_FOR_EACH(elem->attributes, link) {
|
||||
JXmlAttr attr = (JXmlAttr)link->data;
|
||||
if (strcmp(name, jxmlattr_get_name(attr)) == 0) {
|
||||
return jxmlattr_get_value(attr);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void jxmlelem_set_attr(JXmlElem elem, const char *name, const char *value)
|
||||
{
|
||||
JXmlAttr attr;
|
||||
JLink link;
|
||||
|
||||
/* does the attribute exist? */
|
||||
JI_LIST_FOR_EACH(elem->attributes, link) {
|
||||
attr = (JXmlAttr)link->data;
|
||||
if (strcmp(name, jxmlattr_get_name(attr)) == 0) {
|
||||
jxmlattr_set_value(attr, value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
attr = jxmlattr_new(name, value);
|
||||
jlist_append(elem->attributes, attr);
|
||||
}
|
||||
|
||||
JXmlElem jxmlelem_get_elem_by_id(JXmlElem elem, const char *id)
|
||||
{
|
||||
const char *elem_id = jxmlelem_get_attr(elem, "id");
|
||||
JLink link;
|
||||
|
||||
/* fprintf(stderr, "- %s id=%s\n", jxmlelem_get_name(elem), elem_id ? elem_id: "(null)"); */
|
||||
|
||||
/* this is the element with the specified ID */
|
||||
if (elem_id && strcmp(elem_id, id) == 0)
|
||||
return elem;
|
||||
|
||||
/* go through the children */
|
||||
JI_LIST_FOR_EACH(((JXmlNode)elem)->children, link) {
|
||||
JXmlNode child = (JXmlNode)link->data;
|
||||
if (child->type == JI_XML_ELEM) {
|
||||
JXmlElem found = jxmlelem_get_elem_by_id((JXmlElem)child, id);
|
||||
if (found)
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**********************************************************************/
|
||||
/* JXmlText */
|
||||
/**********************************************************************/
|
||||
|
||||
JXmlText jxmltext_new(const char *value)
|
||||
{
|
||||
return (JXmlText)jxmlnode_new(JI_XML_TEXT, value);
|
||||
}
|
||||
|
||||
void jxmltext_free(JXmlText text)
|
||||
{
|
||||
jxmlnode_free((JXmlNode)text);
|
||||
}
|
||||
|
||||
const char *jxmltext_get_text(JXmlText text)
|
||||
{
|
||||
return ((JXmlNode)text)->value;
|
||||
}
|
||||
|
||||
void jxmltext_set_text(JXmlText text, const char *value)
|
||||
{
|
||||
if (((JXmlNode)text)->value)
|
||||
jfree(((JXmlNode)text)->value);
|
||||
|
||||
((JXmlNode)text)->value = value ? jstrdup(value): NULL;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************/
|
||||
/* READ XML TAGS */
|
||||
/**********************************************************************/
|
||||
|
||||
static JList read_nodes(JStream stream)
|
||||
{
|
||||
JList root_tags = jlist_new();
|
||||
JList parent_stack = jlist_new();
|
||||
char *s, buf[1024];
|
||||
|
||||
while (jstream_gets(stream, buf, sizeof(buf))) {
|
||||
for (s=buf; *s; s++) {
|
||||
/* beginning of a new element */
|
||||
if (*s == '<') {
|
||||
char *tag_start = s + 1;
|
||||
int open = (s[1] != '/');
|
||||
bool auto_closed = FALSE;
|
||||
JXmlElem tag;
|
||||
|
||||
/* comment? */
|
||||
if (s[1] == '!' && s[2] == '-' && s[3] == '-') {
|
||||
s += 2;
|
||||
for (;;) {
|
||||
if (strncmp (s, "-->", 3) == 0) {
|
||||
s += 2;
|
||||
break;
|
||||
}
|
||||
else if (*s == 0) {
|
||||
if (!jstream_gets(stream, buf+strlen(buf), sizeof(buf)-strlen(buf)))
|
||||
break;
|
||||
s = buf;
|
||||
}
|
||||
else {
|
||||
s++;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* go to end of the tag */
|
||||
for (; ; s++) {
|
||||
if (*s == '>') {
|
||||
if (*(s-1) == '/') {
|
||||
*(s-1) = 0;
|
||||
auto_closed = TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (*s == '\"') {
|
||||
for (s++; ; s++) {
|
||||
if (*s == 0) {
|
||||
if (!jstream_gets(stream, buf+strlen(buf), sizeof(buf)-strlen(buf)))
|
||||
break;
|
||||
s--;
|
||||
}
|
||||
else if ((*s == '\"') && (*(s-1) != '\\')) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (jstream_eof(stream))
|
||||
break;
|
||||
}
|
||||
else if (*s == 0) {
|
||||
if (!jstream_gets(stream, buf+strlen(buf), sizeof(buf)-strlen(buf)))
|
||||
break;
|
||||
s--;
|
||||
}
|
||||
}
|
||||
|
||||
*s = 0;
|
||||
|
||||
/* create the new tag */
|
||||
tag = read_elem(open ? tag_start: tag_start+1);
|
||||
if (tag) {
|
||||
/* fprintf (stderr, "%s tag: %s (parent %s)\n", */
|
||||
/* open ? "open": "close", */
|
||||
/* jxmlelem_get_name(tag), */
|
||||
/* !jlist_empty(parent_stack) ? ((JXmlNode)jlist_first_data(parent_stack))->value: "ROOT"); */
|
||||
|
||||
/* open a level */
|
||||
if (open) {
|
||||
/* add this tag in parent list */
|
||||
if (jlist_empty(parent_stack))
|
||||
jlist_append(root_tags, tag);
|
||||
else
|
||||
jxmlnode_add_child(jlist_first(parent_stack)->data, (JXmlNode)tag);
|
||||
|
||||
/* if it isn't closed in the same open tag */
|
||||
if (!auto_closed)
|
||||
/* add to the parent stack */
|
||||
jlist_prepend(parent_stack, tag);
|
||||
}
|
||||
/* close a level */
|
||||
else {
|
||||
if ((!jlist_empty(parent_stack)) &&
|
||||
(strcmp(((JXmlNode)tag)->value, ((JXmlNode)jlist_first_data(parent_stack))->value) == 0)) {
|
||||
/* remove the first tag from stack */
|
||||
jlist_remove(parent_stack, jlist_first_data(parent_stack));
|
||||
}
|
||||
else {
|
||||
/* XXX error msg */
|
||||
/* printf ("you must open the tag before close it\n"); */
|
||||
}
|
||||
|
||||
jxmlelem_free(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* put characters in the last JXmlText */
|
||||
else {
|
||||
if (!jlist_empty(parent_stack)) {
|
||||
/* TODO */
|
||||
/* JXmlNode tag = jlist_first(parent_stack)->data; */
|
||||
|
||||
/* if (tag->value || IS_BLANK(*s)) { */
|
||||
/* int len = tag->value ? strlen(tag->value): 0; */
|
||||
/* tag->value = jrealloc(tag->value, len+2); */
|
||||
/* tag->value[len] = *s; */
|
||||
/* tag->value[len+1] = 0; */
|
||||
/* } */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jlist_free(parent_stack);
|
||||
return root_tags;
|
||||
}
|
||||
|
||||
static JXmlElem read_elem(char *elem_string)
|
||||
{
|
||||
char c, *s;
|
||||
JXmlElem elem;
|
||||
|
||||
/* find the end of the tag-name */
|
||||
for (s=elem_string; *s && !IS_BLANK(*s); s++)
|
||||
;
|
||||
|
||||
/* create the new tag with the found name */
|
||||
c = *s;
|
||||
*s = 0;
|
||||
elem = jxmlelem_new(elem_string);
|
||||
*s = c;
|
||||
|
||||
/* continue reading attributes */
|
||||
while (*s) {
|
||||
/* jump white spaces */
|
||||
while (*s && IS_BLANK(*s))
|
||||
s++;
|
||||
|
||||
/* isn't end of string? */
|
||||
if (*s) {
|
||||
char *name_beg = s;
|
||||
char *name;
|
||||
char *value = NULL;
|
||||
bool translatable = FALSE;
|
||||
|
||||
/* read the attribute-name */
|
||||
while (*s && !IS_BLANK(*s) && *s != '=')
|
||||
s++;
|
||||
|
||||
c = *s;
|
||||
*s = 0;
|
||||
name = jstrdup(name_beg);
|
||||
*s = c;
|
||||
|
||||
if (*s == '=') {
|
||||
char *value_beg = ++s;
|
||||
bool go_next = FALSE;
|
||||
|
||||
/* see for the translation prefix _() */
|
||||
if (strncmp(s, "_(\"", 3) == 0) {
|
||||
translatable = TRUE;
|
||||
s += 2;
|
||||
}
|
||||
|
||||
if (*s == '\"') {
|
||||
/* jump the double-quote */
|
||||
value_beg = ++s;
|
||||
|
||||
/* read the attribute-value */
|
||||
while (*s) {
|
||||
if (*s == '\\') {
|
||||
memmove(s, s+1, strlen(s)-1);
|
||||
}
|
||||
else if (*s == '\"') {
|
||||
go_next = TRUE;
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* read the attribute-value */
|
||||
while (*s && !IS_BLANK(*s))
|
||||
s++;
|
||||
}
|
||||
|
||||
c = *s;
|
||||
*s = 0;
|
||||
value = jstrdup(value_beg);
|
||||
*s = c;
|
||||
|
||||
if (go_next)
|
||||
s++;
|
||||
}
|
||||
|
||||
/* add the attribute to the tag */
|
||||
/* TODO translatable */
|
||||
jxmlelem_set_attr(elem, name, value);
|
||||
if (name) jfree(name);
|
||||
if (value) jfree(value);
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user