Fix strncpyWtoA to actually act as advertised (and not overflow the
[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 "gdi.h"
31 #include "wine/debug.h"
32 #include "winnls.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(text);
35
36 /***********************************************************************
37  *           FONT_mbtowc
38  *
39  * Returns a '\0' terminated Unicode translation of str using the
40  * charset of the currently selected font in hdc.  If count is -1 then
41  * str is assumed to be '\0' terminated, otherwise it contains the
42  * number of bytes to convert.  If plenW is non-NULL, on return it
43  * will point to the number of WCHARs (excluding the '\0') that have
44  * been written.  If pCP is non-NULL, on return it will point to the
45  * codepage used in the conversion (NB, this may be CP_SYMBOL so watch
46  * out).  The caller should free the returned LPWSTR from the process
47  * heap itself.
48  */
49 LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
50 {
51     UINT cp = CP_ACP;
52     INT lenW, i;
53     LPWSTR strW;
54     CHARSETINFO csi;
55     int charset = GetTextCharset(hdc);
56
57     /* Hmm, nicely designed api this one! */
58     if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
59         cp = csi.ciACP;
60     else {
61         switch(charset) {
62         case OEM_CHARSET:
63             cp = GetOEMCP();
64             break;
65         case DEFAULT_CHARSET:
66             cp = GetACP();
67             break;
68
69         case VISCII_CHARSET:
70         case TCVN_CHARSET:
71         case KOI8_CHARSET:
72         case ISO3_CHARSET:
73         case ISO4_CHARSET:
74         case ISO10_CHARSET:
75         case CELTIC_CHARSET:
76           /* FIXME: These have no place here, but because x11drv
77              enumerates fonts with these (made up) charsets some apps
78              might use them and then the FIXME below would become
79              annoying.  Now we could pick the intended codepage for
80              each of these, but since it's broken anyway we'll just
81              use CP_ACP and hope it'll go away...
82           */
83             cp = CP_ACP;
84             break;
85
86
87         default:
88             FIXME("Can't find codepage for charset %d\n", charset);
89             break;
90         }
91     }
92
93     TRACE("cp == %d\n", cp);
94
95     if(count == -1) count = strlen(str);
96     if(cp != CP_SYMBOL) {
97         lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
98         strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
99         MultiByteToWideChar(cp, 0, str, count, strW, lenW);
100     } else {
101         lenW = count;
102         strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
103         for(i = 0; i < count; i++) strW[i] = (BYTE)str[i];
104     }
105     strW[lenW] = '\0';
106     TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
107     if(plenW) *plenW = lenW;
108     if(pCP) *pCP = cp;
109     return strW;
110 }
111
112
113 /***********************************************************************
114  *           ExtTextOutA    (GDI32.@)
115  */
116 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
117                          const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
118 {
119     INT wlen;
120     UINT codepage;
121     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
122     BOOL ret;
123     LPINT lpDxW = NULL;
124
125     if (lpDx) {
126         unsigned int i = 0, j = 0;
127
128         lpDxW = (LPINT)HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
129         while(i < count) {
130             if(IsDBCSLeadByteEx(codepage, str[i])) {
131                 lpDxW[j++] = lpDx[i] + lpDx[i+1];
132                 i = i + 2;
133             } else {
134                 lpDxW[j++] = lpDx[i];
135                 i = i + 1;
136             }
137         }
138     }
139
140     ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
141
142     HeapFree( GetProcessHeap(), 0, p );
143     if (lpDxW) HeapFree( GetProcessHeap(), 0, lpDxW );
144     return ret;
145 }
146
147
148 /***********************************************************************
149  *           ExtTextOutW    (GDI32.@)
150  */
151 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
152                          const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
153 {
154     BOOL ret = FALSE;
155     DC * dc = DC_GetDCUpdate( hdc );
156     if (dc)
157     {
158         if(PATH_IsPathOpen(dc->path))
159             FIXME("called on an open path\n");
160         else if(dc->funcs->pExtTextOut)
161         {
162             if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail && count>0 )
163             {
164                 /* The caller did not specify that language processing was already done.
165                  */
166                 LPWSTR lpReorderedString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
167
168                 BIDI_Reorder( str, count, GCP_REORDER,
169                               ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
170                               WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
171                               lpReorderedString, count, NULL );
172
173                 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
174                                              lprect,lpReorderedString,count,lpDx);
175                 HeapFree(GetProcessHeap(), 0, lpReorderedString);
176             } else
177                 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,lpDx);
178         }
179         GDI_ReleaseObj( hdc );
180     }
181     return ret;
182 }
183
184
185 /***********************************************************************
186  *           TextOutA    (GDI32.@)
187  */
188 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
189 {
190     return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
191 }
192
193
194 /***********************************************************************
195  *           TextOutW    (GDI32.@)
196  */
197 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
198 {
199     return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
200 }
201
202
203 /***********************************************************************
204  *              PolyTextOutA (GDI32.@)
205  *
206  * Draw several Strings
207  */
208 BOOL WINAPI PolyTextOutA (
209                           HDC hdc,               /* [in] Handle to device context */
210                           PPOLYTEXTA pptxt,      /* [in] Array of strings */
211                           INT cStrings           /* [in] Number of strings in array */
212                           )
213 {
214     for (; cStrings>0; cStrings--, pptxt++)
215         if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
216             return FALSE;
217     return TRUE;
218 }
219
220
221
222 /***********************************************************************
223  *              PolyTextOutW (GDI32.@)
224  *
225  * Draw several Strings
226  */
227 BOOL WINAPI PolyTextOutW (
228                           HDC hdc,               /* [in] Handle to device context */
229                           PPOLYTEXTW pptxt,      /* [in] Array of strings */
230                           INT cStrings           /* [in] Number of strings in array */
231                           )
232 {
233     for (; cStrings>0; cStrings--, pptxt++)
234         if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
235             return FALSE;
236     return TRUE;
237 }