2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2007-2008 Kim Woelders
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 #define DEFAULT_LINKCOLOR_R 30
27 #define DEFAULT_LINKCOLOR_G 50
28 #define DEFAULT_LINKCOLOR_B 160
48 typedef struct _font {
57 typedef struct _object {
62 typedef struct _page {
68 int linkr, linkg, linkb;
72 static int num_pages = 0;
73 static Page *page = NULL;
74 static char *fdat_ptr = NULL;
75 static int fdat_size = 0;
76 static char *fdat = NULL;
83 if (fdat_ptr >= (fdat + fdat_size))
85 val = (int)(*fdat_ptr);
96 if (fdat_ptr >= (fdat + fdat_size))
97 fdat_ptr = (fdat + fdat_size) - 1;
101 AddPage(Object * obj)
104 page = EREALLOC(Page, page, num_pages);
105 page[num_pages - 1].name = NULL;
106 page[num_pages - 1].count = 0;
107 page[num_pages - 1].obj = NULL;
108 page[num_pages - 1].columns = 1;
109 page[num_pages - 1].background = NULL;
110 page[num_pages - 1].padding = 2;
111 page[num_pages - 1].linkr = DEFAULT_LINKCOLOR_R;
112 page[num_pages - 1].linkg = DEFAULT_LINKCOLOR_G;
113 page[num_pages - 1].linkb = DEFAULT_LINKCOLOR_B;
115 if ((obj) && (obj->type == PAGE))
119 pg = (Page *) (obj->object);
121 page[num_pages - 1].name = pg->name;
122 page[num_pages - 1].columns = pg->columns;
123 page[num_pages - 1].padding = pg->padding;
124 page[num_pages - 1].linkr = pg->linkr;
125 page[num_pages - 1].linkg = pg->linkg;
126 page[num_pages - 1].linkb = pg->linkb;
128 page[num_pages - 1].background = pg->background;
133 AddObject(Object * obj)
135 page[num_pages - 1].count++;
136 page[num_pages - 1].obj =
137 EREALLOC(Object, page[num_pages - 1].obj, page[num_pages - 1].count);
138 page[num_pages - 1].obj[page[num_pages - 1].count - 1].type = obj->type;
139 page[num_pages - 1].obj[page[num_pages - 1].count - 1].object = obj->object;
143 BuildObj(Object * obj, char *var, char *param)
145 static Page *pg = NULL;
147 static Font_ *fn = NULL;
148 static Img_ *img = NULL;
155 img = EMALLOC(Img_, 1);
166 if (!strcmp(var, "x"))
167 img->x = atoi(param);
168 else if (!strcmp(var, "y"))
169 img->y = atoi(param);
170 else if (!strcmp(var, "src"))
171 img->src = strdup(param);
172 else if (!strcmp(var, "src2"))
173 img->src2 = strdup(param);
174 else if (!strcmp(var, "src3"))
175 img->src3 = strdup(param);
176 else if (!strcmp(var, "href"))
177 img->link = strdup(param);
184 fn = EMALLOC(Font_, 1);
191 if (!strcmp(var, "face"))
192 fn->face = strdup(param);
193 else if (!strcmp(var, "color"))
201 sscanf(hex, "%x", &(fn->r));
204 sscanf(hex, "%x", &(fn->g));
207 sscanf(hex, "%x", &(fn->b));
218 if (!strcmp(var, "align"))
220 if ((strlen(param) > 0) && (param[strlen(param) - 1] == '%'))
221 param[strlen(param) - 1] = 0;
222 p->align = atof(param);
230 pg = EMALLOC(Page, 1);
235 pg->background = NULL;
236 pg->linkr = DEFAULT_LINKCOLOR_R;
237 pg->linkg = DEFAULT_LINKCOLOR_G;
238 pg->linkb = DEFAULT_LINKCOLOR_B;
240 if (!strcmp(var, "columns"))
241 pg->columns = atoi(param);
242 else if (!strcmp(var, "padding"))
243 pg->padding = atoi(param);
244 else if (!strcmp(var, "name"))
245 pg->name = strdup(param);
246 else if (!strcmp(var, "background"))
247 pg->background = strdup(param);
248 else if (!strcmp(var, "linkcolor"))
256 sscanf(hex, "%x", &(pg->linkr));
259 sscanf(hex, "%x", &(pg->linkg));
262 sscanf(hex, "%x", &(pg->linkb));
272 GetNextTag(Object * obj)
290 if (s[i - 1] == '\n')
305 if (!strcmp(s, "page"))
307 else if (!strcmp(s, "img"))
309 else if (!strcmp(s, "br"))
311 else if (!strcmp(s, "font"))
313 else if (!strcmp(s, "p"))
327 while ((s[j]) && (s[j] != '='))
333 if (j < (int)strlen(s))
334 strcpy(w2, &(s[j + 1]));
335 BuildObj(obj, w1, w2);
351 GetTextUntilTag(void)
368 if (s[i - 1] == '\n')
370 if ((i == 1) && (s[0] == ' '))
372 else if (s[i - 1] == '<')
380 if ((i > 2) && (s[i - 2] == ' ') && (s[i - 1] == ' '))
391 static char have_font = 0;
392 static char in_para = 0;
400 while ((count = fread(buf, 1, 4096, f)) > 0)
403 fdat = EMALLOC(char, count);
406 fdat = EREALLOC(char, fdat, fdat_size + count);
408 memcpy(fdat + fdat_size, buf, count);
417 for (i = 0; i < num_pages; i++)
422 Efree(page[i].background);
423 for (j = 0; j < page[i].count; j++)
425 switch (page[i].obj[j].type)
428 Efree(((Img_ *) page[i].obj[j].object)->src);
429 Efree(((Img_ *) page[i].obj[j].object)->src2);
430 Efree(((Img_ *) page[i].obj[j].object)->src3);
431 Efree(((Img_ *) page[i].obj[j].object)->link);
436 Efree(((Font_ *) page[i].obj[j].object)->face);
445 Efree(page[i].obj[j].object);
459 if ((have_font) && (in_para))
461 txt = GetTextUntilTag();
465 obj.object = (void *)txt;
469 if (!GetNextTag(&obj))
478 if (!GetNextTag(&obj))
484 if (obj.type == PAGE)
496 if (obj.type == FONT)
509 return num_pages - 1;
518 for (i = 0; i < num_pages; i++)
520 if ((page[i].name) && (!strcmp(name, page[i].name)))
527 GetLinkColors(int page_num, int *r, int *g, int *b)
531 *r = DEFAULT_LINKCOLOR_R;
532 *g = DEFAULT_LINKCOLOR_G;
533 *b = DEFAULT_LINKCOLOR_B;
537 *r = page[page_num].linkr;
538 *g = page[page_num].linkg;
539 *b = page[page_num].linkb;
544 CalcOffset(Page * pg, int col_w, int x, int y, int th, int *pxspace, int *poff)
547 int sx, sy, ssx, ssy;
555 ssx = sx + col_w - 1;
557 for (j = 0; j < pg->count; j++)
559 if (pg->obj[j].type != IMG)
562 img = (Img_ *) pg->obj[j].object;
563 if ((img->w > 0) && (img->h > 0))
565 int ix, iy, iix, iiy;
569 iix = img->x + img->w - 1;
570 iiy = img->y + img->h - 1;
572 if ((iy <= ssy) && (iiy >= sy))
574 if ((ix >= sx) && (ix <= ssx))
576 if ((iix >= sx) && (iix <= ssx))
578 if (((ix + iix) / 2) > ((sx + ssx) / 2))
588 else if ((iix >= sx) && (iix <= ssx))
596 xspace = (ssx - sx) + 1;
605 RenderPage(Window win, int page_num, int w, int h)
612 int justification = 0;
617 memset(&ts, 0, sizeof(ts));
618 pg = &(page[page_num]);
621 col_w = ((w - (pg->padding * (pg->columns + 1))) / pg->columns);
622 col_h = h - (pg->padding * 2);
625 im = ImageLoadDoc(pg->background);
628 imlib_context_set_image(im);
629 imlib_context_set_drawable(win);
630 imlib_render_image_on_drawable_at_size(0, 0, w, h);
634 for (i = 0; i < pg->count; i++)
636 char s[32768], ss[32768], wd[4096], *txt;
641 int islink = 0, lx, lw;
643 switch (pg->obj[i].type)
646 img = (Img_ *) pg->obj[i].object;
649 im = ImageLoadDoc(img->src);
652 imlib_context_set_image(im);
653 img->w = imlib_image_get_width();
654 img->h = imlib_image_get_height();
655 imlib_context_set_drawable(win);
656 imlib_render_image_on_drawable_at_size(img->x, img->y,
664 l = EMALLOC(Link, 1);
665 l->name = strdup(img->link);
681 fn = (Font_ *) pg->obj[i].object;
683 ESetColor(&ts.fg_col, 0, 0, 0);
684 ESetColor(&ts.bg_col, 0, 0, 0);
687 Efont_free(ts.efont);
691 XFreeFont(disp, ts.xfont);
695 XFreeFontSet(disp, ts.xfontset);
697 ts.xfontset_ascent = 0;
699 ts.fontname = fn->face;
700 ESetColor(&ts.fg_col, fn->r, fn->g, fn->b);
701 TextStateLoadFont(&ts);
704 p = (P_ *) pg->obj[i].object;
706 justification = (int)((p->align / 100) * 1024);
715 txt = (char *)pg->obj[i].object;
727 char link_link[1024];
728 int spaceflag, oldwc = 0, linkwc;
732 if (MB_CUR_MAX > 1) /* If multibyte locale,... */
733 word_mb(txt, wc, wd, &spaceflag);
746 if ((eot != 1) && spaceflag)
756 TextSize(&ts, s, &lx, &th, 17);
761 if (eol || ((wd[0] != '_') && spaceflag)) /* if NO link tag, ... */
769 word_mb(txt, wc - 1, wd, &spaceflag);
773 word(txt, wc - 1, wd);
789 k = strlen(link_txt);
790 for (; wd[j] != '(' && wd[j] != '\0'; j++, k++)
797 wd[j - 1] = link_txt[k];
808 strcpy(link_link, wd + j);
809 k = strlen(link_link) - 1;
812 for (j = k; j > 0 && link_link[j] != ')'; j--)
815 strcpy(wd, link_txt);
817 strcat(wd, link_link + j + 1);
828 CalcOffset(pg, col_w, x, y, ts.height, &xspace, &off);
830 TextSize(&ts, s, &tw, &th, 17);
834 if (((tw > xspace) || (eol)) && (strlen(txt_disp) > 0))
836 if (txt_disp[strlen(txt_disp) - 1] == ' ')
837 txt_disp[strlen(txt_disp) - 1] = 0;
839 if ((eot == 1) && (tw > xspace))
842 int point = 0, cnt = 0, ii, len;
844 while (txt_disp[(point + cnt)])
847 mblen(txt_disp + point + cnt, MB_CUR_MAX);
854 for (ii = 0; ii < len; ii++, cnt++)
855 p1[cnt] = txt_disp[point + cnt];
857 TextSize(&ts, p1, &tw, &th, 17);
859 || (!txt_disp[(point + cnt)]))
861 if (txt_disp[(point + cnt)])
863 point = point + cnt - len;
874 TextDraw(&ts, win, p1, x + off, y,
880 (pg->padding + ts.height -
881 (ts.height - ts.xfontset_ascent))))
884 x += col_w + pg->padding;
886 CalcOffset(pg, col_w, x, y, ts.height,
893 if ((tw > xspace) && (eot != 1))
896 TextDraw(&ts, win, txt_disp, x + off, y,
897 xspace, 99999, 17, justification);
898 if (islink > 1 && linkwc > wc)
913 gc = XCreateGC(disp, win, 0, &gcv);
914 EGetColor(&ts.fg_col, &rr, &gg, &bb);
915 ESetColor(&ts.fg_col, pg->linkr, pg->linkg,
917 EAllocColor(&ts.fg_col);
918 XSetForeground(disp, gc, ts.fg_col.pixel);
919 TextSize(&ts, txt_disp, &tw, &th, 17);
920 extra = ((xspace - tw) * justification) >> 10;
921 TextDraw(&ts, win, link_txt,
922 x + off + lx + extra, y, 99999, 99999,
924 TextSize(&ts, link_txt, &lw, &th, 17);
925 XDrawLine(disp, win, gc,
926 x + off + lx + extra,
927 y + ts.xfontset_ascent,
928 x + off + lx + lw + extra,
929 y + ts.xfontset_ascent);
930 ESetColor(&ts.fg_col, rr, gg, bb);
936 l = EMALLOC(Link, 1);
937 l->name = strdup(link_link);
938 l->x = x + off + lx + extra;
951 (pg->padding + ts.height -
952 (ts.height - ts.xfontset_ascent))))
955 x += col_w + pg->padding;
970 (h - (pg->padding + ts.height - (ts.height - ts.xfontset_ascent))))
973 x += col_w + pg->padding;
978 Efont_free(ts.efont);
981 XFreeFont(disp, ts.xfont);
984 XFreeFontSet(disp, ts.xfontset);