Added support for cp949.
[wine] / graphics / x11drv / codepage.c
1 /*
2  * X11 codepage handling
3  *
4  * Copyright 2000 Hidenori Takeshima <hidenori@a2.ctktv.ne.jp>
5  */
6
7 #include "config.h"
8
9 #include "ts_xlib.h"
10
11 #include <math.h>
12
13 #include "windef.h"
14 #include "winnls.h"
15 #include "heap.h"
16 #include "x11font.h"
17 #include "debugtools.h"
18
19 DEFAULT_DEBUG_CHANNEL(text);
20
21
22 static WORD X11DRV_enum_subfont_charset_normal( UINT index )
23 {
24     return DEFAULT_CHARSET;
25 }
26
27 static WORD X11DRV_enum_subfont_charset_cp932( UINT index )
28 {
29     switch ( index )
30     {
31     case 0: return X11FONT_JISX0201_CHARSET;
32     case 1: return X11FONT_JISX0212_CHARSET;
33     }
34
35     return DEFAULT_CHARSET;
36 }
37
38 static WORD X11DRV_enum_subfont_charset_cp936( UINT index )
39 {
40     FIXME( "please implement X11DRV_enum_subfont_charset_cp936!\n" );
41     return DEFAULT_CHARSET;
42 }
43
44 static WORD X11DRV_enum_subfont_charset_cp949( UINT index )
45 {
46     switch ( index )
47     {
48     case 0: return ANSI_CHARSET;
49     }
50
51     return DEFAULT_CHARSET;
52 }
53
54 static WORD X11DRV_enum_subfont_charset_cp950( UINT index )
55 {
56     FIXME( "please implement X11DRV_enum_subfont_charset_cp950!\n" );
57     return DEFAULT_CHARSET;
58 }
59
60
61 static XChar2b* X11DRV_unicode_to_char2b_sbcs( fontObject* pfo,
62                                                LPCWSTR lpwstr, UINT count )
63 {
64     XChar2b *str2b;
65     UINT i;
66     BYTE *str;
67     UINT codepage = pfo->fi->codepage;
68     char ch = pfo->fs->default_char;
69
70     if (!(str2b = HeapAlloc( GetProcessHeap(), 0, count * sizeof(XChar2b) )))
71         return NULL;
72     if (!(str = HeapAlloc( GetProcessHeap(), 0, count )))
73     {
74         HeapFree( GetProcessHeap(), 0, str2b );
75         return NULL;
76     }
77
78     WideCharToMultiByte( codepage, 0, lpwstr, count, str, count, &ch, NULL );
79
80     for (i = 0; i < count; i++)
81     {
82         str2b[i].byte1 = 0;
83         str2b[i].byte2 = str[i];
84     }
85     HeapFree( GetProcessHeap(), 0, str );
86
87     return str2b;
88 }
89
90 static XChar2b* X11DRV_unicode_to_char2b_unicode( fontObject* pfo,
91                                                   LPCWSTR lpwstr, UINT count )
92 {
93     XChar2b *str2b;
94     UINT i;
95
96     if (!(str2b = HeapAlloc( GetProcessHeap(), 0, count * sizeof(XChar2b) )))
97         return NULL;
98
99     for (i = 0; i < count; i++)
100     {
101         str2b[i].byte1 = lpwstr[i] >> 8;
102         str2b[i].byte2 = lpwstr[i] & 0xff;
103     }
104
105     return str2b;
106 }
107
108 /* FIXME: handle jisx0212.1990... */
109 static XChar2b* X11DRV_unicode_to_char2b_cp932( fontObject* pfo,
110                                                 LPCWSTR lpwstr, UINT count )
111 {
112     XChar2b *str2b;
113     XChar2b *str2b_dst;
114     BYTE *str;
115     BYTE *str_src;
116     UINT i;
117     UINT codepage = pfo->fi->codepage;
118     char ch = pfo->fs->default_char;
119
120     if (!(str2b = HeapAlloc( GetProcessHeap(), 0, count * sizeof(XChar2b) )))
121         return NULL;
122     if (!(str = HeapAlloc( GetProcessHeap(), 0, count*2 )))
123     {
124         HeapFree( GetProcessHeap(), 0, str2b );
125         return NULL;
126     }
127     WideCharToMultiByte( codepage, 0, lpwstr, count, str, count*2, &ch, NULL );
128
129     str_src = str;
130     str2b_dst = str2b;
131     for (i = 0; i < count; i++, str_src++, str2b_dst++)
132     {
133         if ( ( *str_src >= (BYTE)0x80 && *str_src <= (BYTE)0x9f ) ||
134              ( *str_src >= (BYTE)0xe0 && *str_src <= (BYTE)0xfc ) )
135         {
136             unsigned int  high, low;
137
138             high = (unsigned int)*str_src;
139             low = (unsigned int)*(str_src+1);
140
141             if ( high <= 0x9f )
142                 high = (high<<1) - 0xe0;
143             else
144                 high = (high<<1) - 0x160;
145             if ( low < 0x9f )
146             {
147                 high --;
148                 if ( low < 0x7f )
149                     low -= 0x1f;
150                 else
151                     low -= 0x20;
152             }
153             else
154             {
155                 low -= 0x7e;
156             }
157
158             str2b_dst->byte1 = (unsigned char)high;
159             str2b_dst->byte2 = (unsigned char)low;
160             str_src++;
161         }
162         else
163         {
164             str2b_dst->byte1 = 0;
165             str2b_dst->byte2 = *str_src;
166         }
167     }
168
169     HeapFree( GetProcessHeap(), 0, str );
170
171     return str2b;
172 }
173
174
175 static XChar2b* X11DRV_unicode_to_char2b_cp936( fontObject* pfo,
176                                                 LPCWSTR lpwstr, UINT count )
177 {
178     FIXME( "please implement X11DRV_unicode_to_char2b_cp936!\n" );
179     return NULL;
180 }
181
182
183 static XChar2b* X11DRV_unicode_to_char2b_cp949( fontObject* pfo,
184                                                 LPCWSTR lpwstr, UINT count )
185 {
186     XChar2b *str2b;
187     XChar2b *str2b_dst;
188     BYTE *str;
189     BYTE *str_src;
190     UINT i;
191     UINT codepage = pfo->fi->codepage;
192     char ch = pfo->fs->default_char;
193
194     if (!(str2b = HeapAlloc( GetProcessHeap(), 0, count * sizeof(XChar2b) )))
195         return NULL;
196     if (!(str = HeapAlloc( GetProcessHeap(), 0, count*2 )))
197     {
198         HeapFree( GetProcessHeap(), 0, str2b );
199         return NULL;
200     }
201     WideCharToMultiByte( codepage, 0, lpwstr, count, str, count*2, &ch, NULL );
202
203     str_src = str;
204     str2b_dst = str2b;
205     for (i = 0; i < count; i++, str_src++, str2b_dst++)
206     {
207         if ( (*str_src) & (BYTE)0x80 )
208         {
209             str2b_dst->byte1 = (*str_src) & 0x7f;
210             str2b_dst->byte2 = (*(str_src+1)) & 0x7f;
211             str_src++;
212         }
213         else
214         {
215             str2b_dst->byte1 = 0;
216             str2b_dst->byte2 = *str_src;
217         }
218     }
219
220     HeapFree( GetProcessHeap(), 0, str );
221
222     return str2b;
223 }
224
225
226 static XChar2b* X11DRV_unicode_to_char2b_cp950( fontObject* pfo,
227                                                 LPCWSTR lpwstr, UINT count )
228 {
229     FIXME( "please implement X11DRV_unicode_to_char2b_cp950!\n" );
230     return NULL;
231 }
232
233
234 static void X11DRV_DrawString_normal( fontObject* pfo, Display* pdisp,
235                                       Drawable d, GC gc, int x, int y,
236                                       XChar2b* pstr, int count )
237 {
238     TSXDrawString16( pdisp, d, gc, x, y, pstr, count );
239 }
240
241 static int X11DRV_TextWidth_normal( fontObject* pfo, XChar2b* pstr, int count )
242 {
243     return TSXTextWidth16( pfo->fs, pstr, count );
244 }
245
246 static void X11DRV_DrawText_normal( fontObject* pfo, Display* pdisp, Drawable d,
247                                     GC gc, int x, int y, XTextItem16* pitems,
248                                     int count )
249 {
250     TSXDrawText16( pdisp, d, gc, x, y, pitems, count );
251 }
252
253 static void X11DRV_TextExtents_normal( fontObject* pfo, XChar2b* pstr, int count,
254                                        int* pdir, int* pascent, int* pdescent,
255                                        int* pwidth )
256 {
257     XCharStruct info;
258
259     TSXTextExtents16( pfo->fs, pstr, count, pdir, pascent, pdescent, &info );
260     *pwidth = info.width;
261 }
262
263 static void X11DRV_GetTextMetricsA_normal( fontObject* pfo, LPTEXTMETRICA pTM )
264 {
265     LPIFONTINFO16 pdf = &pfo->fi->df;
266
267     if( ! pfo->lpX11Trans ) {
268       pTM->tmAscent = pfo->fs->ascent;
269       pTM->tmDescent = pfo->fs->descent;
270     } else {
271       pTM->tmAscent = pfo->lpX11Trans->ascent;
272       pTM->tmDescent = pfo->lpX11Trans->descent;
273     }
274
275     pTM->tmAscent *= pfo->rescale;
276     pTM->tmDescent *= pfo->rescale;
277
278     pTM->tmHeight = pTM->tmAscent + pTM->tmDescent;
279
280     pTM->tmAveCharWidth = pfo->foAvgCharWidth * pfo->rescale;
281     pTM->tmMaxCharWidth = pfo->foMaxCharWidth * pfo->rescale;
282
283     pTM->tmInternalLeading = pfo->foInternalLeading * pfo->rescale;
284     pTM->tmExternalLeading = pdf->dfExternalLeading * pfo->rescale;
285
286     pTM->tmStruckOut = (pfo->fo_flags & FO_SYNTH_STRIKEOUT )
287                         ? 1 : pdf->dfStrikeOut;
288     pTM->tmUnderlined = (pfo->fo_flags & FO_SYNTH_UNDERLINE )
289                         ? 1 : pdf->dfUnderline;
290
291     pTM->tmOverhang = 0;
292     if( pfo->fo_flags & FO_SYNTH_ITALIC ) 
293     {
294         pTM->tmOverhang += pTM->tmHeight/3;
295         pTM->tmItalic = 1;
296     } else 
297         pTM->tmItalic = pdf->dfItalic;
298
299     pTM->tmWeight = pdf->dfWeight;
300     if( pfo->fo_flags & FO_SYNTH_BOLD ) 
301     {
302         pTM->tmOverhang++; 
303         pTM->tmWeight += 100;
304     } 
305
306     pTM->tmFirstChar = pdf->dfFirstChar;
307     pTM->tmLastChar = pdf->dfLastChar;
308     pTM->tmDefaultChar = pdf->dfDefaultChar;
309     pTM->tmBreakChar = pdf->dfBreakChar;
310
311     pTM->tmCharSet = pdf->dfCharSet;
312     pTM->tmPitchAndFamily = pdf->dfPitchAndFamily;
313
314     pTM->tmDigitizedAspectX = pdf->dfHorizRes;
315     pTM->tmDigitizedAspectY = pdf->dfVertRes;
316 }
317
318
319
320 static
321 void X11DRV_DrawString_dbcs( fontObject* pfo, Display* pdisp,
322                              Drawable d, GC gc, int x, int y,
323                              XChar2b* pstr, int count )
324 {
325     XTextItem16 item;
326
327     item.chars = pstr;
328     item.delta = 0;
329     item.nchars = count;
330     item.font = None;
331     X11DRV_cptable[pfo->fi->cptable].pDrawText(
332                 pfo, pdisp, d, gc, x, y, &item, 1 );
333 }
334
335 static
336 int X11DRV_TextWidth_dbcs_2fonts( fontObject* pfo, XChar2b* pstr, int count )
337 {
338     int i;
339     int width;
340     int curfont;
341     fontObject* pfos[X11FONT_REFOBJS_MAX+1];
342
343     pfos[0] = XFONT_GetFontObject( pfo->prefobjs[0] );
344     pfos[1] = pfo;
345     if ( pfos[0] == NULL ) pfos[0] = pfo;
346
347     width = 0;
348     for ( i = 0; i < count; i++ )
349     {
350         curfont = ( pstr->byte1 != 0 ) ? 1 : 0;
351         width += TSXTextWidth16( pfos[curfont]->fs, pstr, 1 );
352         pstr ++;
353     }
354
355     return width;
356 }
357
358 static
359 void X11DRV_DrawText_dbcs_2fonts( fontObject* pfo, Display* pdisp, Drawable d,
360                                   GC gc, int x, int y, XTextItem16* pitems,
361                                   int count )
362 {
363     int i, nitems, prevfont = -1, curfont;
364     XChar2b* pstr;
365     XTextItem16* ptibuf;
366     XTextItem16* pti;
367     fontObject* pfos[X11FONT_REFOBJS_MAX+1];
368
369     pfos[0] = XFONT_GetFontObject( pfo->prefobjs[0] );
370     pfos[1] = pfo;
371     if ( pfos[0] == NULL ) pfos[0] = pfo;
372
373     nitems = 0;
374     for ( i = 0; i < count; i++ )
375         nitems += pitems->nchars;
376     ptibuf = HeapAlloc( GetProcessHeap(), 0, sizeof(XTextItem16) * nitems );
377     if ( ptibuf == NULL )
378         return; /* out of memory */
379
380     pti = ptibuf;
381     while ( count-- > 0 )
382     {
383         pti->chars = pstr = pitems->chars;
384         pti->delta = pitems->delta;
385         pti->font = None;
386         for ( i = 0; i < pitems->nchars; i++, pstr++ )
387         {
388             curfont = ( pstr->byte1 != 0 ) ? 1 : 0;
389             if ( curfont != prevfont )
390             {
391                 if ( pstr != pti->chars )
392                 {
393                     pti->nchars = pstr - pti->chars;
394                     pti ++;
395                     pti->chars = pstr;
396                     pti->delta = 0;
397                 }
398                 pti->font = pfos[curfont]->fs->fid;
399                 prevfont = curfont;
400             }
401         }
402         pti->nchars = pstr - pti->chars;
403         pitems ++; pti ++;
404     }
405     TSXDrawText16( pdisp, d, gc, x, y, ptibuf, pti - ptibuf );
406     HeapFree( GetProcessHeap(), 0, ptibuf );
407 }
408
409 static
410 void X11DRV_TextExtents_dbcs_2fonts( fontObject* pfo, XChar2b* pstr, int count,
411                                      int* pdir, int* pascent, int* pdescent,
412                                      int* pwidth )
413 {
414     XCharStruct info;
415     int ascent, descent, width;
416     int i;
417     int curfont;
418     fontObject* pfos[X11FONT_REFOBJS_MAX+1];
419
420     pfos[0] = XFONT_GetFontObject( pfo->prefobjs[0] );
421     pfos[1] = pfo;
422     if ( pfos[0] == NULL ) pfos[0] = pfo;
423
424     width = 0;
425     *pascent = 0;
426     *pdescent = 0;
427     for ( i = 0; i < count; i++ )
428     {
429         curfont = ( pstr->byte1 != 0 ) ? 1 : 0;
430         TSXTextExtents16( pfos[curfont]->fs, pstr, 1, pdir,
431                           &ascent, &descent, &info );
432         if ( *pascent < ascent ) *pascent = ascent;
433         if ( *pdescent < descent ) *pdescent = descent;
434         width += info.width;
435
436         pstr ++;
437     }
438
439     *pwidth = width;
440 }
441
442 static void X11DRV_GetTextMetricsA_cp932( fontObject* pfo, LPTEXTMETRICA pTM )
443 {
444     fontObject* pfo_ansi = XFONT_GetFontObject( pfo->prefobjs[0] );
445     LPIFONTINFO16 pdf = &pfo->fi->df;
446     LPIFONTINFO16 pdf_ansi;
447
448     pdf_ansi = ( pfo_ansi != NULL ) ? (&pfo_ansi->fi->df) : pdf;
449
450     if( ! pfo->lpX11Trans ) {
451       pTM->tmAscent = pfo->fs->ascent;
452       pTM->tmDescent = pfo->fs->descent;
453     } else {
454       pTM->tmAscent = pfo->lpX11Trans->ascent;
455       pTM->tmDescent = pfo->lpX11Trans->descent;
456     }
457
458     pTM->tmAscent *= pfo->rescale;
459     pTM->tmDescent *= pfo->rescale;
460
461     pTM->tmHeight = pTM->tmAscent + pTM->tmDescent;
462
463     if ( pfo_ansi != NULL )
464     {
465         pTM->tmAveCharWidth = floor((pfo_ansi->foAvgCharWidth * 2.0 + pfo->foAvgCharWidth) / 3.0 * pfo->rescale + 0.5);
466         pTM->tmMaxCharWidth = __max(pfo_ansi->foMaxCharWidth, pfo->foMaxCharWidth) * pfo->rescale;
467     }
468     else
469     {
470         pTM->tmAveCharWidth = floor((pfo->foAvgCharWidth * pfo->rescale + 1.0) / 2.0);
471         pTM->tmMaxCharWidth = pfo->foMaxCharWidth * pfo->rescale;
472     }
473
474     pTM->tmInternalLeading = pfo->foInternalLeading * pfo->rescale;
475     pTM->tmExternalLeading = pdf->dfExternalLeading * pfo->rescale;
476
477     pTM->tmStruckOut = (pfo->fo_flags & FO_SYNTH_STRIKEOUT )
478                         ? 1 : pdf->dfStrikeOut;
479     pTM->tmUnderlined = (pfo->fo_flags & FO_SYNTH_UNDERLINE )
480                         ? 1 : pdf->dfUnderline;
481
482     pTM->tmOverhang = 0;
483     if( pfo->fo_flags & FO_SYNTH_ITALIC ) 
484     {
485         pTM->tmOverhang += pTM->tmHeight/3;
486         pTM->tmItalic = 1;
487     } else 
488         pTM->tmItalic = pdf->dfItalic;
489
490     pTM->tmWeight = pdf->dfWeight;
491     if( pfo->fo_flags & FO_SYNTH_BOLD ) 
492     {
493         pTM->tmOverhang++; 
494         pTM->tmWeight += 100;
495     } 
496
497     pTM->tmFirstChar = pdf_ansi->dfFirstChar;
498     pTM->tmLastChar = pdf_ansi->dfLastChar;
499     pTM->tmDefaultChar = pdf_ansi->dfDefaultChar;
500     pTM->tmBreakChar = pdf_ansi->dfBreakChar;
501
502     pTM->tmCharSet = pdf->dfCharSet;
503     pTM->tmPitchAndFamily = pdf->dfPitchAndFamily;
504
505     pTM->tmDigitizedAspectX = pdf->dfHorizRes;
506     pTM->tmDigitizedAspectY = pdf->dfVertRes;
507 }
508
509
510
511
512
513 const X11DRV_CP X11DRV_cptable[X11DRV_CPTABLE_COUNT] =
514 {
515     { /* SBCS */
516         X11DRV_enum_subfont_charset_normal,
517         X11DRV_unicode_to_char2b_sbcs,
518         X11DRV_DrawString_normal,
519         X11DRV_TextWidth_normal,
520         X11DRV_DrawText_normal,
521         X11DRV_TextExtents_normal,
522         X11DRV_GetTextMetricsA_normal,
523     },
524     { /* UNICODE */
525         X11DRV_enum_subfont_charset_normal,
526         X11DRV_unicode_to_char2b_unicode,
527         X11DRV_DrawString_normal,
528         X11DRV_TextWidth_normal,
529         X11DRV_DrawText_normal,
530         X11DRV_TextExtents_normal,
531         X11DRV_GetTextMetricsA_normal,
532     },
533     { /* CP932 */
534         X11DRV_enum_subfont_charset_cp932,
535         X11DRV_unicode_to_char2b_cp932,
536         X11DRV_DrawString_dbcs,
537         X11DRV_TextWidth_dbcs_2fonts,
538         X11DRV_DrawText_dbcs_2fonts,
539         X11DRV_TextExtents_dbcs_2fonts,
540         X11DRV_GetTextMetricsA_cp932,
541     },
542     { /* CP936 */
543         X11DRV_enum_subfont_charset_cp936,
544         X11DRV_unicode_to_char2b_cp936,
545         X11DRV_DrawString_normal, /* FIXME */
546         X11DRV_TextWidth_normal, /* FIXME */
547         X11DRV_DrawText_normal, /* FIXME */
548         X11DRV_TextExtents_normal, /* FIXME */
549         X11DRV_GetTextMetricsA_normal, /* FIXME */
550     },
551     { /* CP949 */
552         X11DRV_enum_subfont_charset_cp949,
553         X11DRV_unicode_to_char2b_cp949,
554         X11DRV_DrawString_dbcs,
555         X11DRV_TextWidth_dbcs_2fonts,
556         X11DRV_DrawText_dbcs_2fonts,
557         X11DRV_TextExtents_dbcs_2fonts,
558         X11DRV_GetTextMetricsA_normal, /* FIXME */
559     },
560     { /* CP950 */
561         X11DRV_enum_subfont_charset_cp950,
562         X11DRV_unicode_to_char2b_cp950,
563         X11DRV_DrawString_normal, /* FIXME */
564         X11DRV_TextWidth_normal, /* FIXME */
565         X11DRV_DrawText_normal, /* FIXME */
566         X11DRV_TextExtents_normal, /* FIXME */
567         X11DRV_GetTextMetricsA_normal, /* FIXME */
568     },
569 };