+/*
+ * $XConsortium: XCnvCTToWC.c,v 1.22 91/11/17 16:15:29 rws Exp $
+ */
+
+/*
+ * Copyright 1990, 1991 by OMRON Corporation, NTT Software Corporation,
+ * and Nippon Telegraph and Telephone Corporation
+ * Copyright 1991 by the Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 names of OMRON, NTT Software, NTT, and M.I.T.
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. OMRON, NTT Software,
+ * NTT, and M.I.T. make no representations about the suitability of this
+ * software for any purpose. It is provided "as is" without express or
+ * implied warranty.
+ *
+ * OMRON, NTT SOFTWARE, NTT, AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD
+ * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS, IN NO EVENT SHALL OMRON, NTT SOFTWARE, NTT, OR M.I.T. 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.
+ *
+ * Authors: Li Yuhong OMRON Corporation
+ * Hiroshi Kuribayashi OMRON Corporation
+ *
+ */
+
+/*
+ * This files includes 2 functions:
+ *
+ * _XConvertCTToWC()
+ * _XConvertWCToCT()
+ *
+*/
+#include "Xlibint.h"
+#include "Xlocaleint.h"
+#include <X11/Xos.h>
+#include <X11/Xutil.h>
+
+static int _XConvertCTextToWC();
+extern int _XParseISOEncoding();
+extern Bool _XcwEscSetStatus();
+extern void _XwcSetCsid();
+
+/*
+ * Function Name: _XConvertCTToWC
+ *
+*/
+
+/*
+ * Constant Definitions
+*/
+#define HT 0x09 /* horizontal tab */
+#define NL 0x0A /* new line */
+#define ESC 0x1B /* escape */
+#define CSI 0x9B /* control sequence introducer. */
+#define SPACE 0x20 /* space */
+#define GL94MIN 0x21 /* manimun of code of GL 94 charset */
+#define GL94MAX 0x7E /* maximun of code of GL 94 charset */
+
+/*
+ * Macro Procedure Definitions
+*/
+/*
+ * Return():
+ * set result values before funciton returns.
+ * If there is more room for output buffer wc_str, provide additional
+ * service, i.e., append WNULL at tail.
+*/
+#define Return(result) { \
+ *wc_len = wcnt; \
+ *scanned_bytes = ctcnt; \
+ if (wcnt < limit) *wc_str = WNULL; \
+ if (state) *state = xlocale->ct_state; \
+ if (error > 0) return(error); \
+ return(result); \
+ }
+
+/*
+ * SaveStore():
+ * store converted wchar code to buffer, and make sure no overflow.
+*/
+#define SaveStore(wc) { \
+ if (wcnt >= limit) \
+ Return(BadBuffer); \
+ *wc_str++ = wc; \
+ wcnt++; \
+ }
+
+/*
+ * CombineCode():
+ * concatenate the byte with code if the byte is valid.
+*/
+#define CombineCode(code) { \
+ if (byte < stateinfo.code_min || byte > stateinfo.code_max) { \
+ error++; \
+ byte = stateinfo.code_min; \
+ } \
+ code = (code << 8) | byte; \
+ ct_str++, ct_bytes--; \
+ if (ct_bytes < 1) \
+ Return(BadTerminate); \
+ byte = *ct_str; \
+ }
+
+int
+_XConvertCTToWC(xlocale, ct_str, ct_bytes, wc_str, wc_len, scanned_bytes, state)
+ XLocale xlocale;
+ unsigned char *ct_str;
+ int ct_bytes;
+ wchar *wc_str;
+ int *wc_len;
+ int *scanned_bytes;
+ _State *state;
+{
+ register unsigned char byte;
+ register unsigned int code;
+ wchar woffset;
+ int wcnt, ctcnt, limit, len;
+ ISOStateInfo stateinfo;
+ char seq[MAXSEQUENCELENGTH];
+ int error = 0;
+
+ if (!xlocale)
+ xlocale = _XFallBackConvert();
+ if (state && *state != XDEFAULT_STATE) {
+ xlocale->ct_state = *state;
+ if (_XcwIdCheck(xlocale) == False)
+ _Xctinit(xlocale);
+ } else
+ _Xctinit(xlocale);
+
+ limit = *wc_len;
+ wcnt = ctcnt = 0;
+ while (ct_bytes > 0 && (byte = *ct_str) != 0) {
+ switch (byte) {
+ case HT:
+ case NL:
+ case SPACE:
+ SaveStore(_Xatowc(byte));
+ ct_str++, ct_bytes--, ctcnt++;
+ continue;
+ case CSI:
+ /* not supported yet */
+ case ESC:
+ /* parse the control escape sequence of CT encoding. */
+ switch (_XParseISOEncoding(ct_str, ct_bytes, &len, &stateinfo)) {
+ case Success:
+ if (*(ct_str+1) == 0x25) {
+ /* Extend segmant */
+ int tmplen = limit - wcnt;
+ int ret;
+ if((ret = _XConvertCTextToWC(xlocale, ct_str, ct_bytes,
+ wc_str, &tmplen, &len)) < 0)
+ Return(ret);
+ wc_str += tmplen;
+ wcnt +=tmplen;
+ ct_str += len, ct_bytes -= len, ctcnt += len;
+ continue;
+ }
+ /*
+ * In mose case the control sequence is new one, so we
+ * set it to current state directly, enhance little speed
+ * without no comparision.
+ *
+ */
+ (void) strncpy(seq, (char *)ct_str, len);
+ seq[len] = '\0';
+ if (_XcwEscSetStatus(xlocale, seq) == True) {
+ ct_str += len, ct_bytes -= len;
+ ctcnt += len;
+ continue;
+ }
+ /*
+ * Actually, it is not registered encoding, can not be
+ * recognized by this convertor. go to next step.
+ */
+ case BadEncoding:
+ /*
+ * wrong escape sequence, the function can not recover
+ * this error, return it.
+ */
+ Return(BadEncoding);
+ case BadTerminate:
+ Return(BadTerminate);
+ default: /* never go to here */
+ Return(BadEncoding);
+ ;
+ }
+ default:
+ /* get codepoint of character. */
+ ctSetGLorGR(xlocale, byte&0x80);
+ _XcwIdGetAll(xlocale, &woffset, &stateinfo);
+ code = 0;
+ switch (stateinfo.code_bytes) {
+ case 4:
+ CombineCode(code);
+ case 3:
+ CombineCode(code);
+ case 2:
+ CombineCode(code);
+ case 1:
+ if (byte < stateinfo.code_min ||
+ byte > stateinfo.code_max) {
+ error++;
+ byte = stateinfo.code_min;
+ }
+ code = (code << 8) | byte;
+ ct_str++, ct_bytes--;
+ code &= 0x7f7f7f7f; /* MSB off */
+ break;
+ }
+ SaveStore(woffset | code);
+ /*
+ * after no any error, then advance scanned_bytes
+ * "ctcnt".
+ */
+ ctcnt += stateinfo.code_bytes;
+ continue;
+ }
+ }
+ Return(Success);
+}
+
+/*
+ * Function Name: _XConvertWCToCT
+ *
+*/
+#undef Return
+#undef SaveStore
+
+#define Return(result) { \
+ *ct_bytes = ctcnt; \
+ *scanned_len = wcnt; \
+ if (ctcnt < limit) \
+ *ct_str = 0; \
+ if (error > 0) return(error); \
+ return(result); \
+ }
+
+#define SaveStore(c) { \
+ if (ctcnt >= limit) Return(BadBuffer); \
+ *ct_str++ = c; \
+ ctcnt++; \
+ }
+
+#define AppendDesignation(state) { \
+ int len = strlen(state); \
+ if ((ctcnt + len) > limit) \
+ Return(BadBuffer); \
+ (void) strcpy((char *)ct_str, state); \
+ ct_str += len; \
+ ctcnt += len; \
+ }
+
+
+int
+_XConvertWCToCT(xlocale, wc_str, wc_len, ct_str, ct_bytes, scanned_len)
+ XLocale xlocale;
+ wchar *wc_str;
+ int wc_len;
+ unsigned char *ct_str;
+ int *ct_bytes;
+ int *scanned_len;
+{
+ char *esc, seq[MAXSEQUENCELENGTH];
+ wchar woffset, wc;
+ int wcnt, ctcnt, crwcnt, crctcnt, limit;
+ int ret, error = 0;
+ ISOStateInfo stateinfo;
+ _State state_sv, state_ext;
+ unsigned char *ct_str_sv = NULL;
+ int len_sv;
+ char *defstr = XDefaultString();
+
+ if (!xlocale)
+ xlocale = _XFallBackConvert();
+
+ _Xctinit(xlocale);
+ state_sv = xlocale->ct_state;
+ limit = *ct_bytes;
+ wcnt = ctcnt = 0;
+ while ((wc_len > 0) && ((wc = *wc_str) != WNULL)) {
+ _CSID ctGLorGR;
+ /*
+ * filter control characters.
+ */
+ if (_Xiswcntrl(wc)) {
+ SaveStore(_Xwctoa(wc));
+ wc_str++, wc_len--, wcnt++;
+ continue;
+ }
+ _XcwGetAll(xlocale, wc, &esc, &woffset, &stateinfo);
+ if (woffset == 0) {
+ int i;
+ /* XXX BUG: need to check/add designate sequence of default string.
+ But current default string is NULL, so OK. :-) */
+ for (i = 0; *(defstr + i) != 0; i++) {
+ SaveStore(*(defstr + i))
+ }
+ error++;
+ wc_str++, wc_len--, wcnt++;
+ continue;
+ }
+ if ((ctGLorGR = ctGetGLorGR(xlocale)) == GL &&
+ ctGetGLid(xlocale) != (state_sv & 0xff) ||
+ ctGLorGR == GR &&
+ ctGetGRid(xlocale) != ((state_sv >> 8) & 0xff)) {
+ state_ext = state_sv;
+ state_sv = xlocale->ct_state;
+ /*
+ * append designation of control sequence.
+ */
+ if (*(esc+1) == 0x25) {
+ ct_str_sv = ct_str + 4;
+ len_sv = strlen(esc) - 6;
+ }
+ AppendDesignation(esc);
+ }
+ /*
+ * remainning buffer length of ct_str.
+ */
+ crctcnt = limit - ctcnt;
+ if ((ret = _XwcDecomposeGlyphCharset(xlocale, wc_str, wc_len, ct_str,
+ &crctcnt, &crwcnt, (int *)NULL)) < 0)
+ Return(ret);
+ if (ct_str_sv) {
+ *ct_str_sv++ = (crctcnt + len_sv) / 128 + 128;
+ *ct_str_sv = (crctcnt + len_sv) % 128 +128;
+ ct_str_sv = NULL;
+ xlocale->ct_state = state_ext;
+ state_sv = state_ext;
+ }
+ error += ret;
+ wc_str += crwcnt, wc_len -= crwcnt, wcnt += crwcnt;
+ ct_str += crctcnt, ctcnt += crctcnt;
+ }
+ if (!_XcwCheckDefaultState(xlocale)) {
+ (void) _XcwGetDefaultEncoding(xlocale, seq);
+ AppendDesignation(seq);
+ _Xctinit(xlocale);
+ }
+ Return(Success);
+}
+
+int
+_XctIsExtendSegment(xlocale, ct_str, textlen, bytes)
+XLocale xlocale;
+unsigned char *ct_str;
+int *textlen;
+int *bytes;
+{
+ unsigned char *text;
+ int seqlen;
+ unsigned char name[128];
+ _CSID csid;
+ int m, l;
+
+ if(*(ct_str+1) != 0x25 || *(ct_str+2) != 0x2f)
+ return (0); /* Not CT Extend Segment */
+ *bytes = *(ct_str+3) -'0';
+ if (*bytes < 0 || *bytes > 4)
+ return (0); /* Not CT Extend Segment */
+ else if (*bytes == 0)
+ /* I'm not sure. Valiable octes pre char cannot convert */
+ *bytes = 1;
+
+
+ text = (unsigned char *)index((char *)ct_str+6, 0x02) + 1;
+ m = *(ct_str+4);
+ l = *(ct_str+5);
+ seqlen = text - ct_str;
+
+ strncpy((char *)name, (char *)ct_str+6, seqlen - 6);
+ name[seqlen - 7] =0;
+ csid = _XcwNameGetGLorGRId(name, *(text+1) & 0x80);
+ ctSetGLorGR(xlocale, *(text+1) & 0x80);
+ ctSetid(xlocale, csid);
+
+ *textlen = (m-128)*128+(l-128) + 5 - seqlen + 1; /* !!!!! */
+ return(seqlen);
+}
+
+#undef Return
+#undef SaveStore
+#undef CombineCode
+
+#define Return(result) { \
+ *wc_bytes = wccnt; \
+ *scanned_bytes = ctcnt; \
+ if (wccnt < limit) \
+ *wc_str = 0; \
+ if (error > 0) return (error); \
+ return (result); \
+ }
+
+#define SaveStore(wc) { \
+ if (wccnt >= limit) Return(BadBuffer); \
+ *wc_str++ = wc; \
+ wccnt++; \
+ }
+
+/*
+ * CombineCode():
+ * concatenate the byte with code if the byte is valid.
+*/
+#define CombineCode(code) { \
+ code = (code << 8) | byte; \
+ ct_str++; ct_bytes--; \
+ if (ct_bytes < 1) \
+ Return(BadTerminate); \
+ byte = *ct_str; \
+ }
+
+static int
+_XConvertCTextToWC(xlocale, ct_str, ct_bytes, wc_str, wc_bytes, scanned_bytes)
+ XLocale xlocale;
+ unsigned char *ct_str;
+ int ct_bytes;
+ wchar *wc_str;
+ int *wc_bytes;
+ int *scanned_bytes;
+{
+ register unsigned char byte;
+ int wccnt, ctcnt;
+ int code, len, limit, error;
+ int textlen;
+ int bytes;
+ _State state_sv;
+ wchar woffset;
+
+ state_sv = xlocale->ct_state;
+ limit = *wc_bytes;
+ wccnt = ctcnt = error = 0;
+
+ if((len = _XctIsExtendSegment(xlocale, ct_str, &textlen, &bytes)) < 0)
+ /* not register encoding by X. */
+ Return(BadEncoding);
+ ct_str += len; ctcnt += len; ct_bytes -=len;
+
+ if (ct_bytes < textlen)
+ Return(BadTerminate); /* Nor enough data. What should do? */
+
+ _XcwIdGetWoffset(xlocale, &woffset);
+
+ while (textlen > 0) {
+ /* get codepoint of character. */
+ code = 0;
+ byte = *ct_str;
+ switch (bytes) {
+ case 4: CombineCode(code);
+ case 3: CombineCode(code);
+ case 2: CombineCode(code);
+ case 1:
+ code = (code << 8) | byte;
+ ct_str++, ct_bytes--;
+ code &= 0x7f7f7f7f; /* MSB off */
+ break;
+ }
+ SaveStore(woffset | code);
+ textlen -= bytes;
+ ctcnt += bytes;
+ }
+ xlocale->ct_state = state_sv;
+ Return(Success);
+}