gwenhywfar 4.0.3
|
00001 /*************************************************************************** 00002 begin : Sat Feb 20 2010 00003 copyright : (C) 2010 by Martin Preuss 00004 email : martin@libchipcard.de 00005 00006 *************************************************************************** 00007 * Please see toplevel file COPYING for license details * 00008 ***************************************************************************/ 00009 00010 00011 #ifdef HAVE_CONFIG_H 00012 # include <config.h> 00013 #endif 00014 00015 #define DISABLE_DEBUGLOG 00016 00017 00018 #include "g_box_p.h" 00019 #include "g_generic_l.h" 00020 #include "g_table_l.h" 00021 #include "g_unorderedlist_l.h" 00022 #include "htmlctx_l.h" 00023 #include "o_box_l.h" 00024 #include "o_word_l.h" 00025 #include "o_grid_l.h" 00026 #include "o_image_be.h" 00027 00028 #include <gwenhywfar/misc.h> 00029 #include <gwenhywfar/debug.h> 00030 00031 #include <ctype.h> 00032 00033 00034 00035 00036 HTML_GROUP *HtmlGroup_Box_new(const char *groupName, 00037 HTML_GROUP *parent, 00038 GWEN_XML_CONTEXT *ctx) { 00039 HTML_GROUP *g; 00040 00041 /* create base group */ 00042 g=HtmlGroup_Generic_new(groupName, parent, ctx); 00043 assert(g); 00044 00045 /* set virtual functions */ 00046 HtmlGroup_SetStartTagFn(g, HtmlGroup_Box_StartTag); 00047 HtmlGroup_SetAddDataFn(g, HtmlGroup_Box_AddData); 00048 00049 return g; 00050 } 00051 00052 00053 00054 int HtmlGroup_Box_StartTag(HTML_GROUP *g, const char *tagName) { 00055 HTML_GROUP *gNew=NULL; 00056 GWEN_XML_CONTEXT *ctx; 00057 GWEN_DB_NODE *dbAttribs; 00058 00059 assert(g); 00060 00061 ctx=HtmlGroup_GetXmlContext(g); 00062 dbAttribs=HtmlCtx_GetCurrentAttributes(ctx); 00063 00064 if (strcasecmp(tagName, "b")==0) { 00065 /* Create new parser group with new properties but use the same object */ 00066 HTML_PROPS *pr; 00067 HTML_FONT *fnt; 00068 00069 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00070 pr=HtmlProps_dup(HtmlGroup_GetProperties(g)); 00071 fnt=HtmlProps_GetFont(pr); 00072 fnt=HtmlCtx_GetFont(ctx, 00073 HtmlFont_GetFontName(fnt), 00074 HtmlFont_GetFontSize(fnt), 00075 HtmlFont_GetFontFlags(fnt) | HTML_FONT_FLAGS_STRONG); 00076 if (fnt) { 00077 HtmlProps_SetFont(pr, fnt); 00078 //HtmlFont_free(fnt); 00079 } 00080 HtmlGroup_SetProperties(gNew, pr); 00081 HtmlProps_free(pr); 00082 HtmlGroup_SetObject(gNew, HtmlGroup_GetObject(g)); 00083 } 00084 else if (strcasecmp(tagName, "i")==0) { 00085 /* Create new parser group with new properties but use the same object */ 00086 HTML_PROPS *pr; 00087 HTML_FONT *fnt; 00088 00089 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00090 pr=HtmlProps_dup(HtmlGroup_GetProperties(g)); 00091 fnt=HtmlProps_GetFont(pr); 00092 fnt=HtmlCtx_GetFont(ctx, 00093 HtmlFont_GetFontName(fnt), 00094 HtmlFont_GetFontSize(fnt), 00095 HtmlFont_GetFontFlags(fnt) | HTML_FONT_FLAGS_ITALIC); 00096 if (fnt) { 00097 HtmlProps_SetFont(pr, fnt); 00098 //HtmlFont_free(fnt); 00099 } 00100 HtmlGroup_SetProperties(gNew, pr); 00101 HtmlProps_free(pr); 00102 HtmlGroup_SetObject(gNew, HtmlGroup_GetObject(g)); 00103 } 00104 else if (strcasecmp(tagName, "u")==0) { 00105 /* Create new parser group with new properties but use the same object */ 00106 HTML_PROPS *pr; 00107 HTML_FONT *fnt; 00108 00109 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00110 pr=HtmlProps_dup(HtmlGroup_GetProperties(g)); 00111 fnt=HtmlProps_GetFont(pr); 00112 fnt=HtmlCtx_GetFont(ctx, 00113 HtmlFont_GetFontName(fnt), 00114 HtmlFont_GetFontSize(fnt), 00115 HtmlFont_GetFontFlags(fnt) | HTML_FONT_FLAGS_UNDERLINE); 00116 if (fnt) { 00117 HtmlProps_SetFont(pr, fnt); 00118 //HtmlFont_free(fnt); 00119 } 00120 HtmlGroup_SetProperties(gNew, pr); 00121 HtmlProps_free(pr); 00122 HtmlGroup_SetObject(gNew, HtmlGroup_GetObject(g)); 00123 } 00124 else if (strcasecmp(tagName, "p")==0) { 00125 HTML_OBJECT *o; 00126 00127 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00128 HtmlGroup_SetProperties(gNew, HtmlGroup_GetProperties(g)); 00129 o=HtmlObject_Box_new(ctx); 00130 HtmlObject_AddFlags(o, 00131 HTML_OBJECT_FLAGS_START_ON_NEWLINE | 00132 HTML_OBJECT_FLAGS_END_WITH_NEWLINE); 00133 if (dbAttribs) { 00134 const char *s; 00135 00136 s=GWEN_DB_GetCharValue(dbAttribs, "align", 0, "left"); 00137 if (s) { 00138 if (strcasecmp(s, "right")==0) 00139 HtmlObject_AddFlags(o, HTML_OBJECT_FLAGS_JUSTIFY_RIGHT); 00140 else if (strcasecmp(s, "center")==0) 00141 HtmlObject_AddFlags(o, HTML_OBJECT_FLAGS_JUSTIFY_HCENTER); 00142 } 00143 } 00144 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00145 HtmlObject_SetProperties(o, HtmlGroup_GetProperties(g)); 00146 HtmlGroup_SetObject(gNew, o); 00147 } 00148 else if (strcasecmp(tagName, "right")==0) { 00149 HTML_OBJECT *o; 00150 00151 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00152 HtmlGroup_SetProperties(gNew, HtmlGroup_GetProperties(g)); 00153 o=HtmlObject_Box_new(ctx); 00154 HtmlObject_AddFlags(o, 00155 HTML_OBJECT_FLAGS_START_ON_NEWLINE | 00156 HTML_OBJECT_FLAGS_END_WITH_NEWLINE | 00157 HTML_OBJECT_FLAGS_JUSTIFY_RIGHT); 00158 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00159 HtmlObject_SetProperties(o, HtmlGroup_GetProperties(g)); 00160 HtmlGroup_SetObject(gNew, o); 00161 } 00162 else if (strcasecmp(tagName, "br")==0) { 00163 HTML_OBJECT *o; 00164 00165 /* just create and add a control object */ 00166 o=HtmlObject_new(ctx, HtmlObjectType_Control); 00167 HtmlObject_AddFlags(o, HTML_OBJECT_FLAGS_END_WITH_NEWLINE); 00168 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00169 HtmlObject_SetProperties(o, HtmlGroup_GetProperties(g)); 00170 } 00171 else if (strcasecmp(tagName, "img")==0) { 00172 HTML_OBJECT *o; 00173 GWEN_DB_NODE *dbAttribs; 00174 00175 o=HtmlObject_Image_new(ctx); 00176 HtmlObject_AddFlags(o, 00177 HTML_OBJECT_FLAGS_START_ON_NEWLINE | 00178 HTML_OBJECT_FLAGS_END_WITH_NEWLINE); 00179 dbAttribs=HtmlCtx_GetCurrentAttributes(ctx); 00180 if (dbAttribs) { 00181 const char *s; 00182 int w; 00183 int h; 00184 00185 w=GWEN_DB_GetIntValue(dbAttribs, "width", 0, -1); 00186 h=GWEN_DB_GetIntValue(dbAttribs, "height", 0, -1); 00187 00188 /* preset */ 00189 if (w!=-1) 00190 HtmlObject_Image_SetScaledWidth(o, w); 00191 if (h!=-1) 00192 HtmlObject_Image_SetScaledHeight(o, w); 00193 00194 s=GWEN_DB_GetCharValue(dbAttribs, "src", 0, NULL); 00195 if (s && *s) { 00196 HTML_IMAGE *img; 00197 00198 img=HtmlCtx_GetImage(ctx, s); 00199 if (img) { 00200 HtmlObject_Image_SetImage(o, img); 00201 /* adjust scaled width and height if not set by attributes */ 00202 if (w==-1) 00203 HtmlObject_Image_SetScaledWidth(o, HtmlImage_GetWidth(img)); 00204 if (h==-1) 00205 HtmlObject_Image_SetScaledHeight(o, HtmlImage_GetHeight(img)); 00206 } 00207 else { 00208 DBG_ERROR(GWEN_LOGDOMAIN, "Image [%s] not found", s); 00209 } 00210 } 00211 else { 00212 DBG_ERROR(GWEN_LOGDOMAIN, "Missing image name in IMG element"); 00213 } 00214 } 00215 00216 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00217 HtmlObject_SetProperties(o, HtmlGroup_GetProperties(g)); 00218 } 00219 else if (strcasecmp(tagName, "table")==0) { 00220 HTML_OBJECT *o; 00221 00222 gNew=HtmlGroup_Table_new(tagName, g, ctx); 00223 HtmlGroup_SetProperties(gNew, HtmlGroup_GetProperties(g)); 00224 o=HtmlObject_Grid_new(ctx); 00225 HtmlObject_SetProperties(o, HtmlGroup_GetProperties(g)); 00226 HtmlGroup_SetObject(gNew, o); 00227 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00228 } 00229 else if (strcasecmp(tagName, "ul")==0) { 00230 HTML_OBJECT *o; 00231 00232 gNew=HtmlGroup_UnorderedList_new(tagName, g, ctx); 00233 HtmlGroup_SetProperties(gNew, HtmlGroup_GetProperties(g)); 00234 o=HtmlObject_Grid_new(ctx); 00235 HtmlObject_Grid_SetColumns(o, 2); 00236 HtmlObject_SetProperties(o, HtmlGroup_GetProperties(g)); 00237 HtmlGroup_SetObject(gNew, o); 00238 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00239 } 00240 else if (strcasecmp(tagName, "font")==0) { 00241 /* Create new parser group with new properties but use the same object */ 00242 HTML_PROPS *pr; 00243 GWEN_DB_NODE *dbAttribs; 00244 00245 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00246 pr=HtmlProps_dup(HtmlGroup_GetProperties(g)); 00247 00248 dbAttribs=HtmlCtx_GetCurrentAttributes(ctx); 00249 if (dbAttribs) { 00250 HTML_FONT *fnt; 00251 const char *s; 00252 const char *fontName; 00253 int fontSize; 00254 uint32_t fontFlags; 00255 00256 fnt=HtmlProps_GetFont(pr); 00257 fontName=GWEN_DB_GetCharValue(dbAttribs, "face", 0, NULL); 00258 if (fontName==NULL) 00259 fontName=HtmlFont_GetFontName(fnt); 00260 fontFlags=HtmlFont_GetFontFlags(fnt); 00261 fontSize=HtmlFont_GetFontSize(fnt); 00262 s=GWEN_DB_GetCharValue(dbAttribs, "size", 0, NULL); 00263 if (s && *s) { 00264 if (*s=='+') { 00265 int i; 00266 00267 sscanf(s, "%d", &i); 00268 fontSize+=i*4; 00269 } 00270 else if (*s=='-') { 00271 int i; 00272 00273 sscanf(s, "%d", &i); 00274 fontSize+=i*4; 00275 } 00276 else 00277 sscanf(s, "%d", &fontSize); 00278 } 00279 00280 s=GWEN_DB_GetCharValue(dbAttribs, "color", 0, NULL); 00281 if (s && *s) { 00282 uint32_t color; 00283 00284 color=HtmlCtx_GetColorFromName(ctx, s); 00285 HtmlProps_SetForegroundColor(pr, color); 00286 } 00287 00288 fnt=HtmlCtx_GetFont(ctx, fontName, fontSize, fontFlags); 00289 if (fnt) { 00290 HtmlProps_SetFont(pr, fnt); 00291 //HtmlFont_free(fnt); 00292 } 00293 } 00294 00295 HtmlGroup_SetProperties(gNew, pr); 00296 HtmlProps_free(pr); 00297 HtmlGroup_SetObject(gNew, HtmlGroup_GetObject(g)); 00298 } 00299 else if (strcasecmp(tagName, "h1")==0) { 00300 /* Create new parser group with new properties but use the same object */ 00301 HTML_PROPS *pr; 00302 HTML_FONT *fnt; 00303 HTML_OBJECT *o; 00304 00305 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00306 pr=HtmlProps_dup(HtmlGroup_GetProperties(g)); 00307 fnt=HtmlProps_GetFont(pr); 00308 fnt=HtmlCtx_GetFont(ctx, 00309 HtmlFont_GetFontName(fnt), 00310 HtmlFont_GetFontSize(fnt)*1.8, 00311 HtmlFont_GetFontFlags(fnt) | HTML_FONT_FLAGS_STRONG); 00312 if (fnt) { 00313 HtmlProps_SetFont(pr, fnt); 00314 //HtmlFont_free(fnt); 00315 } 00316 HtmlGroup_SetProperties(gNew, pr); 00317 00318 o=HtmlObject_Box_new(ctx); 00319 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00320 HtmlObject_AddFlags(o, 00321 HTML_OBJECT_FLAGS_START_ON_NEWLINE | 00322 HTML_OBJECT_FLAGS_END_WITH_NEWLINE); 00323 HtmlObject_SetProperties(o, pr); 00324 HtmlGroup_SetObject(gNew, o); 00325 HtmlProps_free(pr); 00326 } 00327 else if (strcasecmp(tagName, "h2")==0) { 00328 /* Create new parser group with new properties but use the same object */ 00329 HTML_PROPS *pr; 00330 HTML_FONT *fnt; 00331 HTML_OBJECT *o; 00332 00333 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00334 pr=HtmlProps_dup(HtmlGroup_GetProperties(g)); 00335 fnt=HtmlProps_GetFont(pr); 00336 fnt=HtmlCtx_GetFont(ctx, 00337 HtmlFont_GetFontName(fnt), 00338 HtmlFont_GetFontSize(fnt)*1.5, 00339 HtmlFont_GetFontFlags(fnt) | HTML_FONT_FLAGS_STRONG); 00340 if (fnt) { 00341 HtmlProps_SetFont(pr, fnt); 00342 //HtmlFont_free(fnt); 00343 } 00344 HtmlGroup_SetProperties(gNew, pr); 00345 00346 o=HtmlObject_Box_new(ctx); 00347 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00348 HtmlObject_AddFlags(o, 00349 HTML_OBJECT_FLAGS_START_ON_NEWLINE | 00350 HTML_OBJECT_FLAGS_END_WITH_NEWLINE); 00351 HtmlObject_SetProperties(o, pr); 00352 HtmlGroup_SetObject(gNew, o); 00353 HtmlProps_free(pr); 00354 } 00355 else if (strcasecmp(tagName, "h3")==0) { 00356 /* Create new parser group with new properties but use the same object */ 00357 HTML_PROPS *pr; 00358 HTML_FONT *fnt; 00359 HTML_OBJECT *o; 00360 00361 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00362 pr=HtmlProps_dup(HtmlGroup_GetProperties(g)); 00363 fnt=HtmlProps_GetFont(pr); 00364 fnt=HtmlCtx_GetFont(ctx, 00365 HtmlFont_GetFontName(fnt), 00366 HtmlFont_GetFontSize(fnt), 00367 HtmlFont_GetFontFlags(fnt) | HTML_FONT_FLAGS_STRONG); 00368 if (fnt) { 00369 HtmlProps_SetFont(pr, fnt); 00370 //HtmlFont_free(fnt); 00371 } 00372 HtmlGroup_SetProperties(gNew, pr); 00373 00374 o=HtmlObject_Box_new(ctx); 00375 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00376 HtmlObject_AddFlags(o, 00377 HTML_OBJECT_FLAGS_START_ON_NEWLINE | 00378 HTML_OBJECT_FLAGS_END_WITH_NEWLINE); 00379 HtmlObject_SetProperties(o, pr); 00380 HtmlGroup_SetObject(gNew, o); 00381 HtmlProps_free(pr); 00382 } 00383 else if (strcasecmp(tagName, "html")==0 || 00384 strcasecmp(tagName, "body")==0) { 00385 } 00386 else { 00387 DBG_WARN(GWEN_LOGDOMAIN, 00388 "Unknown group [%s], handling as normal box", tagName); 00389 gNew=HtmlGroup_Box_new(tagName, g, ctx); 00390 HtmlGroup_SetProperties(gNew, HtmlGroup_GetProperties(g)); 00391 HtmlGroup_SetObject(gNew, HtmlGroup_GetObject(g)); 00392 } 00393 00394 if (gNew) { 00395 HtmlCtx_SetCurrentGroup(ctx, gNew); 00396 GWEN_XmlCtx_IncDepth(ctx); 00397 } 00398 00399 return 0; 00400 } 00401 00402 00403 00404 int HtmlGroup_Box_AddData(HTML_GROUP *g, const char *data) { 00405 GWEN_XML_CONTEXT *ctx; 00406 GWEN_BUFFER *buf; 00407 int rv; 00408 uint8_t *s; 00409 HTML_OBJECT *o; 00410 00411 assert(g); 00412 00413 ctx=HtmlGroup_GetXmlContext(g); 00414 if (data && *data) { 00415 buf=GWEN_Buffer_new(0, strlen(data), 0, 1); 00416 rv=HtmlCtx_SanitizeData(ctx, data, buf); 00417 if (rv<0) { 00418 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); 00419 GWEN_Buffer_free(buf); 00420 return rv; 00421 } 00422 if (GWEN_Buffer_GetUsedBytes(buf)) { 00423 s=(uint8_t*)GWEN_Buffer_GetStart(buf); 00424 00425 while(*s) { 00426 uint8_t *t; 00427 uint8_t c; 00428 00429 /* find begin of word */ 00430 while(*s && isspace(*s)) 00431 s++; 00432 00433 /* find end of word */ 00434 t=s; 00435 while(*t && !isspace(*t)) 00436 t++; 00437 c=*t; 00438 *t=0; 00439 o=HtmlObject_Word_new(ctx, (const char*) s); 00440 HtmlObject_SetProperties(o, HtmlGroup_GetProperties(g)); 00441 HtmlObject_Tree_AddChild(HtmlGroup_GetObject(g), o); 00442 *t=c; 00443 s=t; 00444 } 00445 } 00446 GWEN_Buffer_free(buf); 00447 } 00448 00449 return 0; 00450 } 00451 00452 00453