#include <Xm/Label.h>

/* このファイルは日本語EUCで保存してください */

int EUCToXmString();

int
main(ac, av)
int ac;
char *av[];
{
    XtAppContext app;
    String fallbacks[] = {
	"*label.fontList: \
-*-fixed-medium-r-normal--16-*-iso8859-1=ASCII, \
-*-fixed-medium-r-normal--16-*-jisx0208.1983-0=JISX0208, \
-*-fixed-medium-r-normal--16-*-jisx0201.1976-0=JISX0201, \
-*-fixed-medium-r-normal--16-*-jisx0212.1990-0=JISX0212"
    };
    Widget top, label;
    XmString xms;

    top = XtAppInitialize(&app, "Sample",
		    NULL, 0, &ac, av, fallbacks, NULL, 0);
    label = XmCreateLabel(top, "label", NULL, 0);
    XtManageChild(label);
    EUCToXmString("白山比咩神社", &xms);
    XtVaSetValues(label,
		  XmNlabelString, xms,
		  NULL);
    XmStringFree(xms);

    XtRealizeWidget(top);
    XtAppMainLoop(app);
}

int
EUCToXmString(str, xms)
unsigned char *str;
XmString *xms;
{
    int len = strlen(str) + 1;
    unsigned char *p = str;
    unsigned char *buf = XtMalloc(len);
    int idx = 0;
    char *codeset[] = {
	"",
    	"ASCII",     /* for ASCII */
    	"JISX0208",  /* for 漢字 */
	"JISX0201",  /* for 半角カナ */
    	"JISX0212",  /* for 補助漢字 */
    };
    enum { END = 0, ASCII, KANJI,
	   KATAKANA, KANJI2, ERROR } cur, prv;
    prv = cur = END;
    *xms = NULL;
    for (; p <= str + len; p++) {
	/* 文字セットを識別する */
    	if (!*p) cur = END;
	/* 0x8eならJIS X 0201 */
    	else if (*p == 0x8e) cur = KATAKANA;
	/* 0x8fならJIS X 0212 */
    	else if (*p == 0x8f) cur = KANJI2;
	/* その他最上位ビットが1ならJIS X 0208 */
    	else if (*p & 0x80) cur = KANJI;
    	/* 残りはASCII */
	else cur = ASCII;
	if (prv == END) prv = cur;
	else if (prv != cur) {
	/* 文字セットが変わったらbufに保存しておいた
    	   文字列を複合文字列に変換する */
	    XmString tmp1, tmp2;
	    buf[idx] = 0;
	    tmp1 = XmStringCreateLtoR(buf,
				      codeset[prv]);
    	    /* 生成した複合文字列を結合する */
	    if (!*xms) *xms = tmp1;
	    else {
		tmp2 = *xms;
		*xms = XmStringConcat(tmp2, tmp1);
		XmStringFree(tmp1);
		XmStringFree(tmp2);
	    }
	    prv = cur; idx = 0;
	}
	switch (cur)
	{
	case ASCII:
	    /* 1バイトをbufへ保存 */
	    if (*p > 0x7e) cur = ERROR;
	    buf[idx++] = *p; break;
	case KATAKANA:
	    /* 次の1バイトを保存 */
	    p++;
	    if (*p < 0xa1 || *p > 0xdf) cur = ERROR;
	    buf[idx++] = *p; break;
	case KANJI:
	    /* 上位ビットを落して2バイトを保存 */
	    if (*p < 0xa1 || *p > 0xfe) cur = ERROR;
	    buf[idx++] = *p++ & 0x7f;
	    if (*p < 0xa1 || *p > 0xfe) cur = ERROR;
	    buf[idx++] = *p & 0x7f;
	    break;
	case KANJI2:
	    /* 上位ビットを落して次の2バイトを保存 */
	    p++;
	    if (*p < 0xa1 || *p > 0xfe) cur = ERROR;
	    buf[idx++] = *p & 0x7f;
	    if (*p < 0xa1 || *p > 0xfe) cur = ERROR;
	    buf[idx++] = *++p & 0x7f;
	    break;
	}
	if (cur == ERROR) break;
    }
    XtFree(buf);
    return cur;
}
