Fix for metafile ExtTextOut that only includes the rectangle if either
[wine] / dlls / gdi / mfdrv / text.c
1 /*
2  * metafile driver text functions
3  *
4  * Copyright 1993, 1994 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <string.h>
22
23 #include "windef.h"
24 #include "mfdrv/metafiledrv.h"
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
28
29
30 /******************************************************************
31  *         MFDRV_MetaExtTextOut
32  */
33 static BOOL MFDRV_MetaExtTextOut( PHYSDEV dev, short x, short y, UINT16 flags,
34                                  const RECT16 *rect, LPCSTR str, short count,
35                                  const INT16 *lpDx)
36 {
37     BOOL ret;
38     DWORD len;
39     METARECORD *mr;
40     BOOL isrect = flags & (ETO_CLIPPED | ETO_OPAQUE);
41
42     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
43             + sizeof(UINT16);
44     if (isrect)
45         len += sizeof(RECT16);
46     if (lpDx)
47      len+=count*sizeof(INT16);
48     if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len)))
49         return FALSE;
50
51     mr->rdSize = len / 2;
52     mr->rdFunction = META_EXTTEXTOUT;
53     *(mr->rdParm) = y;
54     *(mr->rdParm + 1) = x;
55     *(mr->rdParm + 2) = count;
56     *(mr->rdParm + 3) = flags;
57     if (isrect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
58     memcpy(mr->rdParm + (isrect ? 8 : 4), str, count);
59     if (lpDx)
60      memcpy(mr->rdParm + (isrect ? 8 : 4) + ((count + 1) >> 1),lpDx,
61       count*sizeof(INT16));
62     ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
63     HeapFree( GetProcessHeap(), 0, mr);
64     return ret;
65 }
66
67
68
69 /***********************************************************************
70  *           MFDRV_ExtTextOut
71  */
72 BOOL
73 MFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
74                   const RECT *lprect, LPCWSTR str, UINT count,
75                   const INT *lpDx )
76 {
77     RECT16      rect16;
78     LPINT16     lpdx16 = NULL;
79     BOOL        ret;
80     int         i, j;
81     LPSTR       ascii;
82     DWORD len;
83     CHARSETINFO csi;
84     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
85     int charset = GetTextCharset(physDev->hdc);
86     UINT cp = CP_ACP;
87
88     if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
89         cp = csi.ciACP;
90     else {
91         switch(charset) {
92         case OEM_CHARSET:
93             cp = GetOEMCP();
94             break;
95         case DEFAULT_CHARSET:
96             cp = GetACP();
97             break;
98
99         case VISCII_CHARSET:
100         case TCVN_CHARSET:
101         case KOI8_CHARSET:
102         case ISO3_CHARSET:
103         case ISO4_CHARSET:
104         case ISO10_CHARSET:
105         case CELTIC_CHARSET:
106           /* FIXME: These have no place here, but because x11drv
107              enumerates fonts with these (made up) charsets some apps
108              might use them and then the FIXME below would become
109              annoying.  Now we could pick the intended codepage for
110              each of these, but since it's broken anyway we'll just
111              use CP_ACP and hope it'll go away...
112           */
113             cp = CP_ACP;
114             break;
115
116
117         default:
118             FIXME("Can't find codepage for charset %d\n", charset);
119             break;
120         }
121     }
122
123
124     TRACE("cp == %d\n", cp);
125     if(cp != CP_SYMBOL) {
126         len = WideCharToMultiByte(cp, 0, str, count, NULL, 0, NULL, NULL);
127         ascii = HeapAlloc(GetProcessHeap(), 0, len);
128         WideCharToMultiByte(cp, 0, str, count, ascii, len, NULL, NULL);
129     } else {
130         len = count;
131         ascii = HeapAlloc(GetProcessHeap(), 0, len);
132         for(i = 0; i < count; i++) ascii[i] = (BYTE)(str[i] & 0xff);
133     }
134     TRACE("mapped %s -> %s\n", debugstr_wn(str, count), debugstr_an(ascii, len));
135
136
137     if (lprect) CONV_RECT32TO16(lprect,&rect16);
138
139     if(lpDx) {
140         lpdx16 = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16)*len );
141         for(i = j = 0; i < len; )
142             if(IsDBCSLeadByteEx(cp, ascii[i])) {
143                 lpdx16[i++] = lpDx[j++];
144                 lpdx16[i++] = 0;
145             } else
146                 lpdx16[i++] = lpDx[j++];
147     }
148
149     ret = MFDRV_MetaExtTextOut(dev,x,y,flags,lprect?&rect16:NULL,ascii,len,lpdx16);
150     HeapFree( GetProcessHeap(), 0, ascii );
151     if (lpdx16) HeapFree( GetProcessHeap(), 0, lpdx16 );
152     return ret;
153 }