/* * @implemented */ LONG WINAPI TabbedTextOutA( HDC hDC, int X, int Y, LPCSTR lpString, int nCount, int nTabPositions, CONST INT *lpnTabStopPositions, int nTabOrigin) { LONG ret; DWORD len; LPWSTR strW; UINT cp = GdiGetCodePage( hDC ); // CP_ACP len = MultiByteToWideChar(cp, 0, lpString, nCount, NULL, 0); if (!len) return 0; strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); if (!strW) return 0; MultiByteToWideChar(cp, 0, lpString, nCount, strW, len); ret = TabbedTextOutW(hDC, X, Y, strW, len, nTabPositions, lpnTabStopPositions, nTabOrigin); HeapFree(GetProcessHeap(), 0, strW); return ret; }
/*********************************************************************** * DrawTextExA (USER32.@) * * If DT_MODIFYSTRING is specified then there must be room for up to * 4 extra characters. We take great care about just how much modified * string we return. */ INT WINAPI DrawTextExA( HDC hdc, LPSTR str, INT count, LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp ) { WCHAR *wstr; WCHAR *p; INT ret = 0; int i; DWORD wcount; DWORD wmax; DWORD amax; UINT cp; if (!count) return 0; if( !str || ((count == -1) && !(count = strlen(str)))) { if( flags & DT_CALCRECT) { rect->right = rect->left; rect->bottom = rect->top; } return 0; } cp = GdiGetCodePage( hdc ); wcount = MultiByteToWideChar( cp, 0, str, count, NULL, 0 ); wmax = wcount; amax = count; if (flags & DT_MODIFYSTRING) { wmax += 4; amax += 4; } wstr = HeapAlloc(GetProcessHeap(), 0, wmax * sizeof(WCHAR)); if (wstr) { MultiByteToWideChar( cp, 0, str, count, wstr, wcount ); if (flags & DT_MODIFYSTRING) for (i=4, p=wstr+wcount; i--; p++) *p=0xFFFE; /* Initialise the extra characters so that we can see which ones * change. U+FFFE is guaranteed to be not a unicode character and * so will not be generated by DrawTextEx itself. */ ret = DrawTextExW( hdc, wstr, wcount, rect, flags, dtp ); if (flags & DT_MODIFYSTRING) { /* Unfortunately the returned string may contain multiple \0s * and so we need to measure it ourselves. */ for (i=4, p=wstr+wcount; i-- && *p != 0xFFFE; p++) wcount++; WideCharToMultiByte( cp, 0, wstr, wcount, str, amax, NULL, NULL ); } HeapFree(GetProcessHeap(), 0, wstr); } return ret; }
int DrawTextExA( HDC hdc, LPSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp) { LPWSTR lpwstr; int iRet; int iUniString; WORD wCodePage = (WORD)GdiGetCodePage(hdc); if (cchText == -1) { // USER_AWCONV_COUNTSTRINGSZ does not count/convert trailing \0. cchText = USER_AWCONV_COUNTSTRINGSZ; } else if (cchText < -1) { return 0; } if ((iUniString = MBToWCSEx(wCodePage, lpchText, cchText, &lpwstr, -1, TRUE)) == 0) { if (cchText == USER_AWCONV_COUNTSTRINGSZ) { lpwstr = (LPWSTR)gwszNullStr; format &= ~DT_MODIFYSTRING; } else { return 0; } } /* * Grow the buffer to accomodate the ellipsis (see AddEllipsisAndDrawLine) */ if (format & DT_MODIFYSTRING) { int iNewLen = (iUniString + CCHELLIPSIS + 1) * sizeof(*lpwstr); LPWSTR lpwstrNew = UserLocalReAlloc(lpwstr, iNewLen, HEAP_ZERO_MEMORY); if (lpwstrNew == NULL) { UserLocalFree((HANDLE)lpwstr); return FALSE; } lpwstr = lpwstrNew; } iRet = DrawTextExWorker(hdc, lpwstr, iUniString, lprc, format, lpdtp, GetTextCharset(hdc)); if (format & DT_MODIFYSTRING) { /* * Note that if the buffer grew and the caller provided the string size, * then we won't return the additional characters... fixing this * might break some apps so let's leave it alone until some one complains */ if (cchText < 0) { UserAssert(cchText == USER_AWCONV_COUNTSTRINGSZ); // Guess how many bytes we can put in the buffer... // We can safely assume the maximum bytes available. // At worst, even for DBCS, the buffer size required // will be smaller than or equal to the orignal size, // because some DBCS characters would be substituted // to SBC ".", which is one byte each. // On the other hand, the number of characters converted // is limited by both iUniString and cchText. // if (IS_DBCS_ENABLED()) { cchText = iUniString * DBCS_CHARSIZE; } else { cchText = iUniString * sizeof(CHAR); } } WCSToMBEx(wCodePage, lpwstr, iUniString, &lpchText, cchText, FALSE); } if (lpwstr != gwszNullStr) { UserLocalFree((HANDLE)lpwstr); } return iRet; }