Moved a bunch of definitions from gdi.h into a new gdi_private.h to
[wine] / objects / text.c
1 /*
2  * text functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  * Copyright 2003 Shachar Shemesh
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdarg.h>
23 #include <string.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "wine/winuser16.h"
29 #include "winerror.h"
30 #include "winnls.h"
31 #include "gdi.h"
32 #include "gdi_private.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(text);
36
37 /***********************************************************************
38  *           FONT_mbtowc
39  *
40  * Returns a '\0' terminated Unicode translation of str using the
41  * charset of the currently selected font in hdc.  If count is -1 then
42  * str is assumed to be '\0' terminated, otherwise it contains the
43  * number of bytes to convert.  If plenW is non-NULL, on return it
44  * will point to the number of WCHARs (excluding the '\0') that have
45  * been written.  If pCP is non-NULL, on return it will point to the
46  * codepage used in the conversion (NB, this may be CP_SYMBOL so watch
47  * out).  The caller should free the returned LPWSTR from the process
48  * heap itself.
49  */
50 LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
51 {
52     UINT cp = CP_ACP;
53     INT lenW, i;
54     LPWSTR strW;
55     CHARSETINFO csi;
56     int charset = GetTextCharset(hdc);
57
58     /* Hmm, nicely designed api this one! */
59     if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
60         cp = csi.ciACP;
61     else {
62         switch(charset) {
63         case OEM_CHARSET:
64             cp = GetOEMCP();
65             break;
66         case DEFAULT_CHARSET:
67             cp = GetACP();
68             break;
69
70         case VISCII_CHARSET:
71         case TCVN_CHARSET:
72         case KOI8_CHARSET:
73         case ISO3_CHARSET:
74         case ISO4_CHARSET:
75         case ISO10_CHARSET:
76         case CELTIC_CHARSET:
77           /* FIXME: These have no place here, but because x11drv
78              enumerates fonts with these (made up) charsets some apps
79              might use them and then the FIXME below would become
80              annoying.  Now we could pick the intended codepage for
81              each of these, but since it's broken anyway we'll just
82              use CP_ACP and hope it'll go away...
83           */
84             cp = CP_ACP;
85             break;
86
87
88         default:
89             FIXME("Can't find codepage for charset %d\n", charset);
90             break;
91         }
92     }
93
94     TRACE("cp == %d\n", cp);
95
96     if(count == -1) count = strlen(str);
97     if(cp != CP_SYMBOL) {
98         lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
99         strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
100         MultiByteToWideChar(cp, 0, str, count, strW, lenW);
101     } else {
102         lenW = count;
103         strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
104         for(i = 0; i < count; i++) strW[i] = (BYTE)str[i];
105     }
106     strW[lenW] = '\0';
107     TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
108     if(plenW) *plenW = lenW;
109     if(pCP) *pCP = cp;
110     return strW;
111 }
112
113
114 /***********************************************************************
115  *           ExtTextOutA    (GDI32.@)
116  */
117 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
118                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
119 {
120     INT wlen;
121     UINT codepage;
122     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
123     BOOL ret;
124     LPINT lpDxW = NULL;
125
126     if (lpDx) {
127         unsigned int i = 0, j = 0;
128
129         lpDxW = (LPINT)HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
130         while(i < count) {
131             if(IsDBCSLeadByteEx(codepage, str[i])) {
132                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
133                 i = i + 2;
134             } else {
135                 lpDxW[j++] = lpDx[i];
136                 i = i + 1;
137             }
138         }
139     }
140
141     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
142
143     HeapFree( GetProcessHeap(), 0, p );
144     if (lpDxW) HeapFree( GetProcessHeap(), 0, lpDxW );
145     return ret;
146 }
147
148
149 /***********************************************************************
150  *           ExtTextOutW    (GDI32.@)
151  */
152 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
153                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
154 {
155     BOOL ret = FALSE;
156     DC * dc = DC_GetDCUpdate( hdc );
157     if (dc)
158     {
159         if(PATH_IsPathOpen(dc->path))
160             FIXME("called on an open path\n");
161         else if(dc->funcs->pExtTextOut)
162         {
163             if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail && count>0 )
164             {
165                 /* The caller did not specify that language processing was already done.
166                  */
167                 LPWSTR lpReorderedString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
168
169                 BIDI_Reorder( str, count, GCP_REORDER,
170                               ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
171                               WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
172                               lpReorderedString, count, NULL );
173
174                 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
175                                              lprect,lpReorderedString,count,lpDx);
176                 HeapFree(GetProcessHeap(), 0, lpReorderedString);
177             } else
178                 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,lpDx);
179         }
180         GDI_ReleaseObj( hdc );
181     }
182     return ret;
183 }
184
185
186 /***********************************************************************
187  *           TextOutA    (GDI32.@)
188  */
189 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
190 {
191     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
192 }
193
194
195 /***********************************************************************
196  *           TextOutW    (GDI32.@)
197  */
198 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
199 {
200     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
201 }
202
203
204 /***********************************************************************
205  *              PolyTextOutA (GDI32.@)
206  *
207  * Draw several Strings
208  */
209 BOOL WINAPI PolyTextOutA (
210                           HDC hdc,               /* [in] Handle to device context */
211                           PPOLYTEXTA pptxt,      /* [in] Array of strings */
212                           INT cStrings           /* [in] Number of strings in array */
213                           )
214 {
215     for (; cStrings>0; cStrings--, pptxt++)
216         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
217             return FALSE;
218     return TRUE;
219 }
220
221
222
223 /***********************************************************************
224  *              PolyTextOutW (GDI32.@)
225  *
226  * Draw several Strings
227  */
228 BOOL WINAPI PolyTextOutW (
229                           HDC hdc,               /* [in] Handle to device context */
230                           PPOLYTEXTW pptxt,      /* [in] Array of strings */
231                           INT cStrings           /* [in] Number of strings in array */
232                           )
233 {
234     for (; cStrings>0; cStrings--, pptxt++)
235         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
236             return FALSE;
237     return TRUE;
238 }