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

Last change on this file since 9737 was 9737, checked in by sandervl, 23 years ago

Fixes for InternalTextOutA without y-inversion (not activated)

File size: 16.1 KB
Line 
1/* $Id: text.cpp,v 1.32 2003-01-28 16:21:49 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//#undef INVERT
76//#define INVERT_SETYINVERSION
77//******************************************************************************
78BOOL InternalTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut)
79{
80 pDCData pHps = (pDCData)OSLibGpiQueryDCData(hdc);
81 ULONG flOptions = 0;
82 RECTLOS2 pmRect;
83 POINTLOS2 ptl;
84 LONG hits;
85
86 if (!pHps || (cbCount < 0) || ((lpszString == NULL) && (cbCount != 0)))
87 {
88 dprintf(("InternalTextOutA: invalid parameter"));
89 SetLastError(ERROR_INVALID_HANDLE);
90 return FALSE;
91 }
92
93 if (cbCount > 512)
94 {
95 dprintf(("InternalTextOutA: invalid parameter cbCount"));
96 SetLastError(ERROR_INVALID_PARAMETER);
97 return FALSE;
98 }
99 if (fuOptions & ~((UINT)(ETO_CLIPPED | ETO_OPAQUE)))
100 {
101 dprintf(("InternalTextOutA: invalid fuOptions"));
102 //ETO_GLYPH_INDEX, ETO_RTLLEADING, ETO_NUMERICSLOCAL, ETO_NUMERICSLATIN, ETO_IGNORELANGUAGE, ETO_PDY are ignored
103 return TRUE;
104 }
105
106#if defined(INVERT) && !defined(INVERT_SETYINVERSION)
107 if(pHps->yInvert > 0) {
108 Y = pHps->yInvert - Y;
109 }
110#endif
111
112#ifdef INVERT_SETYINVERSION
113 int oldyinv = GpiQueryYInversion(pHps->hps);
114 Y = oldyinv - Y;
115#endif
116
117 //CB: add metafile info
118
119 if (lprc)
120 {
121 if (fuOptions)
122 {
123 MapWin32ToOS2Rect(*lprc,pmRect);
124 if (excludeBottomRightPoint(pHps,(PPOINTLOS2)&pmRect) == 0)
125 {
126 dprintf(("InternalTextOutA: excludeBottomRightPoint returned 0"));
127 return TRUE;
128 }
129#ifndef INVERT
130#ifdef INVERT_SETYINVERSION
131 if (oldyinv) {
132 int temp = oldyinv - pmRect.yTop;
133 pmRect.yTop = oldyinv - pmRect.yBottom;
134 pmRect.yBottom = temp;
135 }
136#else
137 if (pHps->yInvert > 0) {
138 int temp = pHps->yInvert - pmRect.yTop;
139 pmRect.yTop = pHps->yInvert - pmRect.yBottom;
140 pmRect.yBottom = temp;
141 }
142#endif
143#endif
144
145 if (fuOptions & ETO_CLIPPED) flOptions |= CHSOS_CLIP;
146 if (fuOptions & ETO_OPAQUE) flOptions |= CHSOS_OPAQUE;
147 }
148 }
149 else
150 {
151 if (fuOptions)
152 {
153 dprintf(("InternalTextOutA: ERROR_INVALID_HANDLE"));
154 SetLastError(ERROR_INVALID_HANDLE);
155 return FALSE;
156 }
157 }
158
159 if (cbCount == 0)
160 {
161 if (fuOptions & ETO_OPAQUE)
162 {
163//SvL: This doesn't seem to work (anymore). Look at MFC apps for the missing border
164// between menu & button bar (all white). (e.g. odin app & acrobat reader 4.05)
165#if 0
166 lpszString = " ";
167 cbCount = 1;
168 flOptions |= CHSOS_CLIP;
169#else
170 HBRUSH hbrush = CreateSolidBrush(GetBkColor(hdc));
171 HBRUSH oldbrush;
172
173 oldbrush = SelectObject(hdc, hbrush);
174 FillRect(hdc, lprc, hbrush);
175 SelectObject(hdc, oldbrush);
176 DeleteObject(hbrush);
177 return TRUE;
178#endif
179 }
180 else {
181 dprintf(("InternalTextOutA: cbCount == 0"));
182 return TRUE;
183 }
184 }
185
186#ifdef INVERT_SETYINVERSION
187 GpiEnableYInversion(pHps->hps, 0);
188#endif
189
190 if (lpDx)
191 flOptions |= CHSOS_VECTOR;
192
193 if (!getAlignUpdateCP(pHps))
194 {
195 ptl.x = X;
196 ptl.y = Y;
197
198 flOptions |= CHSOS_LEAVEPOS;
199 }
200 else OSLibGpiQueryCurrentPosition(pHps,&ptl);
201
202 UINT align = GetTextAlign(hdc);
203 LONG pmHAlign,pmVAlign;
204
205#if 0
206 //SvL: This code is broken. TODO: Investigate
207 //CB: TA_RIGHT not supported by PM, only TA_CENTER and TA_LEFT
208 if ((align & 0x6) == TA_RIGHT)
209 {
210 BOOL rc;
211 PPOINTLOS2 pts = (PPOINTLOS2)malloc((cbCount+1)*sizeof(POINTLOS2));
212
213 rc = OSLibGpiQueryCharStringPosAt(pHps,&ptl,flOptions & CHSOS_VECTOR,cbCount,lpszString,lpDx,pts);
214 if(rc) {
215 for(int i=0;i<cbCount+1;i++) {
216 dprintf(("OSLibGpiQueryCharStringPosAt %d (%d,%d)", pts[i].x, pts[i].y));
217 }
218 ptl.x -= pts[cbCount].x-pts[0].x;
219 }
220 free(pts);
221 }
222#endif
223
224 if (lprc && ((align & 0x18) == TA_BASELINE))
225 {
226 //CB: if TA_BASELINE is set, GPI doesn't fill rect
227 // TA_BOTTOM fills rect
228 OSLibGpiQueryTextAlignment(pHps,&pmHAlign,&pmVAlign);
229 OSLibGpiSetTextAlignment(pHps,pmHAlign,(pmVAlign & ~TAOS_BASE) | TAOS_BOTTOM);
230 }
231
232#ifdef INVERT
233 ptl.y += getWorldYDeltaFor1Pixel(pHps);
234#else
235 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
236
237 int vertAdjust = 0;
238 if ((pHps->taMode & 0x18) != TA_TOP)
239 {
240 vertAdjust = OSLibGpiQueryFontMaxHeight(pHps->hps);
241 }
242 ptl.y -= vertAdjust;
243#endif
244
245 hits = OSLibGpiCharStringPosAt(pHps,&ptl,&pmRect,flOptions,cbCount,lpszString,lpDx);
246
247 if (lprc && ((align & 0x18) == TA_BASELINE))
248 OSLibGpiSetTextAlignment(pHps,pmHAlign,pmVAlign);
249
250 if(hits == GPIOS_ERROR) {
251 dprintf(("InternalTextOutA: OSLibGpiCharStringPosAt returned GPIOS_ERROR"));
252#ifdef INVERT_SETYINVERSION
253 GpiEnableYInversion(pHps->hps, oldyinv);
254#endif
255 return FALSE;
256 }
257
258 if (getAlignUpdateCP(pHps))
259 {
260 OSLibGpiQueryCurrentPosition(pHps,&ptl);
261 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
262#ifndef INVERT
263 ptl.y += vertAdjust;
264#endif
265 OSLibGpiSetCurrentPosition(pHps,&ptl);
266 }
267
268#ifdef INVERT_SETYINVERSION
269 GpiEnableYInversion(pHps->hps, oldyinv);
270#endif
271 return TRUE;
272}
273//******************************************************************************
274//******************************************************************************
275BOOL InternalTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut)
276{
277 char *astring = NULL;
278 BOOL rc;
279
280 if(cbCount == -1) {
281 astring = UnicodeToAsciiString((LPWSTR)lpszString);
282 }
283 else
284 if(cbCount) {
285 astring = (char *)HEAP_malloc(cbCount+1);
286 UnicodeToAsciiN((LPWSTR)lpszString, astring, cbCount+1);
287 astring[cbCount] = 0;
288 }
289 rc = InternalTextOutA(hdc,X,Y,fuOptions,lprc,(LPCSTR)astring,cbCount,lpDx,IsExtTextOut);
290 if(astring) {
291 FreeAsciiString(astring);
292 }
293
294 return(rc);
295}
296//******************************************************************************
297//******************************************************************************
298BOOL WIN32API ExtTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,UINT cbCount,CONST INT *lpDx)
299{
300 if(lprc) {
301 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));
302 }
303 else dprintf(("GDI32: ExtTextOutA %x %s (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
304
305 return InternalTextOutA(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
306}
307//******************************************************************************
308//******************************************************************************
309BOOL WIN32API ExtTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,UINT cbCount,CONST int *lpDx)
310{
311 if(lprc) {
312 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));
313 }
314 else dprintf(("GDI32: ExtTextOutW %x %ls (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
315 return InternalTextOutW(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
316}
317//******************************************************************************
318//******************************************************************************
319BOOL WIN32API TextOutA(HDC hdc,int nXStart,int nYStart,LPCSTR lpszString,int cbString)
320{
321 dprintf(("GDI32: TextOutA %x (%d,%d) %d %.*s", hdc, nXStart, nYStart, cbString, cbString, lpszString));
322 return InternalTextOutA(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
323}
324//******************************************************************************
325//******************************************************************************
326BOOL WIN32API TextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpszString,int cbString)
327{
328 dprintf(("GDI32: TextOutW %x (%d,%d) %d %.*ls", hdc, nXStart, nYStart, cbString, cbString, lpszString));
329 return InternalTextOutW(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
330}
331//******************************************************************************
332//******************************************************************************
333BOOL WIN32API PolyTextOutA(HDC hdc,POLYTEXTA *pptxt,int cStrings)
334{
335 dprintf(("GDI32: PolyTextOutA %x %x %d", hdc, pptxt, cStrings));
336
337 for (INT x = 0;x < cStrings;x++)
338 {
339 BOOL rc;
340
341 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);
342 if (!rc) return FALSE;
343 }
344
345 return TRUE;
346}
347//******************************************************************************
348//******************************************************************************
349BOOL WIN32API PolyTextOutW(HDC hdc,POLYTEXTW *pptxt,int cStrings)
350{
351 dprintf(("GDI32: PolyTextOutW %x %x %d", hdc, pptxt, cStrings));
352
353 for (INT x = 0;x < cStrings;x++)
354 {
355 BOOL rc;
356
357 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);
358 if (!rc) return FALSE;
359 }
360
361 return TRUE;
362}
363//******************************************************************************
364//******************************************************************************
365BOOL WIN32API GetTextExtentPointA(HDC hdc, LPCTSTR lpsz, int cbString,
366 LPSIZE lpsSize)
367{
368#if 1
369 dprintf(("GDI32: GetTextExtentPointA %x %.*s %d", hdc, cbString, lpsz, cbString));
370
371 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
372 {
373 dprintf(("!WARNING!: GDI32: GetTextExtentPointA invalid parameter!"));
374 SetLastError(ERROR_INVALID_PARAMETER);
375 return FALSE;
376 }
377
378 lpsSize->cx = 0;
379 lpsSize->cy = 0;
380
381 // Verified with NT4, SP6
382 if(cbString == 0)
383 {
384 dprintf(("GDI32: GetTextExtentPointW cbString == 0"));
385 SetLastError(ERROR_SUCCESS);
386 return TRUE;
387 }
388
389 //SvL: This works better than the code below. Can been seen clearly
390 // in the Settings dialog box of VirtualPC. Strings are clipped.
391 // (e.g.: Hard Disk 1 -> Hard Disk)
392 BOOL rc = O32_GetTextExtentPoint(hdc, lpsz, cbString, lpsSize);
393 if(rc) {
394 dprintf(("GDI32: GetTextExtentPointA returned (%d,%d)", lpsSize->cx, lpsSize->cy));
395 SetLastError(ERROR_SUCCESS);
396 return TRUE;
397 }
398 return FALSE;
399#else
400 BOOL rc;
401 POINTLOS2 pts[TXTBOXOS_COUNT];
402 POINTLOS2 widthHeight = { 0, 0};
403 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
404
405 dprintf(("GDI32: GetTextExtentPointA %s\n", lpsz));
406 if(pHps == NULL)
407 {
408 SetLastError(ERROR_INVALID_HANDLE);
409 return FALSE;
410 }
411
412 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
413 {
414 SetLastError(ERROR_INVALID_PARAMETER);
415 return FALSE;
416 }
417
418 lpsSize->cx = 0;
419 lpsSize->cy = 0;
420
421 // Verified with NT4, SP6
422 if(cbString == 0)
423 {
424 SetLastError(ERROR_SUCCESS);
425 return TRUE;
426 }
427 if(cbString > 512)
428 {
429 DWORD cbStringNew;
430 SIZE newSize;
431
432 dprintf(("WARNING: string longer than 512 chars; splitting up"));
433 lpsSize->cx = 0;
434 lpsSize->cy = 0;
435 while(cbString) {
436 cbStringNew = min(500, cbString);
437 rc = GetTextExtentPointA(hdc, lpsz, cbStringNew, &newSize);
438 if(rc == FALSE) {
439 return FALSE;
440 }
441 lpsSize->cx += newSize.cx;
442 lpsSize->cy = max(newSize.cy, lpsSize->cy);
443 lpsz += cbStringNew;
444 cbString -= cbStringNew;
445 }
446 return TRUE;
447 }
448
449 rc = OSLibGpiQueryTextBox(pHps, cbString, lpsz, TXTBOXOS_COUNT, pts);
450 if(rc == FALSE)
451 {
452 SetLastError(ERROR_INVALID_PARAMETER); //todo wrong error
453 return FALSE;
454 }
455 calcDimensions(pts, &widthHeight);
456 lpsSize->cx = widthHeight.x;
457 lpsSize->cy = widthHeight.y;
458
459 if(pHps && pHps->isPrinter && pHps->hdc)
460 {//scale for printer dcs
461 LONG alArray[2];
462
463 if (OSLibDevQueryCaps(pHps, OSLIB_CAPS_HORIZONTAL_RESOLUTION, 2, &alArray[0]))
464 lpsSize->cx = lpsSize->cx * alArray[0] / alArray[1];
465 }
466
467 dprintf(("GDI32: GetTextExtentPointA %x %s %d returned %d (%d,%d)", hdc, lpsz, cbString, rc, lpsSize->cx, lpsSize->cy));
468 SetLastError(ERROR_SUCCESS);
469 return TRUE;
470#endif
471}
472//******************************************************************************
473//******************************************************************************
474BOOL WIN32API GetTextExtentPointW(HDC hdc,
475 LPCWSTR lpString,
476 int cbString,
477 PSIZE lpSize)
478{
479 char *astring;
480 BOOL rc;
481
482 if(lpString == NULL || cbString < 0 || lpSize == NULL)
483 {
484 dprintf(("!WARNING!: GDI32: GetTextExtentPointW invalid parameter!"));
485 SetLastError(ERROR_INVALID_PARAMETER);
486 return FALSE;
487 }
488
489 lpSize->cx = 0;
490 lpSize->cy = 0;
491
492 // Verified with NT4, SP6
493 if(cbString == 0)
494 {
495 dprintf(("GDI32: GetTextExtentPointW cbString == 0"));
496 SetLastError(ERROR_SUCCESS);
497 return TRUE;
498 }
499
500 dprintf(("GDI32: GetTextExtentPointW %x %.*ls %d %x", hdc, cbString, lpString, cbString, lpSize));
501
502 astring = (char *)malloc((cbString+1)*sizeof(WCHAR));
503 UnicodeToAsciiN(lpString, astring, cbString+1);
504
505 rc = GetTextExtentPointA(hdc, astring,
506 cbString, lpSize);
507
508 free(astring);
509 return(rc);
510}
511//******************************************************************************
512//******************************************************************************
513BOOL WIN32API GetTextExtentPoint32A( HDC hdc, LPCSTR lpsz, int cbString, PSIZE lpSize)
514{
515 return GetTextExtentPointA(hdc, lpsz, cbString, lpSize);
516}
517//******************************************************************************
518//******************************************************************************
519BOOL WIN32API GetTextExtentPoint32W(HDC hdc, LPCWSTR lpsz, int cbString, PSIZE lpSize)
520{
521 return GetTextExtentPointW(hdc, lpsz, cbString, lpSize);
522}
523//******************************************************************************
524//******************************************************************************
Note: See TracBrowser for help on using the repository browser.