Added __wine_get_main_args to retrieve command-line arguments for the
[wine/multimedia.git] / dlls / user / text.c
blob31dcfc2501391e4d787b1320fad5c7472c24cf10
1 /*
2 * USER text functions
4 * Copyright 1993, 1994 Alexandre Julliard
6 */
8 #include <string.h>
10 #include "windef.h"
11 #include "wingdi.h"
12 #include "wine/winuser16.h"
13 #include "winbase.h"
14 #include "winerror.h"
15 #include "winnls.h"
16 #include "cache.h"
17 #include "ldt.h"
18 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(text);
22 #define TAB 9
23 #define LF 10
24 #define CR 13
25 #define SPACE 32
26 #define PREFIX 38
28 #define ELLIPSIS "..."
29 #define FORWARD_SLASH '/'
30 #define BACK_SLASH '\\'
32 #define SWAP_INT(a,b) { int t = a; a = b; b = t; }
34 static int tabstop = 8;
35 static int tabwidth;
36 static int spacewidth;
37 static int prefix_offset;
39 static const char *TEXT_NextLine( HDC hdc, const char *str, int *count,
40 char *dest, int *len, int width, WORD format)
42 /* Return next line of text from a string.
44 * hdc - handle to DC.
45 * str - string to parse into lines.
46 * count - length of str.
47 * dest - destination in which to return line.
48 * len - length of resultant line in dest in chars.
49 * width - maximum width of line in pixels.
50 * format - format type passed to DrawText.
52 * Returns pointer to next char in str after end of the line
53 * or NULL if end of str reached.
56 /* FIXME:
57 * GetTextExtentPoint is used to get the width of each character,
58 * rather than GetCharABCWidth... So the whitespace between
59 * characters is ignored, and the reported len is too great.
62 int i = 0, j = 0, k;
63 int plen = 0;
64 int numspaces;
65 SIZE size;
66 int lasttab = 0;
67 int wb_i = 0, wb_j = 0, wb_count = 0;
69 while (*count)
71 switch (str[i])
73 case CR:
74 case LF:
75 if (!(format & DT_SINGLELINE))
77 if ((*count > 1) && (str[i] == CR) && (str[i+1] == LF))
79 (*count)--;
80 i++;
82 i++;
83 *len = j;
84 (*count)--;
85 return (&str[i]);
87 dest[j++] = str[i++];
88 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
89 (format & DT_WORDBREAK))
91 if (!GetTextExtentPointA(hdc, &dest[j-1], 1, &size))
92 return NULL;
93 plen += size.cx;
95 break;
97 case PREFIX:
98 if (!(format & DT_NOPREFIX) && *count > 1)
100 if (str[++i] == PREFIX)
101 (*count)--;
102 else {
103 prefix_offset = j;
104 break;
107 dest[j++] = str[i++];
108 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
109 (format & DT_WORDBREAK))
111 if (!GetTextExtentPointA(hdc, &dest[j-1], 1, &size))
112 return NULL;
113 plen += size.cx;
115 break;
117 case TAB:
118 if (format & DT_EXPANDTABS)
120 wb_i = ++i;
121 wb_j = j;
122 wb_count = *count;
124 if (!GetTextExtentPointA(hdc, &dest[lasttab], j - lasttab, &size))
125 return NULL;
127 numspaces = (tabwidth - size.cx) / spacewidth;
128 for (k = 0; k < numspaces; k++)
129 dest[j++] = SPACE;
130 plen += tabwidth - size.cx;
131 lasttab = wb_j + numspaces;
133 else
135 dest[j++] = str[i++];
136 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
137 (format & DT_WORDBREAK))
139 if (!GetTextExtentPointA(hdc, &dest[j-1], 1, &size))
140 return NULL;
141 plen += size.cx;
144 break;
146 case SPACE:
147 dest[j++] = str[i++];
148 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
149 (format & DT_WORDBREAK))
151 wb_i = i;
152 wb_j = j - 1;
153 wb_count = *count;
154 if (!GetTextExtentPointA(hdc, &dest[j-1], 1, &size))
155 return NULL;
156 plen += size.cx;
158 break;
160 default:
161 dest[j++] = str[i++];
162 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
163 (format & DT_WORDBREAK))
165 if (!GetTextExtentPointA(hdc, &dest[j-1], 1, &size))
166 return NULL;
167 plen += size.cx;
171 (*count)--;
172 if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
174 if (plen > width)
176 if (format & DT_WORDBREAK)
178 if (wb_j)
180 *len = wb_j;
181 *count = wb_count - 1;
182 return (&str[wb_i]);
185 else
187 *len = j;
188 return (&str[i]);
194 *len = j;
195 return NULL;
199 /***********************************************************************
200 * DrawText16 (USER.85)
202 INT16 WINAPI DrawText16( HDC16 hdc, LPCSTR str, INT16 count, LPRECT16 rect, UINT16 flags )
204 INT16 ret;
206 if (rect)
208 RECT rect32;
209 CONV_RECT16TO32( rect, &rect32 );
210 ret = DrawTextA( hdc, str, count, &rect32, flags );
211 CONV_RECT32TO16( &rect32, rect );
213 else ret = DrawTextA( hdc, str, count, NULL, flags);
214 return ret;
218 /***********************************************************************
219 * DrawTextA (USER32.164)
221 INT WINAPI DrawTextA( HDC hdc, LPCSTR str, INT i_count, LPRECT rect, UINT flags )
223 SIZE size;
224 const char *strPtr;
225 static char line[1024];
226 int len, lh, count=i_count;
227 int prefix_x = 0;
228 int prefix_end = 0;
229 TEXTMETRICA tm;
230 int x = rect->left, y = rect->top;
231 int width = rect->right - rect->left;
232 int max_width = 0;
234 TRACE("%s, %d , [(%d,%d),(%d,%d)]\n",
235 debugstr_an (str, count), count,
236 rect->left, rect->top, rect->right, rect->bottom);
238 if (!str) return 0;
239 if (count == -1) count = strlen(str);
240 if (count == 0) return 0;
241 strPtr = str;
243 GetTextMetricsA(hdc, &tm);
244 if (flags & DT_EXTERNALLEADING)
245 lh = tm.tmHeight + tm.tmExternalLeading;
246 else
247 lh = tm.tmHeight;
249 if (flags & DT_TABSTOP)
250 tabstop = flags >> 8;
252 if (flags & DT_EXPANDTABS)
254 GetTextExtentPointA(hdc, " ", 1, &size);
255 spacewidth = size.cx;
256 GetTextExtentPointA(hdc, "o", 1, &size);
257 tabwidth = size.cx * tabstop;
260 if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
264 prefix_offset = -1;
265 strPtr = TEXT_NextLine(hdc, strPtr, &count, line, &len, width, flags);
267 if (prefix_offset != -1)
269 GetTextExtentPointA(hdc, line, prefix_offset, &size);
270 prefix_x = size.cx;
271 GetTextExtentPointA(hdc, line, prefix_offset + 1, &size);
272 prefix_end = size.cx - 1;
275 if (!GetTextExtentPointA(hdc, line, len, &size)) return 0;
276 if (flags & DT_CENTER) x = (rect->left + rect->right -
277 size.cx) / 2;
278 else if (flags & DT_RIGHT) x = rect->right - size.cx;
280 if (flags & DT_SINGLELINE)
282 if (flags & DT_VCENTER) y = rect->top +
283 (rect->bottom - rect->top) / 2 - size.cy / 2;
284 else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
286 if (flags & (DT_PATH_ELLIPSIS | DT_END_ELLIPSIS | DT_WORD_ELLIPSIS))
288 char swapStr[sizeof(line)];
289 char* fnameDelim = NULL;
290 int totalLen = i_count >= 0 ? i_count : strlen(str);
292 if (size.cx > width)
294 int fnameLen = totalLen;
296 /* allow room for '...' */
297 count = min(totalLen+3, sizeof(line)-3);
299 if (flags & DT_WORD_ELLIPSIS)
300 flags |= DT_WORDBREAK;
302 if (flags & DT_PATH_ELLIPSIS)
304 char* lastBkSlash = NULL;
305 char* lastFwdSlash = NULL;
306 strncpy(line, str, totalLen); line[totalLen] = '\0';
307 lastBkSlash = strrchr(line, BACK_SLASH);
308 lastFwdSlash = strrchr(line, FORWARD_SLASH);
309 fnameDelim = lastFwdSlash ? lastFwdSlash : lastBkSlash;
310 if (lastBkSlash && lastFwdSlash) /* which is last? */
311 if (lastBkSlash > lastFwdSlash)
312 fnameDelim = lastBkSlash;
314 if (fnameDelim)
315 fnameLen = &line[totalLen] - fnameDelim;
316 else
317 fnameDelim = (char*)str;
319 strcpy(swapStr, ELLIPSIS);
320 strncat(swapStr, fnameDelim, fnameLen);
321 swapStr[fnameLen+3] = '\0';
322 strncat(swapStr, str, totalLen - fnameLen);
323 swapStr[totalLen+3] = '\0';
325 else /* DT_END_ELLIPSIS | DT_WORD_ELLIPSIS */
327 strcpy(swapStr, ELLIPSIS);
328 strncat(swapStr, str, totalLen);
331 TEXT_NextLine(hdc, swapStr, &count, line, &len, width, flags);
333 /* if only the ELLIPSIS will fit, just let it be clipped */
334 len = max(3, len);
335 GetTextExtentPointA(hdc, line, len, &size);
337 /* FIXME:
338 * NextLine uses GetTextExtentPoint for each character,
339 * rather than GetCharABCWidth... So the whitespace between
340 * characters is ignored in the width measurement, and the
341 * reported len is too great. To compensate, we must get
342 * the width of the entire line and adjust len accordingly.
344 while ((size.cx > width) && (len > 3))
346 line[--len] = '\0';
347 GetTextExtentPointA(hdc, line, len, &size);
350 if (fnameLen < len-3) /* some of the path will fit */
352 /* put the ELLIPSIS between the path and filename */
353 strncpy(swapStr, &line[fnameLen+3], len-3-fnameLen);
354 swapStr[len-3-fnameLen] = '\0';
355 strcat(swapStr, ELLIPSIS);
356 strncat(swapStr, &line[3], fnameLen);
358 else
360 /* move the ELLIPSIS to the end */
361 strncpy(swapStr, &line[3], len-3);
362 swapStr[len-3] = '\0';
363 strcat(swapStr, ELLIPSIS);
366 strncpy(line, swapStr, len);
367 line[len] = '\0';
368 strPtr = NULL;
372 if (!(flags & DT_CALCRECT))
374 if (!ExtTextOutA(hdc, x, y, (flags & DT_NOCLIP) ? 0 : ETO_CLIPPED,
375 rect, line, len, NULL )) return 0;
376 if (prefix_offset != -1)
378 HPEN hpen = CreatePen( PS_SOLID, 1, GetTextColor(hdc) );
379 HPEN oldPen = SelectObject( hdc, hpen );
380 MoveToEx(hdc, x + prefix_x, y + tm.tmAscent + 1, NULL );
381 LineTo(hdc, x + prefix_end + 1, y + tm.tmAscent + 1 );
382 SelectObject( hdc, oldPen );
383 DeleteObject( hpen );
386 else if (size.cx > max_width)
387 max_width = size.cx;
389 y += lh;
390 if (strPtr)
392 if (!(flags & DT_NOCLIP))
394 if (y > rect->bottom - lh)
395 break;
399 while (strPtr);
400 if (flags & DT_CALCRECT)
402 rect->right = rect->left + max_width;
403 rect->bottom = y;
405 return y - rect->top;
409 /***********************************************************************
410 * DrawTextW (USER32.167)
412 INT WINAPI DrawTextW( HDC hdc, LPCWSTR str, INT count,
413 LPRECT rect, UINT flags )
415 LPSTR p;
416 INT acount;
417 INT ret;
418 UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
420 acount = WideCharToMultiByte(codepage,0,str,count,NULL,0,NULL,NULL);
421 p = HeapAlloc( GetProcessHeap(), 0, acount );
422 acount = WideCharToMultiByte(codepage,0,str,count,p,acount,NULL,NULL);
423 if (count == -1) acount = -1;
424 ret = DrawTextA( hdc, p, acount, rect, flags );
426 HeapFree( GetProcessHeap(), 0, p );
427 return ret;
430 /***********************************************************************
431 * DrawTextExA (USER32.165)
433 INT WINAPI DrawTextExA( HDC hdc, LPCSTR str, INT count,
434 LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp )
436 TRACE("(%d,'%s',%d,%p,0x%08x,%p)\n",hdc,str,count,rect,flags,dtp);
437 if(dtp) {
438 FIXME("Ignores params:%d,%d,%d,%d\n",dtp->cbSize,
439 dtp->iTabLength,dtp->iLeftMargin,dtp->iRightMargin);
441 return DrawTextA(hdc,str,count,rect,flags);
444 /***********************************************************************
445 * DrawTextExW (USER32.166)
447 INT WINAPI DrawTextExW( HDC hdc, LPCWSTR str, INT count,
448 LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp )
450 TRACE("(%d,%p,%d,%p,0x%08x,%p)\n",hdc,str,count,rect,flags,dtp);
451 FIXME("ignores extended functionality\n");
452 return DrawTextW(hdc,str,count,rect,flags);
454 /***********************************************************************
455 * TEXT_GrayString
457 * FIXME: The call to 16-bit code only works because the wine GDI is a 16-bit
458 * heap and we can guarantee that the handles fit in an INT16. We have to
459 * rethink the strategy once the migration to NT handles is complete.
460 * We are going to get a lot of code-duplication once this migration is
461 * completed...
464 static BOOL TEXT_GrayString(HDC hdc, HBRUSH hb, GRAYSTRINGPROC fn, LPARAM lp, INT len,
465 INT x, INT y, INT cx, INT cy, BOOL unicode, BOOL _32bit)
467 HBITMAP hbm, hbmsave;
468 HBRUSH hbsave;
469 HFONT hfsave;
470 HDC memdc = CreateCompatibleDC(hdc);
471 int slen = len;
472 BOOL retval = TRUE;
473 COLORREF fg, bg;
475 if(!hdc) return FALSE;
477 if(len == 0)
479 if(unicode)
480 slen = lstrlenW((LPCWSTR)lp);
481 else if(_32bit)
482 slen = strlen((LPCSTR)lp);
483 else
484 slen = strlen((LPCSTR)PTR_SEG_TO_LIN(lp));
487 if((cx == 0 || cy == 0) && slen != -1)
489 SIZE s;
490 if(unicode)
491 GetTextExtentPoint32W(hdc, (LPCWSTR)lp, slen, &s);
492 else if(_32bit)
493 GetTextExtentPoint32A(hdc, (LPCSTR)lp, slen, &s);
494 else
495 GetTextExtentPoint32A(hdc, (LPCSTR)PTR_SEG_TO_LIN(lp), slen, &s);
496 if(cx == 0) cx = s.cx;
497 if(cy == 0) cy = s.cy;
500 hbm = CreateBitmap(cx, cy, 1, 1, NULL);
501 hbmsave = (HBITMAP)SelectObject(memdc, hbm);
502 hbsave = SelectObject( memdc, GetStockObject(BLACK_BRUSH) );
503 PatBlt( memdc, 0, 0, cx, cy, PATCOPY );
504 SelectObject( memdc, hbsave );
505 SetTextColor(memdc, RGB(255, 255, 255));
506 SetBkColor(memdc, RGB(0, 0, 0));
507 hfsave = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT));
509 if(fn)
510 if(_32bit)
511 retval = fn(memdc, lp, slen);
512 else
513 retval = (BOOL)((BOOL16)((GRAYSTRINGPROC16)fn)((HDC16)memdc, lp, (INT16)slen));
514 else
515 if(unicode)
516 TextOutW(memdc, 0, 0, (LPCWSTR)lp, slen);
517 else if(_32bit)
518 TextOutA(memdc, 0, 0, (LPCSTR)lp, slen);
519 else
520 TextOutA(memdc, 0, 0, (LPCSTR)PTR_SEG_TO_LIN(lp), slen);
522 SelectObject(memdc, hfsave);
525 * Windows doc says that the bitmap isn't grayed when len == -1 and
526 * the callback function returns FALSE. However, testing this on
527 * win95 showed otherwise...
529 #ifdef GRAYSTRING_USING_DOCUMENTED_BEHAVIOUR
530 if(retval || len != -1)
531 #endif
533 hbsave = (HBRUSH)SelectObject(memdc, CACHE_GetPattern55AABrush());
534 PatBlt(memdc, 0, 0, cx, cy, 0x000A0329);
535 SelectObject(memdc, hbsave);
538 if(hb) hbsave = (HBRUSH)SelectObject(hdc, hb);
539 fg = SetTextColor(hdc, RGB(0, 0, 0));
540 bg = SetBkColor(hdc, RGB(255, 255, 255));
541 BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00E20746);
542 SetTextColor(hdc, fg);
543 SetBkColor(hdc, bg);
544 if(hb) SelectObject(hdc, hbsave);
546 SelectObject(memdc, hbmsave);
547 DeleteObject(hbm);
548 DeleteDC(memdc);
549 return retval;
553 /***********************************************************************
554 * GrayString16 (USER.185)
556 BOOL16 WINAPI GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 gsprc,
557 LPARAM lParam, INT16 cch, INT16 x, INT16 y,
558 INT16 cx, INT16 cy )
560 return TEXT_GrayString(hdc, hbr, (GRAYSTRINGPROC)gsprc, lParam, cch, x, y, cx, cy, FALSE, FALSE);
564 /***********************************************************************
565 * GrayStringA (USER32.315)
567 BOOL WINAPI GrayStringA( HDC hdc, HBRUSH hbr, GRAYSTRINGPROC gsprc,
568 LPARAM lParam, INT cch, INT x, INT y,
569 INT cx, INT cy )
571 return TEXT_GrayString(hdc, hbr, gsprc, lParam, cch, x, y, cx, cy, FALSE, TRUE);
575 /***********************************************************************
576 * GrayStringW (USER32.316)
578 BOOL WINAPI GrayStringW( HDC hdc, HBRUSH hbr, GRAYSTRINGPROC gsprc,
579 LPARAM lParam, INT cch, INT x, INT y,
580 INT cx, INT cy )
582 return TEXT_GrayString(hdc, hbr, gsprc, lParam, cch, x, y, cx, cy, TRUE, TRUE);
585 /***********************************************************************
586 * TEXT_TabbedTextOut
588 * Helper function for TabbedTextOut() and GetTabbedTextExtent().
589 * Note: this doesn't work too well for text-alignment modes other
590 * than TA_LEFT|TA_TOP. But we want bug-for-bug compatibility :-)
592 static LONG TEXT_TabbedTextOut( HDC hdc, INT x, INT y, LPCSTR lpstr,
593 INT count, INT cTabStops, const INT16 *lpTabPos16,
594 const INT *lpTabPos32, INT nTabOrg,
595 BOOL fDisplayText )
597 INT defWidth;
598 SIZE extent;
599 int i, tabPos = x;
600 int start = x;
602 extent.cx = 0;
603 extent.cy = 0;
605 if (cTabStops == 1)
607 defWidth = lpTabPos32 ? *lpTabPos32 : *lpTabPos16;
608 cTabStops = 0;
610 else
612 TEXTMETRICA tm;
613 GetTextMetricsA( hdc, &tm );
614 defWidth = 8 * tm.tmAveCharWidth;
617 while (count > 0)
619 for (i = 0; i < count; i++)
620 if (lpstr[i] == '\t') break;
621 GetTextExtentPointA( hdc, lpstr, i, &extent );
622 if (lpTabPos32)
624 while ((cTabStops > 0) &&
625 (nTabOrg + *lpTabPos32 <= x + extent.cx))
627 lpTabPos32++;
628 cTabStops--;
631 else
633 while ((cTabStops > 0) &&
634 (nTabOrg + *lpTabPos16 <= x + extent.cx))
636 lpTabPos16++;
637 cTabStops--;
640 if (i == count)
641 tabPos = x + extent.cx;
642 else if (cTabStops > 0)
643 tabPos = nTabOrg + (lpTabPos32 ? *lpTabPos32 : *lpTabPos16);
644 else
645 tabPos = nTabOrg + ((x + extent.cx - nTabOrg) / defWidth + 1) * defWidth;
646 if (fDisplayText)
648 RECT r;
649 r.left = x;
650 r.top = y;
651 r.right = tabPos;
652 r.bottom = y + extent.cy;
653 ExtTextOutA( hdc, x, y,
654 GetBkMode(hdc) == OPAQUE ? ETO_OPAQUE : 0,
655 &r, lpstr, i, NULL );
657 x = tabPos;
658 count -= i+1;
659 lpstr += i+1;
661 return MAKELONG(tabPos - start, extent.cy);
665 /***********************************************************************
666 * TabbedTextOut16 (USER.196)
668 LONG WINAPI TabbedTextOut16( HDC16 hdc, INT16 x, INT16 y, LPCSTR lpstr,
669 INT16 count, INT16 cTabStops,
670 const INT16 *lpTabPos, INT16 nTabOrg )
672 TRACE("%04x %d,%d '%.*s' %d\n",
673 hdc, x, y, count, lpstr, count );
674 return TEXT_TabbedTextOut( hdc, x, y, lpstr, count, cTabStops,
675 lpTabPos, NULL, nTabOrg, TRUE );
679 /***********************************************************************
680 * TabbedTextOutA (USER32.542)
682 LONG WINAPI TabbedTextOutA( HDC hdc, INT x, INT y, LPCSTR lpstr,
683 INT count, INT cTabStops,
684 const INT *lpTabPos, INT nTabOrg )
686 TRACE("%04x %d,%d '%.*s' %d\n",
687 hdc, x, y, count, lpstr, count );
688 return TEXT_TabbedTextOut( hdc, x, y, lpstr, count, cTabStops,
689 NULL, lpTabPos, nTabOrg, TRUE );
693 /***********************************************************************
694 * TabbedTextOutW (USER32.543)
696 LONG WINAPI TabbedTextOutW( HDC hdc, INT x, INT y, LPCWSTR str,
697 INT count, INT cTabStops,
698 const INT *lpTabPos, INT nTabOrg )
700 LONG ret;
701 LPSTR p;
702 INT acount;
703 UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
705 acount = WideCharToMultiByte(codepage,0,str,count,NULL,0,NULL,NULL);
706 p = HeapAlloc( GetProcessHeap(), 0, acount );
707 if(p == NULL) return 0; /* FIXME: is this the correct return on failure */
708 acount = WideCharToMultiByte(codepage,0,str,count,p,acount,NULL,NULL);
709 ret = TabbedTextOutA( hdc, x, y, p, acount, cTabStops,
710 lpTabPos, nTabOrg );
711 HeapFree( GetProcessHeap(), 0, p );
712 return ret;
716 /***********************************************************************
717 * GetTabbedTextExtent16 (USER.197)
719 DWORD WINAPI GetTabbedTextExtent16( HDC16 hdc, LPCSTR lpstr, INT16 count,
720 INT16 cTabStops, const INT16 *lpTabPos )
722 TRACE("%04x '%.*s' %d\n",
723 hdc, count, lpstr, count );
724 return TEXT_TabbedTextOut( hdc, 0, 0, lpstr, count, cTabStops,
725 lpTabPos, NULL, 0, FALSE );
729 /***********************************************************************
730 * GetTabbedTextExtentA (USER32.293)
732 DWORD WINAPI GetTabbedTextExtentA( HDC hdc, LPCSTR lpstr, INT count,
733 INT cTabStops, const INT *lpTabPos )
735 TRACE("%04x '%.*s' %d\n",
736 hdc, count, lpstr, count );
737 return TEXT_TabbedTextOut( hdc, 0, 0, lpstr, count, cTabStops,
738 NULL, lpTabPos, 0, FALSE );
742 /***********************************************************************
743 * GetTabbedTextExtentW (USER32.294)
745 DWORD WINAPI GetTabbedTextExtentW( HDC hdc, LPCWSTR lpstr, INT count,
746 INT cTabStops, const INT *lpTabPos )
748 LONG ret;
749 LPSTR p;
750 INT acount;
751 UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
753 acount = WideCharToMultiByte(codepage,0,lpstr,count,NULL,0,NULL,NULL);
754 p = HeapAlloc( GetProcessHeap(), 0, acount );
755 if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
756 acount = WideCharToMultiByte(codepage,0,lpstr,count,p,acount,NULL,NULL);
757 ret = GetTabbedTextExtentA( hdc, p, acount, cTabStops, lpTabPos );
758 HeapFree( GetProcessHeap(), 0, p );
759 return ret;