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

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

Replaced TabbedTextOutA/W & GetTabbedTextExtentA/W with Wine version

File size: 29.4 KB
Line 
1/* $Id: text.cpp,v 1.23 2001-05-27 19:01:14 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;
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 lpszString = " ";
714 cbCount = 1;
715 flOptions |= CHSOS_CLIP;
716 }
717 else {
718 dprintf(("InternalTextOutA: cbCount == 0"));
719 return TRUE;
720 }
721 }
722 if (lpDx)
723 flOptions |= CHSOS_VECTOR;
724
725 if (!getAlignUpdateCP(pHps))
726 {
727 ptl.x = X;
728 ptl.y = Y;
729
730#ifndef INVERT
731 if (pHps->yInvert > 0) {
732 ptl.y = pHps->yInvert - Y;
733 }
734#endif
735
736 flOptions |= CHSOS_LEAVEPOS;
737 }
738 else OSLibGpiQueryCurrentPosition(pHps,&ptl);
739
740 UINT align = GetTextAlign(hdc);
741 LONG pmHAlign,pmVAlign;
742
743 //CB: TA_RIGHT not supported by PM, only TA_CENTER and TA_LEFT
744 if ((align & 0x6) == TA_RIGHT)
745 {
746 PPOINTLOS2 pts = (PPOINTLOS2)malloc((cbCount+1)*sizeof(POINTLOS2));
747
748 OSLibGpiQueryCharStringPosAt(pHps,&ptl,flOptions,cbCount,lpszString,lpDx,pts);
749 ptl.x -= pts[cbCount].x-pts[0].x;
750 free(pts);
751 }
752
753 if (lprc && ((align & 0x18) == TA_BASELINE))
754 {
755 //CB: if TA_BASELINE is set, GPI doesn't fill rect
756 // TA_BOTTOM fills rect
757 OSLibGpiQueryTextAlignment(pHps,&pmHAlign,&pmVAlign);
758 OSLibGpiSetTextAlignment(pHps,pmHAlign,(pmVAlign & ~TAOS_BASE) | TAOS_BOTTOM);
759 }
760
761 ptl.y += getWorldYDeltaFor1Pixel(pHps);
762
763#ifndef INVERT
764 int vertAdjust = 0;
765 if ((pHps->taMode & 0x18) == TA_TOP)
766 {
767 vertAdjust = OSLibGpiQueryFontMaxHeight(pHps->hps);
768 }
769 ptl.y -= vertAdjust;
770#endif
771
772 hits = OSLibGpiCharStringPosAt(pHps,&ptl,&pmRect,flOptions,cbCount,lpszString,lpDx);
773
774 if (lprc && ((align & 0x18) == TA_BASELINE))
775 OSLibGpiSetTextAlignment(pHps,pmHAlign,pmVAlign);
776
777 if(hits == GPIOS_ERROR) {
778 dprintf(("InternalTextOutA: OSLibGpiCharStringPosAt returned GPIOS_ERROR"));
779 return FALSE;
780 }
781
782 if (getAlignUpdateCP(pHps))
783 {
784 OSLibGpiQueryCurrentPosition(pHps,&ptl);
785 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
786#ifndef INVERT
787 ptl.y += vertAdjust;
788#endif
789 OSLibGpiSetCurrentPosition(pHps,&ptl);
790 }
791
792 return TRUE;
793}
794//******************************************************************************
795//******************************************************************************
796BOOL InternalTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut)
797{
798 char *astring = NULL;
799 BOOL rc;
800
801 if(cbCount == -1) {
802 astring = UnicodeToAsciiString((LPWSTR)lpszString);
803 }
804 else
805 if(cbCount) {
806 astring = (char *)HEAP_malloc(cbCount+1);
807 UnicodeToAsciiN((LPWSTR)lpszString, astring, cbCount+1);
808 astring[cbCount] = 0;
809 }
810 rc = InternalTextOutA(hdc,X,Y,fuOptions,lprc,(LPCSTR)astring,cbCount,lpDx,IsExtTextOut);
811 if(astring) {
812 FreeAsciiString(astring);
813 }
814
815 return(rc);
816}
817//******************************************************************************
818//******************************************************************************
819BOOL WIN32API ExtTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,UINT cbCount,CONST INT *lpDx)
820{
821 if(lprc) {
822 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));
823 }
824 else dprintf(("GDI32: ExtTextOutA %x %s (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
825
826 return InternalTextOutA(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
827}
828//******************************************************************************
829//******************************************************************************
830BOOL WIN32API ExtTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,UINT cbCount,CONST int *lpDx)
831{
832 if(lprc) {
833 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));
834 }
835 else dprintf(("GDI32: ExtTextOutW %x %ls (%d,%d) %x %d %x", hdc, lpszString, X, Y, fuOptions, cbCount, lpDx));
836 return InternalTextOutW(hdc, X, Y, fuOptions, lprc, lpszString, cbCount, lpDx, TRUE);
837}
838//******************************************************************************
839//******************************************************************************
840BOOL WIN32API TextOutA(HDC hdc,int nXStart,int nYStart,LPCSTR lpszString,int cbString)
841{
842 dprintf(("GDI32: TextOutA %x (%d,%d) %s", hdc, nXStart, nYStart, lpszString));
843
844 return InternalTextOutA(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
845}
846//******************************************************************************
847//******************************************************************************
848BOOL WIN32API TextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpszString,int cbString)
849{
850 dprintf(("GDI32: TextOutW"));
851
852 return InternalTextOutW(hdc,nXStart,nYStart,0,NULL,lpszString,cbString,NULL,FALSE);
853}
854//******************************************************************************
855//******************************************************************************
856BOOL WIN32API PolyTextOutA(HDC hdc,POLYTEXTA *pptxt,int cStrings)
857{
858 dprintf(("GDI32: PolyTextOutA"));
859
860 for (INT x = 0;x < cStrings;x++)
861 {
862 BOOL rc;
863
864 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);
865 if (!rc) return FALSE;
866 }
867
868 return TRUE;
869}
870//******************************************************************************
871//******************************************************************************
872BOOL WIN32API PolyTextOutW(HDC hdc,POLYTEXTW *pptxt,int cStrings)
873{
874 dprintf(("GDI32: PolyTextOutW"));
875
876 for (INT x = 0;x < cStrings;x++)
877 {
878 BOOL rc;
879
880 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);
881 if (!rc) return FALSE;
882 }
883
884 return TRUE;
885}
886//******************************************************************************
887//******************************************************************************
888BOOL WIN32API GetTextExtentPointA(HDC hdc, LPCTSTR lpsz, int cbString,
889 LPSIZE lpsSize)
890{
891#if 1
892 //SvL: This works better than the code below. Can been seen clearly
893 // in the Settings dialog box of VirtualPC. Strings are clipped.
894 // (e.g.: Hard Disk 1 -> Hard Disk)
895 dprintf(("GDI32: GetTextExtentPointA %s\n", lpsz));
896 BOOL rc = O32_GetTextExtentPoint(hdc, lpsz, cbString, lpsSize);
897 if(rc) {
898 dprintf(("GDI32: GetTextExtentPointA %x %s %d returned %d (%d,%d)", hdc, lpsz, cbString, rc, lpsSize->cx, lpsSize->cy));
899 SetLastError(ERROR_SUCCESS);
900 return TRUE;
901 }
902 return FALSE;
903#else
904 BOOL rc;
905 POINTLOS2 pts[TXTBOXOS_COUNT];
906 POINTLOS2 widthHeight = { 0, 0};
907 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
908
909 dprintf(("GDI32: GetTextExtentPointA %s\n", lpsz));
910 if(pHps == NULL)
911 {
912 SetLastError(ERROR_INVALID_HANDLE);
913 return FALSE;
914 }
915
916 if(lpsz == NULL || cbString < 0 || lpsSize == NULL)
917 {
918 SetLastError(ERROR_INVALID_PARAMETER);
919 return FALSE;
920 }
921
922 lpsSize->cx = 0;
923 lpsSize->cy = 0;
924
925 // Verified with NT4, SP6
926 if(cbString == 0)
927 {
928 SetLastError(ERROR_SUCCESS);
929 return TRUE;
930 }
931 if(cbString > 512)
932 {
933 DWORD cbStringNew;
934 SIZE newSize;
935
936 dprintf(("WARNING: string longer than 512 chars; splitting up"));
937 lpsSize->cx = 0;
938 lpsSize->cy = 0;
939 while(cbString) {
940 cbStringNew = min(500, cbString);
941 rc = GetTextExtentPointA(hdc, lpsz, cbStringNew, &newSize);
942 if(rc == FALSE) {
943 return FALSE;
944 }
945 lpsSize->cx += newSize.cx;
946 lpsSize->cy = max(newSize.cy, lpsSize->cy);
947 lpsz += cbStringNew;
948 cbString -= cbStringNew;
949 }
950 return TRUE;
951 }
952
953 rc = OSLibGpiQueryTextBox(pHps, cbString, lpsz, TXTBOXOS_COUNT, pts);
954 if(rc == FALSE)
955 {
956 SetLastError(ERROR_INVALID_PARAMETER); //todo wrong error
957 return FALSE;
958 }
959 calcDimensions(pts, &widthHeight);
960 lpsSize->cx = widthHeight.x;
961 lpsSize->cy = widthHeight.y;
962
963 if(pHps && pHps->isPrinter && pHps->hdc)
964 {//scale for printer dcs
965 LONG alArray[2];
966
967 if (OSLibDevQueryCaps(pHps, OSLIB_CAPS_HORIZONTAL_RESOLUTION, 2, &alArray[0]))
968 lpsSize->cx = lpsSize->cx * alArray[0] / alArray[1];
969 }
970
971 dprintf(("GDI32: GetTextExtentPointA %x %s %d returned %d (%d,%d)", hdc, lpsz, cbString, rc, lpsSize->cx, lpsSize->cy));
972 SetLastError(ERROR_SUCCESS);
973 return TRUE;
974#endif
975}
976//******************************************************************************
977//******************************************************************************
978BOOL WIN32API GetTextExtentPointW(HDC hdc,
979 LPCWSTR lpString,
980 int cbString,
981 PSIZE lpSize)
982{
983 char *astring = UnicodeToAsciiString((LPWSTR)lpString);
984 BOOL rc;
985
986 dprintf(("GDI32: GetTextExtentPointW %s\n", astring));
987 lpSize->cx = lpSize->cy = 0;
988 rc = GetTextExtentPointA(hdc,
989 astring,
990 cbString,
991 lpSize);
992 FreeAsciiString(astring);
993 return(rc);
994}
995//******************************************************************************
996//******************************************************************************
997BOOL WIN32API GetTextExtentPoint32A( HDC hdc, LPCSTR lpsz, int cbString, PSIZE lpSize)
998{
999 BOOL rc;
1000
1001 dprintf(("GDI32: GetTextExtentPoint32A %s\n", lpsz));
1002 lpSize->cx = lpSize->cy = 0;
1003 rc = GetTextExtentPointA(hdc, lpsz, cbString, lpSize);
1004 return rc;
1005}
1006//******************************************************************************
1007//******************************************************************************
1008BOOL WIN32API GetTextExtentPoint32W(HDC arg1, LPCWSTR arg2, int arg3, PSIZE lpSize)
1009{
1010 char *astring = UnicodeToAsciiString((LPWSTR)arg2);
1011 BOOL rc;
1012
1013 dprintf(("GDI32: GetTextExtentPoint32W %s\n", astring));
1014 rc = GetTextExtentPointA(arg1, astring, arg3, lpSize);
1015 FreeAsciiString(astring);
1016 return(rc);
1017}
1018//******************************************************************************
1019//******************************************************************************
Note: See TracBrowser for help on using the repository browser.