Projekt

Allgemein

Profil

Herunterladen (17,2 KB) Statistiken
| Zweig: | Markierung: | Revision:
/***************************************************************************
begin : Sat Feb 20 2010
copyright : (C) 2010 by Martin Preuss
email : martin@libchipcard.de

***************************************************************************
* Please see toplevel file COPYING for license details *
***************************************************************************/



#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#define DISABLE_DEBUGLOG


#include "htmlctx_p.h"
#include "o_box_l.h"
#include "g_box_l.h"

#include <gwenhywfar/misc.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/text.h>



GWEN_INHERIT(GWEN_XML_CONTEXT, HTML_XMLCTX)




GWEN_XML_CONTEXT *HtmlCtx_new(uint32_t flags) {
GWEN_XML_CONTEXT *ctx;
HTML_XMLCTX *xctx;
HTML_GROUP *g;
HTML_OBJECT *o;

/* create base object */
ctx=GWEN_XmlCtx_new(flags);
assert(ctx);

/* create and assign extension */
GWEN_NEW_OBJECT(HTML_XMLCTX, xctx);
assert(xctx);
GWEN_INHERIT_SETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx, xctx,
HtmlCtx_FreeData);

/* set virtual functions */
GWEN_XmlCtx_SetStartTagFn(ctx, HtmlCtx_StartTag);
GWEN_XmlCtx_SetEndTagFn(ctx, HtmlCtx_EndTag);
GWEN_XmlCtx_SetAddDataFn(ctx, HtmlCtx_AddData);
GWEN_XmlCtx_SetAddCommentFn(ctx, HtmlCtx_AddComment);
GWEN_XmlCtx_SetAddAttrFn(ctx, HtmlCtx_AddAttr);

xctx->objects=HtmlObject_Tree_new();
xctx->mediaPaths=GWEN_StringList_new();

xctx->resolutionX=75;
xctx->resolutionY=75;

/* create initial group */
g=HtmlGroup_Box_new("HTML_ROOT", NULL, ctx);
assert(g);
o=HtmlObject_Box_new(ctx);
HtmlGroup_SetObject(g, o);
HtmlObject_Tree_Add(xctx->objects, o);
HtmlCtx_SetCurrentGroup(ctx, g);

/* return base object */
return ctx;
}



GWENHYWFAR_CB
void HtmlCtx_FreeData(void *bp, void *p) {
HTML_XMLCTX *xctx;
HTML_GROUP *g;

xctx=(HTML_XMLCTX*)p;

g=xctx->currentGroup;
while (g) {
HTML_GROUP *gParent;

gParent=HtmlGroup_GetParent(g);
HtmlGroup_free(g);
g=gParent;
}

GWEN_DB_Group_free(xctx->dbCurrentAttribs);
free(xctx->currentTagName);
HtmlObject_Tree_free(xctx->objects);

GWEN_StringList_free(xctx->mediaPaths);

HtmlProps_free(xctx->standardProps);

GWEN_FREE_OBJECT(xctx);
}



int HtmlCtx_GetResolutionX(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return xctx->resolutionX;
}



void HtmlCtx_SetResolutionX(GWEN_XML_CONTEXT *ctx, int i) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

xctx->resolutionX=i;
}



int HtmlCtx_GetResolutionY(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return xctx->resolutionY;
}



void HtmlCtx_SetResolutionY(GWEN_XML_CONTEXT *ctx, int i) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

xctx->resolutionY=i;
}



GWEN_STRINGLIST *HtmlCtx_GetMediaPaths(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return xctx->mediaPaths;
}



void HtmlCtx_AddMediaPath(GWEN_XML_CONTEXT *ctx, const char *s) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

assert(s && *s);
GWEN_StringList_AppendString(xctx->mediaPaths, s, 0, 1);
}




HTML_GROUP *HtmlCtx_GetCurrentGroup(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return xctx->currentGroup;
}



void HtmlCtx_SetCurrentGroup(GWEN_XML_CONTEXT *ctx, HTML_GROUP *g) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

xctx->currentGroup=g;
}



const char *HtmlCtx_GetCurrentTagName(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return xctx->currentTagName;
}



void HtmlCtx_SetCurrentTagName(GWEN_XML_CONTEXT *ctx, const char *s) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

free(xctx->currentTagName);
if (s) xctx->currentTagName=strdup(s);
else xctx->currentTagName=NULL;
}



GWEN_DB_NODE *HtmlCtx_GetCurrentAttributes(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return xctx->dbCurrentAttribs;
}



HTML_OBJECT_TREE *HtmlCtx_GetObjects(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return xctx->objects;
}



HTML_OBJECT_TREE *HtmlCtx_TakeObjects(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;
HTML_OBJECT_TREE *t;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

t=xctx->objects;
xctx->objects=NULL;

return t;
}



HTML_OBJECT *HtmlCtx_GetRootObject(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return HtmlObject_Tree_GetFirst(xctx->objects);
}



int HtmlCtx_SanitizeData(GWEN_XML_CONTEXT *ctx,
const char *data,
GWEN_BUFFER *buf) {
if (data && *data) {
const uint8_t *p;
uint8_t *dst;
uint8_t *src;
unsigned int size;
unsigned int i;
int lastWasBlank;
uint8_t *lastBlankPos;
uint32_t bStart=0;

if (GWEN_Text_UnescapeXmlToBuffer(data, buf)) {
DBG_INFO(GWEN_LOGDOMAIN, "here");
return GWEN_ERROR_BAD_DATA;
}
if (GWEN_Buffer_GetUsedBytes(buf)==0) {
DBG_INFO(GWEN_LOGDOMAIN, "Empty data.");
return 0;
}

dst=(uint8_t*)GWEN_Buffer_GetStart(buf);
src=dst;

/* skip leading blanks */
while(*src && (*src<33 || *src==127))
src++;

p=src;
bStart=src-((uint8_t*)GWEN_Buffer_GetStart(buf));
size=GWEN_Buffer_GetUsedBytes(buf)-bStart;
lastWasBlank=0;
lastBlankPos=0;

for (i=0; i<size; i++) {
uint8_t c;

c=*p;
if (c<32 || c==127)
c=32;

/* remember next loop whether this char was a blank */
if (c==32) {
if (!lastWasBlank) {
/* store only one blank */
lastWasBlank=1;
lastBlankPos=dst;
*(dst++)=c;
}
}
else {
lastWasBlank=0;
lastBlankPos=0;
*(dst++)=c;
}
p++;
}

/* remove trailing blanks */
if (lastBlankPos!=0)
dst=lastBlankPos;

size=dst-(uint8_t*)GWEN_Buffer_GetStart(buf);
GWEN_Buffer_Crop(buf, 0, size);
}

return 0;
}



HTML_PROPS *HtmlCtx_GetStandardProps(const GWEN_XML_CONTEXT *ctx) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

return xctx->standardProps;
}



void HtmlCtx_SetStandardProps(GWEN_XML_CONTEXT *ctx, HTML_PROPS *pr) {
HTML_XMLCTX *xctx;
HTML_OBJECT *o;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

HtmlProps_Attach(pr);
HtmlProps_free(xctx->standardProps);
xctx->standardProps=pr;

if (pr) {
if (xctx->currentGroup && HtmlGroup_GetParent(xctx->currentGroup)==NULL)
HtmlGroup_SetProperties(xctx->currentGroup, pr);
o=HtmlObject_Tree_GetFirst(xctx->objects);
if (o && HtmlObject_GetProperties(o)==NULL)
HtmlObject_SetProperties(o, pr);
}
}



int HtmlCtx_StartTag(GWEN_XML_CONTEXT *ctx, const char *tagName) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

DBG_DEBUG(GWEN_LOGDOMAIN, "Starting tag [%s]", tagName);

/* store for later, do nothing more here */
HtmlCtx_SetCurrentTagName(ctx, tagName);
GWEN_DB_Group_free(xctx->dbCurrentAttribs);
xctx->dbCurrentAttribs=GWEN_DB_Group_new("attribs");

return 0;
}



int HtmlCtx_EndTag(GWEN_XML_CONTEXT *ctx, int closing) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

if (closing) {
/* just ignore empty tags which are closed immediately */
DBG_DEBUG(GWEN_LOGDOMAIN, "Closing empty tag [%s]",
(xctx->currentTagName)?xctx->currentTagName:"<noname>");
return 0;
}

if (xctx->currentTagName==NULL) {
DBG_INFO(GWEN_LOGDOMAIN, "No tag name, malformed HTML data");
return GWEN_ERROR_BAD_DATA;
}

DBG_DEBUG(GWEN_LOGDOMAIN, "Completed tag [%s]", xctx->currentTagName);

if (xctx->currentGroup) {
if (*(xctx->currentTagName)=='/') {
int rv;

/* it is a closing tag, call EndTagFn */
DBG_DEBUG(GWEN_LOGDOMAIN,
"Calling %s->EndTag(%s)",
HtmlGroup_GetGroupName(xctx->currentGroup),
xctx->currentTagName);
rv=HtmlGroup_EndTag(xctx->currentGroup, xctx->currentTagName+1);
if (rv<0) {
if (rv!=GWEN_ERROR_NOT_IMPLEMENTED) {
DBG_INFO(GWEN_LOGDOMAIN,
"Error in EndTag(%s) for [%s]",
HtmlGroup_GetGroupName(xctx->currentGroup),
xctx->currentTagName);
return rv;
}
}
else if (rv==1) {
HTML_GROUP *g;
HTML_GROUP *gParent;

/* pop current group from stack */
g=xctx->currentGroup;
gParent=HtmlGroup_GetParent(g);
xctx->currentGroup=gParent;
if (gParent) {
DBG_DEBUG(GWEN_LOGDOMAIN,
"Calling %s->EndSubGroup(%s)",
HtmlGroup_GetGroupName(gParent),
HtmlGroup_GetGroupName(g));
HtmlGroup_EndSubGroup(gParent, g);
}
HtmlGroup_free(g);
GWEN_XmlCtx_DecDepth(ctx);
}
}
else {
int rv;

/* it is an opening tag, call StartTagFn */
DBG_DEBUG(GWEN_LOGDOMAIN,
"Calling %s->StartTag(%s)",
HtmlGroup_GetGroupName(xctx->currentGroup),
xctx->currentTagName);
rv=HtmlGroup_StartTag(xctx->currentGroup, xctx->currentTagName);
if (rv<0) {
if (rv!=GWEN_ERROR_NOT_IMPLEMENTED) {
DBG_INFO(GWEN_LOGDOMAIN,
"Error in StartTag(%s) for [%s]",
HtmlGroup_GetGroupName(xctx->currentGroup),
xctx->currentTagName);
return rv;
}
}
}
}

return 0;
}






int HtmlCtx_AddData(GWEN_XML_CONTEXT *ctx, const char *data) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

if (xctx->currentGroup) {
int rv;

DBG_DEBUG(GWEN_LOGDOMAIN,
"Calling %s->AddData()",
HtmlGroup_GetGroupName(xctx->currentGroup));
rv=HtmlGroup_AddData(xctx->currentGroup, data);
if (rv<0) {
if (rv!=GWEN_ERROR_NOT_IMPLEMENTED) {
DBG_INFO(GWEN_LOGDOMAIN,
"Error in AddData(%s)",
HtmlGroup_GetGroupName(xctx->currentGroup));
return rv;
}
}
}

return 0;
}



int HtmlCtx_AddComment(GWEN_XML_CONTEXT *ctx, const char *data) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

/* ignore comments */
return 0;
}



int HtmlCtx_AddAttr(GWEN_XML_CONTEXT *ctx,
const char *attrName,
const char *attrData) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

if (xctx->currentGroup) {
assert(xctx->dbCurrentAttribs);
GWEN_DB_SetCharValue(xctx->dbCurrentAttribs,
GWEN_DB_FLAGS_DEFAULT,
attrName, attrData);
}

return 0;
}



int HtmlCtx_GetTextWidth(GWEN_XML_CONTEXT *ctx,
HTML_FONT *fnt,
const char *s) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

if (xctx->getTextWidthFn)
return xctx->getTextWidthFn(ctx, fnt, s);
else
return -1;
}



int HtmlCtx_GetTextHeight(GWEN_XML_CONTEXT *ctx,
HTML_FONT *fnt,
const char *s) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

if (xctx->getTextHeightFn)
return xctx->getTextHeightFn(ctx, fnt, s);
else
return -1;
}



uint32_t HtmlCtx_GetColorFromName(const GWEN_XML_CONTEXT *ctx,
const char *name) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

if (xctx->getColorFromNameFn)
return xctx->getColorFromNameFn(ctx, name);
else
return 0xffffffff;
}



HTML_FONT *HtmlCtx_GetFont(GWEN_XML_CONTEXT *ctx,
const char *fontName,
int fontSize,
uint32_t fontFlags) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

if (xctx->getFontFn)
return xctx->getFontFn(ctx, fontName, fontSize, fontFlags);
else
return NULL;
}



HTML_IMAGE *HtmlCtx_GetImage(GWEN_XML_CONTEXT *ctx, const char *imageName) {
HTML_XMLCTX *xctx;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

if (xctx->getImageFn)
return xctx->getImageFn(ctx, imageName);
else
return NULL;
}



HTMLCTX_GET_TEXT_WIDTH_FN HtmlCtx_SetGetTextWidthFn(GWEN_XML_CONTEXT *ctx,
HTMLCTX_GET_TEXT_WIDTH_FN fn) {
HTML_XMLCTX *xctx;
HTMLCTX_GET_TEXT_WIDTH_FN of;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

of=xctx->getTextWidthFn;
xctx->getTextWidthFn=fn;

return of;
}



HTMLCTX_GET_TEXT_HEIGHT_FN HtmlCtx_SetGetTextHeightFn(GWEN_XML_CONTEXT *ctx,
HTMLCTX_GET_TEXT_HEIGHT_FN fn) {
HTML_XMLCTX *xctx;
HTMLCTX_GET_TEXT_HEIGHT_FN of;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

of=xctx->getTextHeightFn;
xctx->getTextHeightFn=fn;

return of;
}



HTMLCTX_GET_COLOR_FROM_NAME_FN HtmlCtx_SetGetColorFromNameFn(GWEN_XML_CONTEXT *ctx,
HTMLCTX_GET_COLOR_FROM_NAME_FN fn) {
HTML_XMLCTX *xctx;
HTMLCTX_GET_COLOR_FROM_NAME_FN of;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

of=xctx->getColorFromNameFn;
xctx->getColorFromNameFn=fn;

return of;
}



HTMLCTX_GET_FONT_FN HtmlCtx_SetGetFontFn(GWEN_XML_CONTEXT *ctx, HTMLCTX_GET_FONT_FN fn) {
HTML_XMLCTX *xctx;
HTMLCTX_GET_FONT_FN of;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

of=xctx->getFontFn;
xctx->getFontFn=fn;

return of;
}



HTMLCTX_GET_IMAGE_FN HtmlCtx_SetGetImageFn(GWEN_XML_CONTEXT *ctx, HTMLCTX_GET_IMAGE_FN fn) {
HTML_XMLCTX *xctx;
HTMLCTX_GET_IMAGE_FN of;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

of=xctx->getImageFn;
xctx->getImageFn=fn;

return of;
}



int HtmlCtx_Layout(GWEN_XML_CONTEXT *ctx, int width, int height) {
HTML_XMLCTX *xctx;
HTML_OBJECT *o;
int rv;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

o=HtmlObject_Tree_GetFirst(xctx->objects);
if (o==NULL) {
DBG_ERROR(GWEN_LOGDOMAIN, "No objects");
return 0;
}

HtmlObject_SetWidth(o, width);
HtmlObject_SetHeight(o, height);
rv=HtmlObject_Layout(o);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
return rv;
}

return 0;
}



void HtmlCtx_SetText(GWEN_XML_CONTEXT *ctx, const char *s) {
HTML_XMLCTX *xctx;
int rv;
HTML_GROUP *g;
HTML_OBJECT *o;

assert(ctx);
xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
assert(xctx);

/* reset */
HtmlObject_Tree_Clear(xctx->objects);

/* create initial group */
g=HtmlGroup_Box_new("HTML_ROOT", NULL, ctx);
assert(g);

HtmlGroup_SetProperties(g, xctx->standardProps);
o=HtmlObject_Box_new(ctx);
HtmlObject_SetProperties(o, xctx->standardProps);
HtmlGroup_SetObject(g, o);
HtmlObject_Tree_Add(xctx->objects, o);
HtmlCtx_SetCurrentGroup(ctx, g);

if (s && *s) {
rv=GWEN_XMLContext_ReadFromString(ctx, s);
if (rv<0) {
DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
}
}

#if 0
fprintf(stderr, "============ Objects:\n");
fprintf(stderr, "String: [%s]\n", s);
o=HtmlObject_Tree_GetFirst(xctx->objects);
while(o) {
const char *xx;

xx=HtmlObject_GetText(o);
fprintf(stderr, "Object(%d): [%s]\n",
HtmlObject_GetObjectType(o),
xx?xx:"(NULL)");
o=HtmlObject_Tree_GetBelow(o);
}
#endif
}



int HtmlCtx_GetWidth(const GWEN_XML_CONTEXT *ctx) {
HTML_OBJECT *o;

o=HtmlCtx_GetRootObject(ctx);
if (o)
return HtmlObject_GetWidth(o);
else
return -1;
}



int HtmlCtx_GetHeight(const GWEN_XML_CONTEXT *ctx) {
HTML_OBJECT *o;

o=HtmlCtx_GetRootObject(ctx);
if (o)
return HtmlObject_GetHeight(o);
else
return -1;
}


(17-17/50)