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

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

minor updates

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