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

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

Removed broken handling of TA_RIGHT in TextOut

File size: 15.4 KB
Line 
1/* $Id: text.cpp,v 1.31 2003-01-04 13:45:10 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#if 0
186 //SvL: This code is broken. TODO: Investigate
187 //CB: TA_RIGHT not supported by PM, only TA_CENTER and TA_LEFT
188 if ((align & 0x6) == TA_RIGHT)
189 {
190 BOOL rc;
191 PPOINTLOS2 pts = (PPOINTLOS2)malloc((cbCount+1)*sizeof(POINTLOS2));
192
193 rc = OSLibGpiQueryCharStringPosAt(pHps,&ptl,flOptions & CHSOS_VECTOR,cbCount,lpszString,lpDx,pts);
194 if(rc) {
195 for(int i=0;i<cbCount+1;i++) {
196 dprintf(("OSLibGpiQueryCharStringPosAt %d (%d,%d)", pts[i].x, pts[i].y));
197 }
198 ptl.x -= pts[cbCount].x-pts[0].x;
199 }
200 free(pts);
201 }
202#endif
203
204 if (lprc && ((align & 0x18) == TA_BASELINE))
205 {
206 //CB: if TA_BASELINE is set, GPI doesn't fill rect
207 // TA_BOTTOM fills rect
208 OSLibGpiQueryTextAlignment(pHps,&pmHAlign,&pmVAlign);
209 OSLibGpiSetTextAlignment(pHps,pmHAlign,(pmVAlign & ~TAOS_BASE) | TAOS_BOTTOM);
210 }
211
212 ptl.y += getWorldYDeltaFor1Pixel(pHps);
213
214#ifndef INVERT
215 int vertAdjust = 0;
216 if ((pHps->taMode & 0x18) == TA_TOP)
217 {
218 vertAdjust = OSLibGpiQueryFontMaxHeight(pHps->hps);
219 }
220 ptl.y -= vertAdjust;
221#endif
222
223 hits = OSLibGpiCharStringPosAt(pHps,&ptl,&pmRect,flOptions,cbCount,lpszString,lpDx);
224
225 if (lprc && ((align & 0x18) == TA_BASELINE))
226 OSLibGpiSetTextAlignment(pHps,pmHAlign,pmVAlign);
227
228 if(hits == GPIOS_ERROR) {
229 dprintf(("InternalTextOutA: OSLibGpiCharStringPosAt returned GPIOS_ERROR"));
230 return FALSE;
231 }
232
233 if (getAlignUpdateCP(pHps))
234 {
235 OSLibGpiQueryCurrentPosition(pHps,&ptl);
236 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
237#ifndef INVERT
238 ptl.y += vertAdjust;
239#endif
240 OSLibGpiSetCurrentPosition(pHps,&ptl);
241 }
242
243 return TRUE;
244}
245//******************************************************************************
246//******************************************************************************
247BOOL InternalTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut)
248{
249 char *astring = NULL;
250 BOOL rc;
251
252 if(cbCount == -1) {
253 astring = UnicodeToAsciiString((LPWSTR)lpszString);
254 }
255 else
256 if(cbCount) {
257 astring = (char *)HEAP_malloc(cbCount+1);
258 UnicodeToAsciiN((LPWSTR)lpszString, astring, cbCount+1);
259 astring[cbCount] = 0;
260 }
261 rc = InternalTextOutA(hdc,X,Y,fuOptions,lprc,(LPCSTR)astring,cbCount,lpDx,IsExtTextOut);
262 if(astring) {
263 FreeAsciiString(astring);
264 }
265
266 return(rc);
267}
268//******************************************************************************
269//******************************************************************************
270BOOL WIN32API ExtTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,UINT cbCount,CONST INT *lpDx)
271{
272 if(lprc) {
273 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));
274 }
275 else dprintf(("GDI32: ExtTextOutA %x %s (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
276
277 return InternalTextOutA(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
278}
279//******************************************************************************
280//******************************************************************************
281BOOL WIN32API ExtTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,UINT cbCount,CONST int *lpDx)
282{
283 if(lprc) {
284 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));
285 }
286 else dprintf(("GDI32: ExtTextOutW %x %ls (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
287 return InternalTextOutW(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
288}
289//******************************************************************************
290//******************************************************************************
291BOOL WIN32API TextOutA(HDC hdc,int nXStart,int nYStart,LPCSTR lpszString,int cbString)
292{
293 dprintf(("GDI32: TextOutA %x (%d,%d) %d %.*s", hdc, nXStart, nYStart, cbString, cbString, lpszString));
294 return InternalTextOutA(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
295}
296//******************************************************************************
297//******************************************************************************
298BOOL WIN32API TextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpszString,int cbString)
299{
300 dprintf(("GDI32: TextOutW %x (%d,%d) %d %.*ls", hdc, nXStart, nYStart, cbString, cbString, lpszString));
301 return InternalTextOutW(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
302}
303//******************************************************************************
304//******************************************************************************
305BOOL WIN32API PolyTextOutA(HDC hdc,POLYTEXTA *pptxt,int cStrings)
306{
307 dprintf(("GDI32: PolyTextOutA %x %x %d", hdc, pptxt, cStrings));
308
309 for (INT x = 0;x < cStrings;x++)
310 {
311 BOOL rc;
312
313 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);
314 if (!rc) return FALSE;
315 }
316
317 return TRUE;
318}
319//******************************************************************************
320//******************************************************************************
321BOOL WIN32API PolyTextOutW(HDC hdc,POLYTEXTW *pptxt,int cStrings)
322{
323 dprintf(("GDI32: PolyTextOutW %x %x %d", hdc, pptxt, cStrings));
324
325 for (INT x = 0;x < cStrings;x++)
326 {
327 BOOL rc;
328
329 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);
330 if (!rc) return FALSE;
331 }
332
333 return TRUE;
334}
335//******************************************************************************
336//******************************************************************************
337BOOL WIN32API GetTextExtentPointA(HDC hdc, LPCTSTR lpsz, int cbString,
338 LPSIZE lpsSize)
339{
340#if 1
341 dprintf(("GDI32: GetTextExtentPointA %x %.*s %d", hdc, cbString, lpsz, cbString));
342
343 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
344 {
345 dprintf(("!WARNING!: GDI32: GetTextExtentPointA invalid parameter!"));
346 SetLastError(ERROR_INVALID_PARAMETER);
347 return FALSE;
348 }
349
350 lpsSize->cx = 0;
351 lpsSize->cy = 0;
352
353 // Verified with NT4, SP6
354 if(cbString == 0)
355 {
356 dprintf(("GDI32: GetTextExtentPointW cbString == 0"));
357 SetLastError(ERROR_SUCCESS);
358 return TRUE;
359 }
360
361 //SvL: This works better than the code below. Can been seen clearly
362 // in the Settings dialog box of VirtualPC. Strings are clipped.
363 // (e.g.: Hard Disk 1 -> Hard Disk)
364 BOOL rc = O32_GetTextExtentPoint(hdc, lpsz, cbString, lpsSize);
365 if(rc) {
366 dprintf(("GDI32: GetTextExtentPointA returned (%d,%d)", lpsSize->cx, lpsSize->cy));
367 SetLastError(ERROR_SUCCESS);
368 return TRUE;
369 }
370 return FALSE;
371#else
372 BOOL rc;
373 POINTLOS2 pts[TXTBOXOS_COUNT];
374 POINTLOS2 widthHeight = { 0, 0};
375 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
376
377 dprintf(("GDI32: GetTextExtentPointA %s\n", lpsz));
378 if(pHps == NULL)
379 {
380 SetLastError(ERROR_INVALID_HANDLE);
381 return FALSE;
382 }
383
384 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
385 {
386 SetLastError(ERROR_INVALID_PARAMETER);
387 return FALSE;
388 }
389
390 lpsSize->cx = 0;
391 lpsSize->cy = 0;
392
393 // Verified with NT4, SP6
394 if(cbString == 0)
395 {
396 SetLastError(ERROR_SUCCESS);
397 return TRUE;
398 }
399 if(cbString > 512)
400 {
401 DWORD cbStringNew;
402 SIZE newSize;
403
404 dprintf(("WARNING: string longer than 512 chars; splitting up"));
405 lpsSize->cx = 0;
406 lpsSize->cy = 0;
407 while(cbString) {
408 cbStringNew = min(500, cbString);
409 rc = GetTextExtentPointA(hdc, lpsz, cbStringNew, &newSize);
410 if(rc == FALSE) {
411 return FALSE;
412 }
413 lpsSize->cx += newSize.cx;
414 lpsSize->cy = max(newSize.cy, lpsSize->cy);
415 lpsz += cbStringNew;
416 cbString -= cbStringNew;
417 }
418 return TRUE;
419 }
420
421 rc = OSLibGpiQueryTextBox(pHps, cbString, lpsz, TXTBOXOS_COUNT, pts);
422 if(rc == FALSE)
423 {
424 SetLastError(ERROR_INVALID_PARAMETER); //todo wrong error
425 return FALSE;
426 }
427 calcDimensions(pts, &widthHeight);
428 lpsSize->cx = widthHeight.x;
429 lpsSize->cy = widthHeight.y;
430
431 if(pHps && pHps->isPrinter && pHps->hdc)
432 {//scale for printer dcs
433 LONG alArray[2];
434
435 if (OSLibDevQueryCaps(pHps, OSLIB_CAPS_HORIZONTAL_RESOLUTION, 2, &alArray[0]))
436 lpsSize->cx = lpsSize->cx * alArray[0] / alArray[1];
437 }
438
439 dprintf(("GDI32: GetTextExtentPointA %x %s %d returned %d (%d,%d)", hdc, lpsz, cbString, rc, lpsSize->cx, lpsSize->cy));
440 SetLastError(ERROR_SUCCESS);
441 return TRUE;
442#endif
443}
444//******************************************************************************
445//******************************************************************************
446BOOL WIN32API GetTextExtentPointW(HDC hdc,
447 LPCWSTR lpString,
448 int cbString,
449 PSIZE lpSize)
450{
451 char *astring;
452 BOOL rc;
453
454 if(lpString == NULL || cbString < 0 || lpSize == NULL)
455 {
456 dprintf(("!WARNING!: GDI32: GetTextExtentPointW invalid parameter!"));
457 SetLastError(ERROR_INVALID_PARAMETER);
458 return FALSE;
459 }
460
461 lpSize->cx = 0;
462 lpSize->cy = 0;
463
464 // Verified with NT4, SP6
465 if(cbString == 0)
466 {
467 dprintf(("GDI32: GetTextExtentPointW cbString == 0"));
468 SetLastError(ERROR_SUCCESS);
469 return TRUE;
470 }
471
472 dprintf(("GDI32: GetTextExtentPointW %x %.*ls %d %x", hdc, cbString, lpString, cbString, lpSize));
473
474 astring = (char *)malloc((cbString+1)*sizeof(WCHAR));
475 UnicodeToAsciiN(lpString, astring, cbString+1);
476
477 rc = GetTextExtentPointA(hdc, astring,
478 cbString, lpSize);
479
480 free(astring);
481 return(rc);
482}
483//******************************************************************************
484//******************************************************************************
485BOOL WIN32API GetTextExtentPoint32A( HDC hdc, LPCSTR lpsz, int cbString, PSIZE lpSize)
486{
487 return GetTextExtentPointA(hdc, lpsz, cbString, lpSize);
488}
489//******************************************************************************
490//******************************************************************************
491BOOL WIN32API GetTextExtentPoint32W(HDC hdc, LPCWSTR lpsz, int cbString, PSIZE lpSize)
492{
493 return GetTextExtentPointW(hdc, lpsz, cbString, lpSize);
494}
495//******************************************************************************
496//******************************************************************************
Note: See TracBrowser for help on using the repository browser.