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

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

ExtTextOutA fix

File size: 29.9 KB
Line 
1/* $Id: text.cpp,v 1.24 2001-06-01 19:59:00 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 <misc.h>
17#include <string.h>
18#include <float.h>
19#include "oslibgpi.h"
20#include <dcdata.h>
21#include <unicode.h>
22
23#define DBG_LOCALLOG DBG_text
24#include "dbglocal.h"
25
26#define ELLIPSIS "..."
27#define ELLIPSISLEN 3
28
29typedef struct _POLYTEXTA
30{
31 int x;
32 int y;
33 UINT n;
34 LPCSTR lpstr;
35 UINT uiFlags;
36 RECT rcl;
37 int *pdx;
38} POLYTEXTA;
39
40typedef struct _POLYTEXTW
41{
42 int x;
43 int y;
44 UINT n;
45 LPCWSTR lpstr;
46 UINT uiFlags;
47 RECT rcl;
48 int *pdx;
49} POLYTEXTW;
50
51//******************************************************************************
52//******************************************************************************
53UINT WINAPI GetTextCharsetInfo(
54 HDC hdc, /* [in] Handle to device context */
55 LPFONTSIGNATURE fs, /* [out] Pointer to struct to receive data */
56 DWORD flags) /* [in] Reserved - must be 0 */
57{
58 HGDIOBJ hFont;
59 UINT charSet = DEFAULT_CHARSET;
60 LOGFONTW lf;
61 CHARSETINFO csinfo;
62
63 dprintf(("GetTextCharsetInfo %x %x %x", hdc, fs, flags));
64
65 hFont = GetCurrentObject(hdc, OBJ_FONT);
66 if (hFont == 0)
67 return(DEFAULT_CHARSET);
68 if ( GetObjectW(hFont, sizeof(LOGFONTW), &lf) != 0 )
69 charSet = lf.lfCharSet;
70
71 if (fs != NULL) {
72 if (!TranslateCharsetInfo((LPDWORD)charSet, &csinfo, TCI_SRCCHARSET))
73 return (DEFAULT_CHARSET);
74 memcpy(fs, &csinfo.fs, sizeof(FONTSIGNATURE));
75 }
76 return charSet;
77}
78/***********************************************************************
79 * GetTextCharset32 [GDI32.226] Gets character set for font in DC
80 *
81 * NOTES
82 * Should it return a UINT32 instead of an INT32?
83 * => YES, as GetTextCharsetInfo returns UINT32
84 *
85 * RETURNS
86 * Success: Character set identifier
87 * Failure: DEFAULT_CHARSET
88 */
89UINT WINAPI GetTextCharset(HDC hdc) /* [in] Handle to device context */
90{
91 /* MSDN docs say this is equivalent */
92 return GetTextCharsetInfo(hdc, NULL, 0);
93}
94//******************************************************************************
95// CB: USER32 function, but here is the better place
96//******************************************************************************
97INT SYSTEM EXPORT InternalDrawTextExA(HDC hdc,LPCSTR lpchText,INT cchText,LPRECT lprc,UINT dwDTFormat,LPDRAWTEXTPARAMS lpDTParams,BOOL isDrawTextEx)
98{
99 INT rc;
100 ULONG flCmd;
101 RECT localRectangle;
102 PRECT rectPtr;
103 LONG lTabs,xLeft,yTop;
104 UINT fpuctrlword;
105
106 //SvL: Open32's DrawText messes up the fpu control word! (@#$@#$@#$)
107 //CB: don't know if this is still the case with WinDrawTabbedText (-> testcase)
108 fpuctrlword = _control87(0, 0);
109
110 if ((!lpchText) || (cchText == 0) || (cchText < -1) || (lprc == NULL))
111 {
112 SetLastError(ERROR_INVALID_PARAMETER);
113 return 0;
114 }
115
116 pDCData pHps = (pDCData)OSLibGpiQueryDCData(hdc);
117
118 if (!pHps)
119 {
120 SetLastError(ERROR_INVALID_HANDLE);
121 return 0;
122 }
123
124 if (cchText == -1)
125 {
126 cchText = strlen(lpchText);
127 if (cchText == 0)
128 return 0; //CB: does Win32 return textheight in this case?
129 }
130
131 if (lpDTParams)
132 {
133 // set margins
134 lprc->left += lpDTParams->iLeftMargin;
135 lprc->right -= lpDTParams->iRightMargin;
136
137 // just assume all the text has been drawn
138 lpDTParams->uiLengthDrawn = cchText;
139 }
140
141 if (!(dwDTFormat & DT_CALCRECT))
142 {
143 BOOL bTopBottomIsOkay;
144
145 if ((getIsTopTop(pHps) && lprc->top > lprc->bottom) ||
146 (!getIsTopTop(pHps) && lprc->top < lprc->bottom))
147 bTopBottomIsOkay = FALSE;
148 else
149 bTopBottomIsOkay = TRUE;
150
151 if ((lprc->left >= lprc->right) || !bTopBottomIsOkay)
152 {
153 TEXTMETRICA txtMetrics;
154 BOOL result;
155
156 result = GetTextMetricsA(hdc,&txtMetrics);
157 if (result)
158 rc = (int)txtMetrics.tmHeight;
159 else
160 rc = 0;
161
162 if (lpDTParams)
163 {
164 lprc->left -= lpDTParams->iLeftMargin;
165 lprc->right += lpDTParams->iRightMargin;
166 }
167
168 return rc;
169 }
170 }
171#ifdef INVERT
172 flCmd = DTOS_INVERT | DTOS_WORLDRECT | DTOS_TEXTATTRS | DTOS_AMPERSAND | DTOS_VERTICALEXTENT;
173#else
174 flCmd = DTOS_WORLDRECT | DTOS_TEXTATTRS | DTOS_AMPERSAND | DTOS_VERTICALEXTENT;
175#endif
176
177 LONG lMixMode = OSLibGpiQueryBackMix(pHps);
178 if (lMixMode == BMOS_OVERPAINT) flCmd |= DTOS_OPAQUE;
179
180 if (dwDTFormat & DT_CALCRECT)
181 {
182 rectPtr = lprc;
183 flCmd |= DTOS_QUERYEXTENT;
184
185 xLeft = rectPtr->left;
186 yTop = rectPtr->top;
187
188 if (dwDTFormat & DT_RIGHT)
189 {
190 if (rectPtr->left >= rectPtr->right)
191 rectPtr->left = rectPtr->right-1;
192 } else
193 {
194 if (rectPtr->right <= rectPtr->left)
195 rectPtr->right = rectPtr->left+1;
196 }
197
198 if (dwDTFormat & DT_BOTTOM)
199 {
200 if (rectPtr->top >= rectPtr->bottom)
201 rectPtr->top = rectPtr->bottom-1;
202 } else
203 {
204 if (rectPtr->bottom <= rectPtr->top)
205 rectPtr->bottom = rectPtr->top+1;
206 }
207 } else
208 {
209 rectPtr = &localRectangle;
210
211 if ((getMapMode(pHps) == MMOS_ANISOTROPIC) || (getMapMode(pHps) == MMOS_ISOTROPIC))
212 {
213 if (doesYAxisGrowNorth(pHps))
214 {
215 flCmd &= ~DTOS_INVERT;
216 flCmd |= DTOS_INVERTCHAR;
217 }
218 }
219
220 if (lprc->left > lprc->right)
221 {
222 rectPtr->left = lprc->right;
223 rectPtr->right = lprc->left;
224 } else
225 {
226 rectPtr->left = lprc->left;
227 rectPtr->right = lprc->right;
228 }
229 if (lprc->top > lprc->bottom)
230 {
231 rectPtr->top = lprc->bottom;
232 rectPtr->bottom = lprc->top;
233 } else
234 {
235 rectPtr->top = lprc->top;
236 rectPtr->bottom = lprc->bottom;
237 }
238
239#ifndef INVERT
240 if (pHps->yInvert > 0) {
241 int temp = pHps->yInvert - rectPtr->bottom;
242 rectPtr->bottom = pHps->yInvert - rectPtr->top;
243 rectPtr->top = temp;
244 }
245#endif
246 }
247
248#ifndef INVERT
249//// dwDTFormat &= ~DT_INVERT;
250//// dwDTFormat |= DT_INVERTCHAR;
251 int top = rectPtr->top;
252#endif
253
254 if (dwDTFormat & DT_EXPANDTABS)
255 {
256 if (isDrawTextEx)
257 {
258 lTabs = (lpDTParams && (dwDTFormat & DT_TABSTOP)) ? lpDTParams->iTabLength:8;
259 } else
260 {
261 lTabs = 8;
262
263 if (dwDTFormat & DT_TABSTOP)
264 {
265 lTabs = (dwDTFormat >> 8) & 0x000000FF;
266 dwDTFormat &= 0xFFFF00FF;
267 }
268 }
269 } else lTabs = -1;
270
271 if (dwDTFormat & DT_RIGHT)
272 flCmd |= DTOS_RIGHT;
273 else
274 if (dwDTFormat & DT_CENTER) flCmd |= DTOS_CENTER;
275 if (dwDTFormat & DT_BOTTOM) flCmd |= DTOS_BOTTOM;
276 if (dwDTFormat & DT_VCENTER) flCmd |= DTOS_VCENTER;
277 if (dwDTFormat & DT_WORDBREAK) flCmd |= DTOS_WORDBREAK;
278 if (dwDTFormat & DT_EXTERNALLEADING) flCmd |= DTOS_EXTERNALLEADING;
279 if (!(dwDTFormat & DT_NOPREFIX)) flCmd |= DTOS_MNEMONIC;
280 if (dwDTFormat & DT_SINGLELINE)
281 flCmd |= DTOS_SINGLELINE;
282 else
283 flCmd |= DTOS_MULTILINE;
284 if (dwDTFormat & DT_NOCLIP) flCmd |= DTOS_NOCLIP;
285
286 //CB: DT_EDITCONTROL, DT_RTLREADING ignored
287
288 BOOL done = FALSE;
289
290 if ((dwDTFormat & DT_END_ELLIPSIS) && (cchText > 1))
291 {
292 int textWidth,width;
293 RECT rect;
294
295 SetRectEmpty(&rect);
296 OSLibWinDrawTabbedText(pHps,cchText,lTabs,lpchText,&rect,0,0,flCmd | DTOS_QUERYEXTENT);
297 width = rectPtr->right-rectPtr->left;
298 textWidth = rect.right-rect.left;
299 if ((textWidth > width) && (width > 0))
300 {
301 char* newText;
302 int newTextLen = cchText-1+ELLIPSISLEN;
303 int preLen = cchText-1;
304
305 newText = (char*)malloc(newTextLen+1);
306 strncpy(newText,lpchText,cchText-1);
307 do
308 {
309 strcpy(&newText[preLen],ELLIPSIS);
310 OSLibWinDrawTabbedText(pHps,newTextLen,lTabs,newText,&rect,0,0,flCmd | DTOS_QUERYEXTENT);
311 textWidth = rect.right-rect.left;
312 if (textWidth <= width || preLen == 1) break;
313 newTextLen--;
314 preLen--;
315 } while (TRUE);
316 rc = OSLibWinDrawTabbedText(pHps,newTextLen,lTabs,newText,rectPtr,0,0,flCmd);
317 if (dwDTFormat & DT_MODIFYSTRING) strcpy((LPSTR)lpchText,newText); //check length?
318 free(newText);
319
320 done = TRUE;
321 }
322 } else if ((dwDTFormat & DT_PATH_ELLIPSIS) && (cchText > 1))
323 {
324 int textWidth,width;
325 RECT rect;
326
327//CB: code not yet checked (-> testcase)
328
329 SetRectEmpty(&rect);
330 OSLibWinDrawTabbedText(pHps,cchText,lTabs,lpchText,&rect,0,0,flCmd | DTOS_QUERYEXTENT);
331 width = rectPtr->right-rectPtr->left;
332 textWidth = rect.right-rect.left;
333 if ((textWidth > width) && (width > 0))
334 {
335 char *newText,*slashPos;
336 int newTextLen = cchText+ELLIPSISLEN;
337
338 newText = (char*)malloc(newTextLen+1);
339 strncpy(newText,lpchText,cchText);
340
341 // PH 2000/10/01 "//" appeared wrong ...
342 slashPos = strrchr(newText,(int)'\\');
343 if (slashPos != NULL)
344 {
345 int preLen = slashPos-newText;
346 char* endPtr = (char*)lpchText+preLen;
347 int endLen = cchText-preLen;
348 BOOL ok = FALSE;
349
350 //delete start
351 do
352 {
353 strcpy(&newText[preLen],ELLIPSIS);
354 strncpy(&newText[preLen+ELLIPSISLEN],endPtr,endLen);
355 OSLibWinDrawTabbedText(pHps,newTextLen,lTabs,newText,&rect,0,0,flCmd | DTOS_QUERYEXTENT);
356 textWidth = rect.right-rect.left;
357 if (textWidth <= width)
358 {
359 ok = TRUE;
360 break;
361 }
362 if (preLen == 0) break;
363 newTextLen--;
364 preLen--;
365 } while (TRUE);
366
367 if (!ok)
368 {
369 //delete end
370 do
371 {
372 endPtr++;
373 endLen--;
374 newTextLen--;
375 strncpy(&newText[ELLIPSISLEN],endPtr,endLen);
376 OSLibWinDrawTabbedText(pHps,newTextLen,lTabs,newText,&rect,0,0,flCmd | DTOS_QUERYEXTENT);
377 textWidth = rect.right-rect.left;
378 if ((textWidth <= width) || (endLen == 0)) break;
379 } while (TRUE);
380 }
381 } else
382 {
383 int preLen,endLen;
384
385 preLen = cchText/2;
386 endLen = cchText-preLen; //endLen >= preLen
387 char* endPtr = (char*)lpchText+preLen;
388
389 do
390 {
391 strcpy(&newText[preLen],ELLIPSIS);
392 strncpy(&newText[preLen+ELLIPSISLEN],endPtr,endLen);
393 OSLibWinDrawTabbedText(pHps,newTextLen,lTabs,newText,&rect,0,0,flCmd | DTOS_QUERYEXTENT);
394 textWidth = rect.right-rect.left;
395 if ((textWidth <= width) || (preLen+endLen == 0)) break;
396 if (endLen > preLen)
397 {
398 endLen--;
399 endPtr++;
400 } else preLen--;
401 newTextLen--;
402 } while (TRUE);
403 }
404 rc = OSLibWinDrawTabbedText(pHps,newTextLen,lTabs,newText,rectPtr,0,0,flCmd);
405 if (dwDTFormat & DT_MODIFYSTRING) strcpy((LPSTR)lpchText,newText); //check length?
406 free(newText);
407
408 done = TRUE;
409 }
410 }
411
412 if (!done)
413 {
414 rc = OSLibWinDrawTabbedText(pHps,cchText,lTabs,lpchText,rectPtr,0,0,flCmd);
415 }
416
417 if (dwDTFormat & DT_CALCRECT)
418 {
419#ifndef INVERT
420 if (pHps->yInvert > 0) {
421 top = top - rectPtr->top;
422 rectPtr->top += top;
423 rectPtr->bottom += top;
424 } /* endif */
425#endif
426 if (!(dwDTFormat & DT_RIGHT) && (rectPtr->left < xLeft))
427 {
428 rectPtr->right = xLeft+(rectPtr->right-rectPtr->left);
429 rectPtr->left = xLeft;
430 }
431 if (!(dwDTFormat & DT_BOTTOM) && (rectPtr->top < yTop))
432 {
433 rectPtr->bottom = yTop+(rectPtr->bottom-rectPtr->top);
434 rectPtr->top = yTop;
435 }
436 }
437
438 if (lpDTParams)
439 {
440 // don't forget to restore the margins
441 lprc->left -= lpDTParams->iLeftMargin;
442 lprc->right += lpDTParams->iRightMargin;
443 }
444
445 _control87(fpuctrlword, 0xFFFF);
446
447 return rc;
448}
449//******************************************************************************
450//******************************************************************************
451INT SYSTEM EXPORT InternalDrawTextExW(HDC hdc,LPCWSTR lpchText,INT cchText,LPRECT lprc,UINT dwDTFormat,LPDRAWTEXTPARAMS lpDTParams,BOOL isDrawTextEx)
452{
453 char *astring = NULL;
454 INT rc;
455
456 if(cchText == -1) {
457 astring = UnicodeToAsciiString((LPWSTR)lpchText);
458 }
459 else {
460 astring = (char *)HEAP_malloc(cchText+1);
461 UnicodeToAsciiN((LPWSTR)lpchText, astring, cchText+1);
462 astring[cchText] = 0;
463 }
464
465 dprintf(("InternalDrawTextExW %x %s %d %x", hdc, astring, cchText, dwDTFormat));
466 rc = InternalDrawTextExA(hdc,astring,cchText,lprc,dwDTFormat,lpDTParams,isDrawTextEx);
467 if (dwDTFormat & DT_MODIFYSTRING && (dwDTFormat & (DT_END_ELLIPSIS | DT_PATH_ELLIPSIS))) AsciiToUnicode(astring,(LPWSTR)lpchText);
468 FreeAsciiString(astring);
469
470 return(rc);
471}
472#if 0
473//Replaced with Wine functions in user32\text.cpp)
474//******************************************************************************
475// CB: USER32 function, but here is the better place
476//******************************************************************************
477DWORD SYSTEM EXPORT InternalGetTabbedTextExtentA(HDC hDC,LPCSTR lpString,INT nCount,INT nTabPositions,LPINT lpnTabStopPositions)
478{
479 pDCData pHps = (pDCData)OSLibGpiQueryDCData(hDC);
480 BOOL result;
481 POINTLOS2 pts[TXTBOXOS_COUNT];
482 POINTLOS2 widthHeight = {0,0};
483
484 if (!pHps || (nCount == 0) || (nTabPositions < 0))
485 return 0;
486
487 if (nCount < 0)
488 {
489 SetLastError(ERROR_STACK_OVERFLOW);
490 return 0;
491 }
492 if ((lpString == NULL) || ((nTabPositions > 0) && (lpnTabStopPositions == NULL)))
493 {
494 SetLastError(ERROR_INVALID_PARAMETER);
495 return 0;
496 }
497 if(nCount > 512) {
498 DWORD cbStringNew;
499 DWORD ret1;
500 DWORD ret = 0;
501
502 dprintf(("WARNING: InternalGetTabbedTextExtentA string longer than 512 chars; splitting up"));
503 while(nCount) {
504 cbStringNew = min(500, nCount);
505
506 ret = InternalGetTabbedTextExtentA(hDC, lpString, cbStringNew, nTabPositions, lpnTabStopPositions);
507 lpString += cbStringNew;
508 nCount -= cbStringNew;
509 }
510 return ret;
511 }
512
513 //CB: Win95 supports negative values for right aligned text
514 for (INT i = 0;i < nTabPositions;i++)
515 {
516 if (lpnTabStopPositions[i] < 0)
517 {
518 SetLastError(ERROR_INVALID_PARAMETER);
519 return 0;
520 }
521 }
522
523 result = OSLibGpiQueryTextBox(pHps,(nCount > 1) ? 1:nCount,lpString,TXTBOXOS_COUNT,pts);
524 if (result == FALSE)
525 return 0;
526 calcDimensions(pts,&widthHeight);
527
528 LONG rv1 = OSLibGpiQueryTabbedTextExtent(pHps,nCount,lpString,nTabPositions,lpnTabStopPositions);
529 if (rv1 == GPIOS_ERROR)
530 return 0;
531
532 return (widthHeight.y <<16)+labs(rv1);
533}
534//******************************************************************************
535//******************************************************************************
536DWORD SYSTEM EXPORT InternalGetTabbedTextExtentW(HDC hDC,LPCWSTR lpString,INT nCount,INT nTabPositions,LPINT lpnTabStopPositions)
537{
538 char *astring;
539 DWORD rc;
540
541 if(nCount == -1) {
542 astring = UnicodeToAsciiString((LPWSTR)lpString);
543 }
544 else {
545 astring = (char *)HEAP_malloc(nCount+1);
546 UnicodeToAsciiN((LPWSTR)lpString, astring, nCount+1);
547 astring[nCount] = 0;
548 }
549
550 rc = InternalGetTabbedTextExtentA(hDC,astring,nCount,nTabPositions,lpnTabStopPositions);
551 FreeAsciiString(astring);
552
553 return(rc);
554}
555//******************************************************************************
556// CB: USER32 function, but here is the better place
557//******************************************************************************
558LONG SYSTEM EXPORT InternalTabbedTextOutA(HDC hdc,INT x,INT y,LPCSTR lpString,INT nCount,INT nTabPositions,LPINT lpnTabStopPositions,INT nTabOrigin)
559{
560 pDCData pHps = (pDCData)OSLibGpiQueryDCData(hdc);
561 POINTLOS2 ptl;
562 DWORD dimensions;
563
564 if ((pHps == NULL) || (lpString == NULL))
565 {
566 SetLastError(ERROR_INVALID_HANDLE);
567 return 0;
568 }
569 if (nCount == -1)
570 nCount = strlen(lpString);
571 if (nCount < 1)
572 {
573 SetLastError(ERROR_INVALID_HANDLE);
574 return 0;
575 }
576 if (lpnTabStopPositions == NULL)
577 nTabPositions = 0;
578 if (nTabPositions == 0)
579 lpnTabStopPositions = NULL;
580 if (nTabPositions < 0)
581 {
582 SetLastError(ERROR_INVALID_HANDLE);
583 return 0;
584 }
585 if (getAlignUpdateCP(pHps) == TRUE) {
586 OSLibGpiQueryCurrentPosition(pHps,&ptl);
587 }
588 else
589 {
590 ptl.x = x;
591 ptl.y = y;
592#ifndef INVERT
593 if (pHps->yInvert > 0) {
594 ptl.y = pHps->yInvert - ptl.y;
595 }
596#endif
597 }
598
599 //CB: nTabOrigin is ignored! -> wrong size (width)!
600 // todo: change low word (width), height is ok
601 dimensions = InternalGetTabbedTextExtentA(hdc,lpString,nCount,nTabPositions,lpnTabStopPositions);
602 if (dimensions != 0)
603 {
604 LONG rcGPI;
605
606 ptl.y += getWorldYDeltaFor1Pixel(pHps);
607
608 rcGPI = OSLibGpiTabbedCharStringAt(pHps,&ptl,NULL,0,nCount,lpString,nTabPositions,lpnTabStopPositions,nTabOrigin);
609 if (rcGPI == GPIOS_ALTERROR)
610 return 0;
611 if (getAlignUpdateCP(pHps))
612 {
613 OSLibGpiQueryCurrentPosition (pHps,&ptl);
614 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
615 OSLibGpiSetCurrentPosition (pHps,&ptl);
616 }
617
618 return dimensions;
619 }
620 return 0;
621}
622//******************************************************************************
623//******************************************************************************
624LONG SYSTEM EXPORT InternalTabbedTextOutW(HDC hdc,INT x,INT y,LPCWSTR lpString,INT nCount,INT nTabPositions,LPINT lpnTabStopPositions,INT nTabOrigin)
625{
626 char *astring;
627 LONG rc;
628
629 if(nCount == -1) {
630 astring = UnicodeToAsciiString((LPWSTR)lpString);
631 }
632 else {
633 astring = (char *)HEAP_malloc(nCount+1);
634 UnicodeToAsciiN((LPWSTR)lpString, astring, nCount+1);
635 astring[nCount] = 0;
636 }
637
638 rc = InternalTabbedTextOutA(hdc,x,y,astring,nCount,nTabPositions,lpnTabStopPositions,nTabOrigin);
639 FreeAsciiString(astring);
640
641 return(rc);
642}
643#endif
644//******************************************************************************
645// todo: metafile support
646//******************************************************************************
647BOOL InternalTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut)
648{
649 pDCData pHps = (pDCData)OSLibGpiQueryDCData(hdc);
650 ULONG flOptions = 0;
651 RECTLOS2 pmRect;
652 POINTLOS2 ptl;
653 LONG hits;
654
655 if (!pHps || (cbCount < 0) || ((lpszString == NULL) && (cbCount != 0)))
656 {
657 dprintf(("InternalTextOutA: invalid parameter"));
658 SetLastError(ERROR_INVALID_HANDLE);
659 return FALSE;
660 }
661
662 if (cbCount > 512)
663 {
664 dprintf(("InternalTextOutA: invalid parameter cbCount"));
665 SetLastError(ERROR_INVALID_PARAMETER);
666 return FALSE;
667 }
668 if (fuOptions & ~((UINT)(ETO_CLIPPED | ETO_OPAQUE)))
669 {
670 dprintf(("InternalTextOutA: invalid fuOptions"));
671 //ETO_GLYPH_INDEX, ETO_RTLLEADING, ETO_NUMERICSLOCAL, ETO_NUMERICSLATIN, ETO_IGNORELANGUAGE, ETO_PDY are ignored
672 return TRUE;
673 }
674
675 //CB: add metafile info
676
677 if (lprc)
678 {
679 if (fuOptions)
680 {
681 MapWin32ToOS2Rect(*lprc,pmRect);
682 if (excludeBottomRightPoint(pHps,(PPOINTLOS2)&pmRect) == 0)
683 {
684 dprintf(("InternalTextOutA: excludeBottomRightPoint returned 0"));
685 return TRUE;
686 }
687#ifndef INVERT
688 if (pHps->yInvert > 0) {
689 int temp = pHps->yInvert - pmRect.yTop;
690 pmRect.yTop = pHps->yInvert - pmRect.yBottom;
691 pmRect.yBottom = temp;
692 }
693#endif
694
695 if (fuOptions & ETO_CLIPPED) flOptions |= CHSOS_CLIP;
696 if (fuOptions & ETO_OPAQUE) flOptions |= CHSOS_OPAQUE;
697 }
698 }
699 else
700 {
701 if (fuOptions)
702 {
703 dprintf(("InternalTextOutA: ERROR_INVALID_HANDLE"));
704 SetLastError(ERROR_INVALID_HANDLE);
705 return FALSE;
706 }
707 }
708
709 if (cbCount == 0)
710 {
711 if (fuOptions & ETO_OPAQUE)
712 {
713//SvL: This doesn't seem to work (anymore). Look at MFC apps for the missing border
714// between menu & button bar (all white). (e.g. odin app & acrobat reader 4.05)
715#if 0
716 lpszString = " ";
717 cbCount = 1;
718 flOptions |= CHSOS_CLIP;
719#else
720 HBRUSH hbrush = CreateSolidBrush(GetBkColor(hdc));
721 HBRUSH oldbrush;
722
723 oldbrush = SelectObject(hdc, hbrush);
724 FillRect(hdc, lprc, hbrush);
725 SelectObject(hdc, oldbrush);
726 return TRUE;
727#endif
728 }
729 else {
730 dprintf(("InternalTextOutA: cbCount == 0"));
731 return TRUE;
732 }
733 }
734 if (lpDx)
735 flOptions |= CHSOS_VECTOR;
736
737 if (!getAlignUpdateCP(pHps))
738 {
739 ptl.x = X;
740 ptl.y = Y;
741
742#ifndef INVERT
743 if (pHps->yInvert > 0) {
744 ptl.y = pHps->yInvert - Y;
745 }
746#endif
747
748 flOptions |= CHSOS_LEAVEPOS;
749 }
750 else OSLibGpiQueryCurrentPosition(pHps,&ptl);
751
752 UINT align = GetTextAlign(hdc);
753 LONG pmHAlign,pmVAlign;
754
755 //CB: TA_RIGHT not supported by PM, only TA_CENTER and TA_LEFT
756 if ((align & 0x6) == TA_RIGHT)
757 {
758 PPOINTLOS2 pts = (PPOINTLOS2)malloc((cbCount+1)*sizeof(POINTLOS2));
759
760 OSLibGpiQueryCharStringPosAt(pHps,&ptl,flOptions,cbCount,lpszString,lpDx,pts);
761 ptl.x -= pts[cbCount].x-pts[0].x;
762 free(pts);
763 }
764
765 if (lprc && ((align & 0x18) == TA_BASELINE))
766 {
767 //CB: if TA_BASELINE is set, GPI doesn't fill rect
768 // TA_BOTTOM fills rect
769 OSLibGpiQueryTextAlignment(pHps,&pmHAlign,&pmVAlign);
770 OSLibGpiSetTextAlignment(pHps,pmHAlign,(pmVAlign & ~TAOS_BASE) | TAOS_BOTTOM);
771 }
772
773 ptl.y += getWorldYDeltaFor1Pixel(pHps);
774
775#ifndef INVERT
776 int vertAdjust = 0;
777 if ((pHps->taMode & 0x18) == TA_TOP)
778 {
779 vertAdjust = OSLibGpiQueryFontMaxHeight(pHps->hps);
780 }
781 ptl.y -= vertAdjust;
782#endif
783
784 hits = OSLibGpiCharStringPosAt(pHps,&ptl,&pmRect,flOptions,cbCount,lpszString,lpDx);
785
786 if (lprc && ((align & 0x18) == TA_BASELINE))
787 OSLibGpiSetTextAlignment(pHps,pmHAlign,pmVAlign);
788
789 if(hits == GPIOS_ERROR) {
790 dprintf(("InternalTextOutA: OSLibGpiCharStringPosAt returned GPIOS_ERROR"));
791 return FALSE;
792 }
793
794 if (getAlignUpdateCP(pHps))
795 {
796 OSLibGpiQueryCurrentPosition(pHps,&ptl);
797 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
798#ifndef INVERT
799 ptl.y += vertAdjust;
800#endif
801 OSLibGpiSetCurrentPosition(pHps,&ptl);
802 }
803
804 return TRUE;
805}
806//******************************************************************************
807//******************************************************************************
808BOOL InternalTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut)
809{
810 char *astring = NULL;
811 BOOL rc;
812
813 if(cbCount == -1) {
814 astring = UnicodeToAsciiString((LPWSTR)lpszString);
815 }
816 else
817 if(cbCount) {
818 astring = (char *)HEAP_malloc(cbCount+1);
819 UnicodeToAsciiN((LPWSTR)lpszString, astring, cbCount+1);
820 astring[cbCount] = 0;
821 }
822 rc = InternalTextOutA(hdc,X,Y,fuOptions,lprc,(LPCSTR)astring,cbCount,lpDx,IsExtTextOut);
823 if(astring) {
824 FreeAsciiString(astring);
825 }
826
827 return(rc);
828}
829//******************************************************************************
830//******************************************************************************
831BOOL WIN32API ExtTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,UINT cbCount,CONST INT *lpDx)
832{
833 if(lprc) {
834 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));
835 }
836 else dprintf(("GDI32: ExtTextOutA %x %s (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
837
838 return InternalTextOutA(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
839}
840//******************************************************************************
841//******************************************************************************
842BOOL WIN32API ExtTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,UINT cbCount,CONST int *lpDx)
843{
844 if(lprc) {
845 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));
846 }
847 else dprintf(("GDI32: ExtTextOutW %x %ls (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
848 return InternalTextOutW(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
849}
850//******************************************************************************
851//******************************************************************************
852BOOL WIN32API TextOutA(HDC hdc,int nXStart,int nYStart,LPCSTR lpszString,int cbString)
853{
854 dprintf(("GDI32: TextOutA %x (%d,%d) %s", hdc, nXStart, nYStart, lpszString));
855
856 return InternalTextOutA(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
857}
858//******************************************************************************
859//******************************************************************************
860BOOL WIN32API TextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpszString,int cbString)
861{
862 dprintf(("GDI32: TextOutW"));
863
864 return InternalTextOutW(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
865}
866//******************************************************************************
867//******************************************************************************
868BOOL WIN32API PolyTextOutA(HDC hdc,POLYTEXTA *pptxt,int cStrings)
869{
870 dprintf(("GDI32: PolyTextOutA"));
871
872 for (INT x = 0;x < cStrings;x++)
873 {
874 BOOL rc;
875
876 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);
877 if (!rc) return FALSE;
878 }
879
880 return TRUE;
881}
882//******************************************************************************
883//******************************************************************************
884BOOL WIN32API PolyTextOutW(HDC hdc,POLYTEXTW *pptxt,int cStrings)
885{
886 dprintf(("GDI32: PolyTextOutW"));
887
888 for (INT x = 0;x < cStrings;x++)
889 {
890 BOOL rc;
891
892 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);
893 if (!rc) return FALSE;
894 }
895
896 return TRUE;
897}
898//******************************************************************************
899//******************************************************************************
900BOOL WIN32API GetTextExtentPointA(HDC hdc, LPCTSTR lpsz, int cbString,
901 LPSIZE lpsSize)
902{
903#if 1
904 //SvL: This works better than the code below. Can been seen clearly
905 // in the Settings dialog box of VirtualPC. Strings are clipped.
906 // (e.g.: Hard Disk 1 -> Hard Disk)
907 dprintf(("GDI32: GetTextExtentPointA %s\n", lpsz));
908 BOOL rc = O32_GetTextExtentPoint(hdc, lpsz, cbString, lpsSize);
909 if(rc) {
910 dprintf(("GDI32: GetTextExtentPointA %x %s %d returned %d (%d,%d)", hdc, lpsz, cbString, rc, lpsSize->cx, lpsSize->cy));
911 SetLastError(ERROR_SUCCESS);
912 return TRUE;
913 }
914 return FALSE;
915#else
916 BOOL rc;
917 POINTLOS2 pts[TXTBOXOS_COUNT];
918 POINTLOS2 widthHeight = { 0, 0};
919 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
920
921 dprintf(("GDI32: GetTextExtentPointA %s\n", lpsz));
922 if(pHps == NULL)
923 {
924 SetLastError(ERROR_INVALID_HANDLE);
925 return FALSE;
926 }
927
928 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
929 {
930 SetLastError(ERROR_INVALID_PARAMETER);
931 return FALSE;
932 }
933
934 lpsSize->cx = 0;
935 lpsSize->cy = 0;
936
937 // Verified with NT4, SP6
938 if(cbString == 0)
939 {
940 SetLastError(ERROR_SUCCESS);
941 return TRUE;
942 }
943 if(cbString > 512)
944 {
945 DWORD cbStringNew;
946 SIZE newSize;
947
948 dprintf(("WARNING: string longer than 512 chars; splitting up"));
949 lpsSize->cx = 0;
950 lpsSize->cy = 0;
951 while(cbString) {
952 cbStringNew = min(500, cbString);
953 rc = GetTextExtentPointA(hdc, lpsz, cbStringNew, &newSize);
954 if(rc == FALSE) {
955 return FALSE;
956 }
957 lpsSize->cx += newSize.cx;
958 lpsSize->cy = max(newSize.cy, lpsSize->cy);
959 lpsz += cbStringNew;
960 cbString -= cbStringNew;
961 }
962 return TRUE;
963 }
964
965 rc = OSLibGpiQueryTextBox(pHps, cbString, lpsz, TXTBOXOS_COUNT, pts);
966 if(rc == FALSE)
967 {
968 SetLastError(ERROR_INVALID_PARAMETER); //todo wrong error
969 return FALSE;
970 }
971 calcDimensions(pts, &widthHeight);
972 lpsSize->cx = widthHeight.x;
973 lpsSize->cy = widthHeight.y;
974
975 if(pHps && pHps->isPrinter && pHps->hdc)
976 {//scale for printer dcs
977 LONG alArray[2];
978
979 if (OSLibDevQueryCaps(pHps, OSLIB_CAPS_HORIZONTAL_RESOLUTION, 2, &alArray[0]))
980 lpsSize->cx = lpsSize->cx * alArray[0] / alArray[1];
981 }
982
983 dprintf(("GDI32: GetTextExtentPointA %x %s %d returned %d (%d,%d)", hdc, lpsz, cbString, rc, lpsSize->cx, lpsSize->cy));
984 SetLastError(ERROR_SUCCESS);
985 return TRUE;
986#endif
987}
988//******************************************************************************
989//******************************************************************************
990BOOL WIN32API GetTextExtentPointW(HDC hdc,
991 LPCWSTR lpString,
992 int cbString,
993 PSIZE lpSize)
994{
995 char *astring = UnicodeToAsciiString((LPWSTR)lpString);
996 BOOL rc;
997
998 dprintf(("GDI32: GetTextExtentPointW %s\n", astring));
999 lpSize->cx = lpSize->cy = 0;
1000 rc = GetTextExtentPointA(hdc,
1001 astring,
1002 cbString,
1003 lpSize);
1004 FreeAsciiString(astring);
1005 return(rc);
1006}
1007//******************************************************************************
1008//******************************************************************************
1009BOOL WIN32API GetTextExtentPoint32A( HDC hdc, LPCSTR lpsz, int cbString, PSIZE lpSize)
1010{
1011 BOOL rc;
1012
1013 dprintf(("GDI32: GetTextExtentPoint32A %s\n", lpsz));
1014 lpSize->cx = lpSize->cy = 0;
1015 rc = GetTextExtentPointA(hdc, lpsz, cbString, lpSize);
1016 return rc;
1017}
1018//******************************************************************************
1019//******************************************************************************
1020BOOL WIN32API GetTextExtentPoint32W(HDC arg1, LPCWSTR arg2, int arg3, PSIZE lpSize)
1021{
1022 char *astring = UnicodeToAsciiString((LPWSTR)arg2);
1023 BOOL rc;
1024
1025 dprintf(("GDI32: GetTextExtentPoint32W %s\n", astring));
1026 rc = GetTextExtentPointA(arg1, astring, arg3, lpSize);
1027 FreeAsciiString(astring);
1028 return(rc);
1029}
1030//******************************************************************************
1031//******************************************************************************
Note: See TracBrowser for help on using the repository browser.