4 * Copyright 1993, 1994 Alexandre Julliard
14 /* #define DEBUG_TEXT */
24 #define SWAP_INT(a,b) { int t = a; a = b; b = t; }
26 static int tabstop
= 8;
28 static int spacewidth
;
29 static int prefix_offset
;
31 static const char *TEXT_NextLine( HDC16 hdc
, const char *str
, int *count
,
32 char *dest
, int *len
, int width
, WORD format
)
34 /* Return next line of text from a string.
37 * str - string to parse into lines.
38 * count - length of str.
39 * dest - destination in which to return line.
40 * len - length of resultant line in dest in chars.
41 * width - maximum width of line in pixels.
42 * format - format type passed to DrawText.
44 * Returns pointer to next char in str after end of the line
45 * or NULL if end of str reached.
53 int wb_i
= 0, wb_j
= 0, wb_count
= 0;
61 if (!(format
& DT_SINGLELINE
))
63 if (str
[i
] == CR
&& str
[i
+1] == LF
)
71 if (!(format
& DT_NOCLIP
) || !(format
& DT_NOPREFIX
) ||
72 (format
& DT_WORDBREAK
))
74 if (!GetTextExtentPoint16(hdc
, &dest
[j
-1], 1, &size
))
81 if (!(format
& DT_NOPREFIX
))
83 if (str
[++i
] != PREFIX
)
90 if (!(format
& DT_NOCLIP
) || !(format
& DT_NOPREFIX
) ||
91 (format
& DT_WORDBREAK
))
93 if (!GetTextExtentPoint16(hdc
, &dest
[j
-1], 1, &size
))
100 if (format
& DT_EXPANDTABS
)
106 if (!GetTextExtentPoint16(hdc
, &dest
[lasttab
], j
- lasttab
,
110 numspaces
= (tabwidth
- size
.cx
) / spacewidth
;
111 for (k
= 0; k
< numspaces
; k
++)
113 plen
+= tabwidth
- size
.cx
;
114 lasttab
= wb_j
+ numspaces
;
118 dest
[j
++] = str
[i
++];
119 if (!(format
& DT_NOCLIP
) || !(format
& DT_NOPREFIX
) ||
120 (format
& DT_WORDBREAK
))
122 if (!GetTextExtentPoint16(hdc
, &dest
[j
-1], 1, &size
))
130 dest
[j
++] = str
[i
++];
131 if (!(format
& DT_NOCLIP
) || !(format
& DT_NOPREFIX
) ||
132 (format
& DT_WORDBREAK
))
137 if (!GetTextExtentPoint16(hdc
, &dest
[j
-1], 1, &size
))
144 dest
[j
++] = str
[i
++];
145 if (!(format
& DT_NOCLIP
) || !(format
& DT_NOPREFIX
) ||
146 (format
& DT_WORDBREAK
))
148 if (!GetTextExtentPoint16(hdc
, &dest
[j
-1], 1, &size
))
155 if (!(format
& DT_NOCLIP
) || (format
& DT_WORDBREAK
))
159 if (format
& DT_WORDBREAK
)
164 *count
= wb_count
- 1;
182 /***********************************************************************
183 * DrawText16 (USER.85)
185 INT16
DrawText16( HDC16 hdc
, LPCSTR str
, INT16 i_count
,
186 LPRECT16 rect
, UINT16 flags
)
190 static char line
[1024];
191 int len
, lh
, count
=i_count
;
195 int x
= rect
->left
, y
= rect
->top
;
196 int width
= rect
->right
- rect
->left
;
199 dprintf_text(stddeb
,"DrawText: '%s', %d , [(%d,%d),(%d,%d)]\n", str
,
200 count
, rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
202 if (count
== -1) count
= strlen(str
);
205 GetTextMetrics16(hdc
, &tm
);
206 if (flags
& DT_EXTERNALLEADING
)
207 lh
= tm
.tmHeight
+ tm
.tmExternalLeading
;
211 if (flags
& DT_TABSTOP
)
212 tabstop
= flags
>> 8;
214 if (flags
& DT_EXPANDTABS
)
216 GetTextExtentPoint16(hdc
, " ", 1, &size
);
217 spacewidth
= size
.cx
;
218 GetTextExtentPoint16(hdc
, "o", 1, &size
);
219 tabwidth
= size
.cx
* tabstop
;
222 if (flags
& DT_CALCRECT
) flags
|= DT_NOCLIP
;
227 strPtr
= TEXT_NextLine(hdc
, strPtr
, &count
, line
, &len
, width
, flags
);
229 if (prefix_offset
!= -1)
231 GetTextExtentPoint16(hdc
, line
, prefix_offset
, &size
);
233 GetTextExtentPoint16(hdc
, line
, prefix_offset
+ 1, &size
);
234 prefix_end
= size
.cx
- 1;
237 if (!GetTextExtentPoint16(hdc
, line
, len
, &size
)) return 0;
238 if (flags
& DT_CENTER
) x
= (rect
->left
+ rect
->right
-
240 else if (flags
& DT_RIGHT
) x
= rect
->right
- size
.cx
;
242 if (flags
& DT_SINGLELINE
)
244 if (flags
& DT_VCENTER
) y
= rect
->top
+
245 (rect
->bottom
- rect
->top
) / 2 - size
.cy
/ 2;
246 else if (flags
& DT_BOTTOM
) y
= rect
->bottom
- size
.cy
;
248 if (!(flags
& DT_CALCRECT
))
250 if (!ExtTextOut16(hdc
, x
, y
, (flags
& DT_NOCLIP
) ? 0 : ETO_CLIPPED
,
251 rect
, line
, len
, NULL
)) return 0;
252 if (prefix_offset
!= -1)
254 HPEN32 hpen
= CreatePen32( PS_SOLID
, 1, GetTextColor32(hdc
) );
255 HPEN32 oldPen
= SelectObject32( hdc
, hpen
);
256 MoveTo(hdc
, x
+ prefix_x
, y
+ tm
.tmAscent
+ 1 );
257 LineTo32(hdc
, x
+ prefix_end
, y
+ tm
.tmAscent
+ 1 );
258 SelectObject32( hdc
, oldPen
);
259 DeleteObject32( hpen
);
262 else if (size
.cx
> max_width
)
268 if (!(flags
& DT_NOCLIP
))
270 if (y
> rect
->bottom
- lh
)
276 if (flags
& DT_CALCRECT
)
278 rect
->right
= rect
->left
+ max_width
;
281 return y
- rect
->top
;
285 /***********************************************************************
286 * DrawText32A (USER32.163)
288 INT32
DrawText32A( HDC32 hdc
, LPCSTR str
, INT32 count
,
289 LPRECT32 rect
, UINT32 flags
)
295 return DrawText16( (HDC16
)hdc
, str
, (INT16
)count
, NULL
, (UINT16
)flags
);
296 CONV_RECT32TO16( rect
, &rect16
);
297 ret
= DrawText16( (HDC16
)hdc
, str
, (INT16
)count
, &rect16
, (UINT16
)flags
);
298 CONV_RECT16TO32( &rect16
, rect
);
303 /***********************************************************************
304 * DrawText32W (USER32.166)
306 INT32
DrawText32W( HDC32 hdc
, LPCWSTR str
, INT32 count
,
307 LPRECT32 rect
, UINT32 flags
)
309 LPSTR p
= HEAP_strdupWtoA( GetProcessHeap(), 0, str
);
310 INT32 ret
= DrawText32A( hdc
, p
, count
, rect
, flags
);
311 HeapFree( GetProcessHeap(), 0, p
);
316 /***********************************************************************
317 * ExtTextOut16 (GDI.351)
319 BOOL16
ExtTextOut16( HDC16 hdc
, INT16 x
, INT16 y
, UINT16 flags
,
320 const RECT16
*lprect
, LPCSTR str
, UINT16 count
,
326 LPINT32 lpdx32
= lpDx
?(LPINT32
)xmalloc(sizeof(INT32
)*count
):NULL
;
328 if (lprect
) CONV_RECT16TO32(lprect
,&rect32
);
329 if (lpdx32
) for (i
=count
;i
--;) lpdx32
[i
]=lpDx
[i
];
330 ret
= ExtTextOut32A(hdc
,x
,y
,flags
,lprect
?&rect32
:NULL
,str
,count
,lpdx32
);
331 if (lpdx32
) free(lpdx32
);
338 /***********************************************************************
339 * ExtTextOut32A (GDI32.98)
341 BOOL32
ExtTextOut32A( HDC32 hdc
, INT32 x
, INT32 y
, UINT32 flags
,
342 const RECT32
*lprect
, LPCSTR str
, UINT32 count
,
345 DC
* dc
= DC_GetDCPtr( hdc
);
346 return dc
&& dc
->funcs
->pExtTextOut
&&
347 dc
->funcs
->pExtTextOut(dc
,x
,y
,flags
,lprect
,str
,count
,lpDx
);
351 /***********************************************************************
352 * ExtTextOut32W (GDI32.99)
354 BOOL32
ExtTextOut32W( HDC32 hdc
, INT32 x
, INT32 y
, UINT32 flags
,
355 const RECT32
*lprect
, LPCWSTR str
, UINT32 count
,
358 LPSTR p
= HEAP_strdupWtoA( GetProcessHeap(), 0, str
);
359 INT32 ret
= ExtTextOut32A( hdc
, x
, y
, flags
, lprect
, p
, count
, lpDx
);
360 HeapFree( GetProcessHeap(), 0, p
);
365 /***********************************************************************
368 BOOL16
TextOut16( HDC16 hdc
, INT16 x
, INT16 y
, LPCSTR str
, INT16 count
)
370 return ExtTextOut16( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
374 /***********************************************************************
375 * TextOut32A (GDI32.355)
377 BOOL32
TextOut32A( HDC32 hdc
, INT32 x
, INT32 y
, LPCSTR str
, INT32 count
)
379 return ExtTextOut32A( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
383 /***********************************************************************
384 * TextOut32W (GDI32.356)
386 BOOL32
TextOut32W( HDC32 hdc
, INT32 x
, INT32 y
, LPCWSTR str
, INT32 count
)
388 return ExtTextOut32W( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
392 /***********************************************************************
393 * GrayString16 (USER.185)
395 BOOL16
GrayString16( HDC16 hdc
, HBRUSH16 hbr
, GRAYSTRINGPROC16 gsprc
,
396 LPARAM lParam
, INT16 cch
, INT16 x
, INT16 y
,
400 COLORREF current_color
;
402 if (!cch
) cch
= lstrlen16( (LPCSTR
)PTR_SEG_TO_LIN(lParam
) );
403 if (gsprc
) return gsprc( hdc
, lParam
, cch
);
404 current_color
= SetTextColor32( hdc
, GetSysColor32(COLOR_GRAYTEXT
) );
405 ret
= TextOut16( hdc
, x
, y
, (LPCSTR
)PTR_SEG_TO_LIN(lParam
), cch
);
406 SetTextColor32( hdc
, current_color
);
411 /***********************************************************************
412 * GrayString32A (USER32.314)
414 BOOL32
GrayString32A( HDC32 hdc
, HBRUSH32 hbr
, GRAYSTRINGPROC32 gsprc
,
415 LPARAM lParam
, INT32 cch
, INT32 x
, INT32 y
,
419 COLORREF current_color
;
421 if (!cch
) cch
= lstrlen32A( (LPCSTR
)lParam
);
422 if (gsprc
) return gsprc( hdc
, lParam
, cch
);
423 current_color
= SetTextColor32( hdc
, GetSysColor32(COLOR_GRAYTEXT
) );
424 ret
= TextOut32A( hdc
, x
, y
, (LPCSTR
)lParam
, cch
);
425 SetTextColor32( hdc
, current_color
);
430 /***********************************************************************
431 * GrayString32W (USER32.315)
433 BOOL32
GrayString32W( HDC32 hdc
, HBRUSH32 hbr
, GRAYSTRINGPROC32 gsprc
,
434 LPARAM lParam
, INT32 cch
, INT32 x
, INT32 y
,
438 COLORREF current_color
;
440 if (!cch
) cch
= lstrlen32W( (LPCWSTR
)lParam
);
441 if (gsprc
) return gsprc( hdc
, lParam
, cch
);
442 current_color
= SetTextColor32( hdc
, GetSysColor32(COLOR_GRAYTEXT
) );
443 ret
= TextOut32W( hdc
, x
, y
, (LPCWSTR
)lParam
, cch
);
444 SetTextColor32( hdc
, current_color
);
449 /***********************************************************************
452 * Helper function for TabbedTextOut() and GetTabbedTextExtent().
453 * Note: this doesn't work too well for text-alignment modes other
454 * than TA_LEFT|TA_TOP. But we want bug-for-bug compatibility :-)
456 LONG
TEXT_TabbedTextOut( HDC32 hdc
, INT32 x
, INT32 y
, LPCSTR lpstr
,
457 INT32 count
, INT32 cTabStops
, const INT16
*lpTabPos16
,
458 const INT32
*lpTabPos32
, INT32 nTabOrg
,
459 BOOL32 fDisplayText
)
468 defWidth
= lpTabPos32
? *lpTabPos32
: *lpTabPos16
;
474 GetTextMetrics16( hdc
, &tm
);
475 defWidth
= 8 * tm
.tmAveCharWidth
;
480 for (i
= 0; i
< count
; i
++)
481 if (lpstr
[i
] == '\t') break;
482 extent
= GetTextExtent( hdc
, lpstr
, i
);
485 while ((cTabStops
> 0) &&
486 (nTabOrg
+ *lpTabPos32
<= x
+ LOWORD(extent
)))
494 while ((cTabStops
> 0) &&
495 (nTabOrg
+ *lpTabPos16
<= x
+ LOWORD(extent
)))
502 tabPos
= x
+ LOWORD(extent
);
503 else if (cTabStops
> 0)
504 tabPos
= nTabOrg
+ (lpTabPos32
? *lpTabPos32
: *lpTabPos16
);
506 tabPos
= nTabOrg
+ ((x
+ LOWORD(extent
) - nTabOrg
) / defWidth
+ 1) * defWidth
;
510 SetRect32( &r
, x
, y
, tabPos
, y
+HIWORD(extent
) );
511 ExtTextOut32A( hdc
, x
, y
,
512 GetBkMode32(hdc
) == OPAQUE
? ETO_OPAQUE
: 0,
513 &r
, lpstr
, i
, NULL
);
519 return MAKELONG(tabPos
- start
, HIWORD(extent
));
523 /***********************************************************************
524 * TabbedTextOut16 (USER.196)
526 LONG
TabbedTextOut16( HDC16 hdc
, INT16 x
, INT16 y
, LPCSTR lpstr
, INT16 count
,
527 INT16 cTabStops
, const INT16
*lpTabPos
, INT16 nTabOrg
)
529 dprintf_text( stddeb
, "TabbedTextOut16: %04x %d,%d '%.*s' %d\n",
530 hdc
, x
, y
, count
, lpstr
, count
);
531 return TEXT_TabbedTextOut( hdc
, x
, y
, lpstr
, count
, cTabStops
,
532 lpTabPos
, NULL
, nTabOrg
, TRUE
);
536 /***********************************************************************
537 * TabbedTextOut32A (USER32.541)
539 LONG
TabbedTextOut32A( HDC32 hdc
, INT32 x
, INT32 y
, LPCSTR lpstr
, INT32 count
,
540 INT32 cTabStops
, const INT32
*lpTabPos
, INT32 nTabOrg
)
542 dprintf_text( stddeb
, "TabbedTextOut32A: %04x %d,%d '%.*s' %d\n",
543 hdc
, x
, y
, count
, lpstr
, count
);
544 return TEXT_TabbedTextOut( hdc
, x
, y
, lpstr
, count
, cTabStops
,
545 NULL
, lpTabPos
, nTabOrg
, TRUE
);
549 /***********************************************************************
550 * TabbedTextOut32W (USER32.542)
552 LONG
TabbedTextOut32W( HDC32 hdc
, INT32 x
, INT32 y
, LPCWSTR str
, INT32 count
,
553 INT32 cTabStops
, const INT32
*lpTabPos
, INT32 nTabOrg
)
556 LPSTR p
= HEAP_xalloc( GetProcessHeap(), 0, count
+ 1 );
557 lstrcpynWtoA( p
, str
, count
+ 1 );
558 ret
= TabbedTextOut32A( hdc
, x
, y
, p
, count
, cTabStops
,
560 HeapFree( GetProcessHeap(), 0, p
);
565 /***********************************************************************
566 * GetTabbedTextExtent16 (USER.197)
568 DWORD
GetTabbedTextExtent16( HDC16 hdc
, LPCSTR lpstr
, INT16 count
,
569 INT16 cTabStops
, const INT16
*lpTabPos
)
571 dprintf_text( stddeb
, "GetTabbedTextExtent: %04x '%.*s' %d\n",
572 hdc
, count
, lpstr
, count
);
573 return TEXT_TabbedTextOut( hdc
, 0, 0, lpstr
, count
, cTabStops
,
574 lpTabPos
, NULL
, 0, FALSE
);
578 /***********************************************************************
579 * GetTabbedTextExtent32A (USER32.292)
581 DWORD
GetTabbedTextExtent32A( HDC32 hdc
, LPCSTR lpstr
, INT32 count
,
582 INT32 cTabStops
, const INT32
*lpTabPos
)
584 dprintf_text( stddeb
, "GetTabbedTextExtent: %04x '%.*s' %d\n",
585 hdc
, count
, lpstr
, count
);
586 return TEXT_TabbedTextOut( hdc
, 0, 0, lpstr
, count
, cTabStops
,
587 NULL
, lpTabPos
, 0, FALSE
);
591 /***********************************************************************
592 * GetTabbedTextExtent32W (USER32.293)
594 DWORD
GetTabbedTextExtent32W( HDC32 hdc
, LPCWSTR lpstr
, INT32 count
,
595 INT32 cTabStops
, const INT32
*lpTabPos
)
598 LPSTR p
= HEAP_xalloc( GetProcessHeap(), 0, count
+ 1 );
599 lstrcpynWtoA( p
, lpstr
, count
+ 1 );
600 ret
= GetTabbedTextExtent32A( hdc
, p
, count
, cTabStops
, lpTabPos
);
601 HeapFree( GetProcessHeap(), 0, p
);
605 /***********************************************************************
606 * GetTextCharset (USER32.226) (USER.612)
608 INT32
GetTextCharset32(HDC32 hdc
) {
609 fprintf(stdnimp
,"GetTextCharset(0x%x)\n",hdc
);
610 return DEFAULT_CHARSET
; /* FIXME */
613 INT16
GetTextCharset16(HDC16 hdc
) {
614 return GetTextCharset32(hdc
);