1/*
2 * Copyright 1992, 1993 by TOSHIBA Corp.
3 *
4 * Permission to use, copy, modify, and distribute this software and its
5 * documentation for any purpose and without fee is hereby granted, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of TOSHIBA not be used in advertising
9 * or publicity pertaining to distribution of the software without specific,
10 * written prior permission. TOSHIBA make no representations about the
11 * suitability of this software for any purpose.  It is provided "as is"
12 * without express or implied warranty.
13 *
14 * TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 * TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 * SOFTWARE.
21 *
22 * Author: Katsuhisa Yano	TOSHIBA Corp.
23 *			   	mopi@osa.ilab.toshiba.co.jp
24 */
25/*
26 * Copyright 1995 by FUJITSU LIMITED
27 * This is source code modified by FUJITSU LIMITED under the Joint
28 * Development Agreement for the CDE/Motif PST.
29 *
30 * Modifier: Takanori Tateno   FUJITSU LIMITED
31 *
32 */
33/*
34 * Modifiers: Jeff Walls, Paul Anderson (HEWLETT-PACKARD)
35 */
36
37#ifdef HAVE_CONFIG_H
38#include <config.h>
39#endif
40#include "Xlibint.h"
41#include "XlcPublic.h"
42#include "XomGeneric.h"
43#include <stdio.h>
44
45/* for VW/UDC start */
46static Bool
47ismatch_scopes(
48    FontData      fontdata,
49    unsigned long *value,
50    Bool	  is_shift)
51{
52    register int scopes_num = fontdata->scopes_num;
53    FontScope scopes = fontdata->scopes;
54    if (!scopes_num)
55        return False;
56
57    if(fontdata->font == NULL)
58	return False;
59
60    for(;scopes_num--;scopes++)
61        if ((scopes->start <= (*value & 0x7f7f)) &&
62                        ((scopes->end) >= (*value & 0x7f7f))){
63	    if(is_shift == True) {
64                if(scopes->shift){
65                    if(scopes->shift_direction == '+'){
66                        *value += scopes->shift ;
67                    } else if( scopes->shift_direction == '-'){
68                        *value -= scopes->shift ;
69                    }
70                }
71            }
72            return True;
73        }
74
75    return False;
76}
77
78static int
79check_vertical_fonttype(
80    char	*name)
81{
82    char	*ptr;
83    int		type = 0;
84
85    if(name == (char *)NULL || (int) strlen(name) <= 0)
86	return False;
87
88    /* Obtains the pointer of CHARSET_ENCODING_FIELD. */
89    if((ptr = strchr(name, '-')) == (char *) NULL)
90	return False;
91    ptr++;
92
93    /* Obtains the pointer of vertical_map font type. */
94    if((ptr = strchr(ptr, '.')) == (char *) NULL)
95	return False;
96    ptr++;
97
98    switch(*ptr) {
99      case '1':
100	type = 1;	break;
101      case '2':
102	type = 2;	break;
103      case '3':
104	type = 3;	break;
105    }
106    return type;
107}
108
109/*
110*/
111#define VMAP          0
112#define VROTATE       1
113#define FONTSCOPE     2
114
115FontData
116_XomGetFontDataFromFontSet(
117    FontSet fs,
118    unsigned char *str,
119    int len,
120    int *len_ret,
121    int is2b,
122    int type)          /* VMAP , VROTATE , else */
123{
124    unsigned long value;
125    int num,i,hit,csize;
126    FontData fontdata;
127    unsigned char *c;
128    int vfont_type;
129
130    c = str;
131    hit = -1;
132    if(type == VMAP){
133	fontdata = fs->vmap;
134	num      = fs->vmap_num;
135    } else if(type == VROTATE){
136        fontdata = (FontData)fs->vrotate;
137	num      = fs->vrotate_num;
138    } else {
139	if(fs->font_data_count <= 0 || fs->font_data == (FontData)NULL) {
140	    fontdata = fs->substitute;
141	    num      = fs->substitute_num;
142	}else {
143            fontdata = fs->font_data;
144	    num      = fs->font_data_count;
145	}
146	/* CDExc20229 fix */
147	if(fontdata == NULL || num == 0){
148	    return(NULL);
149	}
150    }
151
152
153    if(is2b){
154        csize = 2;
155    } else {
156        csize = 1;
157    }
158
159    for(;len;len--){
160        if(is2b){
161            value = (((unsigned long)*c) << 8)|(unsigned long)*(c + 1);
162        } else {
163            value = (unsigned long)*c;
164        }
165
166       /* ### NOTE: This routine DOES NOT WORK!
167	* ###       We can work around the problem in the calling routine,
168	* ###       but we really need to understand this better.  As it
169	* ###       stands, the algorithm ALWAYS returns "fontdata[0]"
170	* ###       for non-VW text!  This is clearly wrong.  In fact,
171	* ###       given the new parse_font[name|data]() algorithms,
172	* ###       we may not even need this routine to do anything
173	* ###       for non-VW text (since font_set->font always contains
174	* ###       the best font for this fontset).  -- jjw/pma (HP)
175	*/
176        for (i=0;i<num;i++) {
177	    if(type == VROTATE) {
178		if(fontdata[i].font) {
179		    /* If the num_cr equal zero, all character is rotated. */
180		    if(fontdata[i].scopes_num == 0) {
181			break;
182		    } else {
183			/* The vertical rotate glyph is not have code shift. */
184			if (ismatch_scopes(&(fontdata[i]),&value,False)) {
185			    break;
186			}
187		    }
188		}
189	    } else if(type == VMAP) {
190		if(fontdata[i].font) {
191		    vfont_type = check_vertical_fonttype(fontdata[i].name);
192		    if(vfont_type == 0 || vfont_type == 1) {
193			break;
194		    } else if(vfont_type == 2 || vfont_type == 3) {
195			if(fontdata[i].scopes_num <= 0)
196			    break;
197
198			if (ismatch_scopes(&(fontdata[i]),&value,True)) {
199			    break;
200			}
201		    }
202		}
203	    } else { /* FONTSCOPE */
204		if(fontdata[i].font) {
205		    if(fontdata[i].scopes_num <= 0)
206                        break;
207		    if (ismatch_scopes(&(fontdata[i]),&value,True)){
208		        break;
209                    }
210		}
211	    }
212        }
213        if((hit != -1) && (i != hit)){
214            break;
215        }
216        if(i == num){
217            if( type == VROTATE || type == VMAP){
218		/* Change 1996.01.23 start */
219		if(fs->font_data_count <= 0 ||
220		   fs->font_data == (FontData)NULL)
221		    fontdata = fs->substitute;
222		else
223		    fontdata = fs->font_data;
224		/* Change 1996.01.23 end */
225	    }
226	    hit = 0;
227            c += csize;
228	    break;
229        }
230        if( hit == -1 ) hit = i;
231        if(is2b){
232            *c = (unsigned char)(value >> 8);
233            *(c + 1) = (unsigned char)(value);
234        } else {
235            *c = (unsigned char)value;
236        }
237        c += csize;
238    }
239    *len_ret = (c - str);
240    return(&(fontdata[hit]));
241}
242/* for VW/UDC end   */
243
244static FontSet
245_XomGetFontSetFromCharSet(
246    XOC oc,
247    XlcCharSet charset)
248{
249    register FontSet font_set = XOC_GENERIC(oc)->font_set;
250    register int num = XOC_GENERIC(oc)->font_set_num;
251    XlcCharSet *charset_list;
252    int charset_count;
253
254    for ( ; num-- > 0; font_set++) {
255	charset_count = font_set->charset_count;
256	charset_list = font_set->charset_list;
257	for ( ; charset_count-- > 0; charset_list++)
258	    if (*charset_list == charset)
259		return font_set;
260    }
261
262    return (FontSet) NULL;
263}
264
265static void
266shift_to_gl(
267    register char *text,
268    register int length)
269{
270    while (length-- > 0)
271	*text++ &= 0x7f;
272}
273
274static void
275shift_to_gr(
276    register char *text,
277    register int length)
278{
279    while (length-- > 0)
280	*text++ |= 0x80;
281}
282
283static Bool
284load_font(
285    XOC oc,
286    FontSet font_set)
287{
288    font_set->font = XLoadQueryFont(oc->core.om->core.display,
289			oc->core.font_info.font_name_list[font_set->id]);
290    if (font_set->font == NULL)
291	return False;
292
293    oc->core.font_info.font_struct_list[font_set->id] = font_set->font;
294    XFreeFontInfo(NULL, font_set->info, 1);
295    font_set->info = NULL;
296
297    if (font_set->font->min_byte1 || font_set->font->max_byte1)
298	font_set->is_xchar2b = True;
299    else
300	font_set->is_xchar2b = False;
301
302    return True;
303}
304
305int
306_XomConvert(
307    XOC oc,
308    XlcConv conv,
309    XPointer *from,
310    int *from_left,
311    XPointer *to,
312    int *to_left,
313    XPointer *args,
314    int num_args)
315{
316    XPointer cs, lc_args[1];
317    XlcCharSet charset;
318    int length, cs_left, ret;
319    FontSet font_set;
320
321    cs = *to;
322    cs_left = *to_left;
323    lc_args[0] = (XPointer) &charset;
324
325    ret = _XlcConvert(conv, from, from_left, &cs, &cs_left, lc_args, 1);
326    if (ret < 0)
327	return -1;
328
329    font_set = _XomGetFontSetFromCharSet(oc, charset);
330    if (font_set == NULL)
331	return -1;
332
333    if (font_set->font == NULL && load_font(oc, font_set) == False)
334	return -1;
335
336    length = *to_left - cs_left;
337
338    if (font_set->side != charset->side) {
339	if (font_set->side == XlcGL)
340	    shift_to_gl(*to, length);
341	else if (font_set->side == XlcGR)
342	    shift_to_gr(*to, length);
343    }
344
345    if (font_set->is_xchar2b)
346	length >>= 1;
347    *to = cs;
348    *to_left -= length;
349
350    *((XFontStruct **) args[0]) = font_set->font;
351    *((Bool *) args[1]) = font_set->is_xchar2b;
352    if(num_args >= 3){
353        *((FontSet *) args[2]) = font_set;
354    }
355
356    return ret;
357}
358
359XlcConv
360_XomInitConverter(
361    XOC oc,
362    XOMTextType type)
363{
364    XOCGenericPart *gen = XOC_GENERIC(oc);
365    XlcConv *convp;
366    const char *conv_type;
367    XlcConv conv;
368    XLCd lcd;
369
370    switch (type) {
371    case XOMWideChar:
372	convp = &gen->wcs_to_cs;
373	conv_type = XlcNWideChar;
374	break;
375    case XOMMultiByte:
376	convp = &gen->mbs_to_cs;
377	conv_type = XlcNMultiByte;
378	break;
379    case XOMUtf8String:
380	convp = &gen->utf8_to_cs;
381	conv_type = XlcNUtf8String;
382	break;
383    default:
384	return (XlcConv) NULL;
385    }
386
387    conv = *convp;
388    if (conv) {
389	_XlcResetConverter(conv);
390	return conv;
391    }
392
393    lcd = oc->core.om->core.lcd;
394
395    conv = _XlcOpenConverter(lcd, conv_type, lcd, XlcNFontCharSet);
396    if (conv == (XlcConv) NULL) {
397        conv = _XlcOpenConverter(lcd, conv_type, lcd, XlcNCharSet);
398        if (conv == (XlcConv) NULL)
399	    return (XlcConv) NULL;
400    }
401
402    *convp = conv;
403    return conv;
404}
405