chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / dox / format.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2007-2008 Kim Woelders
4  *
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:
11  *
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.
16  *
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.
23  */
24 #include "dox.h"
25
26 #define DEFAULT_LINKCOLOR_R 30
27 #define DEFAULT_LINKCOLOR_G 50
28 #define DEFAULT_LINKCOLOR_B 160
29
30 typedef enum _type {
31    IMG,
32    BR,
33    FONT,
34    P,
35    TEXT,
36    PAGE
37 } Type;
38
39 typedef struct _img {
40    char               *src;
41    char               *src2;
42    char               *src3;
43    int                 x, y;
44    char               *link;
45    int                 w, h;
46 } Img_;
47
48 typedef struct _font {
49    char               *face;
50    int                 r, g, b;
51 } Font_;
52
53 typedef struct _p {
54    float               align;
55 } P_;
56
57 typedef struct _object {
58    Type                type;
59    void               *object;
60 } Object;
61
62 typedef struct _page {
63    char               *name;
64    int                 count;
65    Object             *obj;
66    int                 columns;
67    int                 padding;
68    int                 linkr, linkg, linkb;
69    char               *background;
70 } Page;
71
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;
77
78 static int
79 fdgetc(void)
80 {
81    int                 val;
82
83    if (fdat_ptr >= (fdat + fdat_size))
84       return EOF;
85    val = (int)(*fdat_ptr);
86    fdat_ptr++;
87    return val;
88 }
89
90 static void
91 fdjump(int count)
92 {
93    fdat_ptr += count;
94    if (fdat_ptr < fdat)
95       fdat_ptr = fdat;
96    if (fdat_ptr >= (fdat + fdat_size))
97       fdat_ptr = (fdat + fdat_size) - 1;
98 }
99
100 static void
101 AddPage(Object * obj)
102 {
103    num_pages++;
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;
114
115    if ((obj) && (obj->type == PAGE))
116      {
117         Page               *pg;
118
119         pg = (Page *) (obj->object);
120         if (pg->name)
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;
127         if (pg->background)
128            page[num_pages - 1].background = pg->background;
129      }
130 }
131
132 static void
133 AddObject(Object * obj)
134 {
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;
140 }
141
142 static void
143 BuildObj(Object * obj, char *var, char *param)
144 {
145    static Page        *pg = NULL;
146    static P_          *p = NULL;
147    static Font_       *fn = NULL;
148    static Img_        *img = NULL;
149
150    switch (obj->type)
151      {
152      case IMG:
153         if (!obj->object)
154           {
155              img = EMALLOC(Img_, 1);
156              obj->object = img;
157              img->src = NULL;
158              img->src2 = NULL;
159              img->src3 = NULL;
160              img->x = 0;
161              img->y = 0;
162              img->link = NULL;
163              img->w = 0;
164              img->h = 0;
165           }
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);
178         break;
179      case BR:
180         break;
181      case FONT:
182         if (!obj->object)
183           {
184              fn = EMALLOC(Font_, 1);
185              obj->object = fn;
186              fn->face = NULL;
187              fn->r = 0;
188              fn->g = 0;
189              fn->b = 0;
190           }
191         if (!strcmp(var, "face"))
192            fn->face = strdup(param);
193         else if (!strcmp(var, "color"))
194           {
195              char                hex[3] = "00";
196
197              if (param[0] == '#')
198                {
199                   hex[0] = param[1];
200                   hex[1] = param[2];
201                   sscanf(hex, "%x", &(fn->r));
202                   hex[0] = param[3];
203                   hex[1] = param[4];
204                   sscanf(hex, "%x", &(fn->g));
205                   hex[0] = param[5];
206                   hex[1] = param[6];
207                   sscanf(hex, "%x", &(fn->b));
208                }
209           }
210         break;
211      case P:
212         if (!obj->object)
213           {
214              p = EMALLOC(P_, 1);
215              obj->object = p;
216              p->align = 0;
217           }
218         if (!strcmp(var, "align"))
219           {
220              if ((strlen(param) > 0) && (param[strlen(param) - 1] == '%'))
221                 param[strlen(param) - 1] = 0;
222              p->align = atof(param);
223           }
224         break;
225      case TEXT:
226         break;
227      case PAGE:
228         if (!obj->object)
229           {
230              pg = EMALLOC(Page, 1);
231              obj->object = pg;
232              pg->columns = 1;
233              pg->padding = 1;
234              pg->name = NULL;
235              pg->background = NULL;
236              pg->linkr = DEFAULT_LINKCOLOR_R;
237              pg->linkg = DEFAULT_LINKCOLOR_G;
238              pg->linkb = DEFAULT_LINKCOLOR_B;
239           }
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"))
249           {
250              char                hex[3] = "00";
251
252              if (param[0] == '#')
253                {
254                   hex[0] = param[1];
255                   hex[1] = param[2];
256                   sscanf(hex, "%x", &(pg->linkr));
257                   hex[0] = param[3];
258                   hex[1] = param[4];
259                   sscanf(hex, "%x", &(pg->linkg));
260                   hex[0] = param[5];
261                   hex[1] = param[6];
262                   sscanf(hex, "%x", &(pg->linkb));
263                }
264           }
265         break;
266      default:
267         break;
268      }
269 }
270
271 static int
272 GetNextTag(Object * obj)
273 {
274    char                s[65536];
275    int                 i = 0, wd = 0;
276    int                 val;
277    char                intag = 0;
278    char                havobj = 0;
279
280    for (;;)
281      {
282         val = fdgetc();
283         if (val == EOF)
284            return 0;
285         if (intag)
286           {
287              if (val == '>')
288                 intag = 0;
289              s[i++] = (char)val;
290              if (s[i - 1] == '\n')
291                 s[i - 1] = ' ';
292              if (s[i - 1] == '>')
293                 s[i - 1] = ' ';
294              if (s[i - 1] == ' ')
295                {
296                   if (i == 1)
297                      i = 0;
298                   else
299                     {
300                        s[i - 1] = 0;
301                        if (!havobj)
302                          {
303                             if (wd == 0)
304                               {
305                                  if (!strcmp(s, "page"))
306                                     obj->type = PAGE;
307                                  else if (!strcmp(s, "img"))
308                                     obj->type = IMG;
309                                  else if (!strcmp(s, "br"))
310                                     obj->type = BR;
311                                  else if (!strcmp(s, "font"))
312                                     obj->type = FONT;
313                                  else if (!strcmp(s, "p"))
314                                     obj->type = P;
315                                  havobj = 1;
316                               }
317                             i = 0;
318                          }
319                        else
320                          {
321                             char                w1[1024];
322                             char                w2[1024];
323                             int                 j = 0;
324
325                             w1[0] = 0;
326                             w2[0] = 0;
327                             while ((s[j]) && (s[j] != '='))
328                               {
329                                  w1[j] = s[j];
330                                  j++;
331                               }
332                             w1[j] = 0;
333                             if (j < (int)strlen(s))
334                                strcpy(w2, &(s[j + 1]));
335                             BuildObj(obj, w1, w2);
336                             i = 0;
337                          }
338                        wd++;
339                     }
340                }
341              if (!intag)
342                 return 1;
343           }
344         if (val == '<')
345            intag = 1;
346      }
347    return 1;
348 }
349
350 static char        *
351 GetTextUntilTag(void)
352 {
353    char                s[65536];
354    int                 i = 0;
355    int                 val;
356
357    for (;;)
358      {
359         val = fdgetc();
360         if (val == EOF)
361           {
362              s[i] = 0;
363              if (strlen(s) < 1)
364                 return NULL;
365              return strdup(s);
366           }
367         s[i++] = (char)val;
368         if (s[i - 1] == '\n')
369            s[i - 1] = ' ';
370         if ((i == 1) && (s[0] == ' '))
371            i--;
372         else if (s[i - 1] == '<')
373           {
374              s[i - 1] = 0;
375              fdjump(-1);
376              if (strlen(s) < 1)
377                 return NULL;
378              return strdup(s);
379           }
380         if ((i > 2) && (s[i - 2] == ' ') && (s[i - 1] == ' '))
381            i--;
382         if (i > 65530)
383            return NULL;
384      }
385    return NULL;
386 }
387
388 int
389 GetObjects(FILE * f)
390 {
391    static char         have_font = 0;
392    static char         in_para = 0;
393    Object              obj;
394    char               *txt;
395    char                buf[4096];
396    int                 count;
397
398    fdat = NULL;
399    fdat_size = 0;
400    while ((count = fread(buf, 1, 4096, f)) > 0)
401      {
402         if (!fdat)
403            fdat = EMALLOC(char, count);
404
405         else
406            fdat = EREALLOC(char, fdat, fdat_size + count);
407
408         memcpy(fdat + fdat_size, buf, count);
409         fdat_size += count;
410      }
411    fdat_ptr = fdat;
412
413    if (page)
414      {
415         int                 i;
416
417         for (i = 0; i < num_pages; i++)
418           {
419              int                 j;
420
421              Efree(page[i].name);
422              Efree(page[i].background);
423              for (j = 0; j < page[i].count; j++)
424                {
425                   switch (page[i].obj[j].type)
426                     {
427                     case IMG:
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);
432                        break;
433                     case BR:
434                        break;
435                     case FONT:
436                        Efree(((Font_ *) page[i].obj[j].object)->face);
437                        break;
438                     case P:
439                        break;
440                     case TEXT:
441                        break;
442                     case PAGE:
443                        break;
444                     }
445                   Efree(page[i].obj[j].object);
446                }
447              Efree(page[i].obj);
448           }
449         Efree(page);
450         num_pages = 0;
451         page = NULL;
452         have_font = 0;
453         in_para = 0;
454      }
455
456    obj.object = NULL;
457    for (;;)
458      {
459         if ((have_font) && (in_para))
460           {
461              txt = GetTextUntilTag();
462              if (txt)
463                {
464                   obj.type = TEXT;
465                   obj.object = (void *)txt;
466                }
467              else
468                {
469                   if (!GetNextTag(&obj))
470                     {
471                        Efree(fdat);
472                        return 0;
473                     }
474                }
475           }
476         else
477           {
478              if (!GetNextTag(&obj))
479                {
480                   Efree(fdat);
481                   return 0;
482                }
483           }
484         if (obj.type == PAGE)
485           {
486              in_para = 0;
487              have_font = 0;
488              AddPage(&obj);
489           }
490         else if (page)
491            AddObject(&obj);
492         if (obj.type == IMG)
493            in_para = 0;
494         if (obj.type == P)
495            in_para = 1;
496         if (obj.type == FONT)
497            have_font = 1;
498         obj.object = NULL;
499      }
500    Efree(fdat);
501 }
502
503 int
504 FixPage(int p)
505 {
506    if (p < 0)
507       return 0;
508    if (p >= num_pages)
509       return num_pages - 1;
510    return p;
511 }
512
513 int
514 GetPage(char *name)
515 {
516    int                 i;
517
518    for (i = 0; i < num_pages; i++)
519      {
520         if ((page[i].name) && (!strcmp(name, page[i].name)))
521            return i;
522      }
523    return -1;
524 }
525
526 void
527 GetLinkColors(int page_num, int *r, int *g, int *b)
528 {
529    if (page_num < 0)
530      {
531         *r = DEFAULT_LINKCOLOR_R;
532         *g = DEFAULT_LINKCOLOR_G;
533         *b = DEFAULT_LINKCOLOR_B;
534      }
535    else
536      {
537         *r = page[page_num].linkr;
538         *g = page[page_num].linkg;
539         *b = page[page_num].linkb;
540      }
541 }
542
543 static void
544 CalcOffset(Page * pg, int col_w, int x, int y, int th, int *pxspace, int *poff)
545 {
546    int                 xspace, off;
547    int                 sx, sy, ssx, ssy;
548    Img_               *img;
549    int                 j;
550
551    xspace = col_w;
552    off = 0;
553    sx = x + off;
554    sy = y;
555    ssx = sx + col_w - 1;
556    ssy = sy + th - 1;
557    for (j = 0; j < pg->count; j++)
558      {
559         if (pg->obj[j].type != IMG)
560            continue;
561
562         img = (Img_ *) pg->obj[j].object;
563         if ((img->w > 0) && (img->h > 0))
564           {
565              int                 ix, iy, iix, iiy;
566
567              ix = img->x;
568              iy = img->y;
569              iix = img->x + img->w - 1;
570              iiy = img->y + img->h - 1;
571
572              if ((iy <= ssy) && (iiy >= sy))
573                {
574                   if ((ix >= sx) && (ix <= ssx))
575                     {
576                        if ((iix >= sx) && (iix <= ssx))
577                          {
578                             if (((ix + iix) / 2) > ((sx + ssx) / 2))
579                                ssx = ix - 1;
580                             else
581                                sx = iix + 1;
582                          }
583                        else
584                          {
585                             ssx = ix - 1;
586                          }
587                     }
588                   else if ((iix >= sx) && (iix <= ssx))
589                     {
590                        sx = iix + 1;
591                     }
592                }
593           }
594      }
595    off = sx - x;
596    xspace = (ssx - sx) + 1;
597    if (xspace < 0)
598       xspace = 0;
599
600    *pxspace = xspace;
601    *poff = off;
602 }
603
604 Link               *
605 RenderPage(Window win, int page_num, int w, int h)
606 {
607    Link               *ll = NULL;
608    Page               *pg;
609    TextState           ts;
610    int                 i, col_w, col_h;
611    int                 x, y;
612    int                 justification = 0;
613    int                 firstp = 1;
614    Imlib_Image         im;
615    int                 wastext = 0;
616
617    memset(&ts, 0, sizeof(ts));
618    pg = &(page[page_num]);
619    x = pg->padding;
620    y = pg->padding;
621    col_w = ((w - (pg->padding * (pg->columns + 1))) / pg->columns);
622    col_h = h - (pg->padding * 2);
623    if (pg->background)
624      {
625         im = ImageLoadDoc(pg->background);
626         if (im)
627           {
628              imlib_context_set_image(im);
629              imlib_context_set_drawable(win);
630              imlib_render_image_on_drawable_at_size(0, 0, w, h);
631              imlib_free_image();
632           }
633      }
634    for (i = 0; i < pg->count; i++)
635      {
636         char                s[32768], ss[32768], wd[4096], *txt;
637         Img_               *img;
638         Font_              *fn;
639         P_                 *p;
640         int                 wc, eol, eot;
641         int                 islink = 0, lx, lw;
642
643         switch (pg->obj[i].type)
644           {
645           case IMG:
646              img = (Img_ *) pg->obj[i].object;
647              if (img->src)
648                {
649                   im = ImageLoadDoc(img->src);
650                   if (im)
651                     {
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,
657                                                               img->w, img->h);
658                        imlib_free_image();
659                     }
660                   if (img->link)
661                     {
662                        Link               *l;
663
664                        l = EMALLOC(Link, 1);
665                        l->name = strdup(img->link);
666                        l->x = img->x;
667                        l->y = img->y;
668                        l->w = img->w;
669                        l->h = img->h;
670                        l->next = ll;
671                        ll = l;
672                     }
673                }
674              break;
675           case BR:
676              if (!wastext)
677                 y += ts.height;
678              wastext = 0;
679              break;
680           case FONT:
681              fn = (Font_ *) pg->obj[i].object;
682              ts.fontname = NULL;
683              ESetColor(&ts.fg_col, 0, 0, 0);
684              ESetColor(&ts.bg_col, 0, 0, 0);
685              ts.effect = 0;
686              if (ts.efont)
687                 Efont_free(ts.efont);
688              ts.efont = NULL;
689 #if USE_XFONT
690              if (ts.xfont)
691                 XFreeFont(disp, ts.xfont);
692              ts.xfont = NULL;
693 #endif
694              if (ts.xfontset)
695                 XFreeFontSet(disp, ts.xfontset);
696              ts.xfontset = NULL;
697              ts.xfontset_ascent = 0;
698              ts.height = 0;
699              ts.fontname = fn->face;
700              ESetColor(&ts.fg_col, fn->r, fn->g, fn->b);
701              TextStateLoadFont(&ts);
702              break;
703           case P:
704              p = (P_ *) pg->obj[i].object;
705              if (p)
706                 justification = (int)((p->align / 100) * 1024);
707              else
708                 justification = 0;
709              if (!firstp)
710                 y += ts.height;
711              else
712                 firstp = 0;
713              break;
714           case TEXT:
715              txt = (char *)pg->obj[i].object;
716              wc = 1;
717              ss[0] = 0;
718              s[0] = 0;
719              eol = 0;
720              eot = 0;
721              for (;;)
722                {
723                   char               *txt_disp;
724                   int                 tw, th, xspace;
725                   int                 off, j;
726                   char                link_txt[1024];
727                   char                link_link[1024];
728                   int                 spaceflag, oldwc = 0, linkwc;
729
730                   wd[0] = 0;
731 #ifdef USE_WORD_MB
732                   if (MB_CUR_MAX > 1)   /* If multibyte locale,... */
733                      word_mb(txt, wc, wd, &spaceflag);
734                   else
735 #endif
736                     {
737                        word(txt, wc, wd);
738                        spaceflag = 1;
739                     }
740                   if (!wd[0])
741                      eol = 1;
742
743                   wc++;
744                   eot++;
745                   strcpy(ss, s);
746                   if ((eot != 1) && spaceflag)
747                      strcat(s, " ");
748
749                   linkwc = -1;
750                   if (wd[0] == '_')
751                     {
752                        link_txt[0] = '\0';
753                        link_link[0] = '\0';
754                        islink = 1;
755                        oldwc = wc;
756                        TextSize(&ts, s, &lx, &th, 17);
757                     }
758
759                   if (islink == 1)
760                     {
761                        if (eol || ((wd[0] != '_') && spaceflag))        /* if NO link tag, ... */
762                          {
763                             link_txt[0] = '\0';
764                             link_link[0] = '\0';
765                             islink = 0;
766                             wc = oldwc;
767 #ifdef USE_WORD_MB
768                             if (MB_CUR_MAX > 1)
769                                word_mb(txt, wc - 1, wd, &spaceflag);
770                             else
771 #endif
772                               {
773                                  word(txt, wc - 1, wd);
774                                  spaceflag = 1;
775                               }
776                          }
777                        else
778                          {
779                             int                 k, linkflg;
780
781                             j = 0;
782                             linkflg = 0;
783                             if (wd[0] == '_')
784                               {
785                                  j++;
786                                  linkflg++;
787                               }
788
789                             k = strlen(link_txt);
790                             for (; wd[j] != '(' && wd[j] != '\0'; j++, k++)
791                               {
792                                  if (wd[j] == '_')
793                                     link_txt[k] = ' ';
794                                  else
795                                     link_txt[k] = wd[j];
796                                  if (linkflg)
797                                     wd[j - 1] = link_txt[k];
798                                  else
799                                     wd[j] = link_txt[k];
800                               }
801                             link_txt[k] = '\0';
802                             if (linkflg)
803                                wd[j - 1] = '\0';
804
805                             if (wd[j] == '(')
806                               {
807                                  wd[j++] = '\0';
808                                  strcpy(link_link, wd + j);
809                                  k = strlen(link_link) - 1;
810                                  if (k <= 0)
811                                     continue;
812                                  for (j = k; j > 0 && link_link[j] != ')'; j--)
813                                     ;
814                                  link_link[j] = '\0';
815                                  strcpy(wd, link_txt);
816                                  if (j < k)
817                                     strcat(wd, link_link + j + 1);
818                                  islink = 2;
819                                  linkwc = wc;
820                               }
821                             else
822                                continue;
823                          }
824                     }
825
826                   strcat(s, wd);
827
828                   CalcOffset(pg, col_w, x, y, ts.height, &xspace, &off);
829
830                   TextSize(&ts, s, &tw, &th, 17);
831                   txt_disp = ss;
832                   if (eot == 1)
833                      txt_disp = s;
834                   if (((tw > xspace) || (eol)) && (strlen(txt_disp) > 0))
835                     {
836                        if (txt_disp[strlen(txt_disp) - 1] == ' ')
837                           txt_disp[strlen(txt_disp) - 1] = 0;
838
839                        if ((eot == 1) && (tw > xspace))
840                          {
841                             char                p1[4096];
842                             int                 point = 0, cnt = 0, ii, len;
843
844                             while (txt_disp[(point + cnt)])
845                               {
846                                  len =
847                                     mblen(txt_disp + point + cnt, MB_CUR_MAX);
848                                  if (len < 0)
849                                    {
850                                       cnt++;
851                                       continue;
852                                    }
853                                  else
854                                     for (ii = 0; ii < len; ii++, cnt++)
855                                        p1[cnt] = txt_disp[point + cnt];
856                                  p1[cnt] = 0;
857                                  TextSize(&ts, p1, &tw, &th, 17);
858                                  if ((tw > xspace)
859                                      || (!txt_disp[(point + cnt)]))
860                                    {
861                                       if (txt_disp[(point + cnt)])
862                                         {
863                                            point = point + cnt - len;
864                                            p1[cnt - len] = 0;
865                                            cnt = 0;
866                                         }
867                                       else
868                                         {
869                                            point = point + cnt;
870                                            p1[cnt] = 0;
871                                            cnt = 0;
872                                         }
873                                       wastext = 1;
874                                       TextDraw(&ts, win, p1, x + off, y,
875                                                xspace, 99999, 17,
876                                                justification);
877                                       y += ts.height;
878                                       if (y >=
879                                           (h -
880                                            (pg->padding + ts.height -
881                                             (ts.height - ts.xfontset_ascent))))
882                                         {
883                                            y = pg->padding;
884                                            x += col_w + pg->padding;
885                                         }
886                                       CalcOffset(pg, col_w, x, y, ts.height,
887                                                  &xspace, &off);
888                                    }
889                               }
890                          }
891                        else
892                          {
893                             if ((tw > xspace) && (eot != 1))
894                                wc--;
895                             wastext = 1;
896                             TextDraw(&ts, win, txt_disp, x + off, y,
897                                      xspace, 99999, 17, justification);
898                             if (islink > 1 && linkwc > wc)
899                               {
900                                  islink = 0;
901                                  link_link[0] = '\0';
902                                  link_txt[0] = '\0';
903                                  wc = oldwc - 1;
904                               }
905
906                             if (islink > 1)
907                               {
908                                  int                 rr, gg, bb;
909                                  int                 extra;
910                                  GC                  gc;
911                                  XGCValues           gcv;
912
913                                  gc = XCreateGC(disp, win, 0, &gcv);
914                                  EGetColor(&ts.fg_col, &rr, &gg, &bb);
915                                  ESetColor(&ts.fg_col, pg->linkr, pg->linkg,
916                                            pg->linkb);
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,
923                                           17, 0);
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);
931                                  islink = 0;
932                                  XFreeGC(disp, gc);
933                                  {
934                                     Link               *l;
935
936                                     l = EMALLOC(Link, 1);
937                                     l->name = strdup(link_link);
938                                     l->x = x + off + lx + extra;
939                                     l->y = y;
940                                     l->w = lw;
941                                     l->h = ts.height;
942                                     l->next = ll;
943                                     ll = l;
944                                  }
945                                  link_link[0] = '\0';
946                                  link_txt[0] = '\0';
947                               }
948                             y += ts.height;
949                             if (y >=
950                                 (h -
951                                  (pg->padding + ts.height -
952                                   (ts.height - ts.xfontset_ascent))))
953                               {
954                                  y = pg->padding;
955                                  x += col_w + pg->padding;
956                               }
957                          }
958                        eot = 0;
959                        s[0] = 0;
960                     }
961                   if (eol)
962                      break;
963                }
964
965              break;
966           default:
967              break;
968           }
969         if (y >=
970             (h - (pg->padding + ts.height - (ts.height - ts.xfontset_ascent))))
971           {
972              y = pg->padding;
973              x += col_w + pg->padding;
974           }
975      }
976
977    if (ts.efont)
978       Efont_free(ts.efont);
979 #if USE_XFONT
980    if (ts.xfont)
981       XFreeFont(disp, ts.xfont);
982 #endif
983    if (ts.xfontset)
984       XFreeFontSet(disp, ts.xfontset);
985
986    return ll;
987 }