1 /***************************************************************************
2  begin       : Sat Feb 20 2010
3  copyright   : (C) 2010 by Martin Preuss
4  email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *          Please see toplevel file COPYING for license details           *
8  ***************************************************************************/
9 
10 
11 
12 #ifdef HAVE_CONFIG_H
13 # include <config.h>
14 #endif
15 
16 #define DISABLE_DEBUGLOG
17 
18 
19 #include "htmlctx_p.h"
20 #include "o_box_l.h"
21 #include "g_box_l.h"
22 
23 #include <gwenhywfar/misc.h>
24 #include <gwenhywfar/debug.h>
25 #include <gwenhywfar/text.h>
26 
27 
28 
GWEN_INHERIT(GWEN_XML_CONTEXT,HTML_XMLCTX)29 GWEN_INHERIT(GWEN_XML_CONTEXT, HTML_XMLCTX)
30 
31 
32 
33 
34 GWEN_XML_CONTEXT *HtmlCtx_new(uint32_t flags)
35 {
36   GWEN_XML_CONTEXT *ctx;
37   HTML_XMLCTX *xctx;
38   HTML_GROUP *g;
39   HTML_OBJECT *o;
40 
41   /* create base object */
42   ctx=GWEN_XmlCtx_new(flags);
43   assert(ctx);
44 
45   /* create and assign extension */
46   GWEN_NEW_OBJECT(HTML_XMLCTX, xctx);
47   assert(xctx);
48   GWEN_INHERIT_SETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx, xctx,
49                        HtmlCtx_FreeData);
50 
51   /* set virtual functions */
52   GWEN_XmlCtx_SetStartTagFn(ctx, HtmlCtx_StartTag);
53   GWEN_XmlCtx_SetEndTagFn(ctx, HtmlCtx_EndTag);
54   GWEN_XmlCtx_SetAddDataFn(ctx, HtmlCtx_AddData);
55   GWEN_XmlCtx_SetAddCommentFn(ctx, HtmlCtx_AddComment);
56   GWEN_XmlCtx_SetAddAttrFn(ctx, HtmlCtx_AddAttr);
57 
58   xctx->objects=HtmlObject_Tree_new();
59   xctx->mediaPaths=GWEN_StringList_new();
60 
61   xctx->resolutionX=75;
62   xctx->resolutionY=75;
63 
64   /* create initial group */
65   g=HtmlGroup_Box_new("HTML_ROOT", NULL, ctx);
66   assert(g);
67   o=HtmlObject_Box_new(ctx);
68   HtmlGroup_SetObject(g, o);
69   HtmlObject_Tree_Add(xctx->objects, o);
70   HtmlCtx_SetCurrentGroup(ctx, g);
71 
72   /* return base object */
73   return ctx;
74 }
75 
76 
77 
78 GWENHYWFAR_CB
HtmlCtx_FreeData(GWEN_UNUSED void * bp,void * p)79 void HtmlCtx_FreeData(GWEN_UNUSED void *bp, void *p)
80 {
81   HTML_XMLCTX *xctx;
82   HTML_GROUP *g;
83 
84   xctx=(HTML_XMLCTX *)p;
85 
86   g=xctx->currentGroup;
87   while (g) {
88     HTML_GROUP *gParent;
89 
90     gParent=HtmlGroup_GetParent(g);
91     HtmlGroup_free(g);
92     g=gParent;
93   }
94 
95   GWEN_DB_Group_free(xctx->dbCurrentAttribs);
96   free(xctx->currentTagName);
97   HtmlObject_Tree_free(xctx->objects);
98 
99   GWEN_StringList_free(xctx->mediaPaths);
100 
101   HtmlProps_free(xctx->standardProps);
102 
103   GWEN_FREE_OBJECT(xctx);
104 }
105 
106 
107 
HtmlCtx_GetResolutionX(const GWEN_XML_CONTEXT * ctx)108 int HtmlCtx_GetResolutionX(const GWEN_XML_CONTEXT *ctx)
109 {
110   HTML_XMLCTX *xctx;
111 
112   assert(ctx);
113   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
114   assert(xctx);
115 
116   return xctx->resolutionX;
117 }
118 
119 
120 
HtmlCtx_SetResolutionX(GWEN_XML_CONTEXT * ctx,int i)121 void HtmlCtx_SetResolutionX(GWEN_XML_CONTEXT *ctx, int i)
122 {
123   HTML_XMLCTX *xctx;
124 
125   assert(ctx);
126   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
127   assert(xctx);
128 
129   xctx->resolutionX=i;
130 }
131 
132 
133 
HtmlCtx_GetResolutionY(const GWEN_XML_CONTEXT * ctx)134 int HtmlCtx_GetResolutionY(const GWEN_XML_CONTEXT *ctx)
135 {
136   HTML_XMLCTX *xctx;
137 
138   assert(ctx);
139   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
140   assert(xctx);
141 
142   return xctx->resolutionY;
143 }
144 
145 
146 
HtmlCtx_SetResolutionY(GWEN_XML_CONTEXT * ctx,int i)147 void HtmlCtx_SetResolutionY(GWEN_XML_CONTEXT *ctx, int i)
148 {
149   HTML_XMLCTX *xctx;
150 
151   assert(ctx);
152   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
153   assert(xctx);
154 
155   xctx->resolutionY=i;
156 }
157 
158 
159 
HtmlCtx_GetMediaPaths(const GWEN_XML_CONTEXT * ctx)160 GWEN_STRINGLIST *HtmlCtx_GetMediaPaths(const GWEN_XML_CONTEXT *ctx)
161 {
162   HTML_XMLCTX *xctx;
163 
164   assert(ctx);
165   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
166   assert(xctx);
167 
168   return xctx->mediaPaths;
169 }
170 
171 
172 
HtmlCtx_AddMediaPath(GWEN_XML_CONTEXT * ctx,const char * s)173 void HtmlCtx_AddMediaPath(GWEN_XML_CONTEXT *ctx, const char *s)
174 {
175   HTML_XMLCTX *xctx;
176 
177   assert(ctx);
178   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
179   assert(xctx);
180 
181   assert(s && *s);
182   GWEN_StringList_AppendString(xctx->mediaPaths, s, 0, 1);
183 }
184 
185 
186 
187 
HtmlCtx_GetCurrentGroup(const GWEN_XML_CONTEXT * ctx)188 HTML_GROUP *HtmlCtx_GetCurrentGroup(const GWEN_XML_CONTEXT *ctx)
189 {
190   HTML_XMLCTX *xctx;
191 
192   assert(ctx);
193   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
194   assert(xctx);
195 
196   return xctx->currentGroup;
197 }
198 
199 
200 
HtmlCtx_SetCurrentGroup(GWEN_XML_CONTEXT * ctx,HTML_GROUP * g)201 void HtmlCtx_SetCurrentGroup(GWEN_XML_CONTEXT *ctx, HTML_GROUP *g)
202 {
203   HTML_XMLCTX *xctx;
204 
205   assert(ctx);
206   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
207   assert(xctx);
208 
209   xctx->currentGroup=g;
210 }
211 
212 
213 
HtmlCtx_GetCurrentTagName(const GWEN_XML_CONTEXT * ctx)214 const char *HtmlCtx_GetCurrentTagName(const GWEN_XML_CONTEXT *ctx)
215 {
216   HTML_XMLCTX *xctx;
217 
218   assert(ctx);
219   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
220   assert(xctx);
221 
222   return xctx->currentTagName;
223 }
224 
225 
226 
HtmlCtx_SetCurrentTagName(GWEN_XML_CONTEXT * ctx,const char * s)227 void HtmlCtx_SetCurrentTagName(GWEN_XML_CONTEXT *ctx, const char *s)
228 {
229   HTML_XMLCTX *xctx;
230 
231   assert(ctx);
232   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
233   assert(xctx);
234 
235   free(xctx->currentTagName);
236   if (s)
237     xctx->currentTagName=strdup(s);
238   else
239     xctx->currentTagName=NULL;
240 }
241 
242 
243 
HtmlCtx_GetCurrentAttributes(const GWEN_XML_CONTEXT * ctx)244 GWEN_DB_NODE *HtmlCtx_GetCurrentAttributes(const GWEN_XML_CONTEXT *ctx)
245 {
246   HTML_XMLCTX *xctx;
247 
248   assert(ctx);
249   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
250   assert(xctx);
251 
252   return xctx->dbCurrentAttribs;
253 }
254 
255 
256 
HtmlCtx_GetObjects(const GWEN_XML_CONTEXT * ctx)257 HTML_OBJECT_TREE *HtmlCtx_GetObjects(const GWEN_XML_CONTEXT *ctx)
258 {
259   HTML_XMLCTX *xctx;
260 
261   assert(ctx);
262   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
263   assert(xctx);
264 
265   return xctx->objects;
266 }
267 
268 
269 
HtmlCtx_TakeObjects(const GWEN_XML_CONTEXT * ctx)270 HTML_OBJECT_TREE *HtmlCtx_TakeObjects(const GWEN_XML_CONTEXT *ctx)
271 {
272   HTML_XMLCTX *xctx;
273   HTML_OBJECT_TREE *t;
274 
275   assert(ctx);
276   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
277   assert(xctx);
278 
279   t=xctx->objects;
280   xctx->objects=NULL;
281 
282   return t;
283 }
284 
285 
286 
HtmlCtx_GetRootObject(const GWEN_XML_CONTEXT * ctx)287 HTML_OBJECT *HtmlCtx_GetRootObject(const GWEN_XML_CONTEXT *ctx)
288 {
289   HTML_XMLCTX *xctx;
290 
291   assert(ctx);
292   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
293   assert(xctx);
294 
295   return HtmlObject_Tree_GetFirst(xctx->objects);
296 }
297 
298 
299 
HtmlCtx_SanitizeData(GWEN_UNUSED GWEN_XML_CONTEXT * ctx,const char * data,GWEN_BUFFER * buf)300 int HtmlCtx_SanitizeData(GWEN_UNUSED GWEN_XML_CONTEXT *ctx,
301                          const char *data,
302                          GWEN_BUFFER *buf)
303 {
304   if (data && *data) {
305     const uint8_t *p;
306     uint8_t *dst;
307     uint8_t *src;
308     unsigned int size;
309     unsigned int i;
310     int lastWasBlank;
311     uint8_t *lastBlankPos;
312     uint32_t bStart=0;
313 
314     if (GWEN_Text_UnescapeXmlToBuffer(data, buf)) {
315       DBG_INFO(GWEN_LOGDOMAIN, "here");
316       return GWEN_ERROR_BAD_DATA;
317     }
318     if (GWEN_Buffer_GetUsedBytes(buf)==0) {
319       DBG_INFO(GWEN_LOGDOMAIN, "Empty data.");
320       return 0;
321     }
322 
323     dst=(uint8_t *)GWEN_Buffer_GetStart(buf);
324     src=dst;
325 
326     /* skip leading blanks */
327     while (*src && (*src<33 || *src==127))
328       src++;
329 
330     p=src;
331     bStart=src-((uint8_t *)GWEN_Buffer_GetStart(buf));
332     size=GWEN_Buffer_GetUsedBytes(buf)-bStart;
333     lastWasBlank=0;
334     lastBlankPos=0;
335 
336     for (i=0; i<size; i++) {
337       uint8_t c;
338 
339       c=*p;
340       if (c<32 || c==127)
341         c=32;
342 
343       /* remember next loop whether this char was a blank */
344       if (c==32) {
345         if (!lastWasBlank) {
346           /* store only one blank */
347           lastWasBlank=1;
348           lastBlankPos=dst;
349           *(dst++)=c;
350         }
351       }
352       else {
353         lastWasBlank=0;
354         lastBlankPos=0;
355         *(dst++)=c;
356       }
357       p++;
358     }
359 
360     /* remove trailing blanks */
361     if (lastBlankPos!=0)
362       dst=lastBlankPos;
363 
364     size=dst-(uint8_t *)GWEN_Buffer_GetStart(buf);
365     GWEN_Buffer_Crop(buf, 0, size);
366   }
367 
368   return 0;
369 }
370 
371 
372 
HtmlCtx_GetStandardProps(const GWEN_XML_CONTEXT * ctx)373 HTML_PROPS *HtmlCtx_GetStandardProps(const GWEN_XML_CONTEXT *ctx)
374 {
375   HTML_XMLCTX *xctx;
376 
377   assert(ctx);
378   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
379   assert(xctx);
380 
381   return xctx->standardProps;
382 }
383 
384 
385 
HtmlCtx_SetStandardProps(GWEN_XML_CONTEXT * ctx,HTML_PROPS * pr)386 void HtmlCtx_SetStandardProps(GWEN_XML_CONTEXT *ctx, HTML_PROPS *pr)
387 {
388   HTML_XMLCTX *xctx;
389   HTML_OBJECT *o;
390 
391   assert(ctx);
392   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
393   assert(xctx);
394 
395   HtmlProps_Attach(pr);
396   HtmlProps_free(xctx->standardProps);
397   xctx->standardProps=pr;
398 
399   if (pr) {
400     if (xctx->currentGroup && HtmlGroup_GetParent(xctx->currentGroup)==NULL)
401       HtmlGroup_SetProperties(xctx->currentGroup, pr);
402     o=HtmlObject_Tree_GetFirst(xctx->objects);
403     if (o && HtmlObject_GetProperties(o)==NULL)
404       HtmlObject_SetProperties(o, pr);
405   }
406 }
407 
408 
409 
HtmlCtx_StartTag(GWEN_XML_CONTEXT * ctx,const char * tagName)410 int HtmlCtx_StartTag(GWEN_XML_CONTEXT *ctx, const char *tagName)
411 {
412   HTML_XMLCTX *xctx;
413 
414   assert(ctx);
415   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
416   assert(xctx);
417 
418   DBG_DEBUG(GWEN_LOGDOMAIN, "Starting tag [%s]", tagName);
419 
420   /* store for later, do nothing more here */
421   HtmlCtx_SetCurrentTagName(ctx, tagName);
422   GWEN_DB_Group_free(xctx->dbCurrentAttribs);
423   xctx->dbCurrentAttribs=GWEN_DB_Group_new("attribs");
424 
425   return 0;
426 }
427 
428 
429 
HtmlCtx_EndTag(GWEN_XML_CONTEXT * ctx,int closing)430 int HtmlCtx_EndTag(GWEN_XML_CONTEXT *ctx, int closing)
431 {
432   HTML_XMLCTX *xctx;
433 
434   assert(ctx);
435   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
436   assert(xctx);
437 
438   if (closing) {
439     /* just ignore empty tags which are closed immediately */
440     DBG_DEBUG(GWEN_LOGDOMAIN, "Closing empty tag [%s]",
441               (xctx->currentTagName)?xctx->currentTagName:"<noname>");
442     return 0;
443   }
444 
445   if (xctx->currentTagName==NULL) {
446     DBG_INFO(GWEN_LOGDOMAIN, "No tag name, malformed HTML data");
447     return GWEN_ERROR_BAD_DATA;
448   }
449 
450   DBG_DEBUG(GWEN_LOGDOMAIN, "Completed tag [%s]", xctx->currentTagName);
451 
452   if (xctx->currentGroup) {
453     if (*(xctx->currentTagName)=='/') {
454       int rv;
455 
456       /* it is a closing tag, call EndTagFn */
457       DBG_DEBUG(GWEN_LOGDOMAIN,
458                 "Calling %s->EndTag(%s)",
459                 HtmlGroup_GetGroupName(xctx->currentGroup),
460                 xctx->currentTagName);
461       rv=HtmlGroup_EndTag(xctx->currentGroup, xctx->currentTagName+1);
462       if (rv<0) {
463         if (rv!=GWEN_ERROR_NOT_IMPLEMENTED) {
464           DBG_INFO(GWEN_LOGDOMAIN,
465                    "Error in EndTag(%s) for [%s]",
466                    HtmlGroup_GetGroupName(xctx->currentGroup),
467                    xctx->currentTagName);
468           return rv;
469         }
470       }
471       else if (rv==1) {
472         HTML_GROUP *g;
473         HTML_GROUP *gParent;
474 
475         /* pop current group from stack */
476         g=xctx->currentGroup;
477         gParent=HtmlGroup_GetParent(g);
478         xctx->currentGroup=gParent;
479         if (gParent) {
480           DBG_DEBUG(GWEN_LOGDOMAIN,
481                     "Calling %s->EndSubGroup(%s)",
482                     HtmlGroup_GetGroupName(gParent),
483                     HtmlGroup_GetGroupName(g));
484           HtmlGroup_EndSubGroup(gParent, g);
485         }
486         HtmlGroup_free(g);
487         GWEN_XmlCtx_DecDepth(ctx);
488       }
489     }
490     else {
491       int rv;
492 
493       /* it is an opening tag, call StartTagFn */
494       DBG_DEBUG(GWEN_LOGDOMAIN,
495                 "Calling %s->StartTag(%s)",
496                 HtmlGroup_GetGroupName(xctx->currentGroup),
497                 xctx->currentTagName);
498       rv=HtmlGroup_StartTag(xctx->currentGroup, xctx->currentTagName);
499       if (rv<0) {
500         if (rv!=GWEN_ERROR_NOT_IMPLEMENTED) {
501           DBG_INFO(GWEN_LOGDOMAIN,
502                    "Error in StartTag(%s) for [%s]",
503                    HtmlGroup_GetGroupName(xctx->currentGroup),
504                    xctx->currentTagName);
505           return rv;
506         }
507       }
508     }
509   }
510 
511   return 0;
512 }
513 
514 
515 
516 
517 
518 
HtmlCtx_AddData(GWEN_XML_CONTEXT * ctx,const char * data)519 int HtmlCtx_AddData(GWEN_XML_CONTEXT *ctx, const char *data)
520 {
521   HTML_XMLCTX *xctx;
522 
523   assert(ctx);
524   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
525   assert(xctx);
526 
527   if (xctx->currentGroup) {
528     int rv;
529 
530     DBG_DEBUG(GWEN_LOGDOMAIN,
531               "Calling %s->AddData()",
532               HtmlGroup_GetGroupName(xctx->currentGroup));
533     rv=HtmlGroup_AddData(xctx->currentGroup, data);
534     if (rv<0) {
535       if (rv!=GWEN_ERROR_NOT_IMPLEMENTED) {
536         DBG_INFO(GWEN_LOGDOMAIN,
537                  "Error in AddData(%s)",
538                  HtmlGroup_GetGroupName(xctx->currentGroup));
539         return rv;
540       }
541     }
542   }
543 
544   return 0;
545 }
546 
547 
548 
HtmlCtx_AddComment(GWEN_XML_CONTEXT * ctx,GWEN_UNUSED const char * data)549 int HtmlCtx_AddComment(GWEN_XML_CONTEXT *ctx, GWEN_UNUSED const char *data)
550 {
551   HTML_XMLCTX *xctx;
552 
553   assert(ctx);
554   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
555   assert(xctx);
556 
557   /* ignore comments */
558   return 0;
559 }
560 
561 
562 
HtmlCtx_AddAttr(GWEN_XML_CONTEXT * ctx,const char * attrName,const char * attrData)563 int HtmlCtx_AddAttr(GWEN_XML_CONTEXT *ctx,
564                     const char *attrName,
565                     const char *attrData)
566 {
567   HTML_XMLCTX *xctx;
568 
569   assert(ctx);
570   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
571   assert(xctx);
572 
573   if (xctx->currentGroup) {
574     assert(xctx->dbCurrentAttribs);
575     GWEN_DB_SetCharValue(xctx->dbCurrentAttribs,
576                          GWEN_DB_FLAGS_DEFAULT,
577                          attrName, attrData);
578   }
579 
580   return 0;
581 }
582 
583 
584 
HtmlCtx_GetTextWidth(GWEN_XML_CONTEXT * ctx,HTML_FONT * fnt,const char * s)585 int HtmlCtx_GetTextWidth(GWEN_XML_CONTEXT *ctx,
586                          HTML_FONT *fnt,
587                          const char *s)
588 {
589   HTML_XMLCTX *xctx;
590 
591   assert(ctx);
592   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
593   assert(xctx);
594 
595   if (xctx->getTextWidthFn)
596     return xctx->getTextWidthFn(ctx, fnt, s);
597   else
598     return -1;
599 }
600 
601 
602 
HtmlCtx_GetTextHeight(GWEN_XML_CONTEXT * ctx,HTML_FONT * fnt,const char * s)603 int HtmlCtx_GetTextHeight(GWEN_XML_CONTEXT *ctx,
604                           HTML_FONT *fnt,
605                           const char *s)
606 {
607   HTML_XMLCTX *xctx;
608 
609   assert(ctx);
610   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
611   assert(xctx);
612 
613   if (xctx->getTextHeightFn)
614     return xctx->getTextHeightFn(ctx, fnt, s);
615   else
616     return -1;
617 }
618 
619 
620 
HtmlCtx_GetColorFromName(const GWEN_XML_CONTEXT * ctx,const char * name)621 uint32_t HtmlCtx_GetColorFromName(const GWEN_XML_CONTEXT *ctx,
622                                   const char *name)
623 {
624   HTML_XMLCTX *xctx;
625 
626   assert(ctx);
627   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
628   assert(xctx);
629 
630   if (xctx->getColorFromNameFn)
631     return xctx->getColorFromNameFn(ctx, name);
632   else
633     return 0xffffffff;
634 }
635 
636 
637 
HtmlCtx_GetFont(GWEN_XML_CONTEXT * ctx,const char * fontName,int fontSize,uint32_t fontFlags)638 HTML_FONT *HtmlCtx_GetFont(GWEN_XML_CONTEXT *ctx,
639                            const char *fontName,
640                            int fontSize,
641                            uint32_t fontFlags)
642 {
643   HTML_XMLCTX *xctx;
644 
645   assert(ctx);
646   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
647   assert(xctx);
648 
649   if (xctx->getFontFn)
650     return xctx->getFontFn(ctx, fontName, fontSize, fontFlags);
651   else
652     return NULL;
653 }
654 
655 
656 
HtmlCtx_GetImage(GWEN_XML_CONTEXT * ctx,const char * imageName)657 HTML_IMAGE *HtmlCtx_GetImage(GWEN_XML_CONTEXT *ctx, const char *imageName)
658 {
659   HTML_XMLCTX *xctx;
660 
661   assert(ctx);
662   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
663   assert(xctx);
664 
665   if (xctx->getImageFn)
666     return xctx->getImageFn(ctx, imageName);
667   else
668     return NULL;
669 }
670 
671 
672 
HtmlCtx_SetGetTextWidthFn(GWEN_XML_CONTEXT * ctx,HTMLCTX_GET_TEXT_WIDTH_FN fn)673 HTMLCTX_GET_TEXT_WIDTH_FN HtmlCtx_SetGetTextWidthFn(GWEN_XML_CONTEXT *ctx,
674                                                     HTMLCTX_GET_TEXT_WIDTH_FN fn)
675 {
676   HTML_XMLCTX *xctx;
677   HTMLCTX_GET_TEXT_WIDTH_FN of;
678 
679   assert(ctx);
680   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
681   assert(xctx);
682 
683   of=xctx->getTextWidthFn;
684   xctx->getTextWidthFn=fn;
685 
686   return of;
687 }
688 
689 
690 
HtmlCtx_SetGetTextHeightFn(GWEN_XML_CONTEXT * ctx,HTMLCTX_GET_TEXT_HEIGHT_FN fn)691 HTMLCTX_GET_TEXT_HEIGHT_FN HtmlCtx_SetGetTextHeightFn(GWEN_XML_CONTEXT *ctx,
692                                                       HTMLCTX_GET_TEXT_HEIGHT_FN fn)
693 {
694   HTML_XMLCTX *xctx;
695   HTMLCTX_GET_TEXT_HEIGHT_FN of;
696 
697   assert(ctx);
698   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
699   assert(xctx);
700 
701   of=xctx->getTextHeightFn;
702   xctx->getTextHeightFn=fn;
703 
704   return of;
705 }
706 
707 
708 
HtmlCtx_SetGetColorFromNameFn(GWEN_XML_CONTEXT * ctx,HTMLCTX_GET_COLOR_FROM_NAME_FN fn)709 HTMLCTX_GET_COLOR_FROM_NAME_FN HtmlCtx_SetGetColorFromNameFn(GWEN_XML_CONTEXT *ctx,
710                                                              HTMLCTX_GET_COLOR_FROM_NAME_FN fn)
711 {
712   HTML_XMLCTX *xctx;
713   HTMLCTX_GET_COLOR_FROM_NAME_FN of;
714 
715   assert(ctx);
716   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
717   assert(xctx);
718 
719   of=xctx->getColorFromNameFn;
720   xctx->getColorFromNameFn=fn;
721 
722   return of;
723 }
724 
725 
726 
HtmlCtx_SetGetFontFn(GWEN_XML_CONTEXT * ctx,HTMLCTX_GET_FONT_FN fn)727 HTMLCTX_GET_FONT_FN HtmlCtx_SetGetFontFn(GWEN_XML_CONTEXT *ctx, HTMLCTX_GET_FONT_FN fn)
728 {
729   HTML_XMLCTX *xctx;
730   HTMLCTX_GET_FONT_FN of;
731 
732   assert(ctx);
733   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
734   assert(xctx);
735 
736   of=xctx->getFontFn;
737   xctx->getFontFn=fn;
738 
739   return of;
740 }
741 
742 
743 
HtmlCtx_SetGetImageFn(GWEN_XML_CONTEXT * ctx,HTMLCTX_GET_IMAGE_FN fn)744 HTMLCTX_GET_IMAGE_FN HtmlCtx_SetGetImageFn(GWEN_XML_CONTEXT *ctx, HTMLCTX_GET_IMAGE_FN fn)
745 {
746   HTML_XMLCTX *xctx;
747   HTMLCTX_GET_IMAGE_FN of;
748 
749   assert(ctx);
750   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
751   assert(xctx);
752 
753   of=xctx->getImageFn;
754   xctx->getImageFn=fn;
755 
756   return of;
757 }
758 
759 
760 
HtmlCtx_Layout(GWEN_XML_CONTEXT * ctx,int width,int height)761 int HtmlCtx_Layout(GWEN_XML_CONTEXT *ctx, int width, int height)
762 {
763   HTML_XMLCTX *xctx;
764   HTML_OBJECT *o;
765   int rv;
766 
767   assert(ctx);
768   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
769   assert(xctx);
770 
771   o=HtmlObject_Tree_GetFirst(xctx->objects);
772   if (o==NULL) {
773     DBG_ERROR(GWEN_LOGDOMAIN, "No objects");
774     return 0;
775   }
776 
777   HtmlObject_SetWidth(o, width);
778   HtmlObject_SetHeight(o, height);
779   rv=HtmlObject_Layout(o);
780   if (rv<0) {
781     DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
782     return rv;
783   }
784 
785   return 0;
786 }
787 
788 
789 
HtmlCtx_SetText(GWEN_XML_CONTEXT * ctx,const char * s)790 void HtmlCtx_SetText(GWEN_XML_CONTEXT *ctx, const char *s)
791 {
792   HTML_XMLCTX *xctx;
793   int rv;
794   HTML_GROUP *g;
795   HTML_OBJECT *o;
796 
797   assert(ctx);
798   xctx=GWEN_INHERIT_GETDATA(GWEN_XML_CONTEXT, HTML_XMLCTX, ctx);
799   assert(xctx);
800 
801   /* reset */
802   HtmlObject_Tree_Clear(xctx->objects);
803 
804   /* create initial group */
805   g=HtmlGroup_Box_new("HTML_ROOT", NULL, ctx);
806   assert(g);
807 
808   HtmlGroup_SetProperties(g, xctx->standardProps);
809   o=HtmlObject_Box_new(ctx);
810   HtmlObject_SetProperties(o, xctx->standardProps);
811   HtmlGroup_SetObject(g, o);
812   HtmlObject_Tree_Add(xctx->objects, o);
813   HtmlCtx_SetCurrentGroup(ctx, g);
814 
815   if (s && *s) {
816     rv=GWEN_XMLContext_ReadFromString(ctx, s);
817     if (rv<0) {
818       DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
819     }
820   }
821 
822 #if 0
823   fprintf(stderr, "============ Objects:\n");
824   fprintf(stderr, "String: [%s]\n", s);
825   o=HtmlObject_Tree_GetFirst(xctx->objects);
826   while (o) {
827     const char *xx;
828 
829     xx=HtmlObject_GetText(o);
830     fprintf(stderr, "Object(%d): [%s]\n",
831             HtmlObject_GetObjectType(o),
832             xx?xx:"(NULL)");
833     o=HtmlObject_Tree_GetBelow(o);
834   }
835 #endif
836 }
837 
838 
839 
HtmlCtx_GetWidth(const GWEN_XML_CONTEXT * ctx)840 int HtmlCtx_GetWidth(const GWEN_XML_CONTEXT *ctx)
841 {
842   HTML_OBJECT *o;
843 
844   o=HtmlCtx_GetRootObject(ctx);
845   if (o)
846     return HtmlObject_GetWidth(o);
847   else
848     return -1;
849 }
850 
851 
852 
HtmlCtx_GetHeight(const GWEN_XML_CONTEXT * ctx)853 int HtmlCtx_GetHeight(const GWEN_XML_CONTEXT *ctx)
854 {
855   HTML_OBJECT *o;
856 
857   o=HtmlCtx_GetRootObject(ctx);
858   if (o)
859     return HtmlObject_GetHeight(o);
860   else
861     return -1;
862 }
863 
864 
865