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