4 * Copyright 1993, 1994 Alexandre Julliard
14 /* #define DEBUG_TEXT */
23 #define SWAP_INT(a,b) { int t = a; a = b; b = t; }
25 static int tabstop = 8;
27 static int spacewidth;
28 static int prefix_offset;
30 static const char *TEXT_NextLine( HDC16 hdc, const char *str, int *count,
31 char *dest, int *len, int width, WORD format)
33 /* Return next line of text from a string.
36 * str - string to parse into lines.
37 * count - length of str.
38 * dest - destination in which to return line.
39 * len - length of resultant line in dest in chars.
40 * width - maximum width of line in pixels.
41 * format - format type passed to DrawText.
43 * Returns pointer to next char in str after end of the line
44 * or NULL if end of str reached.
52 int wb_i = 0, wb_j = 0, wb_count = 0;
60 if (!(format & DT_SINGLELINE))
62 if ((*count > 1) && (str[i] == CR) && (str[i+1] == LF))
73 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
74 (format & DT_WORDBREAK))
76 if (!GetTextExtentPoint16(hdc, &dest[j-1], 1, &size))
83 if (!(format & DT_NOPREFIX) && *count > 1)
85 if (str[++i] == PREFIX)
93 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
94 (format & DT_WORDBREAK))
96 if (!GetTextExtentPoint16(hdc, &dest[j-1], 1, &size))
103 if (format & DT_EXPANDTABS)
109 if (!GetTextExtentPoint16(hdc, &dest[lasttab], j - lasttab,
113 numspaces = (tabwidth - size.cx) / spacewidth;
114 for (k = 0; k < numspaces; k++)
116 plen += tabwidth - size.cx;
117 lasttab = wb_j + numspaces;
121 dest[j++] = str[i++];
122 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
123 (format & DT_WORDBREAK))
125 if (!GetTextExtentPoint16(hdc, &dest[j-1], 1, &size))
133 dest[j++] = str[i++];
134 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
135 (format & DT_WORDBREAK))
140 if (!GetTextExtentPoint16(hdc, &dest[j-1], 1, &size))
147 dest[j++] = str[i++];
148 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
149 (format & DT_WORDBREAK))
151 if (!GetTextExtentPoint16(hdc, &dest[j-1], 1, &size))
158 if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
162 if (format & DT_WORDBREAK)
167 *count = wb_count - 1;
185 /***********************************************************************
186 * DrawText16 (USER.85)
188 INT16 WINAPI DrawText16( HDC16 hdc, LPCSTR str, INT16 i_count,
189 LPRECT16 rect, UINT16 flags )
193 static char line[1024];
194 int len, lh, count=i_count;
198 int x = rect->left, y = rect->top;
199 int width = rect->right - rect->left;
202 dprintf_text(stddeb,"DrawText: '%s', %d , [(%d,%d),(%d,%d)]\n", str,
203 count, rect->left, rect->top, rect->right, rect->bottom);
205 if (count == -1) count = strlen(str);
208 GetTextMetrics16(hdc, &tm);
209 if (flags & DT_EXTERNALLEADING)
210 lh = tm.tmHeight + tm.tmExternalLeading;
214 if (flags & DT_TABSTOP)
215 tabstop = flags >> 8;
217 if (flags & DT_EXPANDTABS)
219 GetTextExtentPoint16(hdc, " ", 1, &size);
220 spacewidth = size.cx;
221 GetTextExtentPoint16(hdc, "o", 1, &size);
222 tabwidth = size.cx * tabstop;
225 if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
230 strPtr = TEXT_NextLine(hdc, strPtr, &count, line, &len, width, flags);
232 if (prefix_offset != -1)
234 GetTextExtentPoint16(hdc, line, prefix_offset, &size);
236 GetTextExtentPoint16(hdc, line, prefix_offset + 1, &size);
237 prefix_end = size.cx - 1;
240 if (!GetTextExtentPoint16(hdc, line, len, &size)) return 0;
241 if (flags & DT_CENTER) x = (rect->left + rect->right -
243 else if (flags & DT_RIGHT) x = rect->right - size.cx;
245 if (flags & DT_SINGLELINE)
247 if (flags & DT_VCENTER) y = rect->top +
248 (rect->bottom - rect->top) / 2 - size.cy / 2;
249 else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
251 if (!(flags & DT_CALCRECT))
253 if (!ExtTextOut16(hdc, x, y, (flags & DT_NOCLIP) ? 0 : ETO_CLIPPED,
254 rect, line, len, NULL )) return 0;
255 if (prefix_offset != -1)
257 HPEN32 hpen = CreatePen32( PS_SOLID, 1, GetTextColor32(hdc) );
258 HPEN32 oldPen = SelectObject32( hdc, hpen );
259 MoveTo(hdc, x + prefix_x, y + tm.tmAscent + 1 );
260 LineTo32(hdc, x + prefix_end + 1, y + tm.tmAscent + 1 );
261 SelectObject32( hdc, oldPen );
262 DeleteObject32( hpen );
265 else if (size.cx > max_width)
271 if (!(flags & DT_NOCLIP))
273 if (y > rect->bottom - lh)
279 if (flags & DT_CALCRECT)
281 rect->right = rect->left + max_width;
284 return y - rect->top;
288 /***********************************************************************
289 * DrawText32A (USER32.163)
291 INT32 WINAPI DrawText32A( HDC32 hdc, LPCSTR str, INT32 count,
292 LPRECT32 rect, UINT32 flags )
298 return DrawText16( (HDC16)hdc, str, (INT16)count, NULL, (UINT16)flags);
299 CONV_RECT32TO16( rect, &rect16 );
300 ret = DrawText16( (HDC16)hdc, str, (INT16)count, &rect16, (UINT16)flags );
301 CONV_RECT16TO32( &rect16, rect );
306 /***********************************************************************
307 * DrawText32W (USER32.166)
309 INT32 WINAPI DrawText32W( HDC32 hdc, LPCWSTR str, INT32 count,
310 LPRECT32 rect, UINT32 flags )
312 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
313 INT32 ret = DrawText32A( hdc, p, count, rect, flags );
314 HeapFree( GetProcessHeap(), 0, p );
318 /***********************************************************************
319 * DrawTextEx32A (USER32.164)
321 INT32 DrawTextEx32A( HDC32 hdc, LPCSTR str, INT32 count,
322 LPRECT32 rect, UINT32 flags, LPDRAWTEXTPARAMS dtp )
324 fprintf(stderr,"DrawTextEx32A(%d,'%s',%d,%p,0x%08x,%p)\n",
325 hdc,str,count,rect,flags,dtp
327 /*FIXME: ignores extended functionality ... */
328 return DrawText32A(hdc,str,count,rect,flags);
331 /***********************************************************************
332 * DrawTextEx32W (USER32.165)
334 INT32 DrawTextEx32W( HDC32 hdc, LPCWSTR str, INT32 count,
335 LPRECT32 rect, UINT32 flags, LPDRAWTEXTPARAMS dtp )
337 fprintf(stderr,"DrawTextEx32A(%d,%p,%d,%p,0x%08x,%p)\n",
338 hdc,str,count,rect,flags,dtp
340 /*FIXME: ignores extended functionality ... */
341 return DrawText32W(hdc,str,count,rect,flags);
344 /***********************************************************************
345 * ExtTextOut16 (GDI.351)
347 BOOL16 WINAPI ExtTextOut16( HDC16 hdc, INT16 x, INT16 y, UINT16 flags,
348 const RECT16 *lprect, LPCSTR str, UINT16 count,
354 LPINT32 lpdx32 = NULL;
356 if (lpDx) lpdx32 = (LPINT32)HEAP_xalloc( GetProcessHeap(), 0,
357 sizeof(INT32)*count );
358 if (lprect) CONV_RECT16TO32(lprect,&rect32);
359 if (lpdx32) for (i=count;i--;) lpdx32[i]=lpDx[i];
360 ret = ExtTextOut32A(hdc,x,y,flags,lprect?&rect32:NULL,str,count,lpdx32);
361 if (lpdx32) HeapFree( GetProcessHeap(), 0, lpdx32 );
368 /***********************************************************************
369 * ExtTextOut32A (GDI32.98)
371 BOOL32 WINAPI ExtTextOut32A( HDC32 hdc, INT32 x, INT32 y, UINT32 flags,
372 const RECT32 *lprect, LPCSTR str, UINT32 count,
375 DC * dc = DC_GetDCPtr( hdc );
376 return dc && dc->funcs->pExtTextOut &&
377 dc->funcs->pExtTextOut(dc,x,y,flags,lprect,str,count,lpDx);
381 /***********************************************************************
382 * ExtTextOut32W (GDI32.99)
384 BOOL32 WINAPI ExtTextOut32W( HDC32 hdc, INT32 x, INT32 y, UINT32 flags,
385 const RECT32 *lprect, LPCWSTR str, UINT32 count,
388 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
389 INT32 ret = ExtTextOut32A( hdc, x, y, flags, lprect, p, count, lpDx );
390 HeapFree( GetProcessHeap(), 0, p );
395 /***********************************************************************
398 BOOL16 WINAPI TextOut16( HDC16 hdc, INT16 x, INT16 y, LPCSTR str, INT16 count )
400 return ExtTextOut16( hdc, x, y, 0, NULL, str, count, NULL );
404 /***********************************************************************
405 * TextOut32A (GDI32.355)
407 BOOL32 WINAPI TextOut32A( HDC32 hdc, INT32 x, INT32 y, LPCSTR str, INT32 count )
409 return ExtTextOut32A( hdc, x, y, 0, NULL, str, count, NULL );
413 /***********************************************************************
414 * TextOut32W (GDI32.356)
416 BOOL32 WINAPI TextOut32W(HDC32 hdc, INT32 x, INT32 y, LPCWSTR str, INT32 count)
418 return ExtTextOut32W( hdc, x, y, 0, NULL, str, count, NULL );
422 /***********************************************************************
423 * GrayString16 (USER.185)
425 BOOL16 WINAPI GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 gsprc,
426 LPARAM lParam, INT16 cch, INT16 x, INT16 y,
430 COLORREF current_color;
432 if (!cch) cch = lstrlen16( (LPCSTR)PTR_SEG_TO_LIN(lParam) );
433 if (gsprc) return gsprc( hdc, lParam, cch );
434 current_color = SetTextColor32( hdc, GetSysColor32(COLOR_GRAYTEXT) );
435 ret = TextOut16( hdc, x, y, (LPCSTR)PTR_SEG_TO_LIN(lParam), cch );
436 SetTextColor32( hdc, current_color );
441 /***********************************************************************
442 * GrayString32A (USER32.314)
444 BOOL32 WINAPI GrayString32A( HDC32 hdc, HBRUSH32 hbr, GRAYSTRINGPROC32 gsprc,
445 LPARAM lParam, INT32 cch, INT32 x, INT32 y,
449 COLORREF current_color;
451 if (!cch) cch = lstrlen32A( (LPCSTR)lParam );
452 if (gsprc) return gsprc( hdc, lParam, cch );
453 current_color = SetTextColor32( hdc, GetSysColor32(COLOR_GRAYTEXT) );
454 ret = TextOut32A( hdc, x, y, (LPCSTR)lParam, cch );
455 SetTextColor32( hdc, current_color );
460 /***********************************************************************
461 * GrayString32W (USER32.315)
463 BOOL32 WINAPI GrayString32W( HDC32 hdc, HBRUSH32 hbr, GRAYSTRINGPROC32 gsprc,
464 LPARAM lParam, INT32 cch, INT32 x, INT32 y,
468 COLORREF current_color;
470 if (!cch) cch = lstrlen32W( (LPCWSTR)lParam );
471 if (gsprc) return gsprc( hdc, lParam, cch );
472 current_color = SetTextColor32( hdc, GetSysColor32(COLOR_GRAYTEXT) );
473 ret = TextOut32W( hdc, x, y, (LPCWSTR)lParam, cch );
474 SetTextColor32( hdc, current_color );
479 /***********************************************************************
482 * Helper function for TabbedTextOut() and GetTabbedTextExtent().
483 * Note: this doesn't work too well for text-alignment modes other
484 * than TA_LEFT|TA_TOP. But we want bug-for-bug compatibility :-)
486 LONG TEXT_TabbedTextOut( HDC32 hdc, INT32 x, INT32 y, LPCSTR lpstr,
487 INT32 count, INT32 cTabStops, const INT16 *lpTabPos16,
488 const INT32 *lpTabPos32, INT32 nTabOrg,
489 BOOL32 fDisplayText )
498 defWidth = lpTabPos32 ? *lpTabPos32 : *lpTabPos16;
504 GetTextMetrics16( hdc, &tm );
505 defWidth = 8 * tm.tmAveCharWidth;
510 for (i = 0; i < count; i++)
511 if (lpstr[i] == '\t') break;
512 extent = GetTextExtent( hdc, lpstr, i );
515 while ((cTabStops > 0) &&
516 (nTabOrg + *lpTabPos32 <= x + LOWORD(extent)))
524 while ((cTabStops > 0) &&
525 (nTabOrg + *lpTabPos16 <= x + LOWORD(extent)))
532 tabPos = x + LOWORD(extent);
533 else if (cTabStops > 0)
534 tabPos = nTabOrg + (lpTabPos32 ? *lpTabPos32 : *lpTabPos16);
536 tabPos = nTabOrg + ((x + LOWORD(extent) - nTabOrg) / defWidth + 1) * defWidth;
540 SetRect32( &r, x, y, tabPos, y+HIWORD(extent) );
541 ExtTextOut32A( hdc, x, y,
542 GetBkMode32(hdc) == OPAQUE ? ETO_OPAQUE : 0,
543 &r, lpstr, i, NULL );
549 return MAKELONG(tabPos - start, HIWORD(extent));
553 /***********************************************************************
554 * TabbedTextOut16 (USER.196)
556 LONG WINAPI TabbedTextOut16( HDC16 hdc, INT16 x, INT16 y, LPCSTR lpstr,
557 INT16 count, INT16 cTabStops,
558 const INT16 *lpTabPos, INT16 nTabOrg )
560 dprintf_text( stddeb, "TabbedTextOut16: %04x %d,%d '%.*s' %d\n",
561 hdc, x, y, count, lpstr, count );
562 return TEXT_TabbedTextOut( hdc, x, y, lpstr, count, cTabStops,
563 lpTabPos, NULL, nTabOrg, TRUE );
567 /***********************************************************************
568 * TabbedTextOut32A (USER32.541)
570 LONG WINAPI TabbedTextOut32A( HDC32 hdc, INT32 x, INT32 y, LPCSTR lpstr,
571 INT32 count, INT32 cTabStops,
572 const INT32 *lpTabPos, INT32 nTabOrg )
574 dprintf_text( stddeb, "TabbedTextOut32A: %04x %d,%d '%.*s' %d\n",
575 hdc, x, y, count, lpstr, count );
576 return TEXT_TabbedTextOut( hdc, x, y, lpstr, count, cTabStops,
577 NULL, lpTabPos, nTabOrg, TRUE );
581 /***********************************************************************
582 * TabbedTextOut32W (USER32.542)
584 LONG WINAPI TabbedTextOut32W( HDC32 hdc, INT32 x, INT32 y, LPCWSTR str,
585 INT32 count, INT32 cTabStops,
586 const INT32 *lpTabPos, INT32 nTabOrg )
589 LPSTR p = HEAP_xalloc( GetProcessHeap(), 0, count + 1 );
590 lstrcpynWtoA( p, str, count + 1 );
591 ret = TabbedTextOut32A( hdc, x, y, p, count, cTabStops,
593 HeapFree( GetProcessHeap(), 0, p );
598 /***********************************************************************
599 * GetTabbedTextExtent16 (USER.197)
601 DWORD WINAPI GetTabbedTextExtent16( HDC16 hdc, LPCSTR lpstr, INT16 count,
602 INT16 cTabStops, const INT16 *lpTabPos )
604 dprintf_text( stddeb, "GetTabbedTextExtent: %04x '%.*s' %d\n",
605 hdc, count, lpstr, count );
606 return TEXT_TabbedTextOut( hdc, 0, 0, lpstr, count, cTabStops,
607 lpTabPos, NULL, 0, FALSE );
611 /***********************************************************************
612 * GetTabbedTextExtent32A (USER32.292)
614 DWORD WINAPI GetTabbedTextExtent32A( HDC32 hdc, LPCSTR lpstr, INT32 count,
615 INT32 cTabStops, const INT32 *lpTabPos )
617 dprintf_text( stddeb, "GetTabbedTextExtent: %04x '%.*s' %d\n",
618 hdc, count, lpstr, count );
619 return TEXT_TabbedTextOut( hdc, 0, 0, lpstr, count, cTabStops,
620 NULL, lpTabPos, 0, FALSE );
624 /***********************************************************************
625 * GetTabbedTextExtent32W (USER32.293)
627 DWORD WINAPI GetTabbedTextExtent32W( HDC32 hdc, LPCWSTR lpstr, INT32 count,
628 INT32 cTabStops, const INT32 *lpTabPos )
631 LPSTR p = HEAP_xalloc( GetProcessHeap(), 0, count + 1 );
632 lstrcpynWtoA( p, lpstr, count + 1 );
633 ret = GetTabbedTextExtent32A( hdc, p, count, cTabStops, lpTabPos );
634 HeapFree( GetProcessHeap(), 0, p );
638 /***********************************************************************
639 * GetTextCharset (USER32.226) (USER.612)
641 INT32 WINAPI GetTextCharset32(HDC32 hdc)
643 fprintf(stdnimp,"GetTextCharset(0x%x)\n",hdc);
644 return DEFAULT_CHARSET; /* FIXME */
647 INT16 WINAPI GetTextCharset16(HDC16 hdc)
649 return GetTextCharset32(hdc);