953d776bacdc21eb2a80888dc4226efe6686e170
[reactos.git] / reactos / win32ss / user / user32 / windows / font.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS user32.dll
21 * FILE: win32ss/user/user32/windows/font.c
22 * PURPOSE: Draw Text
23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
24 * UPDATE HISTORY:
25 * 09-05-2001 CSH Created
26 */
27
28 /* INCLUDES ******************************************************************/
29
30 #include <user32.h>
31
32 #include <wine/debug.h>
33
34 WINE_DEFAULT_DEBUG_CHANNEL(text);
35
36 DWORD WINAPI GdiGetCodePage(HDC hdc);
37
38 INT WINAPI DrawTextExWorker( HDC hdc, LPWSTR str, INT i_count,
39 LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp );
40
41 LONG TEXT_TabbedTextOut( HDC hdc, INT x, INT y, LPCWSTR lpstr,
42 INT count, INT cTabStops, const INT *lpTabPos, INT nTabOrg,
43 BOOL fDisplayText );
44
45 /* FUNCTIONS *****************************************************************/
46
47 /*
48 * @implemented
49 */
50 LONG
51 WINAPI
52 TabbedTextOutA(
53 HDC hDC,
54 int X,
55 int Y,
56 LPCSTR lpString,
57 int nCount,
58 int nTabPositions,
59 CONST INT *lpnTabStopPositions,
60 int nTabOrigin)
61 {
62 LONG ret;
63 DWORD len;
64 LPWSTR strW;
65 UINT cp = GdiGetCodePage( hDC ); // CP_ACP
66
67 len = MultiByteToWideChar(cp, 0, lpString, nCount, NULL, 0);
68 if (!len) return 0;
69 strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
70 if (!strW) return 0;
71 MultiByteToWideChar(cp, 0, lpString, nCount, strW, len);
72 ret = TabbedTextOutW(hDC, X, Y, strW, len, nTabPositions, lpnTabStopPositions, nTabOrigin);
73 HeapFree(GetProcessHeap(), 0, strW);
74 return ret;
75 }
76
77 /*
78 * @implemented
79 */
80 LONG
81 WINAPI
82 TabbedTextOutW(
83 HDC hDC,
84 int X,
85 int Y,
86 LPCWSTR lpString,
87 int nCount,
88 int nTabPositions,
89 CONST INT *lpnTabStopPositions,
90 int nTabOrigin)
91 {
92 return TEXT_TabbedTextOut(hDC, X, Y, lpString, nCount, nTabPositions, lpnTabStopPositions, nTabOrigin, TRUE);
93 }
94
95 /* WINE synced 22-May-2006 */
96 /*
97 * @implemented
98 */
99 DWORD
100 WINAPI
101 GetTabbedTextExtentA(
102 HDC hDC,
103 LPCSTR lpString,
104 int nCount,
105 int nTabPositions,
106 CONST INT *lpnTabStopPositions)
107 {
108 LONG ret;
109 UINT cp = GdiGetCodePage( hDC ); // CP_ACP
110 DWORD len;
111 LPWSTR strW;
112
113 len = MultiByteToWideChar(cp, 0, lpString, nCount, NULL, 0);
114 if (!len) return 0;
115 strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
116 if (!strW) return 0;
117 MultiByteToWideChar(cp, 0, lpString, nCount, strW, len);
118 ret = GetTabbedTextExtentW(hDC, strW, len, nTabPositions, lpnTabStopPositions);
119 HeapFree(GetProcessHeap(), 0, strW);
120 return ret;
121 }
122
123 /*
124 * @implemented
125 */
126 DWORD
127 WINAPI
128 GetTabbedTextExtentW(
129 HDC hDC,
130 LPCWSTR lpString,
131 int nCount,
132 int nTabPositions,
133 CONST INT *lpnTabStopPositions)
134 {
135 return TEXT_TabbedTextOut(hDC, 0, 0, lpString, nCount, nTabPositions, lpnTabStopPositions, 0, FALSE);
136 }
137
138
139 /***********************************************************************
140 * DrawTextExW (USER32.@)
141 *
142 * The documentation on the extra space required for DT_MODIFYSTRING at MSDN
143 * is not quite complete, especially with regard to \0. We will assume that
144 * the returned string could have a length of up to i_count+3 and also have
145 * a trailing \0 (which would be 4 more than a not-null-terminated string but
146 * 3 more than a null-terminated string). If this is not so then increase
147 * the allowance in DrawTextExA.
148 */
149 #define MAX_BUFFER 1024
150 /*
151 * @implemented
152 *
153 * Synced with Wine Staging 1.7.37
154 */
155 INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
156 LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp )
157 {
158 return DrawTextExWorker( hdc, str, i_count, rect, flags, dtp );
159 }
160
161 /***********************************************************************
162 * DrawTextExA (USER32.@)
163 *
164 * If DT_MODIFYSTRING is specified then there must be room for up to
165 * 4 extra characters. We take great care about just how much modified
166 * string we return.
167 *
168 * @implemented
169 *
170 * Synced with Wine Staging 1.7.37
171 */
172 INT WINAPI DrawTextExA( HDC hdc, LPSTR str, INT count,
173 LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp )
174 {
175 WCHAR *wstr;
176 WCHAR *p;
177 INT ret = 0;
178 int i;
179 DWORD wcount;
180 DWORD wmax;
181 DWORD amax;
182 UINT cp;
183
184 if (!count) return 0;
185 if (!str && count > 0) return 0;
186 if( !str || ((count == -1) && !(count = strlen(str))))
187 {
188 int lh;
189 TEXTMETRICA tm;
190
191 if (dtp && dtp->cbSize != sizeof(DRAWTEXTPARAMS))
192 return 0;
193
194 GetTextMetricsA(hdc, &tm);
195 if (flags & DT_EXTERNALLEADING)
196 lh = tm.tmHeight + tm.tmExternalLeading;
197 else
198 lh = tm.tmHeight;
199
200 if( flags & DT_CALCRECT)
201 {
202 rect->right = rect->left;
203 if( flags & DT_SINGLELINE)
204 rect->bottom = rect->top + lh;
205 else
206 rect->bottom = rect->top;
207 }
208 return lh;
209 }
210 cp = GdiGetCodePage( hdc );
211 wcount = MultiByteToWideChar( cp, 0, str, count, NULL, 0 );
212 wmax = wcount;
213 amax = count;
214 if (flags & DT_MODIFYSTRING)
215 {
216 wmax += 4;
217 amax += 4;
218 }
219 wstr = HeapAlloc(GetProcessHeap(), 0, wmax * sizeof(WCHAR));
220 if (wstr)
221 {
222 MultiByteToWideChar( cp, 0, str, count, wstr, wcount );
223 if (flags & DT_MODIFYSTRING)
224 for (i=4, p=wstr+wcount; i--; p++) *p=0xFFFE;
225 /* Initialise the extra characters so that we can see which ones
226 * change. U+FFFE is guaranteed to be not a unicode character and
227 * so will not be generated by DrawTextEx itself.
228 */
229 ret = DrawTextExW( hdc, wstr, wcount, rect, flags, dtp );
230 if (flags & DT_MODIFYSTRING)
231 {
232 /* Unfortunately the returned string may contain multiple \0s
233 * and so we need to measure it ourselves.
234 */
235 for (i=4, p=wstr+wcount; i-- && *p != 0xFFFE; p++) wcount++;
236 WideCharToMultiByte( cp, 0, wstr, wcount, str, amax, NULL, NULL );
237 }
238 HeapFree(GetProcessHeap(), 0, wstr);
239 }
240 return ret;
241 }
242
243 /***********************************************************************
244 * DrawTextW (USER32.@)
245 *
246 * @implemented
247 * Synced with Wine Staging 1.7.37
248 */
249 INT WINAPI DrawTextW( HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags )
250 {
251 DRAWTEXTPARAMS dtp;
252
253 memset (&dtp, 0, sizeof(dtp));
254 dtp.cbSize = sizeof(dtp);
255 if (flags & DT_TABSTOP)
256 {
257 dtp.iTabLength = (flags >> 8) & 0xff;
258 flags &= 0xffff00ff;
259 }
260 return DrawTextExW(hdc, (LPWSTR)str, count, rect, flags, &dtp);
261 }
262
263 /***********************************************************************
264 * DrawTextA (USER32.@)
265 *
266 * @implemented
267 * Synced with Wine Staging 1.7.37
268 */
269 INT WINAPI DrawTextA( HDC hdc, LPCSTR str, INT count, LPRECT rect, UINT flags )
270 {
271 DRAWTEXTPARAMS dtp;
272
273 memset (&dtp, 0, sizeof(dtp));
274 dtp.cbSize = sizeof(dtp);
275 if (flags & DT_TABSTOP)
276 {
277 dtp.iTabLength = (flags >> 8) & 0xff;
278 flags &= 0xffff00ff;
279 }
280 return DrawTextExA( hdc, (LPSTR)str, count, rect, flags, &dtp );
281 }