chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / dox / text.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 static char       **
27 TextGetLines(const char *text, int *count)
28 {
29    int                 i, j, k;
30    char              **list = NULL;
31
32    *count = 0;
33    i = 0;
34    k = 0;
35    if (!text)
36       return NULL;
37    *count = 1;
38    while (text[i])
39      {
40         j = i;
41         while ((text[j]) && (text[j] != '\n'))
42            j++;
43         k++;
44         list = EREALLOC(char *, list, k);
45         list[k - 1] = EMALLOC(char, j - i + 1);
46
47         strncpy(list[k - 1], &(text[i]), (j - i));
48         list[k - 1][j - i] = 0;
49         i = j;
50         if (text[i] == '\n')
51            i++;
52      }
53    *count = k;
54    return list;
55 }
56
57 void
58 TextStateLoadFont(TextState * ts)
59 {
60 #if USE_XFONT
61    if ((ts->efont) || (ts->xfont) || (ts->xfontset))
62 #else
63    if ((ts->efont) || (ts->xfontset))
64 #endif
65       return;
66
67    if (!ts->fontname)
68       return;
69
70    if (!ts->efont)
71      {
72         char                s[4096], w[4046], *s2, *ss;
73
74         s2 = NULL;
75         s2 = strdup(ts->fontname);
76         ss = strchr(s2, '/');
77         if (ss)
78           {
79              *ss = ' ';
80              word(s2, 1, s);
81              word(s2, 2, w);
82              ts->efont = Efont_load(s, atoi(w));
83              if (ts->efont)
84                {
85                   int                 as, ds;
86
87                   Efont_extents(ts->efont, " ", &as, &ds, NULL, NULL, NULL,
88                                 NULL, NULL);
89                   ts->xfontset_ascent = as;
90                   ts->height = as + ds;
91                }
92           }
93         Efree(s2);
94         if (ts->efont)
95            return;
96      }
97
98 #if USE_XFONT
99    if ((!ts->xfont) && (strchr(ts->fontname, ',') == NULL))
100      {
101         ts->xfont = XLoadQueryFont(disp, ts->fontname);
102         if (ts->xfont)
103           {
104              ts->xfontset_ascent = ts->xfont->ascent;
105              ts->height = ts->xfont->ascent + ts->xfont->descent;
106              return;
107           }
108      }
109 #endif
110
111    if (!ts->xfontset)
112      {
113         int                 i, missing_cnt, font_cnt;
114         int                 descent;
115         char              **missing_list, *def_str, **fn;
116         XFontStruct       **fs;
117
118         ts->xfontset = XCreateFontSet(disp, ts->fontname, &missing_list,
119                                       &missing_cnt, &def_str);
120         if (!ts->xfontset)
121            ts->xfontset = XCreateFontSet(disp, "fixed", &missing_list,
122                                          &missing_cnt, &def_str);
123         if (missing_cnt)
124            XFreeStringList(missing_list);
125         if (!ts->xfontset)
126            return;
127         font_cnt = XFontsOfFontSet(ts->xfontset, &fs, &fn);
128         ts->xfontset_ascent = 0;
129         for (i = 0; i < font_cnt; i++)
130            ts->xfontset_ascent = MAX(fs[i]->ascent, ts->xfontset_ascent);
131         descent = 0;
132         for (i = 0; i < font_cnt; i++)
133            descent = MAX(fs[i]->descent, descent);
134         ts->height = ts->xfontset_ascent + descent;
135      }
136 }
137
138 void
139 TextSize(TextState * ts, const char *text, int *width, int *height, int fsize)
140 {
141    char              **lines;
142    int                 i, num_lines;
143
144    *width = 0;
145    *height = 0;
146
147    lines = TextGetLines(text, &num_lines);
148    if (!lines)
149       return;
150
151    if (!ts)
152       return;
153
154    TextStateLoadFont(ts);
155
156    if (ts->efont)
157      {
158         for (i = 0; i < num_lines; i++)
159           {
160              int                 ascent, descent, wid;
161
162              Efont_extents(ts->efont, lines[i], &ascent, &descent, &wid,
163                            NULL, NULL, NULL, NULL);
164              *height += ascent + descent;
165              if (wid > *width)
166                 *width = wid;
167           }
168      }
169    else if (ts->xfontset)
170      {
171         for (i = 0; i < num_lines; i++)
172           {
173              XRectangle          ret1, ret2;
174
175              XmbTextExtents(ts->xfontset, lines[i], strlen(lines[i]), &ret1,
176                             &ret2);
177              *height += ret2.height;
178              if (ret2.width > *width)
179                 *width = ret2.width;
180           }
181      }
182 #if USE_XFONT
183    else if ((ts->xfont) && (ts->xfont->min_byte1 == 0) &&
184             (ts->xfont->max_byte1 == 0))
185      {
186         for (i = 0; i < num_lines; i++)
187           {
188              int                 wid;
189
190              wid = XTextWidth(ts->xfont, lines[i], strlen(lines[i]));
191              *height += ts->xfont->ascent + ts->xfont->descent;
192              if (wid > *width)
193                 *width = wid;
194           }
195      }
196    else if ((ts->xfont))
197      {
198         for (i = 0; i < num_lines; i++)
199           {
200              int                 wid;
201
202              wid = XTextWidth16(ts->xfont, (XChar2b *) lines[i],
203                                 strlen(lines[i]) / 2);
204              *height += ts->xfont->ascent + ts->xfont->descent;
205              if (wid > *width)
206                 *width = wid;
207           }
208      }
209 #endif /* USE_XFONT */
210    freestrlist(lines, num_lines);
211    return;
212    fsize = 0;
213 }
214
215 void
216 TextDraw(TextState * ts, Window win, char *text,
217          int x, int y, int w, int h, int fsize, int justification)
218 {
219    char              **lines;
220    int                 i, num_lines;
221    int                 xx, yy;
222    XGCValues           gcv;
223    static GC           gc = 0;
224
225    lines = TextGetLines(text, &num_lines);
226    if (!lines)
227       return;
228
229    if (!ts)
230       return;
231
232    TextStateLoadFont(ts);
233    xx = x;
234    yy = y;
235
236    if (!gc)
237       gc = XCreateGC(disp, win, 0, &gcv);
238
239    if (ts->efont)
240      {
241         for (i = 0; i < num_lines; i++)
242           {
243              int                 ascent, descent, wid;
244
245              Efont_extents(ts->efont, lines[i], &ascent, &descent, &wid,
246                            NULL, NULL, NULL, NULL);
247              if (i == 0)
248                 yy += ascent;
249              xx = x + (((w - wid) * justification) >> 10);
250              if (ts->effect == 1)
251                {
252                   EAllocColor(&ts->bg_col);
253                   XSetForeground(disp, gc, ts->bg_col.pixel);
254                   EFont_draw_string(disp, win, gc, xx + 1, yy + 1,
255                                     lines[i], ts->efont, VRoot.vis, VRoot.cmap);
256                }
257              else if (ts->effect == 2)
258                {
259                   EAllocColor(&ts->bg_col);
260                   XSetForeground(disp, gc, ts->bg_col.pixel);
261                   EFont_draw_string(disp, win, gc, xx - 1, yy,
262                                     lines[i], ts->efont, VRoot.vis, VRoot.cmap);
263                   EFont_draw_string(disp, win, gc, xx + 1, yy,
264                                     lines[i], ts->efont, VRoot.vis, VRoot.cmap);
265                   EFont_draw_string(disp, win, gc, xx, yy - 1,
266                                     lines[i], ts->efont, VRoot.vis, VRoot.cmap);
267                   EFont_draw_string(disp, win, gc, xx, yy + 1,
268                                     lines[i], ts->efont, VRoot.vis, VRoot.cmap);
269                }
270              EAllocColor(&ts->fg_col);
271              XSetForeground(disp, gc, ts->fg_col.pixel);
272              EFont_draw_string(disp, win, gc, xx, yy,
273                                lines[i], ts->efont, VRoot.vis, VRoot.cmap);
274              yy += ascent + descent;
275           }
276      }
277    else if (ts->xfontset)
278      {
279         for (i = 0; i < num_lines; i++)
280           {
281              XRectangle          ret1, ret2;
282
283              XmbTextExtents(ts->xfontset, lines[i], strlen(lines[i]), &ret1,
284                             &ret2);
285              if (i == 0)
286                 yy += ts->xfontset_ascent;
287              xx = x + (((w - ret2.width) * justification) >> 10);
288              if (ts->effect == 1)
289                {
290                   EAllocColor(&ts->bg_col);
291                   XSetForeground(disp, gc, ts->bg_col.pixel);
292                   XmbDrawString(disp, win, ts->xfontset, gc, xx + 1, yy + 1,
293                                 lines[i], strlen(lines[i]));
294                }
295              else if (ts->effect == 2)
296                {
297                   EAllocColor(&ts->bg_col);
298                   XSetForeground(disp, gc, ts->bg_col.pixel);
299                   XmbDrawString(disp, win, ts->xfontset, gc, xx - 1, yy,
300                                 lines[i], strlen(lines[i]));
301                   XmbDrawString(disp, win, ts->xfontset, gc, xx + 1, yy,
302                                 lines[i], strlen(lines[i]));
303                   XmbDrawString(disp, win, ts->xfontset, gc, xx, yy - 1,
304                                 lines[i], strlen(lines[i]));
305                   XmbDrawString(disp, win, ts->xfontset, gc, xx, yy + 1,
306                                 lines[i], strlen(lines[i]));
307                }
308              EAllocColor(&ts->fg_col);
309              XSetForeground(disp, gc, ts->fg_col.pixel);
310              XmbDrawString(disp, win, ts->xfontset, gc, xx, yy,
311                            lines[i], strlen(lines[i]));
312              yy += ret2.height;
313           }
314      }
315 #if USE_XFONT
316    else if ((ts->xfont) && (ts->xfont->min_byte1 == 0) &&
317             (ts->xfont->max_byte1 == 0))
318      {
319         XSetFont(disp, gc, ts->xfont->fid);
320         for (i = 0; i < num_lines; i++)
321           {
322              int                 wid;
323
324              wid = XTextWidth(ts->xfont, lines[i], strlen(lines[i]));
325              if (i == 0)
326                 yy += ts->xfont->ascent;
327              xx = x + (((w - wid) * justification) >> 10);
328              if (ts->effect == 1)
329                {
330                   EAllocColor(&ts->bg_col);
331                   XSetForeground(disp, gc, ts->bg_col.pixel);
332                   XDrawString(disp, win, gc, xx + 1, yy + 1,
333                               lines[i], strlen(lines[i]));
334                }
335              else if (ts->effect == 2)
336                {
337                   EAllocColor(&ts->bg_col);
338                   XSetForeground(disp, gc, ts->bg_col.pixel);
339                   XDrawString(disp, win, gc, xx - 1, yy,
340                               lines[i], strlen(lines[i]));
341                   XDrawString(disp, win, gc, xx + 1, yy,
342                               lines[i], strlen(lines[i]));
343                   XDrawString(disp, win, gc, xx, yy - 1,
344                               lines[i], strlen(lines[i]));
345                   XDrawString(disp, win, gc, xx, yy + 1,
346                               lines[i], strlen(lines[i]));
347                }
348              EAllocColor(&ts->fg_col);
349              XSetForeground(disp, gc, ts->fg_col.pixel);
350              XDrawString(disp, win, gc, xx, yy, lines[i], strlen(lines[i]));
351              yy += ts->xfont->ascent + ts->xfont->descent;
352           }
353      }
354    else if ((ts->xfont))
355      {
356         XSetFont(disp, gc, ts->xfont->fid);
357         for (i = 0; i < num_lines; i++)
358           {
359              int                 wid;
360
361              wid = XTextWidth16(ts->xfont, (XChar2b *) lines[i],
362                                 strlen(lines[i]) / 2);
363              if (i == 0)
364                 yy += ts->xfont->ascent;
365              xx = x + (((w - wid) * justification) >> 10);
366              if (ts->effect == 1)
367                {
368                   EAllocColor(&ts->bg_col);
369                   XSetForeground(disp, gc, ts->bg_col.pixel);
370                   XDrawString16(disp, win, gc, xx + 1, yy + 1,
371                                 (XChar2b *) lines[i], strlen(lines[i]) / 2);
372                }
373              else if (ts->effect == 2)
374                {
375                   EAllocColor(&ts->bg_col);
376                   XSetForeground(disp, gc, ts->bg_col.pixel);
377                   XDrawString16(disp, win, gc, xx - 1, yy,
378                                 (XChar2b *) lines[i], strlen(lines[i]) / 2);
379                   XDrawString16(disp, win, gc, xx + 1, yy,
380                                 (XChar2b *) lines[i], strlen(lines[i]) / 2);
381                   XDrawString16(disp, win, gc, xx, yy - 1,
382                                 (XChar2b *) lines[i], strlen(lines[i]) / 2);
383                   XDrawString16(disp, win, gc, xx, yy + 1,
384                                 (XChar2b *) lines[i], strlen(lines[i]) / 2);
385                }
386              EAllocColor(&ts->fg_col);
387              XSetForeground(disp, gc, ts->fg_col.pixel);
388              XDrawString16(disp, win, gc, xx, yy,
389                            (XChar2b *) lines[i], strlen(lines[i]) / 2);
390              yy += ts->xfont->ascent + ts->xfont->descent;
391           }
392      }
393 #endif /* USE_XFONT */
394    freestrlist(lines, num_lines);
395    return;
396    h = fsize = 0;
397 }