BSTR of length 0 is allowed.
[wine.git] / objects / text.c
blobb3d863e278a59b9712db3a0a725db6eac378f843
1 /*
2 * text functions
4 * Copyright 1993, 1994 Alexandre Julliard
5 * Copyright 2003 Shachar Shemesh
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.
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.
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
22 #include <stdarg.h>
23 #include <string.h>
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"
35 WINE_DEFAULT_DEBUG_CHANNEL(text);
37 /***********************************************************************
38 * FONT_mbtowc
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.
47 * The caller should free the returned LPWSTR from the process
48 * heap itself.
50 LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
52 UINT cp = CP_ACP;
53 INT lenW;
54 LPWSTR strW;
55 CHARSETINFO csi;
56 int charset = GetTextCharset(hdc);
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;
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...
84 cp = CP_ACP;
85 break;
88 default:
89 FIXME("Can't find codepage for charset %d\n", charset);
90 break;
94 TRACE("cp == %d\n", cp);
96 if(count == -1) count = strlen(str);
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 strW[lenW] = '\0';
101 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
102 if(plenW) *plenW = lenW;
103 if(pCP) *pCP = cp;
104 return strW;
108 /***********************************************************************
109 * ExtTextOutA (GDI32.@)
111 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
112 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
114 INT wlen;
115 UINT codepage;
116 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
117 BOOL ret;
118 LPINT lpDxW = NULL;
120 if (lpDx) {
121 unsigned int i = 0, j = 0;
123 lpDxW = (LPINT)HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
124 while(i < count) {
125 if(IsDBCSLeadByteEx(codepage, str[i])) {
126 lpDxW[j++] = lpDx[i] + lpDx[i+1];
127 i = i + 2;
128 } else {
129 lpDxW[j++] = lpDx[i];
130 i = i + 1;
135 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
137 HeapFree( GetProcessHeap(), 0, p );
138 if (lpDxW) HeapFree( GetProcessHeap(), 0, lpDxW );
139 return ret;
143 /***********************************************************************
144 * ExtTextOutW (GDI32.@)
146 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
147 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
149 BOOL ret = FALSE;
150 DC * dc = DC_GetDCUpdate( hdc );
151 if (dc)
153 if(PATH_IsPathOpen(dc->path))
154 FIXME("called on an open path\n");
155 else if(dc->funcs->pExtTextOut)
157 if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail && count>0 )
159 /* The caller did not specify that language processing was already done.
161 LPWSTR lpReorderedString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
163 BIDI_Reorder( str, count, GCP_REORDER,
164 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
165 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
166 lpReorderedString, count, NULL );
168 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
169 lprect,lpReorderedString,count,lpDx,dc->breakExtra);
170 HeapFree(GetProcessHeap(), 0, lpReorderedString);
171 } else
172 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,
173 lpDx,dc->breakExtra);
175 GDI_ReleaseObj( hdc );
177 return ret;
181 /***********************************************************************
182 * TextOutA (GDI32.@)
184 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
186 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
190 /***********************************************************************
191 * TextOutW (GDI32.@)
193 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
195 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
199 /***********************************************************************
200 * PolyTextOutA (GDI32.@)
202 * Draw several Strings
204 BOOL WINAPI PolyTextOutA (
205 HDC hdc, /* [in] Handle to device context */
206 PPOLYTEXTA pptxt, /* [in] Array of strings */
207 INT cStrings /* [in] Number of strings in array */
210 for (; cStrings>0; cStrings--, pptxt++)
211 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
212 return FALSE;
213 return TRUE;
218 /***********************************************************************
219 * PolyTextOutW (GDI32.@)
221 * Draw several Strings
223 BOOL WINAPI PolyTextOutW (
224 HDC hdc, /* [in] Handle to device context */
225 PPOLYTEXTW pptxt, /* [in] Array of strings */
226 INT cStrings /* [in] Number of strings in array */
229 for (; cStrings>0; cStrings--, pptxt++)
230 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
231 return FALSE;
232 return TRUE;