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

Last change on this file since 5120 was 4602, checked in by sandervl, 25 years ago

GetTextExtentPoint reimplemented

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