Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

text.c

Go to the documentation of this file.
00001 /*
00002  * USER text functions
00003  *
00004  * Copyright 1993, 1994 Alexandre Julliard
00005  *
00006  */
00007 
00008 #include <string.h>
00009 
00010 #include "windef.h"
00011 #include "wingdi.h"
00012 #include "wine/winuser16.h"
00013 #include "wine/unicode.h"
00014 #include "winbase.h"
00015 #include "winerror.h"
00016 #include "winnls.h"
00017 #include "user.h"
00018 #include "debugtools.h"
00019 
00020 #ifdef __WIN32OS2__
00021 #define CACHE_GetPattern55AABrush GetPattern55AABrush
00022 
00023 #define MapSL(a)        a
00024 
00025 #define DBG_LOCALLOG    DBG_text
00026 #include "dbglocal.h"
00027 
00028 #endif
00029 
00030 DEFAULT_DEBUG_CHANNEL(text);
00031 
00032 #define TAB     9
00033 #define LF     10
00034 #define CR     13
00035 #define SPACE  32
00036 #define PREFIX 38
00037 
00038 #define ELLIPSIS "..."
00039 #define FORWARD_SLASH '/'
00040 #define BACK_SLASH '\\'
00041 
00042 static const WCHAR SPACEW[] = {' ', 0};
00043 static const WCHAR oW[] = {'o', 0};
00044 static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
00045 static const WCHAR FORWARD_SLASHW[] = {'/', 0};
00046 static const WCHAR BACK_SLASHW[] = {'\\', 0};
00047 
00048 #define SWAP_INT(a,b)  { int t = a; a = b; b = t; }
00049 
00050 static int tabstop = 8;
00051 static int tabwidth;
00052 static int spacewidth;
00053 static int prefix_offset;
00054 
00055 /*********************************************************************
00056  *  Return next line of text from a string.
00057  * 
00058  * hdc - handle to DC.
00059  * str - string to parse into lines.
00060  * count - length of str.
00061  * dest - destination in which to return line.
00062  * len - dest buffer size in chars on input, copied length into dest on output.
00063  * width - maximum width of line in pixels.
00064  * format - format type passed to DrawText.
00065  *
00066  * Returns pointer to next char in str after end of the line
00067  * or NULL if end of str reached.
00068  *
00069  * FIXME:
00070  * GetTextExtentPoint is used to get the width of each character, 
00071  * rather than GetCharABCWidth...  So the whitespace between
00072  * characters is ignored, and the reported len is too great.
00073  */
00074 static const WCHAR *TEXT_NextLineW( HDC hdc, const WCHAR *str, int *count,
00075                                   WCHAR *dest, int *len, int width, WORD format)
00076 {
00077     int i = 0, j = 0, k;
00078     int plen = 0;
00079     int numspaces;
00080     SIZE size;
00081     int lasttab = 0;
00082     int wb_i = 0, wb_j = 0, wb_count = 0;
00083     int maxl = *len;
00084 
00085     while (*count && j < maxl)
00086     {
00087         switch (str[i])
00088         {
00089         case CR:
00090         case LF:
00091             if (!(format & DT_SINGLELINE))
00092             {
00093                 if ((*count > 1) && (str[i] == CR) && (str[i+1] == LF))
00094                 {
00095                     (*count)--;
00096                     i++;
00097                 }
00098                 i++;
00099                 *len = j;
00100                 (*count)--;
00101                 return (&str[i]);
00102             }
00103             dest[j++] = str[i++];
00104             if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
00105                 (format & DT_WORDBREAK))
00106             {
00107                 if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
00108                     return NULL;
00109                 plen += size.cx;
00110             }
00111             break;
00112             
00113         case PREFIX:
00114             if (!(format & DT_NOPREFIX) && *count > 1)
00115                 {
00116                 if (str[++i] == PREFIX)
00117                     (*count)--;
00118                 else {
00119                     prefix_offset = j;
00120                     break;
00121                 }
00122             }
00123             dest[j++] = str[i++];
00124             if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
00125                 (format & DT_WORDBREAK))
00126             {
00127                 if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
00128                     return NULL;
00129                 plen += size.cx;
00130             }
00131             break;
00132             
00133         case TAB:
00134             if (format & DT_EXPANDTABS)
00135             {
00136                 wb_i = ++i;
00137                 wb_j = j;
00138                 wb_count = *count;
00139 
00140                 if (!GetTextExtentPointW(hdc, &dest[lasttab], j - lasttab, &size))
00141                     return NULL;
00142 
00143                 numspaces = (tabwidth - size.cx) / spacewidth;
00144                 for (k = 0; k < numspaces; k++)
00145                     dest[j++] = SPACE;
00146                 plen += tabwidth - size.cx;
00147                 lasttab = wb_j + numspaces;
00148             }
00149             else
00150             {
00151                 dest[j++] = str[i++];
00152                 if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
00153                     (format & DT_WORDBREAK))
00154                 {
00155                     if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
00156                         return NULL;
00157                     plen += size.cx;
00158                 }
00159             }
00160             break;
00161 
00162         case SPACE:
00163             dest[j++] = str[i++];
00164             if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
00165                 (format & DT_WORDBREAK))
00166             {
00167                 wb_i = i;
00168                 wb_j = j - 1;
00169                 wb_count = *count;
00170                 if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
00171                     return NULL;
00172                 plen += size.cx;
00173             }
00174             break;
00175 
00176         default:
00177             dest[j++] = str[i++];
00178             if (!(format & DT_NOCLIP) || !(format & DT_NOPREFIX) ||
00179                 (format & DT_WORDBREAK))
00180             {
00181                 if (!GetTextExtentPointW(hdc, &dest[j-1], 1, &size))
00182                     return NULL;
00183                 plen += size.cx;
00184             }
00185         }
00186 
00187         (*count)--;
00188         if (!(format & DT_NOCLIP) || (format & DT_WORDBREAK))
00189         {
00190             if (plen > width)
00191             {
00192                 if (format & DT_WORDBREAK)
00193                 {
00194                     if (wb_j)
00195                     {
00196                         *len = wb_j;
00197                         *count = wb_count - 1;
00198                         return (&str[wb_i]);
00199                     }
00200                 }
00201                 else
00202                 {
00203                     *len = j;
00204                     return (&str[i]);
00205                 }
00206             }
00207         }
00208     }
00209     
00210     *len = j;
00211     return NULL;
00212 }
00213 
00214 
00215 #ifndef __WIN32OS2__
00216 /***********************************************************************
00217  *           DrawText    (USER.85)
00218  */
00219 INT16 WINAPI DrawText16( HDC16 hdc, LPCSTR str, INT16 count, LPRECT16 rect, UINT16 flags )
00220 {
00221     INT16 ret;
00222 
00223     if (rect)
00224     {
00225         RECT rect32;
00226         CONV_RECT16TO32( rect, &rect32 );
00227         ret = DrawTextA( hdc, str, count, &rect32, flags );
00228         CONV_RECT32TO16( &rect32, rect );
00229     }
00230     else ret = DrawTextA( hdc, str, count, NULL, flags);
00231     return ret;
00232 }
00233 #endif
00234 
00235 /***********************************************************************
00236  *           DrawTextExW    (USER32.@)
00237  */
00238 #define MAX_STATIC_BUFFER 1024
00239 INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count,
00240                         LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp )
00241 {
00242     SIZE size;
00243     const WCHAR *strPtr;
00244     static WCHAR line[MAX_STATIC_BUFFER];
00245     int len, lh, count=i_count;
00246     int prefix_x = 0;
00247     int prefix_end = 0;
00248     TEXTMETRICW tm;
00249     int lmargin = 0, rmargin = 0;
00250     int x = rect->left, y = rect->top;
00251     int width = rect->right - rect->left;
00252     int max_width = 0;
00253 
00254 #ifdef __WIN32OS2__
00255     dprintf(("DrawTextExW: %ls, %d , [(%d,%d),(%d,%d)]\n", str, count,
00256             rect->left, rect->top, rect->right, rect->bottom));
00257 #else
00258     TRACE("%s, %d , [(%d,%d),(%d,%d)]\n", debugstr_wn (str, count), count,
00259           rect->left, rect->top, rect->right, rect->bottom);
00260 #endif
00261 
00262    if (dtp) TRACE("Params: iTabLength=%d, iLeftMargin=%d, iRightMargin=%d\n",
00263           dtp->iTabLength, dtp->iLeftMargin, dtp->iRightMargin);
00264 
00265     if (!str) return 0;
00266     if (count == -1) count = strlenW(str);
00267     if (count == 0) return 0;
00268     strPtr = str;
00269 
00270     GetTextMetricsW(hdc, &tm);
00271     if (flags & DT_EXTERNALLEADING)
00272         lh = tm.tmHeight + tm.tmExternalLeading;
00273     else
00274         lh = tm.tmHeight;
00275 
00276     if (dtp)
00277     {
00278         lmargin = dtp->iLeftMargin * tm.tmAveCharWidth;
00279         rmargin = dtp->iRightMargin * tm.tmAveCharWidth;
00280         if (!(flags & (DT_CENTER | DT_RIGHT)))
00281             x += lmargin;
00282         dtp->uiLengthDrawn = 0;     /* This param RECEIVES number of chars processed */
00283     }
00284 
00285     if (flags & DT_TABSTOP)
00286         tabstop = dtp ? dtp->iTabLength : flags >> 8;
00287 
00288     if (flags & DT_EXPANDTABS)
00289     {
00290         GetTextExtentPointW(hdc, SPACEW, 1, &size);
00291         spacewidth = size.cx;
00292         GetTextExtentPointW(hdc, oW, 1, &size);
00293         tabwidth = size.cx * tabstop;
00294     }
00295 
00296     if (flags & DT_CALCRECT) flags |= DT_NOCLIP;
00297 
00298     do
00299     {
00300         prefix_offset = -1;
00301         len = MAX_STATIC_BUFFER;
00302         strPtr = TEXT_NextLineW(hdc, strPtr, &count, line, &len, width, flags);
00303 
00304         if (prefix_offset != -1)
00305         {
00306             GetTextExtentPointW(hdc, line, prefix_offset, &size);
00307             prefix_x = size.cx;
00308             GetTextExtentPointW(hdc, line, prefix_offset + 1, &size);
00309             prefix_end = size.cx - 1;
00310         }
00311 
00312         if (!GetTextExtentPointW(hdc, line, len, &size)) return 0;
00313         if (flags & DT_CENTER) x = (rect->left + rect->right -
00314                                     size.cx) / 2;
00315         else if (flags & DT_RIGHT) x = rect->right - size.cx;
00316 
00317         if (flags & DT_SINGLELINE)
00318         {
00319             if (flags & DT_VCENTER) y = rect->top +
00320                 (rect->bottom - rect->top) / 2 - size.cy / 2;
00321             else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
00322 
00323             if (flags & (DT_PATH_ELLIPSIS | DT_END_ELLIPSIS | DT_WORD_ELLIPSIS))
00324             {
00325                 WCHAR swapStr[sizeof(line)];
00326                 WCHAR* fnameDelim = NULL;
00327                 int totalLen = i_count >= 0 ? i_count : strlenW(str);
00328 
00329                 if (size.cx > width)
00330                 {
00331                     int fnameLen = totalLen;
00332 
00333                     /* allow room for '...' */
00334                     count = min(totalLen+3, sizeof(line)-3);
00335 
00336                     if (flags & DT_WORD_ELLIPSIS)
00337                         flags |= DT_WORDBREAK;
00338 
00339                     if (flags & DT_PATH_ELLIPSIS)
00340                     {
00341                         WCHAR* lastBkSlash = NULL;
00342                         WCHAR* lastFwdSlash = NULL;
00343                         strncpyW(line, str, totalLen);
00344                         line[totalLen] = '\0';
00345                         lastBkSlash = strrchrW(line, BACK_SLASHW[0]);
00346                         lastFwdSlash = strrchrW(line, FORWARD_SLASHW[0]);
00347                         fnameDelim = lastBkSlash > lastFwdSlash ? lastBkSlash : lastFwdSlash;
00348 
00349                         if (fnameDelim)
00350                             fnameLen = &line[totalLen] - fnameDelim;
00351                         else
00352                             fnameDelim = (WCHAR*)str;
00353 
00354                         strcpyW(swapStr, ELLIPSISW);
00355                         strncpyW(swapStr+strlenW(swapStr), fnameDelim, fnameLen);
00356                         swapStr[fnameLen+3] = '\0';
00357                         strncpyW(swapStr+strlenW(swapStr), str, totalLen - fnameLen);
00358                         swapStr[totalLen+3] = '\0';
00359                     }
00360                     else  /* DT_END_ELLIPSIS | DT_WORD_ELLIPSIS */
00361                     {
00362                         strcpyW(swapStr, ELLIPSISW);
00363                         strncpyW(swapStr+strlenW(swapStr), str, totalLen);
00364                     }
00365 
00366                     len = MAX_STATIC_BUFFER;
00367                     TEXT_NextLineW(hdc, swapStr, &count, line, &len, width, flags);
00368 
00369                     /* if only the ELLIPSIS will fit, just let it be clipped */
00370                     len = max(3, len);
00371                     GetTextExtentPointW(hdc, line, len, &size);
00372 
00373                     /* FIXME:
00374                      * NextLine uses GetTextExtentPoint for each character,
00375                      * rather than GetCharABCWidth...  So the whitespace between
00376                      * characters is ignored in the width measurement, and the
00377                      * reported len is too great.  To compensate, we must get
00378                      * the width of the entire line and adjust len accordingly.
00379                     */
00380                     while ((size.cx > width) && (len > 3))
00381                     {
00382                         line[--len] = '\0';
00383                         GetTextExtentPointW(hdc, line, len, &size);
00384                     }
00385 
00386                     if (fnameLen < len-3) /* some of the path will fit */
00387                     {
00388                         /* put the ELLIPSIS between the path and filename */
00389                         strncpyW(swapStr, &line[fnameLen+3], len-3-fnameLen);
00390                         swapStr[len-3-fnameLen] = '\0';
00391                         strcatW(swapStr, ELLIPSISW);
00392                         strncpyW(swapStr+strlenW(swapStr), &line[3], fnameLen);
00393                     }
00394                     else
00395                     {
00396                         /* move the ELLIPSIS to the end */
00397                         strncpyW(swapStr, &line[3], len-3);
00398                         swapStr[len-3] = '\0';
00399                         strcpyW(swapStr+strlenW(swapStr), ELLIPSISW);
00400                     }
00401 
00402                     strncpyW(line, swapStr, len);
00403                     line[len] = '\0';
00404                     strPtr = NULL;
00405                 }
00406                if (flags & DT_MODIFYSTRING)
00407                     strcpyW(str, swapStr);
00408             }
00409         }
00410         if (!(flags & DT_CALCRECT))
00411         {
00412            if (!ExtTextOutW( hdc, x, y,
00413                              ((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
00414                              ((flags & DT_RTLREADING) ? ETO_RTLREADING : 0),
00415                     rect, line, len, NULL ))  return 0;
00416             if (prefix_offset != -1)
00417             {
00418                 HPEN hpen = CreatePen( PS_SOLID, 1, GetTextColor(hdc) );
00419                 HPEN oldPen = SelectObject( hdc, hpen );
00420                 MoveToEx(hdc, x + prefix_x, y + tm.tmAscent + 1, NULL );
00421                 LineTo(hdc, x + prefix_end + 1, y + tm.tmAscent + 1 );
00422                 SelectObject( hdc, oldPen );
00423                 DeleteObject( hpen );
00424             }
00425         }
00426         else if (size.cx > max_width)
00427             max_width = size.cx;
00428 
00429         y += lh;
00430         if (strPtr)
00431         {
00432             if (!(flags & DT_NOCLIP))
00433             {
00434                 if (y > rect->bottom - lh)
00435                     break;
00436             }
00437         }
00438         if (dtp)
00439             dtp->uiLengthDrawn += len;
00440     }
00441     while (strPtr);
00442 
00443     if (flags & DT_CALCRECT)
00444     {
00445         rect->right = rect->left + max_width;
00446         rect->bottom = y;
00447         if (dtp)
00448             rect->right += lmargin + rmargin;
00449     }
00450     return y - rect->top;
00451 }
00452 
00453 /***********************************************************************
00454  *           DrawTextExA    (USER32.@)
00455  */
00456 INT WINAPI DrawTextExA( HDC hdc, LPCSTR str, INT count,
00457                         LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp )
00458 {
00459    WCHAR *wstr;
00460    INT ret = 0;
00461    DWORD wcount;
00462 
00463    if (count == -1) count = strlen(str);
00464    if (!count) return 0;
00465    wcount = MultiByteToWideChar( CP_ACP, 0, str, count, NULL, 0 );
00466    wstr = HeapAlloc(GetProcessHeap(), 0, wcount * sizeof(WCHAR));
00467    if (wstr)
00468    {
00469        MultiByteToWideChar( CP_ACP, 0, str, count, wstr, wcount );
00470        ret = DrawTextExW( hdc, wstr, wcount, rect, flags, NULL );
00471        if (flags & DT_MODIFYSTRING)
00472             WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, count, NULL, NULL );
00473        HeapFree(GetProcessHeap(), 0, wstr);
00474    }
00475    return ret;
00476 }
00477 
00478 /***********************************************************************
00479  *           DrawTextW    (USER32.@)
00480  */
00481 INT WINAPI DrawTextW( HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags )
00482 {
00483     return DrawTextExW(hdc, (LPWSTR)str, count, rect, flags, NULL);
00484 }
00485 
00486 /***********************************************************************
00487  *           DrawTextA    (USER32.@)
00488  */
00489 INT WINAPI DrawTextA( HDC hdc, LPCSTR str, INT count, LPRECT rect, UINT flags )
00490 {
00491     return DrawTextExA( hdc, (LPSTR)str, count, rect, flags, NULL );
00492 }
00493 
00494 /***********************************************************************
00495  *           TEXT_GrayString
00496  *
00497  * FIXME: The call to 16-bit code only works because the wine GDI is a 16-bit
00498  * heap and we can guarantee that the handles fit in an INT16. We have to
00499  * rethink the strategy once the migration to NT handles is complete.
00500  * We are going to get a lot of code-duplication once this migration is
00501  * completed...
00502  * 
00503  */
00504 static BOOL TEXT_GrayString(HDC hdc, HBRUSH hb, GRAYSTRINGPROC fn, LPARAM lp, INT len,
00505                             INT x, INT y, INT cx, INT cy, BOOL unicode, BOOL _32bit)
00506 {
00507     HBITMAP hbm, hbmsave;
00508     HBRUSH hbsave;
00509     HFONT hfsave;
00510     HDC memdc = CreateCompatibleDC(hdc);
00511     int slen = len;
00512     BOOL retval = TRUE;
00513     COLORREF fg, bg;
00514 
00515 #ifdef __WIN32OS2__
00516     dprintf(("GrayString %x %x %x %x %d (%d,%d)(%d,%d)", hdc, hb, fn, lp, len, x, y, cx, cy));
00517     if(!hdc) {
00518         DeleteDC(memdc);
00519         return FALSE;
00520     }
00521 #else
00522     if(!hdc) return FALSE;
00523 #endif
00524     
00525     if(len == 0)
00526     {
00527         if(unicode)
00528             slen = lstrlenW((LPCWSTR)lp);
00529         else if(_32bit)
00530             slen = strlen((LPCSTR)lp);
00531         else
00532             slen = strlen(MapSL(lp));
00533     }
00534 
00535     if((cx == 0 || cy == 0) && slen != -1)
00536     {
00537         SIZE s;
00538         if(unicode)
00539             GetTextExtentPoint32W(hdc, (LPCWSTR)lp, slen, &s);
00540         else if(_32bit)
00541             GetTextExtentPoint32A(hdc, (LPCSTR)lp, slen, &s);
00542         else
00543             GetTextExtentPoint32A(hdc, MapSL(lp), slen, &s);
00544         if(cx == 0) cx = s.cx;
00545         if(cy == 0) cy = s.cy;
00546     }
00547 
00548     hbm = CreateBitmap(cx, cy, 1, 1, NULL);
00549     hbmsave = (HBITMAP)SelectObject(memdc, hbm);
00550     hbsave = SelectObject( memdc, GetStockObject(BLACK_BRUSH) );
00551     PatBlt( memdc, 0, 0, cx, cy, PATCOPY );
00552     SelectObject( memdc, hbsave );
00553     SetTextColor(memdc, RGB(255, 255, 255));
00554     SetBkColor(memdc, RGB(0, 0, 0));
00555     hfsave = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT));
00556 
00557     if(fn)
00558     {
00559         if(_32bit)
00560             retval = fn(memdc, lp, slen);
00561         else
00562             retval = (BOOL)((BOOL16)((GRAYSTRINGPROC16)fn)((HDC16)memdc, lp, (INT16)slen));
00563     }
00564     else
00565     {
00566         if(unicode)
00567             TextOutW(memdc, 0, 0, (LPCWSTR)lp, slen);
00568         else if(_32bit)
00569             TextOutA(memdc, 0, 0, (LPCSTR)lp, slen);
00570         else
00571             TextOutA(memdc, 0, 0, MapSL(lp), slen);
00572     }
00573 
00574     SelectObject(memdc, hfsave);
00575 
00576 /*
00577  * Windows doc says that the bitmap isn't grayed when len == -1 and
00578  * the callback function returns FALSE. However, testing this on
00579  * win95 showed otherwise...
00580 */
00581 #ifdef GRAYSTRING_USING_DOCUMENTED_BEHAVIOUR
00582     if(retval || len != -1)
00583 #endif
00584     {
00585         hbsave = (HBRUSH)SelectObject(memdc, CACHE_GetPattern55AABrush());
00586         PatBlt(memdc, 0, 0, cx, cy, 0x000A0329);
00587         SelectObject(memdc, hbsave);
00588     }
00589 
00590     if(hb) hbsave = (HBRUSH)SelectObject(hdc, hb);
00591     fg = SetTextColor(hdc, RGB(0, 0, 0));
00592     bg = SetBkColor(hdc, RGB(255, 255, 255));
00593     BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00E20746);
00594     SetTextColor(hdc, fg);
00595     SetBkColor(hdc, bg);
00596     if(hb) SelectObject(hdc, hbsave);
00597 
00598     SelectObject(memdc, hbmsave);
00599     DeleteObject(hbm);
00600     DeleteDC(memdc);
00601     return retval;
00602 }
00603 
00604 
00605 #ifndef __WIN32OS2__
00606 /***********************************************************************
00607  *           GrayString16   (USER.185)
00608  */
00609 BOOL16 WINAPI GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 gsprc,
00610                             LPARAM lParam, INT16 cch, INT16 x, INT16 y,
00611                             INT16 cx, INT16 cy )
00612 {
00613     return TEXT_GrayString(hdc, hbr, (GRAYSTRINGPROC)gsprc, lParam, cch,
00614                            x, y, cx, cy, FALSE, FALSE);
00615 }
00616 #endif
00617 
00618 /***********************************************************************
00619  *           GrayStringA   (USER32.@)
00620  */
00621 BOOL WINAPI GrayStringA( HDC hdc, HBRUSH hbr, GRAYSTRINGPROC gsprc,
00622                          LPARAM lParam, INT cch, INT x, INT y,
00623                          INT cx, INT cy )
00624 {
00625     return TEXT_GrayString(hdc, hbr, gsprc, lParam, cch, x, y, cx, cy,
00626                            FALSE, TRUE);
00627 }
00628 
00629 
00630 /***********************************************************************
00631  *           GrayStringW   (USER32.@)
00632  */
00633 BOOL WINAPI GrayStringW( HDC hdc, HBRUSH hbr, GRAYSTRINGPROC gsprc,
00634                          LPARAM lParam, INT cch, INT x, INT y,
00635                          INT cx, INT cy )
00636 {
00637     return TEXT_GrayString(hdc, hbr, gsprc, lParam, cch, x, y, cx, cy,
00638                            TRUE, TRUE);
00639 }
00640 
00641 /***********************************************************************
00642  *           TEXT_TabbedTextOut
00643  *
00644  * Helper function for TabbedTextOut() and GetTabbedTextExtent().
00645  * Note: this doesn't work too well for text-alignment modes other
00646  *       than TA_LEFT|TA_TOP. But we want bug-for-bug compatibility :-)
00647  */
00648 static LONG TEXT_TabbedTextOut( HDC hdc, INT x, INT y, LPCSTR lpstr,
00649                                 INT count, INT cTabStops, const INT16 *lpTabPos16,
00650                                 const INT *lpTabPos32, INT nTabOrg,
00651                                 BOOL fDisplayText )
00652 {
00653     INT defWidth;
00654     SIZE extent;
00655     int i, tabPos = x;
00656     int start = x;
00657 
00658     extent.cx = 0;
00659     extent.cy = 0;
00660 
00661     if (cTabStops == 1)
00662     {
00663         defWidth = lpTabPos32 ? *lpTabPos32 : *lpTabPos16;
00664         cTabStops = 0;
00665     }
00666     else
00667     {
00668         TEXTMETRICA tm;
00669         GetTextMetricsA( hdc, &tm );
00670         defWidth = 8 * tm.tmAveCharWidth;
00671     }
00672 
00673     while (count > 0)
00674     {
00675         for (i = 0; i < count; i++)
00676             if (lpstr[i] == '\t') break;
00677         GetTextExtentPointA( hdc, lpstr, i, &extent );
00678         if (lpTabPos32)
00679         {
00680             while ((cTabStops > 0) &&
00681                    (nTabOrg + *lpTabPos32 <= x + extent.cx))
00682             {
00683                 lpTabPos32++;
00684                 cTabStops--;
00685             }
00686         }
00687         else
00688         {
00689             while ((cTabStops > 0) &&
00690                    (nTabOrg + *lpTabPos16 <= x + extent.cx))
00691             {
00692                 lpTabPos16++;
00693                 cTabStops--;
00694             }
00695         }
00696         if (i == count)
00697             tabPos = x + extent.cx;
00698         else if (cTabStops > 0)
00699             tabPos = nTabOrg + (lpTabPos32 ? *lpTabPos32 : *lpTabPos16);
00700         else
00701             tabPos = nTabOrg + ((x + extent.cx - nTabOrg) / defWidth + 1) * defWidth;
00702         if (fDisplayText)
00703         {
00704             RECT r;
00705             r.left   = x;
00706             r.top    = y;
00707             r.right  = tabPos;
00708             r.bottom = y + extent.cy;
00709             ExtTextOutA( hdc, x, y,
00710                            GetBkMode(hdc) == OPAQUE ? ETO_OPAQUE : 0,
00711                            &r, lpstr, i, NULL );
00712         }
00713         x = tabPos;
00714         count -= i+1;
00715         lpstr += i+1;
00716     }
00717     return MAKELONG(tabPos - start, extent.cy);
00718 }
00719 
00720 
00721 #ifndef __WIN32OS2__
00722 /***********************************************************************
00723  *           TabbedTextOut    (USER.196)
00724  */
00725 LONG WINAPI TabbedTextOut16( HDC16 hdc, INT16 x, INT16 y, LPCSTR lpstr,
00726                              INT16 count, INT16 cTabStops,
00727                              const INT16 *lpTabPos, INT16 nTabOrg )
00728 {
00729     TRACE("%04x %d,%d %s %d\n", hdc, x, y, debugstr_an(lpstr,count), count );
00730     return TEXT_TabbedTextOut( hdc, x, y, lpstr, count, cTabStops,
00731                                lpTabPos, NULL, nTabOrg, TRUE );
00732 }
00733 #endif
00734 
00735 /***********************************************************************
00736  *           TabbedTextOutA    (USER32.@)
00737  */
00738 LONG WINAPI TabbedTextOutA( HDC hdc, INT x, INT y, LPCSTR lpstr, INT count,
00739                             INT cTabStops, const INT *lpTabPos, INT nTabOrg )
00740 {
00741 #ifdef __WIN32OS2__
00742     dprintf(("TabbedTextOutA: %04x %d,%d %s %d\n", hdc, x, y, lpstr, count ));
00743 #else
00744     TRACE("%04x %d,%d %s %d\n", hdc, x, y, debugstr_an(lpstr,count), count );
00745 #endif
00746     return TEXT_TabbedTextOut( hdc, x, y, lpstr, count, cTabStops,
00747                                NULL, lpTabPos, nTabOrg, TRUE );
00748 }
00749 
00750 
00751 /***********************************************************************
00752  *           TabbedTextOutW    (USER32.@)
00753  */
00754 LONG WINAPI TabbedTextOutW( HDC hdc, INT x, INT y, LPCWSTR str, INT count,
00755                             INT cTabStops, const INT *lpTabPos, INT nTabOrg )
00756 {
00757     LONG ret;
00758     LPSTR p;
00759     INT acount;
00760     UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
00761 
00762     acount = WideCharToMultiByte(codepage,0,str,count,NULL,0,NULL,NULL);
00763     p = HeapAlloc( GetProcessHeap(), 0, acount );
00764     if(p == NULL) return 0; /* FIXME: is this the correct return on failure */ 
00765     acount = WideCharToMultiByte(codepage,0,str,count,p,acount,NULL,NULL);
00766     ret = TabbedTextOutA( hdc, x, y, p, acount, cTabStops, lpTabPos, nTabOrg );
00767     HeapFree( GetProcessHeap(), 0, p );
00768     return ret;
00769 }
00770 
00771 
00772 #ifndef __WIN32OS2__
00773 /***********************************************************************
00774  *           GetTabbedTextExtent    (USER.197)
00775  */
00776 DWORD WINAPI GetTabbedTextExtent16( HDC16 hdc, LPCSTR lpstr, INT16 count,
00777                                     INT16 cTabStops, const INT16 *lpTabPos )
00778 {
00779     TRACE("%04x %s %d\n", hdc, debugstr_an(lpstr,count), count );
00780     return TEXT_TabbedTextOut( hdc, 0, 0, lpstr, count, cTabStops,
00781                                lpTabPos, NULL, 0, FALSE );
00782 }
00783 #endif
00784 
00785 /***********************************************************************
00786  *           GetTabbedTextExtentA    (USER32.@)
00787  */
00788 DWORD WINAPI GetTabbedTextExtentA( HDC hdc, LPCSTR lpstr, INT count,
00789                                    INT cTabStops, const INT *lpTabPos )
00790 {
00791 #ifdef __WIN32OS2__
00792     dprintf(("GetTabbedTextExtentA: %04x %s %d\n", hdc, lpstr, count ));
00793 #else
00794     TRACE("%04x %s %d\n", hdc, debugstr_an(lpstr,count), count );
00795 #endif
00796     return TEXT_TabbedTextOut( hdc, 0, 0, lpstr, count, cTabStops,
00797                                NULL, lpTabPos, 0, FALSE );
00798 }
00799 
00800 
00801 /***********************************************************************
00802  *           GetTabbedTextExtentW    (USER32.@)
00803  */
00804 DWORD WINAPI GetTabbedTextExtentW( HDC hdc, LPCWSTR lpstr, INT count,
00805                                    INT cTabStops, const INT *lpTabPos )
00806 {
00807     LONG ret;
00808     LPSTR p;
00809     INT acount;
00810     UINT codepage = CP_ACP; /* FIXME: get codepage of font charset */
00811 
00812     acount = WideCharToMultiByte(codepage,0,lpstr,count,NULL,0,NULL,NULL);
00813     p = HeapAlloc( GetProcessHeap(), 0, acount );
00814     if(p == NULL) return 0; /* FIXME: is this the correct failure value? */
00815     acount = WideCharToMultiByte(codepage,0,lpstr,count,p,acount,NULL,NULL);
00816     ret = GetTabbedTextExtentA( hdc, p, acount, cTabStops, lpTabPos );
00817     HeapFree( GetProcessHeap(), 0, p );
00818     return ret;
00819 }

Generated on Wed Jan 23 23:17:43 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001