Release 1.5.29.
[wine] / dlls / gdi32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22 #include <string.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wine/wingdi16.h"
27 #include "mfdrv/metafiledrv.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
31
32
33 /******************************************************************
34  *         MFDRV_MetaExtTextOut
35  */
36 static BOOL MFDRV_MetaExtTextOut( PHYSDEV dev, short x, short y, UINT16 flags,
37                                  const RECT16 *rect, LPCSTR str, short count,
38                                  const INT16 *lpDx)
39 {
40     BOOL ret;
41     DWORD len;
42     METARECORD *mr;
43     BOOL isrect = flags & (ETO_CLIPPED | ETO_OPAQUE);
44
45     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
46             + sizeof(UINT16);
47     if (isrect)
48         len += sizeof(RECT16);
49     if (lpDx)
50      len+=count*sizeof(INT16);
51     if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len)))
52         return FALSE;
53
54     mr->rdSize = len / 2;
55     mr->rdFunction = META_EXTTEXTOUT;
56     *(mr->rdParm) = y;
57     *(mr->rdParm + 1) = x;
58     *(mr->rdParm + 2) = count;
59     *(mr->rdParm + 3) = flags;
60     if (isrect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
61     memcpy(mr->rdParm + (isrect ? 8 : 4), str, count);
62     if (lpDx)
63      memcpy(mr->rdParm + (isrect ? 8 : 4) + ((count + 1) >> 1),lpDx,
64       count*sizeof(INT16));
65     ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
66     HeapFree( GetProcessHeap(), 0, mr);
67     return ret;
68 }
69
70
71
72 /***********************************************************************
73  *           MFDRV_ExtTextOut
74  */
75 BOOL MFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
76                        const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
77 {
78     RECT16      rect16;
79     LPINT16     lpdx16 = NULL;
80     BOOL        ret;
81     unsigned int i, j;
82     LPSTR       ascii;
83     DWORD len;
84     CHARSETINFO csi;
85     int charset = GetTextCharset( dev->hdc );
86     UINT cp = CP_ACP;
87
88     if(TranslateCharsetInfo(ULongToPtr(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     len = WideCharToMultiByte(cp, 0, str, count, NULL, 0, NULL, NULL);
126     ascii = HeapAlloc(GetProcessHeap(), 0, len);
127     WideCharToMultiByte(cp, 0, str, count, ascii, len, NULL, NULL);
128     TRACE("mapped %s -> %s\n", debugstr_wn(str, count), debugstr_an(ascii, len));
129
130
131     if (lprect)
132     {
133         rect16.left   = lprect->left;
134         rect16.top    = lprect->top;
135         rect16.right  = lprect->right;
136         rect16.bottom = lprect->bottom;
137     }
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     HeapFree( GetProcessHeap(), 0, lpdx16 );
152     return ret;
153 }