source: trunk/src/gdi32/text.cpp@ 8706

Last change on this file since 8706 was 7721, checked in by sandervl, 24 years ago

better logging for some functions

File size: 15.4 KB
Line 
1/* $Id: text.cpp,v 1.29 2002-01-02 18:36:01 sandervl Exp $ */
2
3/*
4 * GDI32 text apis
5 *
6 * Based on Wine code (991031) (objects\text.c)
7 *
8 * Copyright 1993, 1994 Alexandre Julliard
9 * Copyright 1999-2000 Christoph Bratschi
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14#include <os2win.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <misc.h>
18#include <string.h>
19#include <float.h>
20#include "oslibgpi.h"
21#include <dcdata.h>
22#include <unicode.h>
23
24#define DBG_LOCALLOG DBG_text
25#include "dbglocal.h"
26
27#define ELLIPSIS "..."
28#define ELLIPSISLEN 3
29
30//******************************************************************************
31//******************************************************************************
32UINT WINAPI GetTextCharsetInfo(
33 HDC hdc, /* [in] Handle to device context */
34 LPFONTSIGNATURE fs, /* [out] Pointer to struct to receive data */
35 DWORD flags) /* [in] Reserved - must be 0 */
36{
37 HGDIOBJ hFont;
38 UINT charSet = DEFAULT_CHARSET;
39 LOGFONTW lf;
40 CHARSETINFO csinfo;
41
42 dprintf(("GetTextCharsetInfo %x %x %x", hdc, fs, flags));
43
44 hFont = GetCurrentObject(hdc, OBJ_FONT);
45 if (hFont == 0)
46 return(DEFAULT_CHARSET);
47 if ( GetObjectW(hFont, sizeof(LOGFONTW), &lf) != 0 )
48 charSet = lf.lfCharSet;
49
50 if (fs != NULL) {
51 if (!TranslateCharsetInfo((LPDWORD)charSet, &csinfo, TCI_SRCCHARSET))
52 return (DEFAULT_CHARSET);
53 memcpy(fs, &csinfo.fs, sizeof(FONTSIGNATURE));
54 }
55 return charSet;
56}
57/***********************************************************************
58 * GetTextCharset32 [GDI32.226] Gets character set for font in DC
59 *
60 * NOTES
61 * Should it return a UINT32 instead of an INT32?
62 * => YES, as GetTextCharsetInfo returns UINT32
63 *
64 * RETURNS
65 * Success: Character set identifier
66 * Failure: DEFAULT_CHARSET
67 */
68UINT WINAPI GetTextCharset(HDC hdc) /* [in] Handle to device context */
69{
70 /* MSDN docs say this is equivalent */
71 return GetTextCharsetInfo(hdc, NULL, 0);
72}
73//******************************************************************************
74// todo: metafile support
75//******************************************************************************
76BOOL InternalTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut)
77{
78 pDCData pHps = (pDCData)OSLibGpiQueryDCData(hdc);
79 ULONG flOptions = 0;
80 RECTLOS2 pmRect;
81 POINTLOS2 ptl;
82 LONG hits;
83
84 if (!pHps || (cbCount < 0) || ((lpszString == NULL) && (cbCount != 0)))
85 {
86 dprintf(("InternalTextOutA: invalid parameter"));
87 SetLastError(ERROR_INVALID_HANDLE);
88 return FALSE;
89 }
90
91 if (cbCount > 512)
92 {
93 dprintf(("InternalTextOutA: invalid parameter cbCount"));
94 SetLastError(ERROR_INVALID_PARAMETER);
95 return FALSE;
96 }
97 if (fuOptions & ~((UINT)(ETO_CLIPPED | ETO_OPAQUE)))
98 {
99 dprintf(("InternalTextOutA: invalid fuOptions"));
100 //ETO_GLYPH_INDEX, ETO_RTLLEADING, ETO_NUMERICSLOCAL, ETO_NUMERICSLATIN, ETO_IGNORELANGUAGE, ETO_PDY are ignored
101 return TRUE;
102 }
103
104 //CB: add metafile info
105
106 if (lprc)
107 {
108 if (fuOptions)
109 {
110 MapWin32ToOS2Rect(*lprc,pmRect);
111 if (excludeBottomRightPoint(pHps,(PPOINTLOS2)&pmRect) == 0)
112 {
113 dprintf(("InternalTextOutA: excludeBottomRightPoint returned 0"));
114 return TRUE;
115 }
116#ifndef INVERT
117 if (pHps->yInvert > 0) {
118 int temp = pHps->yInvert - pmRect.yTop;
119 pmRect.yTop = pHps->yInvert - pmRect.yBottom;
120 pmRect.yBottom = temp;
121 }
122#endif
123
124 if (fuOptions & ETO_CLIPPED) flOptions |= CHSOS_CLIP;
125 if (fuOptions & ETO_OPAQUE) flOptions |= CHSOS_OPAQUE;
126 }
127 }
128 else
129 {
130 if (fuOptions)
131 {
132 dprintf(("InternalTextOutA: ERROR_INVALID_HANDLE"));
133 SetLastError(ERROR_INVALID_HANDLE);
134 return FALSE;
135 }
136 }
137
138 if (cbCount == 0)
139 {
140 if (fuOptions & ETO_OPAQUE)
141 {
142//SvL: This doesn't seem to work (anymore). Look at MFC apps for the missing border
143// between menu & button bar (all white). (e.g. odin app & acrobat reader 4.05)
144#if 0
145 lpszString = " ";
146 cbCount = 1;
147 flOptions |= CHSOS_CLIP;
148#else
149 HBRUSH hbrush = CreateSolidBrush(GetBkColor(hdc));
150 HBRUSH oldbrush;
151
152 oldbrush = SelectObject(hdc, hbrush);
153 FillRect(hdc, lprc, hbrush);
154 SelectObject(hdc, oldbrush);
155 DeleteObject(hbrush);
156 return TRUE;
157#endif
158 }
159 else {
160 dprintf(("InternalTextOutA: cbCount == 0"));
161 return TRUE;
162 }
163 }
164 if (lpDx)
165 flOptions |= CHSOS_VECTOR;
166
167 if (!getAlignUpdateCP(pHps))
168 {
169 ptl.x = X;
170 ptl.y = Y;
171
172#ifndef INVERT
173 if (pHps->yInvert > 0) {
174 ptl.y = pHps->yInvert - Y;
175 }
176#endif
177
178 flOptions |= CHSOS_LEAVEPOS;
179 }
180 else OSLibGpiQueryCurrentPosition(pHps,&ptl);
181
182 UINT align = GetTextAlign(hdc);
183 LONG pmHAlign,pmVAlign;
184
185 //CB: TA_RIGHT not supported by PM, only TA_CENTER and TA_LEFT
186 if ((align & 0x6) == TA_RIGHT)
187 {
188 PPOINTLOS2 pts = (PPOINTLOS2)malloc((cbCount+1)*sizeof(POINTLOS2));
189
190 OSLibGpiQueryCharStringPosAt(pHps,&ptl,flOptions,cbCount,lpszString,lpDx,pts);
191 ptl.x -= pts[cbCount].x-pts[0].x;
192 free(pts);
193 }
194
195 if (lprc && ((align & 0x18) == TA_BASELINE))
196 {
197 //CB: if TA_BASELINE is set, GPI doesn't fill rect
198 // TA_BOTTOM fills rect
199 OSLibGpiQueryTextAlignment(pHps,&pmHAlign,&pmVAlign);
200 OSLibGpiSetTextAlignment(pHps,pmHAlign,(pmVAlign & ~TAOS_BASE) | TAOS_BOTTOM);
201 }
202
203 ptl.y += getWorldYDeltaFor1Pixel(pHps);
204
205#ifndef INVERT
206 int vertAdjust = 0;
207 if ((pHps->taMode & 0x18) == TA_TOP)
208 {
209 vertAdjust = OSLibGpiQueryFontMaxHeight(pHps->hps);
210 }
211 ptl.y -= vertAdjust;
212#endif
213
214 hits = OSLibGpiCharStringPosAt(pHps,&ptl,&pmRect,flOptions,cbCount,lpszString,lpDx);
215
216 if (lprc && ((align & 0x18) == TA_BASELINE))
217 OSLibGpiSetTextAlignment(pHps,pmHAlign,pmVAlign);
218
219 if(hits == GPIOS_ERROR) {
220 dprintf(("InternalTextOutA: OSLibGpiCharStringPosAt returned GPIOS_ERROR"));
221 return FALSE;
222 }
223
224 if (getAlignUpdateCP(pHps))
225 {
226 OSLibGpiQueryCurrentPosition(pHps,&ptl);
227 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
228#ifndef INVERT
229 ptl.y += vertAdjust;
230#endif
231 OSLibGpiSetCurrentPosition(pHps,&ptl);
232 }
233
234 return TRUE;
235}
236//******************************************************************************
237//******************************************************************************
238BOOL InternalTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut)
239{
240 char *astring = NULL;
241 BOOL rc;
242
243 if(cbCount == -1) {
244 astring = UnicodeToAsciiString((LPWSTR)lpszString);
245 }
246 else
247 if(cbCount) {
248 astring = (char *)HEAP_malloc(cbCount+1);
249 UnicodeToAsciiN((LPWSTR)lpszString, astring, cbCount+1);
250 astring[cbCount] = 0;
251 }
252 rc = InternalTextOutA(hdc,X,Y,fuOptions,lprc,(LPCSTR)astring,cbCount,lpDx,IsExtTextOut);
253 if(astring) {
254 FreeAsciiString(astring);
255 }
256
257 return(rc);
258}
259//******************************************************************************
260//******************************************************************************
261BOOL WIN32API ExtTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,UINT cbCount,CONST INT *lpDx)
262{
263 if(lprc) {
264 dprintf(("GDI32: ExtTextOutA %x %s (%d,%d) %x %d %x rect (%d,%d)(%d,%d)", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx, lprc->left, lprc->top, lprc->right, lprc->bottom));
265 }
266 else dprintf(("GDI32: ExtTextOutA %x %s (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
267
268 return InternalTextOutA(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
269}
270//******************************************************************************
271//******************************************************************************
272BOOL WIN32API ExtTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,UINT cbCount,CONST int *lpDx)
273{
274 if(lprc) {
275 dprintf(("GDI32: ExtTextOutW %x %ls (%d,%d) %x %d %x rect (%d,%d)(%d,%d)", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx, lprc->left, lprc->top, lprc->right, lprc->bottom));
276 }
277 else dprintf(("GDI32: ExtTextOutW %x %ls (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
278 return InternalTextOutW(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
279}
280//******************************************************************************
281//******************************************************************************
282BOOL WIN32API TextOutA(HDC hdc,int nXStart,int nYStart,LPCSTR lpszString,int cbString)
283{
284 dprintf(("GDI32: TextOutA %x (%d,%d) %d %*s", hdc, nXStart, nYStart, cbString, cbString, lpszString));
285 return InternalTextOutA(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
286}
287//******************************************************************************
288//******************************************************************************
289BOOL WIN32API TextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpszString,int cbString)
290{
291#ifdef DEBUG
292 //runtime lib ignores width specifier and also prints string until terminator is found
293 LPWSTR buggyrtl = (LPWSTR)malloc((cbString+1)*2);
294 memcpy(buggyrtl, lpszString, cbString*2);
295 buggyrtl[cbString] = 0;
296 dprintf(("GDI32: TextOutW %x (%d,%d) %d %ls", hdc, nXStart, nYStart, cbString, buggyrtl));
297 free(buggyrtl);
298#endif
299 return InternalTextOutW(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
300}
301//******************************************************************************
302//******************************************************************************
303BOOL WIN32API PolyTextOutA(HDC hdc,POLYTEXTA *pptxt,int cStrings)
304{
305 dprintf(("GDI32: PolyTextOutA %x %x %d", hdc, pptxt, cStrings));
306
307 for (INT x = 0;x < cStrings;x++)
308 {
309 BOOL rc;
310
311 rc = InternalTextOutA(hdc,pptxt[x].x,pptxt[x].y,pptxt[x].uiFlags,&pptxt[x].rcl,pptxt[x].lpstr,pptxt[x].n,pptxt[x].pdx,TRUE);
312 if (!rc) return FALSE;
313 }
314
315 return TRUE;
316}
317//******************************************************************************
318//******************************************************************************
319BOOL WIN32API PolyTextOutW(HDC hdc,POLYTEXTW *pptxt,int cStrings)
320{
321 dprintf(("GDI32: PolyTextOutW %x %x %d", hdc, pptxt, cStrings));
322
323 for (INT x = 0;x < cStrings;x++)
324 {
325 BOOL rc;
326
327 rc = InternalTextOutW(hdc,pptxt[x].x,pptxt[x].y,pptxt[x].uiFlags,&pptxt[x].rcl,pptxt[x].lpstr,pptxt[x].n,pptxt[x].pdx,TRUE);
328 if (!rc) return FALSE;
329 }
330
331 return TRUE;
332}
333//******************************************************************************
334//******************************************************************************
335BOOL WIN32API GetTextExtentPointA(HDC hdc, LPCTSTR lpsz, int cbString,
336 LPSIZE lpsSize)
337{
338#if 1
339 dprintf(("GDI32: GetTextExtentPointA %x %*s %d", hdc, cbString, lpsz, cbString));
340
341 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
342 {
343 dprintf(("!WARNING!: GDI32: GetTextExtentPointA invalid parameter!"));
344 SetLastError(ERROR_INVALID_PARAMETER);
345 return FALSE;
346 }
347
348 lpsSize->cx = 0;
349 lpsSize->cy = 0;
350
351 // Verified with NT4, SP6
352 if(cbString == 0)
353 {
354 dprintf(("GDI32: GetTextExtentPointW cbString == 0"));
355 SetLastError(ERROR_SUCCESS);
356 return TRUE;
357 }
358
359 //SvL: This works better than the code below. Can been seen clearly
360 // in the Settings dialog box of VirtualPC. Strings are clipped.
361 // (e.g.: Hard Disk 1 -> Hard Disk)
362 BOOL rc = O32_GetTextExtentPoint(hdc, lpsz, cbString, lpsSize);
363 if(rc) {
364 dprintf(("GDI32: GetTextExtentPointA returned (%d,%d)", lpsSize->cx, lpsSize->cy));
365 SetLastError(ERROR_SUCCESS);
366 return TRUE;
367 }
368 return FALSE;
369#else
370 BOOL rc;
371 POINTLOS2 pts[TXTBOXOS_COUNT];
372 POINTLOS2 widthHeight = { 0, 0};
373 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
374
375 dprintf(("GDI32: GetTextExtentPointA %s\n", lpsz));
376 if(pHps == NULL)
377 {
378 SetLastError(ERROR_INVALID_HANDLE);
379 return FALSE;
380 }
381
382 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
383 {
384 SetLastError(ERROR_INVALID_PARAMETER);
385 return FALSE;
386 }
387
388 lpsSize->cx = 0;
389 lpsSize->cy = 0;
390
391 // Verified with NT4, SP6
392 if(cbString == 0)
393 {
394 SetLastError(ERROR_SUCCESS);
395 return TRUE;
396 }
397 if(cbString > 512)
398 {
399 DWORD cbStringNew;
400 SIZE newSize;
401
402 dprintf(("WARNING: string longer than 512 chars; splitting up"));
403 lpsSize->cx = 0;
404 lpsSize->cy = 0;
405 while(cbString) {
406 cbStringNew = min(500, cbString);
407 rc = GetTextExtentPointA(hdc, lpsz, cbStringNew, &newSize);
408 if(rc == FALSE) {
409 return FALSE;
410 }
411 lpsSize->cx += newSize.cx;
412 lpsSize->cy = max(newSize.cy, lpsSize->cy);
413 lpsz += cbStringNew;
414 cbString -= cbStringNew;
415 }
416 return TRUE;
417 }
418
419 rc = OSLibGpiQueryTextBox(pHps, cbString, lpsz, TXTBOXOS_COUNT, pts);
420 if(rc == FALSE)
421 {
422 SetLastError(ERROR_INVALID_PARAMETER); //todo wrong error
423 return FALSE;
424 }
425 calcDimensions(pts, &widthHeight);
426 lpsSize->cx = widthHeight.x;
427 lpsSize->cy = widthHeight.y;
428
429 if(pHps && pHps->isPrinter && pHps->hdc)
430 {//scale for printer dcs
431 LONG alArray[2];
432
433 if (OSLibDevQueryCaps(pHps, OSLIB_CAPS_HORIZONTAL_RESOLUTION, 2, &alArray[0]))
434 lpsSize->cx = lpsSize->cx * alArray[0] / alArray[1];
435 }
436
437 dprintf(("GDI32: GetTextExtentPointA %x %s %d returned %d (%d,%d)", hdc, lpsz, cbString, rc, lpsSize->cx, lpsSize->cy));
438 SetLastError(ERROR_SUCCESS);
439 return TRUE;
440#endif
441}
442//******************************************************************************
443//******************************************************************************
444BOOL WIN32API GetTextExtentPointW(HDC hdc,
445 LPCWSTR lpString,
446 int cbString,
447 PSIZE lpSize)
448{
449 char *astring;
450 BOOL rc;
451
452 if(lpString == NULL || cbString < 0 || lpSize == NULL)
453 {
454 dprintf(("!WARNING!: GDI32: GetTextExtentPointW invalid parameter!"));
455 SetLastError(ERROR_INVALID_PARAMETER);
456 return FALSE;
457 }
458
459 lpSize->cx = 0;
460 lpSize->cy = 0;
461
462 // Verified with NT4, SP6
463 if(cbString == 0)
464 {
465 dprintf(("GDI32: GetTextExtentPointW cbString == 0"));
466 SetLastError(ERROR_SUCCESS);
467 return TRUE;
468 }
469
470 dprintf(("GDI32: GetTextExtentPointW %x %x %d %x", hdc, lpString, cbString, lpSize));
471
472 astring = (char *)malloc((cbString+1)*sizeof(WCHAR));
473 UnicodeToAsciiN(lpString, astring, cbString+1);
474
475 rc = GetTextExtentPointA(hdc, astring,
476 cbString, lpSize);
477
478 free(astring);
479 return(rc);
480}
481//******************************************************************************
482//******************************************************************************
483BOOL WIN32API GetTextExtentPoint32A( HDC hdc, LPCSTR lpsz, int cbString, PSIZE lpSize)
484{
485 return GetTextExtentPointA(hdc, lpsz, cbString, lpSize);
486}
487//******************************************************************************
488//******************************************************************************
489BOOL WIN32API GetTextExtentPoint32W(HDC hdc, LPCWSTR lpsz, int cbString, PSIZE lpSize)
490{
491 return GetTextExtentPointW(hdc, lpsz, cbString, lpSize);
492}
493//******************************************************************************
494//******************************************************************************
Note: See TracBrowser for help on using the repository browser.