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

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

logging updates

File size: 15.2 KB
Line 
1/* $Id: text.cpp,v 1.30 2002-06-25 07:21:03 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 dprintf(("GDI32: TextOutW %x (%d,%d) %d %.*ls", hdc, nXStart, nYStart, cbString, cbString, lpszString));
292 return InternalTextOutW(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
293}
294//******************************************************************************
295//******************************************************************************
296BOOL WIN32API PolyTextOutA(HDC hdc,POLYTEXTA *pptxt,int cStrings)
297{
298 dprintf(("GDI32: PolyTextOutA %x %x %d", hdc, pptxt, cStrings));
299
300 for (INT x = 0;x < cStrings;x++)
301 {
302 BOOL rc;
303
304 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);
305 if (!rc) return FALSE;
306 }
307
308 return TRUE;
309}
310//******************************************************************************
311//******************************************************************************
312BOOL WIN32API PolyTextOutW(HDC hdc,POLYTEXTW *pptxt,int cStrings)
313{
314 dprintf(("GDI32: PolyTextOutW %x %x %d", hdc, pptxt, cStrings));
315
316 for (INT x = 0;x < cStrings;x++)
317 {
318 BOOL rc;
319
320 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);
321 if (!rc) return FALSE;
322 }
323
324 return TRUE;
325}
326//******************************************************************************
327//******************************************************************************
328BOOL WIN32API GetTextExtentPointA(HDC hdc, LPCTSTR lpsz, int cbString,
329 LPSIZE lpsSize)
330{
331#if 1
332 dprintf(("GDI32: GetTextExtentPointA %x %.*s %d", hdc, cbString, lpsz, cbString));
333
334 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
335 {
336 dprintf(("!WARNING!: GDI32: GetTextExtentPointA invalid parameter!"));
337 SetLastError(ERROR_INVALID_PARAMETER);
338 return FALSE;
339 }
340
341 lpsSize->cx = 0;
342 lpsSize->cy = 0;
343
344 // Verified with NT4, SP6
345 if(cbString == 0)
346 {
347 dprintf(("GDI32: GetTextExtentPointW cbString == 0"));
348 SetLastError(ERROR_SUCCESS);
349 return TRUE;
350 }
351
352 //SvL: This works better than the code below. Can been seen clearly
353 // in the Settings dialog box of VirtualPC. Strings are clipped.
354 // (e.g.: Hard Disk 1 -> Hard Disk)
355 BOOL rc = O32_GetTextExtentPoint(hdc, lpsz, cbString, lpsSize);
356 if(rc) {
357 dprintf(("GDI32: GetTextExtentPointA returned (%d,%d)", lpsSize->cx, lpsSize->cy));
358 SetLastError(ERROR_SUCCESS);
359 return TRUE;
360 }
361 return FALSE;
362#else
363 BOOL rc;
364 POINTLOS2 pts[TXTBOXOS_COUNT];
365 POINTLOS2 widthHeight = { 0, 0};
366 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
367
368 dprintf(("GDI32: GetTextExtentPointA %s\n", lpsz));
369 if(pHps == NULL)
370 {
371 SetLastError(ERROR_INVALID_HANDLE);
372 return FALSE;
373 }
374
375 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
376 {
377 SetLastError(ERROR_INVALID_PARAMETER);
378 return FALSE;
379 }
380
381 lpsSize->cx = 0;
382 lpsSize->cy = 0;
383
384 // Verified with NT4, SP6
385 if(cbString == 0)
386 {
387 SetLastError(ERROR_SUCCESS);
388 return TRUE;
389 }
390 if(cbString > 512)
391 {
392 DWORD cbStringNew;
393 SIZE newSize;
394
395 dprintf(("WARNING: string longer than 512 chars; splitting up"));
396 lpsSize->cx = 0;
397 lpsSize->cy = 0;
398 while(cbString) {
399 cbStringNew = min(500, cbString);
400 rc = GetTextExtentPointA(hdc, lpsz, cbStringNew, &newSize);
401 if(rc == FALSE) {
402 return FALSE;
403 }
404 lpsSize->cx += newSize.cx;
405 lpsSize->cy = max(newSize.cy, lpsSize->cy);
406 lpsz += cbStringNew;
407 cbString -= cbStringNew;
408 }
409 return TRUE;
410 }
411
412 rc = OSLibGpiQueryTextBox(pHps, cbString, lpsz, TXTBOXOS_COUNT, pts);
413 if(rc == FALSE)
414 {
415 SetLastError(ERROR_INVALID_PARAMETER); //todo wrong error
416 return FALSE;
417 }
418 calcDimensions(pts, &widthHeight);
419 lpsSize->cx = widthHeight.x;
420 lpsSize->cy = widthHeight.y;
421
422 if(pHps && pHps->isPrinter && pHps->hdc)
423 {//scale for printer dcs
424 LONG alArray[2];
425
426 if (OSLibDevQueryCaps(pHps, OSLIB_CAPS_HORIZONTAL_RESOLUTION, 2, &alArray[0]))
427 lpsSize->cx = lpsSize->cx * alArray[0] / alArray[1];
428 }
429
430 dprintf(("GDI32: GetTextExtentPointA %x %s %d returned %d (%d,%d)", hdc, lpsz, cbString, rc, lpsSize->cx, lpsSize->cy));
431 SetLastError(ERROR_SUCCESS);
432 return TRUE;
433#endif
434}
435//******************************************************************************
436//******************************************************************************
437BOOL WIN32API GetTextExtentPointW(HDC hdc,
438 LPCWSTR lpString,
439 int cbString,
440 PSIZE lpSize)
441{
442 char *astring;
443 BOOL rc;
444
445 if(lpString == NULL || cbString < 0 || lpSize == NULL)
446 {
447 dprintf(("!WARNING!: GDI32: GetTextExtentPointW invalid parameter!"));
448 SetLastError(ERROR_INVALID_PARAMETER);
449 return FALSE;
450 }
451
452 lpSize->cx = 0;
453 lpSize->cy = 0;
454
455 // Verified with NT4, SP6
456 if(cbString == 0)
457 {
458 dprintf(("GDI32: GetTextExtentPointW cbString == 0"));
459 SetLastError(ERROR_SUCCESS);
460 return TRUE;
461 }
462
463 dprintf(("GDI32: GetTextExtentPointW %x %.*ls %d %x", hdc, cbString, lpString, cbString, lpSize));
464
465 astring = (char *)malloc((cbString+1)*sizeof(WCHAR));
466 UnicodeToAsciiN(lpString, astring, cbString+1);
467
468 rc = GetTextExtentPointA(hdc, astring,
469 cbString, lpSize);
470
471 free(astring);
472 return(rc);
473}
474//******************************************************************************
475//******************************************************************************
476BOOL WIN32API GetTextExtentPoint32A( HDC hdc, LPCSTR lpsz, int cbString, PSIZE lpSize)
477{
478 return GetTextExtentPointA(hdc, lpsz, cbString, lpSize);
479}
480//******************************************************************************
481//******************************************************************************
482BOOL WIN32API GetTextExtentPoint32W(HDC hdc, LPCWSTR lpsz, int cbString, PSIZE lpSize)
483{
484 return GetTextExtentPointW(hdc, lpsz, cbString, lpSize);
485}
486//******************************************************************************
487//******************************************************************************
Note: See TracBrowser for help on using the repository browser.