4bf962f5ddbb72b79b43afddd728949411b1706f
[oweals/cde.git] / cde / lib / DtTerm / TermPrim / TermPrimRenderFontSet.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 #ifndef lint
24 #ifdef  VERBOSE_REV_INFO
25 static char rcs_id[] = "$XConsortium: TermPrimRenderFontSet.c /main/1 1996/04/21 19:18:53 drk $";
26 #endif  /* VERBOSE_REV_INFO */
27 #endif  /* lint */
28
29 /*                                                                      *
30  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
31  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
32  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
33  * (c) Copyright 1993, 1994 Novell, Inc.                                *
34  */
35
36 #include "TermHeader.h"
37 #include "TermPrimP.h"
38 #include "TermPrimDebug.h"
39 #include "TermPrimRenderP.h"
40 #include "TermPrimRenderFontSet.h"
41
42 typedef struct _TermFontSetRec {
43     XFontSet fontSet;
44     int ascent;
45     int height;
46     int width;
47 } TermFontSetRec, *TermFontSet;
48
49 static void
50 FontSetRenderFunction(
51     Widget                w,
52     TermFont              font,
53     Pixel                 fg,
54     Pixel                 bg,
55     unsigned long         flags,
56     int                   x,
57     int                   y,
58     unsigned char        *string,
59     int                   len
60 )
61 {
62     DtTermPrimitiveWidget tw = (DtTermPrimitiveWidget) w;
63     struct termData *tpd = tw->term.tpd;
64     XGCValues values;
65     unsigned long valueMask;
66     TermFontSet termFontSet = (TermFontSet) font->fontInfo;
67     int escapement;
68     XRectangle extents;
69     Boolean fixExtents;
70
71     /* set the renderGC... */
72     valueMask = (unsigned long) 0;
73
74     /* set background... */
75     if (tpd->renderGC.background != bg) {
76         tpd->renderGC.background = bg;
77         values.background = bg;
78         valueMask |= GCBackground;
79     }
80
81     /* since Xlib will be mucking with the GC's font under us, we need to
82      * make sure we trash the cached value...
83      */
84     tpd->renderGC.fid = (Font) 0;
85
86     escapement = (tpd->mbCurMax == 1) ?
87         XmbTextExtents(termFontSet->fontSet, (char *) string, len,
88                        NULL, &extents) :
89         XwcTextExtents(termFontSet->fontSet, (wchar_t*) string, len,
90                        NULL, &extents);
91
92     /* Text height may be smaller than cellHeight (happens when using font sets).
93        In this case we need to fill background manually and then use X*DrawString
94        instead of X*DrawImageString */
95     fixExtents = extents.height < tpd->cellHeight;
96
97     if (fixExtents) {
98       /* set background color as foreground if needed*/
99       if (tpd->renderGC.foreground != bg) {
100         tpd->renderGC.foreground = bg;
101         valueMask|= GCForeground ;
102         values.foreground = bg;
103       }
104       if (valueMask) {
105         (void) XChangeGC(XtDisplay(w), tpd->renderGC.gc, valueMask, &values);
106         valueMask= (unsigned long) 0;
107       }
108       /* paint background manually */
109       (void) XFillRectangle(XtDisplay(w),
110                             XtWindow(w),
111                             tpd->renderGC.gc,
112                             x,
113                             y,
114                             escapement,
115                             tpd->cellHeight);
116     }
117
118     /* set the foreground... */
119     if (TermIS_SECURE(flags)) {
120         if (tpd->renderGC.foreground != bg) {
121             tpd->renderGC.foreground = bg;
122             values.foreground = bg;
123             valueMask |= GCForeground;
124         }
125     } else {
126         if (tpd->renderGC.foreground != fg) {
127             tpd->renderGC.foreground = fg;
128             values.foreground = fg;
129             valueMask |= GCForeground;
130         }
131     }
132     if (valueMask) {
133         (void) XChangeGC(XtDisplay(w), tpd->renderGC.gc, valueMask,
134                 &values);
135     }
136
137     /* draw image string a line of text... */
138     if (isDebugFSet('t', 1)) {
139         /* we need to clear background after the debug draw and delay,
140            so this will cause  X*DrawImageString to be always used
141            in debug mode */
142         fixExtents = 0;
143 #ifdef  BBA
144 #pragma BBA_IGNORE
145 #endif  /*BBA*/
146         /* Fill in the text area so we can see what is going to
147          * be displayed...
148          */
149         (void) XFillRectangle(XtDisplay(w),
150                 XtWindow(w),
151                 tpd->renderGC.gc,
152                 x,
153                 y,
154                 escapement,
155                 extents.height);
156           (void) XSync(XtDisplay(w), False);
157           (void) shortSleep(100000);
158     }
159
160
161     if (tpd->mbCurMax == 1)
162     {
163         /* select right function, we do not want text background be drawn twice */
164         (void) (fixExtents ? XmbDrawString: XmbDrawImageString)
165                  (XtDisplay(w),                 /* Display              */
166                  XtWindow(w),                   /* Drawable             */
167                  termFontSet->fontSet,          /* XFontSet             */
168                  tpd->renderGC.gc,              /* GC                   */
169                  x,                             /* x                    */
170                  y + termFontSet->ascent,       /* y                    */
171                  (char *)string,                /* string               */
172                  len);                          /* length               */
173
174         /* handle overstrike... */
175         if (TermIS_OVERSTRIKE(flags)) {
176             (void) XmbDrawString(XtDisplay(w),  /* Display              */
177                      XtWindow(w),               /* Drawable             */
178                      termFontSet->fontSet,      /* XFontSet             */
179                      tpd->renderGC.gc,          /* GC                   */
180                      x + 1,                     /* x                    */
181                      y + termFontSet->ascent,   /* y                    */
182                      (char *)string,            /* string               */
183                      len);                      /* length               */
184          }
185     }
186     else
187     {
188         /* select right function, we do not want text background be drawn twice */
189         (void)  (fixExtents ? XwcDrawString: XwcDrawImageString)
190                 (XtDisplay(w),                  /* Displa*/
191                 XtWindow(w),                    /* Drawable             */
192                 termFontSet->fontSet,           /* XFontSet             */
193                 tpd->renderGC.gc,               /* GC                   */
194                 x,                              /* x                    */
195                 y + termFontSet->ascent,        /* y                    */
196                 (wchar_t *) string,             /* string               */
197                 len);                           /* length               */
198
199         /* handle overstrike... */
200         if (TermIS_OVERSTRIKE(flags)) {
201             (void) XwcDrawString(XtDisplay(w),  /* Display              */
202                     XtWindow(w),                /* Drawable             */
203                     termFontSet->fontSet,       /* XFontSet             */
204                     tpd->renderGC.gc,           /* GC                   */
205                     x + 1,                      /* x                    */
206                     y + termFontSet->ascent,    /* y                    */
207                     (wchar_t *) string,         /* string               */
208                     len);                       /* length               */
209         }
210     }
211     /* handle the underline enhancement... */
212     /* draw the underline... */
213     if (TermIS_UNDERLINE(flags)) {
214         XDrawLine(XtDisplay(w),             /* Display          */
215                   XtWindow(w),              /* Window           */
216                   tpd->renderGC.gc,         /* GC               */
217                   x,                        /* X1               */
218                   y + tpd->cellHeight - 1,  /* Y1               */
219                   x - 1 + escapement,       /* X2               */
220                   y + tpd->cellHeight - 1); /* Y2               */
221     }
222 }
223
224 static void
225 FontSetDestroyFunction(
226     Widget                w,
227     TermFont              font
228 )
229 {
230     (void) XtFree((char *) font->fontInfo);
231     (void) XtFree((char *) font);
232 }
233
234 static void
235 FontSetExtentsFunction(
236     Widget                w,
237     TermFont              font,
238     unsigned char        *string,
239     int                   len,
240     int                  *widthReturn,
241     int                  *heightReturn,
242     int                  *ascentReturn
243 )
244 {
245     TermFontSet termFontSet = (TermFontSet) font->fontInfo;
246
247     if (widthReturn) {
248         *widthReturn = len * termFontSet->width;
249     }
250     if (heightReturn) {
251         *heightReturn = termFontSet->height;
252     }
253     if (ascentReturn) {
254         *ascentReturn = termFontSet->ascent;
255     }
256     return;
257 }
258
259 TermFont
260 _DtTermPrimRenderFontSetCreate(
261     Widget                w,
262     XFontSet              fontSet
263 )
264 {
265     TermFont termFont;
266     TermFontSet termFontSet;
267     XFontSetExtents *fontSetExtents;
268
269     termFont = (TermFont) XtMalloc(sizeof(TermFontRec));
270     termFont->renderFunction = FontSetRenderFunction;
271     termFont->destroyFunction = FontSetDestroyFunction;
272     termFont->extentsFunction = FontSetExtentsFunction;
273
274     termFontSet = (TermFontSet) XtMalloc(sizeof(TermFontSetRec));
275     termFontSet->fontSet = fontSet;
276     fontSetExtents = XExtentsOfFontSet(fontSet);
277     termFontSet->width = fontSetExtents->max_logical_extent.width;
278     termFontSet->height = fontSetExtents->max_logical_extent.height;
279     termFontSet->ascent = -fontSetExtents->max_logical_extent.y;
280     termFont->fontInfo = (XtPointer) termFontSet;
281
282     return(termFont);
283 }