Handle WM_CHARs and pass them to TREEVIEW_ProcessLetterKeys. See also
[wine] / dlls / wineps / text.c
1 /*
2  *      PostScript driver text functions
3  *
4  *      Copyright 1998  Huw D M Davies
5  *
6  */
7 #include <string.h>
8 #include "psdrv.h"
9 #include "debugtools.h"
10 #include "winspool.h"
11
12 DEFAULT_DEBUG_CHANNEL(psdrv);
13
14 static BOOL PSDRV_Text(DC *dc, INT x, INT y, LPCWSTR str, UINT count,
15                        BOOL bDrawBackground, const INT *lpDx);
16
17 /***********************************************************************
18  *           PSDRV_ExtTextOut
19  */
20 BOOL PSDRV_ExtTextOut( DC *dc, INT x, INT y, UINT flags,
21                        const RECT *lprect, LPCWSTR str, UINT count,
22                        const INT *lpDx )
23 {
24     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
25     BOOL bResult = TRUE;
26     BOOL bClipped = FALSE;
27     BOOL bOpaque = FALSE;
28     RECT rect;
29
30     TRACE("(x=%d, y=%d, flags=0x%08x, str=%s, count=%d, lpDx=%p)\n", x, y,
31           flags, debugstr_wn(str, count), count, lpDx);
32
33     /* write font if not already written */
34     PSDRV_SetFont(dc);
35
36     /* set clipping and/or draw background */
37     if ((flags & (ETO_CLIPPED | ETO_OPAQUE)) && (lprect != NULL))
38     {
39         rect.left = INTERNAL_XWPTODP(dc, lprect->left, lprect->top);
40         rect.right = INTERNAL_XWPTODP(dc, lprect->right, lprect->bottom);
41         rect.top = INTERNAL_YWPTODP(dc, lprect->left, lprect->top);
42         rect.bottom = INTERNAL_YWPTODP(dc, lprect->right, lprect->bottom);
43
44         PSDRV_WriteGSave(dc);
45         PSDRV_WriteRectangle(dc, rect.left, rect.top, rect.right - rect.left, 
46                              rect.bottom - rect.top);
47
48         if (flags & ETO_OPAQUE)
49         {
50             bOpaque = TRUE;
51             PSDRV_WriteGSave(dc);
52             PSDRV_WriteSetColor(dc, &physDev->bkColor);
53             PSDRV_WriteFill(dc);
54             PSDRV_WriteGRestore(dc);
55         }
56
57         if (flags & ETO_CLIPPED)
58         {
59             bClipped = TRUE;
60             PSDRV_WriteClip(dc);
61         }
62
63         bResult = PSDRV_Text(dc, x, y, str, count, !(bClipped && bOpaque), lpDx); 
64         PSDRV_WriteGRestore(dc);
65     }
66     else
67     {
68         bResult = PSDRV_Text(dc, x, y, str, count, TRUE, lpDx); 
69     }
70
71     return bResult;
72 }
73
74 /***********************************************************************
75  *           PSDRV_Text
76  */
77 static BOOL PSDRV_Text(DC *dc, INT x, INT y, LPCWSTR str, UINT count,
78                        BOOL bDrawBackground, const INT *lpDx)
79 {
80     PSDRV_PDEVICE *physDev = (PSDRV_PDEVICE *)dc->physDev;
81     LPWSTR strbuf;
82     SIZE sz;
83
84     strbuf = HeapAlloc( PSDRV_Heap, 0, (count + 1) * sizeof(WCHAR));
85     if(!strbuf) {
86         WARN("HeapAlloc failed\n");
87         return FALSE;
88     }
89
90     if(dc->textAlign & TA_UPDATECP) {
91         x = dc->CursPosX;
92         y = dc->CursPosY;
93     }
94
95     x = INTERNAL_XWPTODP(dc, x, y);
96     y = INTERNAL_YWPTODP(dc, x, y);
97
98     GetTextExtentPoint32W(dc->hSelf, str, count, &sz);
99     if(lpDx) {
100         SIZE tmpsz;
101         INT i;
102         /* Get the width of the last char and add on all the offsets */
103         GetTextExtentPoint32W(dc->hSelf, str + count - 1, 1, &tmpsz);
104         for(i = 0; i < count-1; i++)
105             tmpsz.cx += lpDx[i];
106         sz.cx = tmpsz.cx; /* sz.cy remains untouched */
107     }
108
109     sz.cx = INTERNAL_XWSTODS(dc, sz.cx);
110     sz.cy = INTERNAL_YWSTODS(dc, sz.cy);
111     TRACE("textAlign = %x\n", dc->textAlign);
112     switch(dc->textAlign & (TA_LEFT | TA_CENTER | TA_RIGHT) ) {
113     case TA_LEFT:
114         if(dc->textAlign & TA_UPDATECP) {
115             dc->CursPosX = INTERNAL_XDPTOWP(dc, x + sz.cx, y);
116         }
117         break;
118
119     case TA_CENTER:
120         x -= sz.cx/2;
121         break;
122
123     case TA_RIGHT:
124         x -= sz.cx;
125         if(dc->textAlign & TA_UPDATECP) {
126             dc->CursPosX = INTERNAL_XDPTOWP(dc, x, y);
127         }
128         break;
129     }
130
131     switch(dc->textAlign & (TA_TOP | TA_BASELINE | TA_BOTTOM) ) {
132     case TA_TOP:
133         y += physDev->font.tm.tmAscent;
134         break;
135
136     case TA_BASELINE:
137         break;
138
139     case TA_BOTTOM:
140         y -= physDev->font.tm.tmDescent;
141         break;
142     }
143
144     memcpy(strbuf, str, count * sizeof(WCHAR));
145     *(strbuf + count) = '\0';
146     
147     if ((dc->backgroundMode != TRANSPARENT) && (bDrawBackground != FALSE))
148     {
149         PSDRV_WriteGSave(dc);
150         PSDRV_WriteNewPath(dc);
151         PSDRV_WriteRectangle(dc, x, y - physDev->font.tm.tmAscent, sz.cx, 
152                              physDev->font.tm.tmAscent + 
153                              physDev->font.tm.tmDescent);
154         PSDRV_WriteSetColor(dc, &physDev->bkColor);
155         PSDRV_WriteFill(dc);
156         PSDRV_WriteGRestore(dc);
157     }
158
159     PSDRV_WriteMoveTo(dc, x, y);
160     
161     if(!lpDx)
162         PSDRV_WriteShow(dc, strbuf, lstrlenW(strbuf));
163     else {
164         INT i;
165         float dx = 0.0, dy = 0.0;
166         float cos_theta = cos(physDev->font.escapement * M_PI / 1800.0);
167         float sin_theta = sin(physDev->font.escapement * M_PI / 1800.0);
168         for(i = 0; i < count-1; i++) {
169             TRACE("lpDx[%d] = %d\n", i, lpDx[i]);
170             PSDRV_WriteShow(dc, &strbuf[i], 1);
171             dx += lpDx[i] * cos_theta;
172             dy -= lpDx[i] * sin_theta;
173             PSDRV_WriteMoveTo(dc, x + INTERNAL_XWSTODS(dc, dx),
174                               y + INTERNAL_YWSTODS(dc, dy));
175         }
176         PSDRV_WriteShow(dc, &strbuf[i], 1);
177     }
178
179     /*
180      * Underline and strikeout attributes.
181      */
182     if ((physDev->font.tm.tmUnderlined) || (physDev->font.tm.tmStruckOut)) {
183
184         /* Get the thickness and the position for the underline attribute */
185         /* We'll use the same thickness for the strikeout attribute       */
186
187         float thick = physDev->font.afm->UnderlineThickness * physDev->font.scale;
188         float pos   = -physDev->font.afm->UnderlinePosition * physDev->font.scale;
189         SIZE size;
190         INT escapement =  physDev->font.escapement;
191
192         TRACE("Position = %f Thickness %f Escapement %d\n",
193               pos, thick, escapement);
194
195         /* Get the width of the text */
196
197         PSDRV_GetTextExtentPoint(dc, strbuf, lstrlenW(strbuf), &size);
198         size.cx = INTERNAL_XWSTODS(dc, size.cx);
199
200         /* Do the underline */
201
202         if (physDev->font.tm.tmUnderlined) {
203             if (escapement != 0)  /* rotated text */
204             {
205                 PSDRV_WriteGSave(dc);  /* save the graphics state */
206                 PSDRV_WriteMoveTo(dc, x, y); /* move to the start */
207
208                 /* temporarily rotate the coord system */
209                 PSDRV_WriteRotate(dc, -escapement/10); 
210                 
211                 /* draw the underline relative to the starting point */
212                 PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
213             }
214             else
215                 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
216
217             PSDRV_WriteFill(dc);
218
219             if (escapement != 0)  /* rotated text */
220                 PSDRV_WriteGRestore(dc);  /* restore the graphics state */
221         }
222
223         /* Do the strikeout */
224
225         if (physDev->font.tm.tmStruckOut) {
226             pos = -physDev->font.tm.tmAscent / 2;
227
228             if (escapement != 0)  /* rotated text */
229             {
230                 PSDRV_WriteGSave(dc);  /* save the graphics state */
231                 PSDRV_WriteMoveTo(dc, x, y); /* move to the start */
232
233                 /* temporarily rotate the coord system */
234                 PSDRV_WriteRotate(dc, -escapement/10);
235
236                 /* draw the underline relative to the starting point */
237                 PSDRV_WriteRRectangle(dc, 0, (INT)pos, size.cx, (INT)thick);
238             }
239             else
240                 PSDRV_WriteRectangle(dc, x, y + (INT)pos, size.cx, (INT)thick);
241
242             PSDRV_WriteFill(dc);
243
244             if (escapement != 0)  /* rotated text */
245                 PSDRV_WriteGRestore(dc);  /* restore the graphics state */
246         }
247     }
248
249     HeapFree(PSDRV_Heap, 0, strbuf);
250     return TRUE;
251 }