- Improve LVM_GETITEMRECT values for LVS_ICON style. Now mostly
[wine] / objects / text.c
1 /*
2  * text functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <string.h>
22
23 #include "windef.h"
24 #include "wingdi.h"
25 #include "wine/winuser16.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "gdi.h"
29 #include "wine/debug.h"
30 #include "winnls.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(text);
33
34 /***********************************************************************
35  *           FONT_mbtowc
36  *
37  * Returns a '\0' terminated Unicode translation of str using the
38  * charset of the currently selected font in hdc.  If count is -1 then
39  * str is assumed to be '\0' terminated, otherwise it contains the
40  * number of bytes to convert.  If plenW is non-NULL, on return it
41  * will point to the number of WCHARs (excluding the '\0') that have
42  * been written.  If pCP is non-NULL, on return it will point to the
43  * codepage used in the conversion (NB, this may be CP_SYMBOL so watch
44  * out).  The caller should free the returned LPWSTR from the process
45  * heap itself.
46  */
47 LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
48 {
49     UINT cp = CP_ACP;
50     INT lenW, i;
51     LPWSTR strW;
52     CHARSETINFO csi;
53     int charset = GetTextCharset(hdc);
54
55     /* Hmm, nicely designed api this one! */
56     if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
57         cp = csi.ciACP;
58     else {
59         switch(charset) {
60         case OEM_CHARSET:
61             cp = GetOEMCP();
62             break;
63         case DEFAULT_CHARSET:
64             cp = GetACP();
65             break;
66
67         case VISCII_CHARSET:
68         case TCVN_CHARSET:
69         case KOI8_CHARSET:
70         case ISO3_CHARSET:
71         case ISO4_CHARSET:
72         case ISO10_CHARSET:
73         case CELTIC_CHARSET:
74           /* FIXME: These have no place here, but because x11drv
75              enumerates fonts with these (made up) charsets some apps
76              might use them and then the FIXME below would become
77              annoying.  Now we could pick the intended codepage for
78              each of these, but since it's broken anyway we'll just
79              use CP_ACP and hope it'll go away...
80           */
81             cp = CP_ACP;
82             break;
83
84
85         default:
86             FIXME("Can't find codepage for charset %d\n", charset);
87             break;
88         }
89     }
90
91     TRACE("cp == %d\n", cp);
92
93     if(count == -1) count = strlen(str);
94     if(cp != CP_SYMBOL) {
95         lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
96         strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
97         MultiByteToWideChar(cp, 0, str, count, strW, lenW);
98     } else {
99         lenW = count;
100         strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
101         for(i = 0; i < count; i++) strW[i] = (BYTE)str[i];
102     }
103     strW[lenW] = '\0';
104     TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
105     if(plenW) *plenW = lenW;
106     if(pCP) *pCP = cp;
107     return strW;
108 }
109
110
111 /***********************************************************************
112  *           ExtTextOutA    (GDI32.@)
113  */
114 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
115                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
116 {
117     INT wlen;
118     UINT codepage;
119     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
120     BOOL ret;
121     LPINT lpDxW = NULL;
122
123     if (lpDx) {
124         unsigned int i = 0, j = 0;
125
126         lpDxW = (LPINT)HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
127         while(i < count) {
128             if(IsDBCSLeadByteEx(codepage, str[i])) {
129                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
130                 i = i + 2;
131             } else {
132                 lpDxW[j++] = lpDx[i];
133                 i = i + 1;
134             }
135         }
136     }
137
138     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
139
140     HeapFree( GetProcessHeap(), 0, p );
141     if (lpDxW) HeapFree( GetProcessHeap(), 0, lpDxW );
142     return ret;
143 }
144
145
146 /***********************************************************************
147  *           ExtTextOutW    (GDI32.@)
148  */
149 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
150                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
151 {
152     BOOL ret = FALSE;
153     DC * dc = DC_GetDCUpdate( hdc );
154     if (dc)
155     {
156         if(PATH_IsPathOpen(dc->path))
157             FIXME("called on an open path\n");
158                 else if(dc->funcs->pExtTextOut)
159                 {
160                         DWORD fontLangInfo=0;
161                         if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) &&
162                            ((fontLangInfo=GetFontLanguageInfo( hdc ))&(GCP_REORDER|GCP_GLYPHSHAPE)) )
163                         {
164                                 /* The caller did not specify that language processing was already done,
165                                  * and the font idetifies iteself as requiring language processing.
166                                  */
167                                 GCP_RESULTSW gcp;
168
169                                 gcp.lStructSize=sizeof(gcp);
170                                 gcp.lpOutString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
171                                 gcp.lpOrder=NULL;
172                                 gcp.lpDx=NULL;
173                                 gcp.lpCaretPos=NULL;
174                                 gcp.lpClass=NULL;
175                                 gcp.lpGlyphs=NULL;
176                                 gcp.nGlyphs=0;
177                                 gcp.nMaxFit=0;
178
179                                 GetCharacterPlacementW(hdc, str, count, 0, &gcp, GCP_REORDER );
180
181                                 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
182                                         lprect,gcp.lpOutString,count,lpDx);
183                                 HeapFree(GetProcessHeap(), 0, gcp.lpOutString);
184                         } else
185                                 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,lpDx);
186                 }
187                 GDI_ReleaseObj( hdc );
188     }
189     return ret;
190 }
191
192
193 /***********************************************************************
194  *           TextOutA    (GDI32.@)
195  */
196 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
197 {
198     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
199 }
200
201
202 /***********************************************************************
203  *           TextOutW    (GDI32.@)
204  */
205 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
206 {
207     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
208 }
209
210
211 /***********************************************************************
212  * GetTextCharset [GDI32.@]  Gets character set for font in DC
213  *
214  * NOTES
215  *    Should it return a UINT32 instead of an INT32?
216  *    => YES, as GetTextCharsetInfo returns UINT32
217  *
218  * RETURNS
219  *    Success: Character set identifier
220  *    Failure: DEFAULT_CHARSET
221  */
222 UINT WINAPI GetTextCharset(
223     HDC hdc) /* [in] Handle to device context */
224 {
225     /* MSDN docs say this is equivalent */
226     return GetTextCharsetInfo(hdc, NULL, 0);
227 }
228
229
230 /***********************************************************************
231  * GetTextCharsetInfo [GDI32.@]  Gets character set for font
232  *
233  * NOTES
234  *    Should csi be an LPFONTSIGNATURE instead of an LPCHARSETINFO?
235  *    Should it return a UINT32 instead of an INT32?
236  *    => YES and YES, from win32.hlp from Borland
237  *
238  *    This returns the actual charset selected by the driver rather than the
239  *    value in lf.lfCharSet during CreateFont, to get that use
240  *    GetObject(GetCurrentObject(...),...)
241  *
242  * RETURNS
243  *    Success: Character set identifier
244  *    Failure: DEFAULT_CHARSET
245  */
246 UINT WINAPI GetTextCharsetInfo(
247     HDC hdc,            /* [in]  Handle to device context */
248     LPFONTSIGNATURE fs, /* [out] Pointer to struct to receive data */
249     DWORD flags)        /* [in]  Reserved - must be 0 */
250 {
251     UINT charSet = DEFAULT_CHARSET;
252     CHARSETINFO csinfo;
253     TEXTMETRICW tm;
254
255     if(!GetTextMetricsW(hdc, &tm)) return DEFAULT_CHARSET;
256     charSet = tm.tmCharSet;
257
258     if (fs != NULL) {
259       if (!TranslateCharsetInfo((LPDWORD)charSet, &csinfo, TCI_SRCCHARSET))
260            return DEFAULT_CHARSET;
261       memcpy(fs, &csinfo.fs, sizeof(FONTSIGNATURE));
262     }
263     return charSet;
264 }
265
266 /***********************************************************************
267  *              PolyTextOutA (GDI32.@)
268  *
269  * Draw several Strings
270  */
271 BOOL WINAPI PolyTextOutA (
272                           HDC hdc,               /* [in] Handle to device context */
273                           PPOLYTEXTA pptxt,      /* [in] Array of strings */
274                           INT cStrings           /* [in] Number of strings in array */
275                           )
276 {
277   FIXME("stub!\n");
278   SetLastError ( ERROR_CALL_NOT_IMPLEMENTED );
279   return 0;
280 }
281
282
283
284 /***********************************************************************
285  *              PolyTextOutW (GDI32.@)
286  *
287  * Draw several Strings
288  */
289 BOOL WINAPI PolyTextOutW (
290                           HDC hdc,               /* [in] Handle to device context */
291                           PPOLYTEXTW pptxt,      /* [in] Array of strings */
292                           INT cStrings           /* [in] Number of strings in array */
293                           )
294 {
295   FIXME("stub!\n");
296   SetLastError ( ERROR_CALL_NOT_IMPLEMENTED );
297   return 0;
298 }