Release 0.3.0
[wine] / objects / text.c
1 /*
2  * text functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
8
9 #include <X11/Intrinsic.h>
10 #include <X11/StringDefs.h>
11 #include <X11/Core.h>
12 #include <X11/Shell.h>
13 #include <X11/Xatom.h>
14
15 #include "message.h"
16 #include "callback.h"
17 #include "win.h"
18 #include "gdi.h"
19
20
21 /***********************************************************************
22  *           DrawText    (USER.85)
23  */
24 int DrawText( HDC hdc, LPSTR str, int count, LPRECT rect, WORD flags )
25 {
26     int x = rect->left, y = rect->top;
27     if (flags & DT_CENTER) x = (rect->left + rect->right) / 2;
28     if (flags & DT_VCENTER) y = (rect->top + rect->bottom) / 2;
29     if (count == -1) count = strlen(str);
30
31     if (!TextOut( hdc, x, y, str, count )) return 0;
32     return 1;
33 }
34
35
36 /***********************************************************************
37  *           TextOut    (GDI.33)
38  */
39 BOOL TextOut( HDC hdc, short x, short y, LPSTR str, short count )
40 {
41     int dir, ascent, descent, i;
42     XCharStruct info;
43     XFontStruct *font;
44
45     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
46     if (!dc) return FALSE;
47     if (!DC_SetupGCForText( dc )) return TRUE;
48     font = dc->u.x.font.fstruct;
49
50     if (dc->w.textAlign & TA_UPDATECP)
51     {
52         x = dc->w.CursPosX;
53         y = dc->w.CursPosY;
54     }
55 #ifdef DEBUG_TEXT
56     printf( "TextOut: %d,%d '%s'\n", x, y, str );
57 #endif
58     x = XLPTODP( dc, x );
59     y = YLPTODP( dc, y );
60
61     XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
62     info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
63
64       /* Compute starting position */
65
66     switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
67     {
68       case TA_LEFT:
69           if (dc->w.textAlign & TA_UPDATECP)
70               dc->w.CursPosX = XDPTOLP( dc, x + info.width );
71           break;
72       case TA_RIGHT:
73           x -= info.width;
74           if (dc->w.textAlign & TA_UPDATECP) dc->w.CursPosX = XDPTOLP( dc, x );
75           break;
76       case TA_CENTER:
77           x -= info.width / 2;
78           break;
79     }
80     switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
81     {
82       case TA_TOP:
83           y += font->ascent;
84           break;
85       case TA_BOTTOM:
86           y -= font->descent;
87           break;
88       case TA_BASELINE:
89           break;
90     }
91
92       /* Draw text */
93
94     if (!dc->w.charExtra && !dc->w.breakExtra)
95     {
96         if (dc->w.backgroundMode == TRANSPARENT)
97             XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc, 
98                          x, y, str, count );
99         else
100             XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
101                               x, y, str, count );
102     }
103     else
104     {
105         char * p = str;
106         int xchar = x;
107         for (i = 0; i < count; i++, p++)
108         {
109             XCharStruct * charStr;
110             unsigned char ch = *p;
111             int extraWidth;
112             
113             if ((ch < font->min_char_or_byte2)||(ch > font->max_char_or_byte2))
114                 ch = font->default_char;
115             if (!font->per_char) charStr = &font->min_bounds;
116             else charStr = font->per_char + ch - font->min_char_or_byte2;
117
118             extraWidth = dc->w.charExtra;
119             if (ch == dc->u.x.font.metrics.tmBreakChar)
120                 extraWidth += dc->w.breakExtra;
121
122             if (dc->w.backgroundMode == TRANSPARENT)
123                 XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
124                              xchar, y, p, 1 );
125             else
126             {
127                 XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
128                                   xchar, y, p, 1 );
129                 XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel);
130                 XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
131                                 xchar + charStr->width, y - font->ascent,
132                                 extraWidth, font->ascent + font->descent );
133                 XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
134             }
135             xchar += charStr->width + extraWidth;
136         }
137     }
138
139       /* Draw underline and strike-out if needed */
140
141     if (dc->u.x.font.metrics.tmUnderlined)
142     {
143         long linePos, lineWidth;       
144         if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
145             linePos = font->descent-1;
146         if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
147             lineWidth = 0;
148         else if (lineWidth == 1) lineWidth = 0;
149         XSetLineAttributes( XT_display, dc->u.x.gc, lineWidth,
150                             LineSolid, CapRound, JoinBevel ); 
151         XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
152                    x, y + linePos, x + info.width, y + linePos );
153     }
154     if (dc->u.x.font.metrics.tmStruckOut)
155     {
156         long lineAscent, lineDescent;
157         if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
158             lineAscent = font->ascent / 3;
159         if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
160             lineDescent = -lineAscent;
161         XSetLineAttributes( XT_display, dc->u.x.gc, lineAscent + lineDescent,
162                             LineSolid, CapRound, JoinBevel ); 
163         XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
164                    x, y - lineAscent, x + info.width, y - lineAscent );
165     }
166     
167     return TRUE;
168 }