869 lines
20 KiB
C
869 lines
20 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these libraries and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
/* lcCT.c 1.1 - Fujitsu source for CDEnext 95/11/06 20:32:33 */
|
|
/* $XConsortium: _fallcCT.c /main/1 1996/04/08 15:15:33 cde-fuj $ */
|
|
/*
|
|
* Copyright 1992, 1993 by TOSHIBA Corp.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software and its
|
|
* documentation for any purpose and without fee is hereby granted, provided
|
|
* that the above copyright notice appear in all copies and that both that
|
|
* copyright notice and this permission notice appear in supporting
|
|
* documentation, and that the name of TOSHIBA not be used in advertising
|
|
* or publicity pertaining to distribution of the software without specific,
|
|
* written prior permission. TOSHIBA make no representations about the
|
|
* suitability of this software for any purpose. It is provided "as is"
|
|
* without express or implied warranty.
|
|
*
|
|
* TOSHIBA DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
* TOSHIBA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
|
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
* SOFTWARE.
|
|
*
|
|
* Author: Katsuhisa Yano TOSHIBA Corp.
|
|
* mopi@osa.ilab.toshiba.co.jp
|
|
*/
|
|
|
|
#include "_fallibint.h"
|
|
#include "_fallcPubI.h"
|
|
#include <X11/Xos.h>
|
|
#include <stdio.h>
|
|
|
|
typedef struct _StateRec {
|
|
XlcCharSet charset;
|
|
XlcCharSet GL_charset;
|
|
XlcCharSet GR_charset;
|
|
XlcCharSet ext_seg_charset;
|
|
int ext_seg_left;
|
|
} StateRec, *State;
|
|
|
|
typedef struct _CTDataRec {
|
|
char *name;
|
|
char *encoding; /* Compound Text encoding */
|
|
} CTDataRec, *CTData;
|
|
|
|
typedef struct _CTInfoRec {
|
|
XlcCharSet charset;
|
|
int encoding_len;
|
|
char *encoding; /* Compound Text encoding */
|
|
int ext_segment_len;
|
|
char *ext_segment; /* extended segment */
|
|
struct _CTInfoRec *next;
|
|
} CTInfoRec, *CTInfo;
|
|
|
|
static CTDataRec default_ct_data[] =
|
|
{
|
|
{ "ISO8859-1:GL", "\033(B" },
|
|
{ "ISO8859-1:GR", "\033-A" },
|
|
{ "ISO8859-2:GR", "\033-B" },
|
|
{ "ISO8859-3:GR", "\033-C" },
|
|
{ "ISO8859-4:GR", "\033-D" },
|
|
{ "ISO8859-7:GR", "\033-F" },
|
|
{ "ISO8859-6:GR", "\033-G" },
|
|
{ "ISO8859-8:GR", "\033-H" },
|
|
{ "ISO8859-5:GR", "\033-L" },
|
|
{ "ISO8859-9:GR", "\033-M" },
|
|
{ "JISX0201.1976-0:GL", "\033(J" },
|
|
{ "JISX0201.1976-0:GR", "\033)I" },
|
|
|
|
{ "GB2312.1980-0:GL", "\033$(A" },
|
|
{ "GB2312.1980-0:GR", "\033$)A" },
|
|
{ "JISX0208.1983-0:GL", "\033$(B" },
|
|
{ "JISX0208.1983-0:GR", "\033$)B" },
|
|
{ "KSC5601.1987-0:GL", "\033$(C" },
|
|
{ "KSC5601.1987-0:GR", "\033$)C" },
|
|
} ;
|
|
|
|
#define XctC0 0x0000
|
|
#define XctHT 0x0009
|
|
#define XctNL 0x000a
|
|
#define XctESC 0x001b
|
|
#define XctGL 0x0020
|
|
#define XctC1 0x0080
|
|
#define XctCSI 0x009b
|
|
#define XctGR 0x00a0
|
|
|
|
#define XctCntrlFunc 0x0023
|
|
#define XctMB 0x0024
|
|
#define XctOtherCoding 0x0025
|
|
#define XctGL94 0x0028
|
|
#define XctGR94 0x0029
|
|
#define XctGR96 0x002d
|
|
#define XctNonStandard 0x002f
|
|
#define XctIgnoreExt 0x0030
|
|
#define XctNotIgnoreExt 0x0031
|
|
#define XctLeftToRight 0x0031
|
|
#define XctRightToLeft 0x0032
|
|
#define XctDirection 0x005d
|
|
#define XctDirectionEnd 0x005d
|
|
|
|
#define XctGL94MB 0x2428
|
|
#define XctGR94MB 0x2429
|
|
#define XctExtSeg 0x252f
|
|
#define XctOtherSeg 0x2f00
|
|
|
|
#define XctESCSeq 0x1b00
|
|
#define XctCSISeq 0x9b00
|
|
|
|
#define SKIP_I(str) while (*(str) >= 0x20 && *(str) <= 0x2f) (str)++;
|
|
#define SKIP_P(str) while (*(str) >= 0x30 && *(str) <= 0x3f) (str)++;
|
|
|
|
typedef struct {
|
|
XlcSide side;
|
|
int char_size;
|
|
int set_size;
|
|
int ext_seg_length;
|
|
int version;
|
|
CTInfo ct_info;
|
|
} CTParseRec, *CTParse;
|
|
|
|
static CTInfo ct_list = NULL;
|
|
|
|
static CTInfo
|
|
_XlcGetCTInfoFromEncoding(char *encoding, int length)
|
|
{
|
|
CTInfo ct_info;
|
|
|
|
for (ct_info = ct_list; ct_info; ct_info = ct_info->next) {
|
|
if (length >= ct_info->encoding_len) {
|
|
if (ct_info->ext_segment) {
|
|
if (!strncmp(ct_info->encoding, encoding, 4) &&
|
|
!strncmp(ct_info->ext_segment, encoding + 6,
|
|
ct_info->ext_segment_len))
|
|
return ct_info;
|
|
} else if (!strncmp(ct_info->encoding, encoding,
|
|
ct_info->encoding_len)) {
|
|
return ct_info;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (CTInfo) NULL;
|
|
}
|
|
|
|
static unsigned int
|
|
_XlcParseCT(CTParse parse, char **text, int *length)
|
|
{
|
|
unsigned int ret = 0;
|
|
unsigned char ch;
|
|
unsigned char *str = (unsigned char *) *text;
|
|
|
|
bzero((char *) parse, sizeof(CTParseRec));
|
|
|
|
switch (ch = *str++) {
|
|
case XctESC:
|
|
if (*str == XctOtherCoding && *(str + 1) == XctNonStandard
|
|
&& *(str + 2) >= 0x30 && *(str + 2) <= 0x3f && *length >= 6) {
|
|
|
|
/* non-standard encodings */
|
|
parse->side = XlcGLGR;
|
|
parse->set_size = 0;
|
|
str += 2;
|
|
if (*str <= 0x34) {
|
|
parse->char_size = *str - 0x30;
|
|
if (parse->char_size == 0) parse->char_size = 1;
|
|
ret = XctExtSeg;
|
|
parse->ct_info = _XlcGetCTInfoFromEncoding(*text, *length);
|
|
} else
|
|
ret = XctOtherSeg;
|
|
str++;
|
|
parse->ext_seg_length = (*str - 128) * 128 + *(str + 1) - 128;
|
|
str += 2;
|
|
|
|
*length -= (char *) str - *text;
|
|
*text = (char *) str;
|
|
return ret;
|
|
} else if (*str == XctCntrlFunc && *length >= 4 &&
|
|
*(str + 1) >= 0x20 && *(str + 1) <= 0x2f &&
|
|
(*(str + 2) == XctIgnoreExt ||
|
|
*(str + 2) == XctNotIgnoreExt)) {
|
|
|
|
/* ignore extension or not */
|
|
str++;
|
|
parse->version = *str++ - 0x20;
|
|
ret = *str++;
|
|
|
|
*length -= (char *) str - *text;
|
|
*text = (char *) str;
|
|
return ret;
|
|
}
|
|
|
|
if (*str == XctMB) { /* multiple-byte sets */
|
|
parse->char_size = 2;
|
|
str++;
|
|
} else
|
|
parse->char_size = 1;
|
|
|
|
switch (*str) {
|
|
case XctGL94:
|
|
parse->side = XlcGL;
|
|
parse->set_size = 94;
|
|
ret = (parse->char_size == 1) ? XctGL94 : XctGL94MB;
|
|
break;
|
|
case XctGR94:
|
|
parse->side = XlcGR;
|
|
parse->set_size = 94;
|
|
ret = (parse->char_size == 1) ? XctGR94 : XctGR94MB;
|
|
break;
|
|
case XctGR96:
|
|
if (parse->char_size == 1) {
|
|
parse->side = XlcGR;
|
|
parse->set_size = 96;
|
|
ret = XctGR96;
|
|
}
|
|
break;
|
|
}
|
|
if (ret) {
|
|
str++;
|
|
if (*str >= 0x24 && *str <= 0x2f) { /* non-standard */
|
|
ret = 0;
|
|
str++;
|
|
}
|
|
}
|
|
|
|
SKIP_I(str)
|
|
|
|
if (ret && *str < 0x40) /* non-standard */
|
|
ret = 0;
|
|
|
|
if (*str < 0x30 || *str > 0x7e || (char *) str - *text >= *length)
|
|
break;
|
|
|
|
if (ret == 0)
|
|
ret = XctESCSeq;
|
|
else {
|
|
if (parse->char_size == 2) {
|
|
if (*str >= 0x70)
|
|
parse->char_size = 4;
|
|
else if (*str >= 0x60)
|
|
parse->char_size = 3;
|
|
}
|
|
parse->ct_info = _XlcGetCTInfoFromEncoding(*text, *length);
|
|
}
|
|
str++;
|
|
*length -= (char *) str - *text;
|
|
*text = (char *) str;
|
|
return ret;
|
|
case XctCSI:
|
|
/* direction */
|
|
if (*str == XctLeftToRight && *(str + 1) == XctDirection) {
|
|
ret = XctLeftToRight;
|
|
str += 2;
|
|
*length -= (char *) str - *text;
|
|
*text = (char *) str;
|
|
return ret;
|
|
} else if (*str == XctRightToLeft && *(str + 1) == XctDirection) {
|
|
ret = XctRightToLeft;
|
|
str += 2;
|
|
*length -= (char *) str - *text;
|
|
*text = (char *) str;
|
|
return ret;
|
|
} else if (*str == XctDirectionEnd) {
|
|
ret = XctDirectionEnd;
|
|
str++;
|
|
*length -= (char *) str - *text;
|
|
*text = (char *) str;
|
|
return ret;
|
|
}
|
|
|
|
SKIP_P(str)
|
|
SKIP_I(str)
|
|
|
|
if (*str < 0x40 && *str > 0x7e)
|
|
break;
|
|
|
|
ret = XctCSISeq;
|
|
str++;
|
|
*length -= (char *) str - *text;
|
|
*text = (char *) str;
|
|
return ret;
|
|
}
|
|
|
|
if (ch & 0x80) {
|
|
if (ch < 0xa0)
|
|
ret = XctC1;
|
|
else
|
|
ret = XctGR;
|
|
} else {
|
|
if (ch == XctHT || ch == XctNL)
|
|
ret = ch;
|
|
else if (ch < 0x20)
|
|
ret = XctC0;
|
|
else
|
|
ret = XctGL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
XlcCharSet
|
|
_fallcAddCT(char *name, char *encoding)
|
|
{
|
|
CTInfo ct_info;
|
|
XlcCharSet charset;
|
|
CTParseRec parse;
|
|
char *ct_ptr = encoding;
|
|
int length;
|
|
unsigned int type;
|
|
|
|
length = strlen(encoding);
|
|
|
|
switch (type = _XlcParseCT(&parse, &ct_ptr, &length)) {
|
|
case XctExtSeg:
|
|
case XctGL94:
|
|
case XctGL94MB:
|
|
case XctGR94:
|
|
case XctGR94MB:
|
|
case XctGR96:
|
|
if (parse.ct_info) /* existed */
|
|
return parse.ct_info->charset;
|
|
break;
|
|
default:
|
|
return (XlcCharSet) NULL;
|
|
}
|
|
|
|
charset = _fallcCreateDefaultCharSet(name, encoding);
|
|
if (charset == NULL)
|
|
return (XlcCharSet) NULL;
|
|
_fallcAddCharSet(charset);
|
|
|
|
ct_info = (CTInfo) Xmalloc(sizeof(CTInfoRec));
|
|
if (ct_info == NULL)
|
|
return (XlcCharSet) NULL;
|
|
|
|
ct_info->charset = charset;
|
|
ct_info->encoding = charset->ct_sequence;
|
|
ct_info->encoding_len = strlen(ct_info->encoding);
|
|
if (type == XctExtSeg) {
|
|
ct_info->ext_segment = ct_info->encoding + 6;
|
|
ct_info->ext_segment_len = strlen(ct_info->ext_segment);
|
|
} else {
|
|
ct_info->ext_segment = NULL;
|
|
ct_info->ext_segment_len = 0;
|
|
}
|
|
ct_info->next = ct_list;
|
|
ct_list = ct_info;
|
|
|
|
return charset;
|
|
}
|
|
|
|
static CTInfo
|
|
_XlcGetCTInfoFromCharSet(XlcCharSet charset)
|
|
{
|
|
CTInfo ct_info;
|
|
|
|
for (ct_info = ct_list; ct_info; ct_info = ct_info->next)
|
|
if (ct_info->charset == charset)
|
|
return ct_info;
|
|
|
|
return (CTInfo) NULL;
|
|
}
|
|
|
|
Bool
|
|
_fallcParseCharSet(XlcCharSet charset)
|
|
{
|
|
CTParseRec parse;
|
|
char *ptr, buf[BUFSIZ];
|
|
unsigned int type;
|
|
int length;
|
|
|
|
if (charset->ct_sequence == NULL)
|
|
return False;
|
|
|
|
ptr = charset->ct_sequence;
|
|
length = strlen(ptr);
|
|
|
|
type = _XlcParseCT(&parse, &ptr, &length);
|
|
|
|
if (charset->name) {
|
|
charset->xrm_name = falrmStringToQuark(charset->name);
|
|
|
|
snprintf(buf, sizeof(buf), "%s", charset->name);
|
|
if (ptr = strchr(buf, ':'))
|
|
*ptr = '\0';
|
|
charset->xrm_encoding_name = falrmStringToQuark(buf);
|
|
charset->encoding_name = falrmQuarkToString(charset->xrm_encoding_name);
|
|
} else {
|
|
charset->xrm_name = 0;
|
|
charset->encoding_name = NULL;
|
|
charset->xrm_encoding_name = 0;
|
|
}
|
|
|
|
charset->side = parse.side;
|
|
charset->char_size = parse.char_size;
|
|
charset->set_size = parse.set_size;
|
|
|
|
return True;
|
|
}
|
|
|
|
static void init_converter();
|
|
|
|
Bool
|
|
_fallcInitCTInfo(void)
|
|
{
|
|
XlcCharSet charset;
|
|
CTData ct_data;
|
|
int num;
|
|
|
|
if (ct_list == NULL) {
|
|
num = sizeof(default_ct_data) / sizeof(CTDataRec);
|
|
for (ct_data = default_ct_data; num-- > 0; ct_data++) {
|
|
charset = _fallcAddCT(ct_data->name, ct_data->encoding);
|
|
if (charset == NULL)
|
|
continue;
|
|
}
|
|
init_converter();
|
|
}
|
|
|
|
return True;
|
|
}
|
|
|
|
|
|
static int
|
|
_XlcCheckCTSequence(State state, char **ctext, int *ctext_len)
|
|
{
|
|
XlcCharSet charset;
|
|
CTParseRec parse;
|
|
CTInfo ct_info;
|
|
int length;
|
|
|
|
_XlcParseCT(&parse, ctext, ctext_len);
|
|
|
|
ct_info = parse.ct_info;
|
|
if (parse.ext_seg_length > 0) { /* XctExtSeg or XctOtherSeg */
|
|
if (ct_info) {
|
|
length = ct_info->ext_segment_len;
|
|
*ctext += length;
|
|
*ctext_len -= length;
|
|
state->ext_seg_left = parse.ext_seg_length - length;
|
|
state->ext_seg_charset = ct_info->charset;
|
|
} else {
|
|
state->ext_seg_left = parse.ext_seg_length;
|
|
state->ext_seg_charset = NULL;
|
|
}
|
|
} else if (ct_info) {
|
|
if (charset = ct_info->charset) {
|
|
if (charset->side == XlcGL)
|
|
state->GL_charset = charset;
|
|
else if (charset->side == XlcGR)
|
|
state->GR_charset = charset;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void
|
|
init_state(XlcConv conv)
|
|
{
|
|
State state = (State) conv->state;
|
|
static XlcCharSet GL_charset = NULL;
|
|
static XlcCharSet GR_charset = NULL;
|
|
|
|
if (GL_charset == NULL) {
|
|
GL_charset = _fallcGetCharSet("ISO8859-1:GL");
|
|
GR_charset = _fallcGetCharSet("ISO8859-1:GR");
|
|
}
|
|
|
|
state->GL_charset = state->charset = GL_charset;
|
|
state->GR_charset = GR_charset;
|
|
state->ext_seg_charset = NULL;
|
|
state->ext_seg_left = 0;
|
|
}
|
|
|
|
static int
|
|
cttocs(
|
|
XlcConv conv,
|
|
XPointer *from,
|
|
int *from_left,
|
|
XPointer *to,
|
|
int *to_left,
|
|
XPointer *args,
|
|
int num_args)
|
|
{
|
|
State state = (State) conv->state;
|
|
unsigned char ch;
|
|
int length;
|
|
XlcCharSet charset = NULL;
|
|
char *ctptr, *bufptr;
|
|
int ctext_len, buf_len;
|
|
|
|
ctptr = *((char **) from);
|
|
bufptr = *((char **) to);
|
|
ctext_len = *from_left;
|
|
buf_len = *to_left;
|
|
|
|
while (ctext_len > 0 && buf_len > 0) {
|
|
if (state->ext_seg_left > 0) {
|
|
length = min(state->ext_seg_left, ctext_len);
|
|
length = min(length, buf_len);
|
|
|
|
ctext_len -= length;
|
|
state->ext_seg_left -= length;
|
|
|
|
if (state->ext_seg_charset) {
|
|
charset = state->ext_seg_charset;
|
|
buf_len -= length;
|
|
if (charset->side == XlcGL) {
|
|
while (length-- > 0)
|
|
*bufptr++ = *ctptr++ & 0x7f;
|
|
} else if (charset->side == XlcGR) {
|
|
while (length-- > 0)
|
|
*bufptr++ = *ctptr++ | 0x80;
|
|
} else {
|
|
while (length-- > 0)
|
|
*bufptr++ = *ctptr++;
|
|
}
|
|
|
|
if (state->ext_seg_left < 1)
|
|
state->ext_seg_charset = NULL;
|
|
}
|
|
break;
|
|
}
|
|
ch = *((unsigned char *) ctptr);
|
|
if (ch == 0x1b || ch == 0x9b) {
|
|
length = _XlcCheckCTSequence(state, &ctptr, &ctext_len);
|
|
if (length < 0)
|
|
return -1;
|
|
if (state->ext_seg_left > 0 && charset)
|
|
break;
|
|
} else {
|
|
if (charset) {
|
|
if (charset != (ch & 0x80 ? state->GR_charset :
|
|
state->GL_charset))
|
|
break;
|
|
} else
|
|
charset = ch & 0x80 ? state->GR_charset : state->GL_charset;
|
|
|
|
if ((ch < 0x20 && ch != '\0' && ch != '\n' && ch != '\t') ||
|
|
(ch >= 0x80 && ch < 0xa0))
|
|
return -1;
|
|
|
|
*bufptr++ = *ctptr++;
|
|
ctext_len--;
|
|
buf_len--;
|
|
}
|
|
}
|
|
|
|
if (charset)
|
|
state->charset = charset;
|
|
if (num_args > 0)
|
|
*((XlcCharSet *) args[0]) = state->charset;
|
|
|
|
*from_left -= ctptr - *((char **) from);
|
|
*from = (XPointer) ctptr;
|
|
|
|
*to_left -= bufptr - *((char **) to);
|
|
*to = (XPointer) bufptr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
cstoct(
|
|
XlcConv conv,
|
|
XPointer *from,
|
|
int *from_left,
|
|
XPointer *to,
|
|
int *to_left,
|
|
XPointer *args,
|
|
int num_args)
|
|
{
|
|
State state = (State) conv->state;
|
|
XlcSide side;
|
|
unsigned char min_ch, max_ch, ch;
|
|
int length;
|
|
CTInfo ct_info;
|
|
XlcCharSet charset;
|
|
char *csptr, *ctptr;
|
|
int csstr_len, ct_len;
|
|
|
|
if (num_args < 1)
|
|
return -1;
|
|
|
|
csptr = *((char **) from);
|
|
ctptr = *((char **) to);
|
|
csstr_len = *from_left;
|
|
ct_len = *to_left;
|
|
|
|
charset = (XlcCharSet) args[0];
|
|
|
|
ct_info = _XlcGetCTInfoFromCharSet(charset);
|
|
if (ct_info == NULL)
|
|
return -1;
|
|
|
|
side = charset->side;
|
|
|
|
if (ct_info->ext_segment) {
|
|
if (charset != state->ext_seg_charset && state->ext_seg_left < 1) {
|
|
length = ct_info->encoding_len;
|
|
if (ct_len < length)
|
|
return -1;
|
|
strcpy(ctptr, ct_info->encoding);
|
|
ctptr[4] = ((ct_info->ext_segment_len + csstr_len) / 128) | 0x80;
|
|
ctptr[5] = ((ct_info->ext_segment_len + csstr_len) % 128) | 0x80;
|
|
ctptr += length;
|
|
ct_len -= length;
|
|
state->ext_seg_left = csstr_len;
|
|
}
|
|
length = min(state->ext_seg_left, csstr_len);
|
|
state->ext_seg_left -= length;
|
|
|
|
if (side == XlcGL) {
|
|
while (length-- > 0)
|
|
*ctptr++ = *csptr++ & 0x7f;
|
|
} else if (side == XlcGR) {
|
|
while (length-- > 0)
|
|
*ctptr++ = *csptr++ | 0x80;
|
|
} else {
|
|
while (length-- > 0)
|
|
*ctptr++ = *csptr++;
|
|
}
|
|
state->ext_seg_charset = (state->ext_seg_left > 0) ? charset : NULL;
|
|
} else {
|
|
if ((side == XlcGR && charset != state->GR_charset) ||
|
|
(side == XlcGL && charset != state->GL_charset)) {
|
|
|
|
ct_len -= ct_info->encoding_len;
|
|
if (ct_len < 0)
|
|
return -1;
|
|
strcpy(ctptr, ct_info->encoding);
|
|
ctptr += ct_info->encoding_len;
|
|
}
|
|
|
|
min_ch = 0x20;
|
|
max_ch = 0x7f;
|
|
|
|
if (charset->set_size == 94) {
|
|
max_ch--;
|
|
if (charset->char_size > 1 || side == XlcGR)
|
|
min_ch++;
|
|
}
|
|
|
|
while (csstr_len > 0 && ct_len > 0) {
|
|
ch = *((unsigned char *) csptr++) & 0x7f;
|
|
if (ch < min_ch || ch > max_ch)
|
|
if (ch != 0x00 && ch != 0x09 && ch != 0x0a && ch != 0x1b)
|
|
continue; /* XXX */
|
|
if (side == XlcGL)
|
|
*ctptr++ = ch & 0x7f;
|
|
else if (side == XlcGR)
|
|
*ctptr++ = ch | 0x80;
|
|
else
|
|
*ctptr++ = ch;
|
|
csstr_len--;
|
|
ct_len--;
|
|
}
|
|
if (side == XlcGR)
|
|
state->GR_charset = charset;
|
|
else if (side == XlcGL)
|
|
state->GL_charset = charset;
|
|
}
|
|
|
|
*from_left -= csptr - *((char **) from);
|
|
*from = (XPointer) csptr;
|
|
|
|
*to_left -= ctptr - *((char **) to);
|
|
*to = (XPointer) ctptr;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
strtocs(
|
|
XlcConv conv,
|
|
XPointer *from,
|
|
int *from_left,
|
|
XPointer *to,
|
|
int *to_left,
|
|
XPointer *args,
|
|
int num_args)
|
|
{
|
|
State state = (State) conv->state;
|
|
char *src, *dst;
|
|
unsigned char side;
|
|
int length;
|
|
|
|
src = (char *) *from;
|
|
dst = (char *) *to;
|
|
|
|
length = min(*from_left, *to_left);
|
|
side = *((unsigned char *) src) & 0x80;
|
|
|
|
while (side == (*((unsigned char *) src) & 0x80) && length-- > 0)
|
|
*dst++ = *src++;
|
|
|
|
*from_left -= src - (char *) *from;
|
|
*from = (XPointer) src;
|
|
*to_left -= dst - (char *) *to;
|
|
*to = (XPointer) dst;
|
|
|
|
if (num_args > 0)
|
|
*((XlcCharSet *)args[0]) = side ? state->GR_charset : state->GL_charset;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int
|
|
cstostr(
|
|
XlcConv conv,
|
|
XPointer *from,
|
|
int *from_left,
|
|
XPointer *to,
|
|
int *to_left,
|
|
XPointer *args,
|
|
int num_args)
|
|
{
|
|
State state = (State) conv->state;
|
|
char *csptr, *string_ptr;
|
|
int csstr_len, str_len;
|
|
unsigned char ch;
|
|
int unconv_num = 0;
|
|
|
|
if (num_args < 1 || (state->GL_charset != (XlcCharSet) args[0] &&
|
|
state->GR_charset != (XlcCharSet) args[0]))
|
|
return -1;
|
|
|
|
csptr = *((char **) from);
|
|
string_ptr = *((char **) to);
|
|
csstr_len = *from_left;
|
|
str_len = *to_left;
|
|
|
|
while (csstr_len-- > 0 && str_len > 0) {
|
|
ch = *((unsigned char *) csptr++);
|
|
if ((ch < 0x20 && ch != 0x00 && ch != 0x09 && ch != 0x0a) ||
|
|
ch == 0x7f || ((ch & 0x80) && ch < 0xa0)) {
|
|
unconv_num++;
|
|
continue;
|
|
}
|
|
*((unsigned char *) string_ptr++) = ch;
|
|
str_len--;
|
|
}
|
|
|
|
*from_left -= csptr - *((char **) from);
|
|
*from = (XPointer) csptr;
|
|
|
|
*to_left -= string_ptr - *((char **) to);
|
|
*to = (XPointer) string_ptr;
|
|
|
|
return unconv_num;
|
|
}
|
|
|
|
|
|
static void
|
|
close_converter(XlcConv conv)
|
|
{
|
|
if (conv->state)
|
|
Xfree((char *) conv->state);
|
|
|
|
Xfree((char *) conv);
|
|
}
|
|
|
|
static XlcConv
|
|
create_conv(XlcConvMethods methods)
|
|
{
|
|
XlcConv conv;
|
|
|
|
conv = (XlcConv) Xmalloc(sizeof(XlcConvRec));
|
|
if (conv == NULL)
|
|
return (XlcConv) NULL;
|
|
|
|
conv->state = (XPointer) Xmalloc(sizeof(StateRec));
|
|
if (conv->state == NULL) {
|
|
close_converter(conv);
|
|
return (XlcConv) NULL;
|
|
}
|
|
|
|
conv->methods = methods;
|
|
|
|
init_state(conv);
|
|
|
|
return conv;
|
|
}
|
|
|
|
static XlcConvMethodsRec cttocs_methods = {
|
|
close_converter,
|
|
cttocs,
|
|
init_state
|
|
} ;
|
|
|
|
static XlcConv
|
|
open_cttocs(XLCd from_lcd, char *from_type, XLCd to_lcd, char *to_type)
|
|
{
|
|
return create_conv(&cttocs_methods);
|
|
}
|
|
|
|
static XlcConvMethodsRec cstoct_methods = {
|
|
close_converter,
|
|
cstoct,
|
|
init_state
|
|
} ;
|
|
|
|
static XlcConv
|
|
open_cstoct(XLCd from_lcd, char *from_type, XLCd to_lcd, char *to_type)
|
|
{
|
|
return create_conv(&cstoct_methods);
|
|
}
|
|
|
|
static XlcConvMethodsRec strtocs_methods = {
|
|
close_converter,
|
|
strtocs,
|
|
init_state
|
|
} ;
|
|
|
|
static XlcConv
|
|
open_strtocs(XLCd from_lcd, char *from_type, XLCd to_lcd, char *to_type)
|
|
{
|
|
return create_conv(&strtocs_methods);
|
|
}
|
|
|
|
static XlcConvMethodsRec cstostr_methods = {
|
|
close_converter,
|
|
cstostr,
|
|
init_state
|
|
} ;
|
|
|
|
static XlcConv
|
|
open_cstostr(XLCd from_lcd, char *from_type, XLCd to_lcd, char *to_type)
|
|
{
|
|
return create_conv(&cstostr_methods);
|
|
}
|
|
|
|
static void
|
|
init_converter(void)
|
|
{
|
|
_fallcSetConverter((XLCd) NULL, XlcNCompoundText, (XLCd) NULL, XlcNCharSet,
|
|
open_cttocs);
|
|
_fallcSetConverter((XLCd) NULL, XlcNString, (XLCd) NULL, XlcNCharSet,
|
|
open_strtocs);
|
|
|
|
_fallcSetConverter((XLCd) NULL, XlcNCharSet, (XLCd) NULL, XlcNCompoundText,
|
|
open_cstoct);
|
|
_fallcSetConverter((XLCd) NULL, XlcNCharSet, (XLCd) NULL, XlcNString,
|
|
open_cstostr);
|
|
}
|