static char rcsid[] = "@(#)$Id: iso2022.c,v 1.100 2006/04/09 07:37:07 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.100 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
 *****************************************************************************/

#include "headers.h"
#include "s_me.h"
#include "cs_imp.h"

#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif

DEBUG_VAR(Debug,__FILE__,"charset");

struct iso2022_setid return_to_iso2022 = 
{ bank_unspecified, iso2022_other , { 0x40 , 0x00, 0x00, 0x00 } };

static struct iso2022_setid set0_utf8 =
{ bank_unspecified, iso2022_other , { 0x47 , 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_latin7 = /* ISO-8859-13 */
{ bank_unspecified, iso2022_96, { 0x59, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_latin8 = /* ISO-8859-14 */
{ bank_unspecified, iso2022_96, { 0x5F, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_latin9 = /* ISO-8859-15 */
{ bank_unspecified, iso2022_96, { 0x62, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso885916 = /* ISO-8859-16 */
{ bank_unspecified, iso2022_96, { 0x66, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_koi8e = /* ECMA Cyrilic, ISO-IR-111, KOI8-E */
{ bank_unspecified, iso2022_96, { 0x40, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso_ir_2 = /* IRV, ISO_646.irv:1983, ISO-IR-2 */
{ bank_G0, iso2022_94, { 0x40, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso_ir_4 = /* ISO646-GB, BS_4730, ISO-IR-4 */
{ bank_G0, iso2022_94, { 0x41, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso_ir_8_1 = /* NATS-SEFI, ISO-IR-8-1 */
{ bank_G0, iso2022_94, { 0x43, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso_ir_8_2 = /* NATS-SEFI-ADD, ISO-IR-8-2 */
{ bank_G0, iso2022_94, { 0x44, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso_ir_9_1 = /* NATS-DANO, ISO-IR-9-1 */
{ bank_G0, iso2022_94, { 0x45, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso_ir_9_2 = /* NATS-DANO-ADD, ISO-IR-9-2 */
{ bank_G0, iso2022_94, { 0x46, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso_ir_10 = /* ISO646-FI, ISO646-SE, SEN_850200_B, ISO-IR-10 */
{ bank_G0, iso2022_94, { 0x47, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set1_iso_ir_11 = 
/* ISO646-SE2, SEN_850200_C, ISO-IR-11 */
{ bank_G0, iso2022_94, { 0x48, 0x00, 0x00, 0x00 } };   


static struct iso2022_setid set_KSC5601 = 
/* KSC 5601, part of ISO-2022-KR */
{ bank_G1,          iso2022_94x94, { 0x43, 0x00, 0x00, 0x00 } };



static struct iso2022_setid set1_iso_ir_13 = 
/* JIS_C6220-1969-jp, ISO-IR-13 */
{ bank_G1, iso2022_94, { 0x49, 0x00, 0x00, 0x00 } };   

static struct iso2022_setid set_JISC6220 = 
/* JIS C 6220-1976 or JIS X 0201, part of ISO-2022-JP */
{ bank_G0,          iso2022_94, { 0x4A, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_JISX0201_euc = 
/* JIS X 0201:1976, part of EUC-JP */
{ bank_G2,          iso2022_94, { 0x4A, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_15 =
/* IT, ISO-IR-15, ISO646-IT */
{ bank_G0,          iso2022_94, { 0x59, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_16 =
/* PT, ISO-IR-16, ISO646-PT */
{ bank_G0,          iso2022_94, { 0x4C, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_17 =
/* ES, ISO-IR-17, ISO646-ES */
{ bank_G0,          iso2022_94, { 0x5A, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_18 =
/* greek7-old, ISO-IR-18 */
{ bank_G0,          iso2022_94, { 0x5B, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_19 =
/* latin-greek, ISO-IR-19 */
{ bank_G0,          iso2022_94, { 0x5C, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_21 =
/* ISO646-DE, DIN_66003, ISO-IR-21 */
{ bank_G0,          iso2022_94, { 0x4B, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_25 =
/* ISO646-FR1, NF_Z_62-010_(1973), ISO-IR-25 */
{ bank_G0,          iso2022_94, { 0x52, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_27 =
/* Latin-greek-1 , ISO-IR-25 */
{ bank_G0,          iso2022_94, { 0x55, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_37 =
/* ISO_5427 , ISO-IR-37 */
{ bank_G0,          iso2022_94, { 0x4E, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_47 =
/* BS_viewdata" , ISO-IR-47 */
{ bank_G0,          iso2022_94, { 0x56, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_49 =
/* INIS , ISO-IR-49 */
{ bank_G0,          iso2022_94, { 0x57, 0x00, 0x00, 0x00 } };
static struct iso2022_setid set1_iso_ir_50 =
/* INIS-8 , ISO-IR-50 */
{ bank_G1,          iso2022_94, { 0x5D, 0x00, 0x00, 0x00 } };
static struct iso2022_setid set1_iso_ir_51 =
/* INIS-cyrillic , ISO-IR-51 */
{ bank_G1,          iso2022_94, { 0x5E, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_54 =
/* ISO_5427:1981  , ISO-IR-54 */
{ bank_G0,          iso2022_94, { 0x51, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_55 =
/* ISO_5428:1980  , ISO-IR-55 */
{ bank_G0,          iso2022_94, { 0x53, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_57 =
/* ISO646-CN, GB_1988-80  , ISO-IR-57 */
{ bank_G0,          iso2022_94, { 0x54, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_60 =
/* ISO646-NO, NS_4551-1   , ISO-IR-60 */
{ bank_G0,          iso2022_94, { 0x60, 0x00, 0x00, 0x00 } };
static struct iso2022_setid set1_iso_ir_61 =
/* ISO646-NO2, NS_4551-2   , ISO-IR-61 */
{ bank_G0,          iso2022_94, { 0x61, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_69 =
/* ISO646-FR, NF_Z_62-010   , ISO-IR-69 */
{ bank_G0,          iso2022_94, { 0x66, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_70 =
/* codeset videotex-suppl   , ISO-IR-70 */
{ bank_G0,          iso2022_94, { 0x62, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_84 =
/* ISO646-PT2, PT2   , ISO-IR-84 */
{ bank_G0,          iso2022_94, { 0x67, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_85 =
/* ISO646-ES2, ES2   , ISO-IR-85 */
{ bank_G0,          iso2022_94, { 0x68, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_86 =
/* ISO646-HU, MSZ_7795.3 , ISO-IR-86 */
{ bank_G0,          iso2022_94, { 0x69, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_89 =
/* ASMO_449 , ISO-IR-89 */
{ bank_G0,          iso2022_94, { 0x6B, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_90 =
/* ISO-IR-90 */
{ bank_G1,          iso2022_94, { 0x6C, 0x00, 0x00, 0x00 } };


static struct iso2022_setid set1_iso_ir_91 =
/* JIS_C6229-1984-a , ISO-IR-91 */
{ bank_G0,          iso2022_94, { 0x6D, 0x00, 0x00, 0x00 } };
static struct iso2022_setid set1_iso_ir_92 =
/* ISO646-JP-OCR-B, JIS_C6229-1984-b , ISO-IR-92 */
{ bank_G0,          iso2022_94, { 0x6E, 0x00, 0x00, 0x00 } };
static struct iso2022_setid set1_iso_ir_93 =
/* JIS_C6229-1984-b-add , ISO-IR-93 */
{ bank_G1,          iso2022_94, { 0x6F, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_94 =
/* JIS_C6229-1984-hand , ISO-IR-94 */
{ bank_G0,          iso2022_94, { 0x70, 0x00, 0x00, 0x00 } };
static struct iso2022_setid set1_iso_ir_95 =
/* JIS_C6229-1984-hand-add , ISO-IR-95 */
{ bank_G1,          iso2022_94, { 0x71, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_96 =
/* JIS_C6229-1984-kana , ISO-IR-96 */
{ bank_G0,          iso2022_94, { 0x72, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_98 =
/* ISO_2033-1983  , ISO-IR-98 */
{ bank_G0,          iso2022_94, { 0x73, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_99 =
/* ANSI_X3.110-1983  , ISO-IR-99 */
{ bank_G2,          iso2022_94, { 0x74, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_102 =
/* T.61-7bit  , ISO-IR-102 */
{ bank_G0,          iso2022_94, { 0x75, 0x00, 0x00, 0x00 } };
static struct iso2022_setid set1_iso_ir_103 =
/* T.61-8bit  , ISO-IR-103 */
{ bank_G1,          iso2022_94, { 0x76, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_121 =
/* ISO646-CA, CSA_Z243.4-1985-1, ISO-IR-121 */
{ bank_G0,          iso2022_94, { 0x77, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_122 =
/* ISO646-CA2, CSA_Z243.4-1985-2, ISO-IR-122 */
{ bank_G0,          iso2022_94, { 0x78, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_123 =
/* CSA_Z243.4-1985-gr, ISO-IR-123 */
{ bank_G1,          iso2022_96, { 0x45, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_128 =
/* T.101-G2 , ISO-IR-128 */
{ bank_G2,          iso2022_94, { 0x7C, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_139 =
/* CSN_369103 , ISO-IR-139 */
{ bank_unspecified, iso2022_96, { 0x49, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_141 =
/* ISO646-YU, JUS_I.B1.002  , ISO-IR-141 */
{ bank_G0, iso2022_94, { 0x7A, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_142 =
/* ISO_6937-2-add , ISO-IR-142 */
{ bank_G1, iso2022_96, { 0x4A, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_143 =
/* IEC_P27-1 , ISO-IR-143 */
{ bank_G1, iso2022_96, { 0x4B, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_146 =
/* JUS_I.B1.003-serb  , ISO-IR-146 */
{ bank_G0, iso2022_94, { 0x7B, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_147 =
/* JUS_I.B1.003-mac  , ISO-IR-147 */
{ bank_G0, iso2022_94, { 0x7D, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_150 =
/* greek-ccitt  , ISO-IR-150 */
{ bank_G0, iso2022_94, { 0x21, 0x40, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_151 =
/* ISO646-CU, NC_NC00-10:81  , ISO-IR-151 */
{ bank_G0, iso2022_94, { 0x21, 0x41, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_152 =
/* ISO_6937-2-25  , ISO-IR-152 */
{ bank_G1, iso2022_96, { 0x4E, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_153 =
/* GOST_19768-74  , ISO-IR-153 */
{ bank_G1, iso2022_96, { 0x4F, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_154 =
/* ISO_8859-supp   , ISO-IR-154 */
{ bank_G3, iso2022_96, { 0x50, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_155 =
/* ISO_10367-box    , ISO-IR-155 */
{ bank_G1, iso2022_96, { 0x51, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set1_iso_ir_158 =
/* ISO_10367-box    , ISO-IR-158 */
{ bank_G3, iso2022_96, { 0x58, 0x00, 0x00, 0x00 } };


static struct iso2022_setid set_JISC6226a = 
/* JIS C 6226-1978 or JIS X 0208-1978, part of ISO-2022-JP */
{ bank_G0,          iso2022_94x94, { 0x40, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_JISC6226b = 
/* JIS C 6226-1983 or JIS X 0208-1983, part of ISO-2022-JP */
{ bank_G0,          iso2022_94x94, { 0x42, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_JISX0208_1983_euc =
/* JIS X 0208-1983, part of EUC-JP */
{ bank_G1,          iso2022_94x94, { 0x42, 0x00, 0x00, 0x00 } };


static struct iso2022_setid set_GB2312jp = 
/* GB2312-1980, part of ISO-2022-JP-2 */
{ bank_G0,          iso2022_94x94, { 0x41, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_KSC5601jp =   
/* KSC5601-1987, part of ISO-2022-JP-2 */
{ bank_G0,          iso2022_94x94, { 0x43, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_JISX0212 = 
/* JIS X 0212-1990, part of ISO-2022-JP-2 */
{ bank_G0,          iso2022_94x94, { 0x44, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_JISX0212_euc = 
/* JIS X 0212-1990, part of EUC-JP */
{ bank_G3,          iso2022_94x94, { 0x44, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_ISO88591 = 
/* ISO8859-1, part of ISO-2022-JP-2 */
{ bank_G2, iso2022_96, { 0x41, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_ISO88597 = 
/* ISO8859-7(Greek), part of ISO-2022-JP-2 */
{ bank_G2, iso2022_96, { 0x46, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_GB2312 = 
/* GB 2312, part of ISO-2022-CN */
{ bank_G1, iso2022_94x94, { 0x41, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_CNS11643plane1 = 
/* CNS 11643-plane-1, part of ISO-2022-CN */
{ bank_G1, iso2022_94x94, { 0x47, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_CNS11643plane2 = 
/* CNS 11643-plane-1, part of ISO-2022-CN */
{ bank_G2, iso2022_94x94, { 0x48, 0x00, 0x00, 0x00 } };

#if 0
static struct iso2022_setid set_GB12345 = 
/* GB 12345, part of ISO-2022-CN-EXT --   NOTE: Final byte unknown */
{ bank_G1, iso2022_94x94, { 0x00, 0x00, 0x00, 0x00 } };
#endif

static struct iso2022_setid set_ISOIR165 = 
/* ISO-IR-165, part of ISO-2022-CN-EXT */
{ bank_G1, iso2022_94x94, { 0x45, 0x00, 0x00, 0x00 } };

#if 0
static struct iso2022_setid set_GB7589 = 
/* GB 7589, part of ISO-2022-CN-EXT   --   NOTE: Final byte unknown */
{ bank_G2, iso2022_94x94, { 0x00, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_GB13131 = 
/* GB 13131, part of ISO-2022-CN-EXT   --   NOTE: Final byte unknown */
{ bank_G2, iso2022_94x94, { 0x00, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_GB7590 = 
/* GB 7590, part of ISO-2022-CN-EXT   --   NOTE: Final byte unknown */
{ bank_G3, iso2022_94x94, { 0x00, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_GB13132 = 
/* GB 13132, part of ISO-2022-CN-EXT   --   NOTE: Final byte unknown */
{ bank_G3, iso2022_94x94, { 0x00, 0x00, 0x00, 0x00 } };
#endif

static struct iso2022_setid set_CNS11643plane3 = 
/* CNS 11643-plane-3, part of ISO-2022-CN */
{ bank_G3, iso2022_94x94, { 0x49, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_CNS11643plane4 = 
/* CNS 11643-plane-4, part of ISO-2022-CN */
{ bank_G3, iso2022_94x94, { 0x4A, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_CNS11643plane5 = 
/* CNS 11643-plane-5, part of ISO-2022-CN */
{ bank_G3, iso2022_94x94, { 0x4B, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_CNS11643plane6 = 
/* CNS 11643-plane-5, part of ISO-2022-CN */
{ bank_G3, iso2022_94x94, { 0x4C, 0x00, 0x00, 0x00 } };

static struct iso2022_setid set_CNS11643plane7 = 
/* CNS 11643-plane-5, part of ISO-2022-CN */
{ bank_G3, iso2022_94x94, { 0x4D, 0x00, 0x00, 0x00 } };


static struct iso2022_setid latin_banks[] = {
    { bank_G0, iso2022_94, { 0x42, 0x00, 0x00, 0x00 } },   /* ASCII */
    { bank_unspecified, iso2022_96, { 0x41, 0x00, 0x00, 0x00 } },   /* 1 */ 
    { bank_unspecified, iso2022_96, { 0x42, 0x00, 0x00, 0x00 } },   /* 2 */ 
    { bank_unspecified, iso2022_96, { 0x43, 0x00, 0x00, 0x00 } },   /* 3 */ 
    { bank_unspecified, iso2022_96, { 0x44, 0x00, 0x00, 0x00 } },   /* 4 */ 
    { bank_unspecified, iso2022_96, { 0x4C, 0x00, 0x00, 0x00 } },   /* 5 */
    { bank_unspecified, iso2022_96, { 0x47, 0x00, 0x00, 0x00 } },   /* 6 */
    { bank_unspecified, iso2022_96, { 0x46, 0x00, 0x00, 0x00 } },   /* 7 */
    { bank_unspecified, iso2022_96, { 0x48, 0x00, 0x00, 0x00 } },   /* 8 */
    { bank_unspecified, iso2022_96, { 0x4D, 0x00, 0x00, 0x00 } },   /* 9 */
    { bank_unspecified, iso2022_96, { 0x56, 0x00, 0x00, 0x00 } },   /* 10 */
    { bank_unspecified, iso2022_96, { 0x54, 0x00, 0x00, 0x00 } },   /* 11 */   
};

struct iso2022_setid * CONST ASCII_BANK  = &latin_banks[0];
struct iso2022_setid * CONST LATIN1_BANK = &latin_banks[1];

struct iso2022_map_list INITIAL_iso2022_map_list[] = {
    { &return_to_iso2022,    NULL,  ml_system },
    { &set0_utf8,            NULL,  ml_system },
    { & latin_banks[0], &latin_iso2022_map_ascii,  ml_system },/* ASCII */
    { & latin_banks[1], &latin_iso2022_map_latin1, ml_system },/* ISO-8859-1 */
    { & latin_banks[2],      NULL,  ml_system },
    { & latin_banks[3],      NULL,  ml_system },
    { & latin_banks[4],      NULL,  ml_system },
    { & latin_banks[5],      NULL,  ml_system },
    { & latin_banks[6],      NULL,  ml_system },
    { & latin_banks[7],      NULL,  ml_system },
    { & latin_banks[8],      NULL,  ml_system },
    { & latin_banks[9],      NULL,  ml_system },
    { & latin_banks[10],     NULL,  ml_system },
    { & latin_banks[11],     NULL,  ml_system },
    { &set1_latin7,          NULL,  ml_system },
    { &set1_latin8,          NULL,  ml_system },
    { &set1_latin9,          NULL,  ml_system },
    { &set1_iso885916,       NULL,  ml_system },
    { &set1_koi8e,           NULL,  ml_system },
    { &set1_iso_ir_2,        NULL,  ml_system },
    { &set1_iso_ir_4,        NULL,  ml_system },
    { &set1_iso_ir_8_1,      NULL,  ml_system },
    { &set1_iso_ir_8_2,      NULL,  ml_system },
    { &set1_iso_ir_9_1,      NULL,  ml_system },
    { &set1_iso_ir_9_2,      NULL,  ml_system },
    { &set1_iso_ir_10,       NULL,  ml_system },
    { &set1_iso_ir_11,       NULL,  ml_system },
    { &set1_iso_ir_13,       NULL,  ml_system },
    { &set1_iso_ir_15,       NULL,  ml_system },
    { &set1_iso_ir_16,       NULL,  ml_system },
    { &set1_iso_ir_17,       NULL,  ml_system },
    { &set1_iso_ir_18,       NULL,  ml_system },
    { &set1_iso_ir_19,       NULL,  ml_system },
    { &set1_iso_ir_21,       NULL,  ml_system },
    { &set1_iso_ir_25,       NULL,  ml_system },
    { &set1_iso_ir_27,       NULL,  ml_system },
    { &set1_iso_ir_37,       NULL,  ml_system },
    { &set1_iso_ir_47,       NULL,  ml_system },
    { &set1_iso_ir_49,       NULL,  ml_system },
    { &set1_iso_ir_50,       NULL,  ml_system },
    { &set1_iso_ir_51,       NULL,  ml_system },
    { &set1_iso_ir_54,       NULL,  ml_system },
    { &set1_iso_ir_55,       NULL,  ml_system },
    { &set1_iso_ir_57,       NULL,  ml_system },
    { &set1_iso_ir_60,       NULL,  ml_system },
    { &set1_iso_ir_61,       NULL,  ml_system },
    { &set1_iso_ir_69,       NULL,  ml_system },
    { &set1_iso_ir_70,       NULL,  ml_system },
    { &set1_iso_ir_84,       NULL,  ml_system },
    { &set1_iso_ir_85,       NULL,  ml_system },
    { &set1_iso_ir_86,       NULL,  ml_system },
    { &set1_iso_ir_89,       NULL,  ml_system },
    { &set1_iso_ir_90,       NULL,  ml_system },
    { &set1_iso_ir_91,       NULL,  ml_system },
    { &set1_iso_ir_92,       NULL,  ml_system },
    { &set1_iso_ir_93,       NULL,  ml_system },
    { &set1_iso_ir_94,       NULL,  ml_system },
    { &set1_iso_ir_95,       NULL,  ml_system },
    { &set1_iso_ir_96,       NULL,  ml_system },
    { &set1_iso_ir_98,       NULL,  ml_system },
    { &set1_iso_ir_99,       NULL,  ml_system },
    { &set1_iso_ir_102,      NULL,  ml_system },
    { &set1_iso_ir_103,      NULL,  ml_system },
    { &set1_iso_ir_121,      NULL,  ml_system },
    { &set1_iso_ir_122,      NULL,  ml_system },
    { &set1_iso_ir_123,      NULL,  ml_system },
    { &set1_iso_ir_128,      NULL,  ml_system },
    { &set1_iso_ir_139,      NULL,  ml_system },
    { &set1_iso_ir_141,      NULL,  ml_system },
    { &set1_iso_ir_142,      NULL,  ml_system },
    { &set1_iso_ir_143,      NULL,  ml_system },
    { &set1_iso_ir_146,      NULL,  ml_system },
    { &set1_iso_ir_147,      NULL,  ml_system },
    { &set1_iso_ir_150,      NULL,  ml_system },
    { &set1_iso_ir_151,      NULL,  ml_system },
    { &set1_iso_ir_152,      NULL,  ml_system },
    { &set1_iso_ir_153,      NULL,  ml_system },
    { &set1_iso_ir_154,      NULL,  ml_system },
    { &set1_iso_ir_155,      NULL,  ml_system },
    { &set_KSC5601,          NULL,  ml_system },
    { &set_JISC6220,         NULL,  ml_system },
    { &set_JISX0201_euc,      NULL,  ml_system },
    { &set_JISC6226a,        NULL,  ml_system },
    { &set_JISC6226b,        NULL,  ml_system },
    { &set_JISX0208_1983_euc, NULL,  ml_system },
    { &set_GB2312jp,         NULL,  ml_system },
    { &set_KSC5601jp,        NULL,  ml_system },
    { &set_JISX0212,         NULL,  ml_system },
    { &set_JISX0212_euc,     NULL,  ml_system },
    { &set_ISO88591,         &latin_iso2022_map_latin1,  ml_system },
    { &set_ISO88597,         NULL,  ml_system },
    { &set_GB2312,           NULL,  ml_system },
    { &set_CNS11643plane1,   NULL,  ml_system },
    { &set_CNS11643plane2,   NULL,  ml_system },
#if 0               /* Final byte unknown */
    { &set_GB12345,          NULL,  ml_system },
#endif
    { &set_ISOIR165,         NULL,  ml_system },
#if 0               /* Final byte unknown */
    { &set_GB7589,          NULL,  ml_system },
    { &set_GB13131,         NULL,  ml_system },
    { &set_GB7590,          NULL,  ml_system },
    { &set_GB13132,         NULL,  ml_system },
#endif
    { &set_CNS11643plane3,  NULL,  ml_system },
    { &set_CNS11643plane4,  NULL,  ml_system },
    { &set_CNS11643plane5,  NULL,  ml_system },
    { &set_CNS11643plane6,  NULL,  ml_system },
    { &set_CNS11643plane7,  NULL,  ml_system }
};

struct iso2022_map_list    * iso2022_map_list  = INITIAL_iso2022_map_list;
int iso2022_map_list_count = 
   sizeof INITIAL_iso2022_map_list / sizeof (INITIAL_iso2022_map_list[0]);

void fill_iso2022_map_setlist_bytes(iso2022_map_index,type,bytes,bytes_size)
     int iso2022_map_index;
     enum iso2022_settype type;
     unsigned char *bytes;
     int bytes_size;
{
    if (iso2022_map_index < 0 || iso2022_map_index >= iso2022_map_list_count)
	panic("ISO2022 PANIC",__FILE__,__LINE__,
	      "fill_iso2022_map_setlist_bytes",
	      "iso2022_map_index out of range",0);

    if (!iso2022_map_list[iso2022_map_index].setid)
	panic("ISO2022 PANIC",__FILE__,__LINE__,
	      "fill_iso2022_map_setlist_bytes",
	      "No setid",0);

    if (type != iso2022_map_list[iso2022_map_index].setid->type)
	panic("ISO2022 PANIC",__FILE__,__LINE__,
	      "fill_iso2022_map_setlist_bytes",
	      "type mismatch",0);
	
    if (sizeof iso2022_map_list[iso2022_map_index].setid->bytes !=
	bytes_size)
	panic("ISO2022 PANIC",__FILE__,__LINE__,
	      "fill_iso2022_map_setlist_bytes",
	      "size mismatch",0);
	
    memcpy(bytes,iso2022_map_list[iso2022_map_index].setid->bytes,bytes_size);
}



static int realloc_iso2022_map_list P_((int add));
static int realloc_iso2022_map_list(add)
     int add;
{
    int new_max = iso2022_map_list_count + add;

    if (!ISO2022_MAP_LIST_ALLOCED) {
	int i;
	iso2022_map_list = safe_malloc((new_max) *
				       sizeof (iso2022_map_list[0]));
	
	for (i = 0; i < iso2022_map_list_count; i++)
	    iso2022_map_list[i] = INITIAL_iso2022_map_list[i];

    } else {
	iso2022_map_list = safe_realloc(iso2022_map_list, 
					(new_max) * 
					sizeof (iso2022_map_list[0]));
    }

    return new_max;
}

static struct iso2022_keyword {
    CONST char *          keyword;
    enum iso2022_bank     bank; 
    enum iso2022_settype  type;
} iso2022_keywords[] = {
    { "other-set",   bank_unspecified,  iso2022_other },

    /* Sets without bank specification */
    { "bank-94",    bank_unspecified,  iso2022_94 },
    { "bank-96",    bank_unspecified,  iso2022_96 },
    { "bank-94x94", bank_unspecified,  iso2022_94x94 },
    { "bank-96x96", bank_unspecified,  iso2022_96x96 },

    /* Bank G0 */
    { "bank-G0-94",    bank_G0,  iso2022_94 },
    { "bank-G0-94x94", bank_G0,  iso2022_94x94 },

    /* Bank G1 */
    { "bank-G1-94",    bank_G1,  iso2022_94 },
    { "bank-G1-96",    bank_G1,  iso2022_96 },
    { "bank-G1-94x94", bank_G1,  iso2022_94x94 },
    { "bank-G1-96x96", bank_G1,  iso2022_96x96 },

    /* Bank G2 */
    { "bank-G2-94",    bank_G2,  iso2022_94 },
    { "bank-G2-96",    bank_G2,  iso2022_96 },
    { "bank-G2-94x94", bank_G2,  iso2022_94x94 },
    { "bank-G2-96x96", bank_G2,  iso2022_96x96 },

    /* Bank G3 */
    { "bank-G3-94",    bank_G3,  iso2022_94 },
    { "bank-G3-96",    bank_G3,  iso2022_96 },
    { "bank-G3-94x94", bank_G3,  iso2022_94x94 },
    { "bank-G3-96x96", bank_G3,  iso2022_96x96 },

    { NULL, bank_unspecified,  iso2022_other }
};

static int parse_ISO2022_ident_spec P_((const char *val, 
					unsigned char *bytes,
					int size));

static int same_setid_bytes P_((const struct iso2022_setid A,
				const struct iso2022_setid B));


/* -1 == not found, otherwise index to iso2022_map_list[] 
                    index must exist on index_list
*/
int give_iso2022_index(index_list,index_count,set_text)
     int *index_list; 
     int index_count;
     struct iso2022_setid * set_text;
{
    int i;

    /* First exact match */
    for (i = 0; i < index_count; i++) {
	if (-1 != index_list[i]) {
	    int idx;
	    if (index_list[i] < 0 || index_list[i] >= iso2022_map_list_count) 
		panic("ISO2022 PANIC",__FILE__,__LINE__,
		      "give_iso2022_index",
		      "Bad index",0);
	    
	    idx  = index_list[i];
       
	    if (same_setid(*(iso2022_map_list[idx].setid),*set_text)) {
		return idx;
	    }
	}
    }
    
    /* Then match without bank -- if on index there is no bank given */
    for (i = 0; i < index_count; i++) {
	if (-1 != index_list[i]) {
	    int idx;
	    if (index_list[i] < 0 || index_list[i] >= iso2022_map_list_count) 
		panic("ISO2022 PANIC",__FILE__,__LINE__,
		      "give_iso2022_index",
		      "Bad index",0);
	    
	    idx  = index_list[i];
	    if (iso2022_map_list[idx].setid->bank == bank_unspecified &&
		iso2022_map_list[idx].setid->type == set_text->type &&
		same_setid_bytes(*(iso2022_map_list[idx].setid),*set_text)) {

		DPRINT(Debug,61,(&Debug,
				 "Set bank %d type %d match without bank -- iso2022 index %d\n",
				 set_text->bank,
				 set_text->type,
				 idx));
		return idx;
	    }
	}
    }

#ifdef DEBUG
    if (Debug.active > 60) {

	char *x = iso2022_codestr(set_text->bytes,
				  sizeof (set_text->bytes));

	DPRINT(Debug,61,(&Debug,
			 "No set bank %d type %d bytes=%s ",
			 set_text->bank,
			 set_text->type,
			 x ? x : "???"));
	free(x);

	DPRINT(Debug,61,(&Debug,
			 " --- iso2022 indexes :"));
	for (i = 0; i < index_count; i++) {
	    DPRINT(Debug,61,(&Debug," %d",index_list[i]));
	}
	DPRINT(Debug,61,(&Debug,"\n"));
    }
#endif

    return -1;
}


/* -1 == not found, otherwise index to iso2022_map_list[] */
int  find_iso2022_map_spec(name)
     char *name;
{
    int res = -1;

    char * p = strchr(name,' ');
    
    if (p) {
	int kw,i;

	struct iso2022_setid  TMP;

        *p++ = '\0';
	
	for (kw = 0; iso2022_keywords[kw].keyword; kw++)
	    if (0 == strcmp(iso2022_keywords[kw].keyword,name))
		break;

	if (!iso2022_keywords[kw].keyword) {
            lib_error(CATGETS(elm_msg_cat, MeSet, MeNotKWISO2022sets,
                              "Map with keyword %s not found from ISO2022 sets (bad keyword)"),
                      name);
	    return -1;
	}

	TMP.bank = iso2022_keywords[kw].bank;
	TMP.type = iso2022_keywords[kw].type;

	if (!parse_ISO2022_ident_spec(p,TMP.bytes,sizeof (TMP.bytes))) {
            lib_error(CATGETS(elm_msg_cat, MeSet, MeNotIdentISO2022sets,
                              "Map %s %s not found from ISO2022 sets (bad ident)"),
                      name,p);
	    return -1;
	}

	/* Similar than loc_setid algorithm */

	for (i = 0; i < iso2022_map_list_count; i++) {
	    if (iso2022_map_list[i].map) {
		if (same_setid(*(iso2022_map_list[i].setid),TMP)) {
		    res = i;
		}
	    }
	}

	if (res < 0) 
            lib_error(CATGETS(elm_msg_cat, MeSet, MeNoMapISO2022sets,
                              "Map %s %s not found from ISO2022 sets"),
                      name,p);
	
    } else {
	int i;

	for (i = 0; i < iso2022_map_list_count; i++) {
	    if (iso2022_map_list[i].map) {
		if ( 0 == strcmp(name,
				 iso2022_mapname(iso2022_map_list[i].map))) {
		    res = i;
		}	       		
	    }
	}

	if (res < 0) 
            lib_error(CATGETS(elm_msg_cat, MeSet, MeNotFoundISO2022sets,
                              "Map with name %s not found from ISO2022 sets"),
                      name);	
    }
    
    DPRINT(Debug,11,(&Debug,
		     "find_iso2022_map_spec(\"%s\")=%d\n",
		     name,res));
    return res;
}


int parse_iso2022_map(filename,errors,mode)
     CONST char *filename;
     int *errors;
     enum map_list_mode mode;
{
    /*  banktype  "bytes"   file   (flags) */

    int max_count = 0;
    int new_max;
    int count = 0;
    FILE * f;
    char buf[LONG_STRING];
    int c, l1;
    int err = can_open(filename,"r");

    if (err) {
	DPRINT(Debug,2,(&Debug, 
			"parse_iso2022_map=0: %s: %s (can_open)\n",
			filename,error_description(err)));
	return 0;
    }

    f = fopen(filename,"r");
    if (!f) {
	int err = errno;
	DPRINT(Debug,2,(&Debug, 
			"parse_iso2022_map=0: %s: %s\n",
			filename,error_description(err)));
	return 0;
    }
    
    while(EOF != (c = fgetc(f)))
	if ('\n' == c)
	    max_count++;

    DPRINT(Debug,9,(&Debug, 
		    "parse_iso2022_map: %s, max_count=%d\n",
		    filename,max_count));
    
    if (!max_count) {
	fclose(f);
	return 0;
    }
    rewind(f);


    new_max = realloc_iso2022_map_list(max_count);

    
    while (count < max_count &&
	   iso2022_map_list_count < new_max &&
           (l1 = mail_gets(buf,sizeof buf, f)) > 0) {                        

	char *c,*c1,*c2, *c3;
	int code_c3 = 0;
	char * pat = NULL;
	int kw;

	struct iso2022_mapinfo  *map = NULL;

	struct iso2022_setid  TMP, *id;

	if ('\n' == buf[l1 -1])
            buf[l1 - 1] = '\0';
        else {
            lib_error(CATGETS(elm_msg_cat, MeSet, MeTooLongLine,
                              "%.30s: Too long line: %.30s..."),
                      filename,buf);
            (*errors) ++;
            break;
        }                 
	l1--;

        while (l1-- > 0 && whitespace(buf[l1]))
            buf[l1] = '\0';                     

        c = buf;
        while (*c && whitespace (*c)) /* skip leading whitespace */
            c++;
        if ('#' == *c)
            continue;
        if (!*c)
            continue;                       

        c1 = strpbrk(c," \t");
        if (!c1) {
            lib_error(CATGETS(elm_msg_cat, MeSet, MeBadLine,
                              "%.30s: Bad line: %.30s..."),
                      filename,buf);
            (*errors) ++;
            break;
        }
        *c1 = '\0';
        c1++;                                                                  

	for (kw = 0; iso2022_keywords[kw].keyword; kw++)
	    if (0 == strcmp(iso2022_keywords[kw].keyword,c))
		break;

	if (!iso2022_keywords[kw].keyword) {
            lib_error(CATGETS(elm_msg_cat, MeSet, MeBadLine,
                              "%.30s: Bad line: %.30s..."),
                      filename,buf);
            (*errors) ++;
            break;
	}

	TMP.bank = iso2022_keywords[kw].bank;
	TMP.type = iso2022_keywords[kw].type;

        while (*c1 && whitespace (*c1)) /* skip leading whitespace */
            c1++;
        if (!*c1) {
            lib_error(CATGETS(elm_msg_cat, MeSet, MeBadLine,
                              "%.30s: Bad line: %.30s..."),
                      filename,buf);
            (*errors) ++;
            break;
        }                                                    

	c2 = qstrpbrk(c1," \t");
        if (!c2) {
            lib_error(CATGETS(elm_msg_cat, MeSet, MeBadLine,
                              "%.30s: Bad line: %.30s..."),
                      filename,buf);
            (*errors) ++;
            break;
        }
        *c2 = '\0';
        c2++;                                                                  

	pat = dequote_opt(c1,c2-c1);

	if (!parse_ISO2022_ident_spec(pat,TMP.bytes,sizeof (TMP.bytes))) {
	    free(pat); pat = NULL;

            lib_error(CATGETS(elm_msg_cat, MeSet, MeBadLine,
                              "%.30s: Bad line: %.30s..."),
                      filename,buf);
            (*errors) ++;
            break;
	}

	free(pat); pat = NULL;

        while (*c2 && whitespace (*c2)) /* skip leading whitespace */
            c2++;
        if (!*c2) {
            lib_error(CATGETS(elm_msg_cat, MeSet, MeBadLine,
                              "%.30s: Bad line: %.30s..."),
                      filename,buf);
            (*errors) ++;
            break;
        }                                                    

	/* look flags */
	c3 = strpbrk(c2," \t");
	code_c3 = 0;
	if (c3) {
	    *c3 = '\0';
	    c3++;                                                                  
	    while (*c3 && whitespace (*c3)) /* skip leading whitespace */
		c3++;

	    if (*c3) {
		code_c3 = iso2022_parseflag_ok(c3);
		if (!code_c3) {
		    lib_error(CATGETS(elm_msg_cat, MeSet, MeBadLine,
				      "%.30s: Bad line: %.30s..."),
			      filename,buf);
		    (*errors) ++;
		    break;
		}
	    } else
		c3 = NULL;
	}

	if (code_c3 & PF_IS_BUILTIN) {
	    struct  map_info *builtin_map;

	    struct charset_type * MAP_type = NULL;

	    switch (code_c3 & PF_type_mask) {
	    case PF_ascii:    MAP_type = &cs_ascii; break;
	    case PF_bytemap:  MAP_type = &cs_onebyte; break;
	    default:
		panic("ISO2022 PANIC",__FILE__,__LINE__,
		      "parse_iso2022_map",
		      "Bad flags for internal map",0);
	    }

	    DPRINT(Debug,5,(&Debug,"%s: Treating %s as %s map\n",
			     filename,c2,MAP_type->type_name));

	    builtin_map = MAP_type->find_map_type(c2);
	    if (builtin_map)
		map = make_iso2022_map(builtin_map,TMP.type,code_c3,c3);
	    else {
		lib_error(CATGETS(elm_msg_cat, MeSet,
				  MeUnknownMap,
				  "No map %s on charset type %s"),
			  c2,MAP_type->type_name);
		map = NULL;
	    }
	} else
	    map = read_iso2022_map(c2, TMP.type,code_c3,c3);
	if (!map) {
            (*errors) ++;
            break;
	}

	id = safe_malloc(sizeof (struct iso2022_setid));

	*id = TMP;

	iso2022_map_list[iso2022_map_list_count].setid = id;
	iso2022_map_list[iso2022_map_list_count].map   = map;
	iso2022_map_list[iso2022_map_list_count].mode  = mode;
	
	iso2022_map_list_count++;	
	count++;    /* Not actually used */
    }

    DPRINT(Debug,9,(&Debug, 		    
		    "parse_iso2022_map: %s, %d parsed (%d total)\n",
		    filename,count,iso2022_map_list_count));


    fclose(f);

    return 1;
}

void dump_iso2022_map(f,mode)
     FILE  *f;
     enum map_list_mode mode;
{
    int i;

    for (i = 0; i < iso2022_map_list_count; i++) {
	if (mode == iso2022_map_list[i].mode && 
	    iso2022_map_list[i].setid &&
	    iso2022_map_list[i].map) {
	    int j;
	    
	    for (j = 0; iso2022_keywords[j].keyword; j++) {
		if (iso2022_keywords[j].bank == iso2022_map_list[i].setid->bank &&
		    iso2022_keywords[j].type == iso2022_map_list[i].setid->type) {
		    char * t = iso2022_codestr(iso2022_map_list[i].setid->bytes,
					       sizeof iso2022_map_list[i].setid->
					       bytes);

		    if (t) {
			CONST char *X;

			if (0 == strchr(t,' '))
			    elm_fprintf(f,FRM("%s\t%s\t%s"),
					iso2022_keywords[j].keyword,
					t,iso2022_mapname(iso2022_map_list[i].map));
			else
			    elm_fprintf(f,FRM("%s\t%Q\t%s"),
					iso2022_keywords[j].keyword,
					t,iso2022_mapname(iso2022_map_list[i].map));
			

			X = iso2022_mapflags(iso2022_map_list[i].map);

			if (X)
			    fprintf(f,"\t%s",X);

			putc('\n',f);
			
			free(t);
		    }
		}
	    }
	}
    }
}

static int same_setid_bytes(A,B)
     CONST struct iso2022_setid A;
     CONST struct iso2022_setid B;
{
    int i;

    for (i = 0; i < sizeof A.bytes; i++)
	if (A.bytes[i] != B.bytes[i])
	    return 0;
    return 1;
}

int same_setid(A,B)
     CONST struct iso2022_setid A;
     CONST struct iso2022_setid B;
{
    if (A.bank != B.bank)
	return 0;
    if (A.type != B.type)
	return 0;

    if (!same_setid_bytes(A,B))
	return 0;
    return 1;
}

static struct iso2022_setid  * loc_setid P_((const struct iso2022_setid c));
static struct iso2022_setid  * loc_setid(c)
     CONST struct iso2022_setid c;
{
    struct iso2022_setid * ret = NULL;

    int i;
    int found_it = 0;

    /* May have several given on {lib}/elm.iso2022sets and
       ~/.elm/iso2022.sets ... 
    */

    for (i = 0; i < iso2022_map_list_count; i++) {
	if (same_setid(*(iso2022_map_list[i].setid),c)) {
	    ret = iso2022_map_list[i].setid;
	    
	    goto found;
	}
    }

    /* Create new setid */
   
    ret = safe_malloc(sizeof (struct iso2022_setid));
    *ret = c;

    realloc_iso2022_map_list(1);

    iso2022_map_list[iso2022_map_list_count].setid = ret;
    iso2022_map_list[iso2022_map_list_count].map   = NULL;
    iso2022_map_list[iso2022_map_list_count].mode  = ml_none;

    iso2022_map_list_count++;
    
    DPRINT(Debug,25,(&Debug, 
		     "loc_setid: Adding new id to list, count %d",
		     iso2022_map_list_count));
    
 found:
    
    DPRINT(Debug,25,(&Debug, 
		     "loc_setid=%p    *mapnum=%d\n"));

    return ret;
}

struct setlist set_utf8   = { 
    { -1, -1, -1, -1 },
    { &set0_utf8, NULL, NULL, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL },
    bank_unspecified, bank_unspecified
};

struct setlist set_latin7 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_latin7, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G2
};

struct setlist set_latin8 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_latin8, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G2
};

struct setlist set_latin9 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_latin9, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G2
};

struct setlist set_iso885916 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_iso885916, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G2
};

struct setlist set_koi8e = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_koi8e, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G2
};


/* codeset ISO_646.irv:1983   -- iso-ir-2 */ 
struct setlist set_iso_ir_2 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_2, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* ISO646-GB - codeset BS_4730   -- iso-ir-4 */ 
struct setlist set_iso_ir_4 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_4, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset NATS-SEFI   -- iso-ir-8-1 */ 
struct setlist set_iso_ir_8_1 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_8_1, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset NATS-SEFI-ADD   -- iso-ir-8-2 */ 
struct setlist set_iso_ir_8_2 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_8_2, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset NATS-DANO   -- iso-ir-9-1 */ 
struct setlist set_iso_ir_9_1 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_9_1, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset NATS-DANO-ADD   -- iso-ir-9-2 */ 
struct setlist set_iso_ir_9_2 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_9_2, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-FI, codeset SEN_850200_B   -- iso-ir-10 */ 
struct setlist set_iso_ir_10 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_10, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};


/*  ISO646-SE2, codeset SEN_850200_C   -- iso-ir-11 */ 
struct setlist set_iso_ir_11 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_11, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};


/* "KS_C_5601-1987" -- ISO-IR-149 */
struct setlist set_iso_ir_149 =  { 
    { -1, -1, -1, -1 },
    { &set_KSC5601jp, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL },
    bank_G0, bank_unspecified
}; 

/* ... must probably incorrect assigment of backs ... */
struct setlist set_iso_ir_13 = {
    { -1, -1, -1, -1 },
    { &set_JISC6220,  &set1_iso_ir_13, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL },
    bank_G0, bank_G1
};

/*  ISO646-IT, codeset IT   -- iso-ir-15 */ 
struct setlist set_iso_ir_15 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_15, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-PT, codeset PT   -- iso-ir-16 */ 
struct setlist set_iso_ir_16 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_16, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-ES, codeset ES   -- iso-ir-17 */ 
struct setlist set_iso_ir_17 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_17, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset greek7-old   -- iso-ir-18 */ 
struct setlist set_iso_ir_18 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_18, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset latin-greek   -- iso-ir-19 */ 
struct setlist set_iso_ir_19 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_19, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-DE, codeset DIN_66003     -- iso-ir-21 */ 
struct setlist set_iso_ir_21 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_21, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-FR1, codeset NF_Z_62-010_(1973)     -- iso-ir-25 */ 
struct setlist set_iso_ir_25 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_25, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset Latin-greek-1     -- iso-ir-27 */ 
struct setlist set_iso_ir_27 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_27, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset ISO_5427     -- iso-ir-37 */ 
struct setlist set_iso_ir_37 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_37, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset BS_viewdata     -- iso-ir-47 */ 
struct setlist set_iso_ir_47 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_47, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset INIS     -- iso-ir-49 */ 
struct setlist set_iso_ir_49 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_49, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset INIS-8     -- iso-ir-50 */ 
struct setlist set_iso_ir_50 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_49, &set1_iso_ir_50, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/*  codeset INIS-cyrillic  -- iso-ir-51 */ 
struct setlist set_iso_ir_51 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_49, &set1_iso_ir_51, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/*  codeset "ISO_5427:1981"   -- iso-ir-54 */ 
struct setlist set_iso_ir_54 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_54, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset "ISO_5428:1980"   -- iso-ir-55 */ 
struct setlist set_iso_ir_55 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_55, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-CN, codeset "GB_1988-80"   -- iso-ir-57 */ 
struct setlist set_iso_ir_57 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_57, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-NO, codeset "NS_4551-1"   -- iso-ir-60 */ 
struct setlist set_iso_ir_60 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_60, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-NO2, codeset "NS_4551-2"   -- iso-ir-61 */ 
struct setlist set_iso_ir_61 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_61, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-FR, codeset "NF_Z_62-010"   -- iso-ir-69 */ 
struct setlist set_iso_ir_69 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_69, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset "videotex-suppl"   -- iso-ir-70 */ 
struct setlist set_iso_ir_70 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_70, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-PT2, codeset "PT2"   -- iso-ir-84 */ 
struct setlist set_iso_ir_84 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_84, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-ES2, codeset "ES2"   -- iso-ir-85 */ 
struct setlist set_iso_ir_85 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_85, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  ISO646-HU, codeset "MSZ_7795.3"   -- iso-ir-86 */ 
struct setlist set_iso_ir_86 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_86, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset "ASMO_449"   -- iso-ir-89 */ 
struct setlist set_iso_ir_89 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_89, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*  codeset "iso-ir-90" */ 
struct setlist set_iso_ir_90 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_2, &set1_iso_ir_90, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/*  codeset "JIS_C6229-1984-a"   -- iso-ir-91 */ 
struct setlist set_iso_ir_91 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_91, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*   ISO646-JP-OCR-B , codeset "JIS_C6229-1984-b"   -- iso-ir-92 */ 
struct setlist set_iso_ir_92 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_92, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*   This is quite likely wrong...
     codeset "JIS_C6229-1984-b-add"   -- iso-ir-93 */ 
struct setlist set_iso_ir_93 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_92, &set1_iso_ir_93, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/*   codeset "JIS_C6229-1984-hand"   -- iso-ir-94 */ 
struct setlist set_iso_ir_94 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_94, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};
/*   codeset "JIS_C6229-1984-hand-add"   -- iso-ir-95 
     This is quite likely incorrect...
 */ 
struct setlist set_iso_ir_95 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_94, &set1_iso_ir_95, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};


/*   codeset "JIS_C6229-1984-kana"   -- iso-ir-96 */ 
struct setlist set_iso_ir_96 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_96, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*   codeset "ISO_2033-1983"   -- iso-ir-98 
 *   this is likely to be incorrect
*/ 
struct setlist set_iso_ir_98 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_98, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*   codeset "ANSI_X3.110-1983"   -- iso-ir-99
     this is incorrect
*/
struct setlist set_iso_ir_99 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_99, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G2, bank_unspecified
};

/*   codeset "T.61-7bit"   -- iso-ir-102
*/
struct setlist set_iso_ir_102 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_102, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*   codeset "T.61-8bit"   -- iso-ir-103
*/
struct setlist set_iso_ir_103 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_102, &set1_iso_ir_103, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/*   ISO646-CA, codeset "CSA_Z243.4-1985-1"   -- iso-ir-121
*/
struct setlist set_iso_ir_121 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_121, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*   ISO646-CA2, codeset "CSA_Z243.4-1985-2"   -- iso-ir-122
*/
struct setlist set_iso_ir_122 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_122, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/*   codeset "CSA_Z243.4-1985-gr"   -- iso-ir-123
 *   This is probably incorrect
*/
struct setlist set_iso_ir_123 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_121, &set1_iso_ir_123, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/* codeset "T.101-G2",  ISO-IR-128
 * This is likely to be incorrect
 */
struct setlist set_iso_ir_128 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_128, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G2, bank_unspecified
};

/* codeset "CSN_369103",  ISO-IR-139
 * This is almost ISO-8859-2
 */
struct setlist set_iso_ir_139 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_iso_ir_139, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G2
};

/* ISO646-YU, codeset "JUS_I.B1.002", IS-IR-141 */
struct setlist set_iso_ir_141 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_141, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* codeset "ISO_6937-2-add",  ISO-IR-142
 */
struct setlist set_iso_ir_142 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_2, &set1_iso_ir_142, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/* codeset "IEC_P27-1",  ISO-IR-143
 */
struct setlist set_iso_ir_143 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_iso_ir_143, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/* codeset "JUS_I.B1.003-serb",  ISO-IR-146
 */
struct setlist set_iso_ir_146 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_146, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* codeset "JUS_I.B1.003-mac",  ISO-IR-147
 */
struct setlist set_iso_ir_147 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_147, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* codeset "greek-ccitt",  ISO-IR-150
 */
struct setlist set_iso_ir_150 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_150, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* ISO646-CU, codeset "NC_NC00-10:81",  ISO-IR-151
 */
struct setlist set_iso_ir_151 = { 
    { -1, -1, -1, -1 },
    { &set1_iso_ir_151, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};


/* codeset "ISO_6937-2-25",  ISO-IR-152
 * Assumed to be like ISO-8859-*
 */
struct setlist set_iso_ir_152 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_iso_ir_152, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/* codeset "GOST_19768-74 ",  ISO-IR-153
 * Assumed to be like ISO-8859-*
 */
struct setlist set_iso_ir_153 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_iso_ir_153, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/* codeset "ISO_8859-supp",  ISO-IR-154
 * Assumed to be like ISO-8859-*
 * This is likely to be incorrect
 */
struct setlist set_iso_ir_154 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_iso_ir_154, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G3
};


/* codeset "ISO_10367-box ",  ISO-IR-155
 * Assumed to be like ISO-8859-*
 * This is likely to be incorrect
 */
struct setlist set_iso_ir_155 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_iso_ir_155, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};


/* codeset "latin-lap",  ISO-IR-158
 * Assumed to be like ISO-8859-*
 * This is likely to be incorrect
 */
struct setlist set_iso_ir_158 = { 
    { -1, -1, -1, -1 },
    { &(latin_banks[0]), &set1_iso_ir_158, NULL, NULL, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G3
};



/* ISO-2022-KR - RFC 1557  ---   ASCII 
                                 KSC 5601 

   EUC-KR  --  G0 ASCII
               G1 KS X 1001 (KS C 5601)
*/

struct setlist set_ISO2022KR = { 
    { 0, 1, -1, -1 },
    { &(latin_banks[0]),  &set_KSC5601, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL },
    bank_G0, bank_unspecified
}; 

struct setlist set_EUCKR = { 
    { 0, 1, -1, -1 },
    { &(latin_banks[0]),  &set_KSC5601, NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL },
    bank_G0, bank_G1
}; 


/* ISO-2022-JP - RFC 1468 -- ASCII, 
   JIS C 6220 (JIS X 0201) - 1976
   JIS C 6226 (JIS X 0208) - 1978
   JIS C 6226 (JIS X 0208) - 1983
*/
struct setlist set_ISO2022JP = { 
    { 0, -1, -1, -1 },
    { &(latin_banks[0]), &set_JISC6220,
      &set_JISC6226a, &set_JISC6226b, 
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* iso-ir-42 -- must likely incorrenct */
struct setlist set_iso_ir_42 = { 
    { -1, -1, -1, -1 },
    { &set_JISC6226a, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* iso-ir-87 -- must likely incorrenct */
struct setlist set_iso_ir_87 = { 
    { -1, -1, -1, -1 },
    { &set_JISC6226b, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};


/* EUC-JP -   G0 ASCII
                  G1 JIS X 0208-1983 
                  G2 JIS X 0201:1976/1997
                  G3 JIS X 0212:1990
*/		   
struct setlist set_EUCJP = { 
    { 0, 1, 2, 3 },
    { &(latin_banks[0]), &set_JISX0208_1983_euc,
      &set_JISX0201_euc,  &set_JISX0212_euc,
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};

/* ISO646-JP -- JIS C 6220 (JIS X 0201) - 1976 */
struct setlist set_ISO646JP = { 
    { -1, -1, -1, -1 },
    { &set_JISC6220, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL,
      NULL, NULL, 
    },
    bank_G0, bank_unspecified
};	 

/* ISO-2022-JP-2 -- RFC 1554  -- ASCII,
   JIS C 6220 (JIS X 0201) - 1976
   JIS C 6226 (JIS X 0208) - 1978
   JIS C 6226 (JIS X 0208) - 1983
   GB2312-1980
   KSC5601-1987
   JIS X 0212-1990
   ISO8859-1
   ISO8859-7(Greek)
*/
struct setlist set_ISO2022JP2 = { 
    { 0, -1, -1, -1 },
    { &(latin_banks[0]), &set_JISC6220,
      &set_JISC6226a, &set_JISC6226b, 
      &set_GB2312jp, &set_KSC5601jp, 
      &set_JISX0212, &set_ISO88591,
      &set_ISO88597, NULL },
    bank_G0, bank_G2
};

/* GB_2312-80, iso-ir-58 */
struct setlist set_iso_ir_58 = { 
    { -1, -1, -1, -1 },
    { &set_GB2312jp , NULL, NULL, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* codeset JIS_X0212-1990, iso-ir-159 
 * This is likely be incorrect
 */
struct setlist set_iso_ir_159 = { 
    { -1, -1, -1, -1 },
    { &set_JISX0212, NULL, NULL, NULL, NULL, NULL, 
      NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};



    
/* ISO-2022-CN -- RFC 1922, ASCII,
   GB 2312, 
   CNS 11643-plane-1,
   CNS 11643-plane-2
 
   FIXME:  This does not use sigle shifts for 
   CNS 11643-plane-1, CNS 11643-plane-2
*/
struct setlist set_ISO2022CN = { 
    { 0, -1, -1, -1 },
    { &(latin_banks[0]), &set_GB2312,
      &set_CNS11643plane1, &set_CNS11643plane2,
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_unspecified
};

/* ISO-2022-CN-EXT -- RFC 1922, ASCII,
   bank G1: GB 2312, 
            GB 12345,               Final byte unknown!   (set_GB12345)
            CNS 11643-plane-1,
	    ISO-IR-165,
   bank G2: GB 7589,                Final byte unknown!   (set_GB7589)
            GB 13131,               Final byte unknown!   (set_GB13131)
	    CNS 11643-plane-2,
   bank G3: GB 7590,                Final byte unknown!   (set_GB7590)
            GB 13132,               Final byte unknown!   (set_GB13132)
	    CNS 11643-plane-3,
	    CNS 11643-plane-(4-7)
*/
struct setlist set_ISO2022CNEXT = { 
    { 0, -1, -1, -1 },
    {  &(latin_banks[0]), &set_GB2312,
#if 0                          /* Final byte unknown */
				    &set_GB12345,
#endif
				    &set_CNS11643plane1, 
				    &set_ISOIR165,
#if 0                               /* Final byte unknown */
				    &set_GB7589,
				    &set_GB13131,
#endif
				    &set_CNS11643plane2,
#if 0                               /* Final byte unknown */
				    &set_GB7590,
				    &set_GB13132,
#endif
				    &set_CNS11643plane3,
				    &set_CNS11643plane4,
				    &set_CNS11643plane5,
				    &set_CNS11643plane6,
				    &set_CNS11643plane7
    },
    bank_G0, bank_unspecified
};

/* GB2312 (really EUC-CN) -- ASCII + GB 2312-80 */
struct setlist set_EUCCN = { 
    { 0, 1, -1, -1 },
    { &(latin_banks[0]), &set_GB2312,
      NULL, NULL,
      NULL, NULL, NULL, NULL, NULL, NULL },
    bank_G0, bank_G1
};


static struct setlist * INITIAL_setlists[] = {
    &set_utf8,
    &set_latin7,
    &set_latin8,
    &set_latin9,
    &set_iso885916,
    &set_koi8e,
    &set_iso_ir_2,
    &set_iso_ir_4,
    &set_iso_ir_8_1,
    &set_iso_ir_8_2,
    &set_iso_ir_9_1,
    &set_iso_ir_9_2,
    &set_iso_ir_10,
    &set_iso_ir_11,
    &set_iso_ir_13,
    &set_iso_ir_15,
    &set_iso_ir_16,
    &set_iso_ir_17,
    &set_iso_ir_18,
    &set_iso_ir_19,
    &set_iso_ir_21,
    &set_iso_ir_25,
    &set_iso_ir_27,
    &set_iso_ir_37,
    &set_iso_ir_47,
    &set_iso_ir_49,
    &set_iso_ir_50,
    &set_iso_ir_51,
    &set_iso_ir_54,
    &set_iso_ir_55,
    &set_iso_ir_57,
    &set_iso_ir_58,
    &set_iso_ir_60,
    &set_iso_ir_61,
    &set_iso_ir_69,
    &set_iso_ir_70,
    &set_iso_ir_84,
    &set_iso_ir_85,
    &set_iso_ir_86,
    &set_iso_ir_89,
    &set_iso_ir_90,
    &set_iso_ir_91,
    &set_iso_ir_92,
    &set_iso_ir_93,
    &set_iso_ir_94,
    &set_iso_ir_95,
    &set_iso_ir_96,
    &set_iso_ir_98,
    &set_iso_ir_99,
    &set_iso_ir_102,
    &set_iso_ir_103,
    &set_iso_ir_121,
    &set_iso_ir_122,
    &set_iso_ir_123,
    &set_iso_ir_128,
    &set_iso_ir_139,
    &set_iso_ir_141,
    &set_iso_ir_142,
    &set_iso_ir_143,
    &set_iso_ir_146,
    &set_iso_ir_147,
    &set_iso_ir_150,
    &set_iso_ir_151,
    &set_iso_ir_152,
    &set_iso_ir_153,
    &set_iso_ir_154,
    &set_iso_ir_155,
    &set_iso_ir_158,
    &set_iso_ir_159,
    &set_ISO2022KR,
    &set_EUCKR,
    &set_iso_ir_149,
    &set_ISO2022JP,
    &set_EUCJP,
    &set_ISO646JP,
    &set_ISO2022JP2,
    &set_iso_ir_42,
    &set_iso_ir_87,
    &set_ISO2022CN,
    &set_ISO2022CNEXT,
};

struct setlist sets_iso_8859_X [] = { 
    { 
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), NULL,                
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_unspecified
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[1]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[2]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[3]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[4]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[5]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[6]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[7]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[8]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[9]),   
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[10]),  
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
    {
	{ -1, -1, -1, -1 },
	{ &(latin_banks[0]), &(latin_banks[11]),  
	  NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
	bank_G0, bank_G2
    },
};

static int same_setlist P_((const struct setlist A,
			 const struct setlist B));
static int same_setlist(A,B)
     CONST struct setlist A;
     CONST struct setlist B;
{
    int i;

    for (i = 0; 
	 i < sizeof (A.initial_bank) / sizeof (A.initial_bank[0]); 
	 i++) 
	if (A.initial_bank[i] != B.initial_bank[i])
	    return 0;

    for (i = 0; 
	 i < sizeof (A.sets) / sizeof (A.sets[0]);
	 i++)
	if (A.sets[i] != B.sets[i])
	    return 0;

    if (A.initial_L != B.initial_L)
	return 0;
    if (A.initial_R != B.initial_R)
	return 0;

    return 1;
}

struct setlist *loc_setlist(l)
     CONST struct setlist l;
{
    static struct setlist ** setlists = INITIAL_setlists;
    static int setlist_count          = 
	sizeof  (INITIAL_setlists) / sizeof (INITIAL_setlists[0]);
    struct setlist *ret;

    int i;

    for (i = 0; 
	 i < sizeof sets_iso_8859_X / sizeof (sets_iso_8859_X[0]); 
	 i++) {
	if (same_setlist(sets_iso_8859_X[i],l)) {
	    ret = &(sets_iso_8859_X[i]);
	    goto found;
	}
    }

    for (i = 0; i < setlist_count; i++) 
	if (same_setlist(*(setlists[i]),l)) {
	    ret = setlists[i];
	    goto found;
	}
	
    ret = safe_malloc(sizeof (struct setlist));
    *ret = l;
    
    if (INITIAL_setlists == setlists) {
	int k;
	setlists = safe_malloc((setlist_count+1) * sizeof (struct setlist *));
	
	for (k = 0; k < setlist_count; k++)
	    setlists[k] = INITIAL_setlists[k];

    } else
	setlists = safe_realloc(setlists,
				(setlist_count+1) * sizeof (struct setlist *));

    setlists[setlist_count++] = ret;

    DPRINT(Debug,25,(&Debug, 
		     "loc_setlist: Addind new setlist to list, count %d\n",
		     setlist_count));

 found:
    DPRINT(Debug,25,(&Debug, 
		     "loc_setlist=%p\n",ret));
    return ret;
}

/* May be called from signal handler -- on that situation use
   buffer specified as argument -- otherwise result is malloced
*/
char * iso2022_setid_stream(c,buffer,size)
     CONST struct iso2022_setid  c;
     char *buffer; 
     int size;
{
    int len,j;
    char * ret;
    int idx = 0;

    int maybe_signal = buffer != NULL;

    if (maybe_signal) {
	SIGDPRINT(Debug,9,(&Debug,
			   "iso2022_setid_stream: buffer=%p size=%d\n",
			   buffer,size));
    }


    if (maybe_signal) {
	ret = buffer;
	len = size-1;
    } else {
	
	for (len = 0; len < sizeof c.bytes; len++)
	    if (!c.bytes[len])
		break;
	len += 4;       /* ESC {twobyte} bank {bytes} */

	ret = safe_malloc(len+1);
    }

#define ADD(x) if (idx >= len) \
 panic("ISO2022 PANIC",__FILE__,__LINE__,"iso2022_setid_stream","Overlow",\
   maybe_signal); \
 else { ret[idx++]=(x); }

    ADD(0x1B);                /* ESC */
    
    switch(c.type) {
    case iso2022_other:
	ADD(0x25);
	break;
    case iso2022_94x94: 
	ADD(0x24);
	/* FALLTHRU */
    case iso2022_94:
	switch(c.bank) {	    
	case bank_G0: ADD(0x28); break;
	case bank_G1: ADD(0x29); break;
	case bank_G2: ADD(0x2A); break;
	case bank_G3: ADD(0x2B); break;
	}
	break;
    case iso2022_96x96:
	ADD(0x24);
	/* FALLTHRU */
    case iso2022_96:
	switch(c.bank) {
	case bank_G1: ADD(0x2D); break;
	case bank_G2: ADD(0x2E); break;
	case bank_G3: ADD(0x2F); break;
	}
	break;	
    }
 
    for (j = 0; j < sizeof c.bytes && c.bytes[j]; j++) {
	ADD(c.bytes[j]);
    }        
#undef ADD

    ret[idx] = '\0';

    if (maybe_signal && ret != buffer)
	panic("ISO2022 PANIC",__FILE__,__LINE__,
	      "iso2022_setid_stream",
	      "buffer != ret when called from signal",1);

    return ret;
}

/* Special return values:    0    Not a setid 
 *                          -1    Incomplete setid
 *                          > 0   len of setid
 */
static int eat_iso2022_ident P_((CONST unsigned char *buffer, int len)); 
int eat_iso2022_setid P_((struct iso2022_setid *result, 
			  const unsigned char *buffer, int len));
int eat_iso2022_setid(result,buffer,len)
     struct iso2022_setid *result; 
     CONST unsigned char *buffer; 
     int len;
{

    int i = 0,l,j;
    int multi_byte = 0;    

    result->type = iso2022_other;
    result->bank = bank_unspecified;

    if (len < 1) {
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid=-1: Too short %d\n",
			 i));
	return -1;
    } 

    if (buffer[i] != 0x1B)                        /* ESC */
	goto fail;
    DPRINT(Debug,60,(&Debug, 
		     "eat_iso2022_setid: accept [%d]=%02X\n",
		     i,buffer[i]));
    i++;

    if (buffer[i] == 0x24) {
	multi_byte++;
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid: accept [%d]=%02X\n",
			 i,buffer[i]));
	i++;
    }

    if (len <= i) {
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid=-1: Too short %d\n",
			 i));
	return -1;
    } 
    
    switch(buffer[i]) {
    case 0x28:       /* G0 */
	if (multi_byte)  result->type = iso2022_94x94;
	else             result->type = iso2022_94;
	                 result->bank = bank_G0;

	DPRINT(Debug,60,(&Debug, 
		     "eat_iso2022_setid: accept [%d]=%02X\n",
		     i,buffer[i]));
	i++;
	break;
    case 0x29:       /* G1 */
	if (multi_byte)  result->type = iso2022_94x94;
	else             result->type = iso2022_94;
	                 result->bank = bank_G1;

	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid: accept [%d]=%02X\n",
			 i,buffer[i]));
	i++;
	break;
    case 0x2A:       /* G2 */
	if (multi_byte)  result->type = iso2022_94x94;
	else             result->type = iso2022_94;
	                 result->bank = bank_G2;

	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid: accept [%d]=%02X\n",
			 i,buffer[i]));
	i++;
	break;
    case 0x2B:       /* G3 */
	if (multi_byte)  result->type = iso2022_94x94;
	else             result->type = iso2022_94;
	                 result->bank = bank_G3;

	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid: accept [%d]=%02X\n",
			 i,buffer[i]));
	i++;
	break;
    case 0x2D:        /* G1 */
	if (multi_byte)  result->type = iso2022_96x96;
	else             result->type = iso2022_96;
	                 result->bank = bank_G1;

	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid: accept [%d]=%02X\n",
			 i,buffer[i]));
	i++;
	break;

    case 0x2E:        /* G2 */
	if (multi_byte)  result->type = iso2022_96x96;
	else             result->type = iso2022_96;
	                 result->bank = bank_G2;

	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid: accept [%d]=%02X\n",
		     i,buffer[i]));
	i++;
	break;
    case 0x2F:        /* G0 */
	if (multi_byte)  result->type = iso2022_96x96;
	else             result->type = iso2022_96;
	                 result->bank = bank_G3;
	
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid: accept [%d]=%02X\n",
			 i,buffer[i]));
	i++;
	break;
    case 0x40: case 0x41: case 0x42:
	/* Old multibyte designation to bank 0 without bank code */
	if (multi_byte) {
	    result->type = iso2022_94x94;
	    result->bank = bank_G0;
	    /* Do not increment here because that is actually part of set 
             * code
	     */
	    break;
	}
	/* FALLTHROUGH */
    default:
	goto fail;
    }

    l = eat_iso2022_ident(buffer+i,len-i);
    if (l == 0) {
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_setid=0: reject (eat_iso2022_ident) [%d]=%02X\n",
			 i,buffer[i]));
	return 0;
    }
    if (l < 0) {
	DPRINT(Debug,60,(&Debug, 
			 "got_ISO2022_setid=-1: incomplete (eat_iso2022_ident)\n"));
	return -1;
    }

    for (j = 0; j < sizeof (result->bytes) && j < l; j++)
	result->bytes[j] = buffer[i+j];
    for (; j < sizeof (result->bytes); j++)
	result->bytes[j] = 0;

    DPRINT(Debug,60,(&Debug, 
		     "eat_iso2022_setid=%d: accept (eat_iso2022_ident)\n",
		     i+l));
    return i+l;
    
 fail:
    DPRINT(Debug,60,(&Debug, 
		     "eat_iso2022_setid=0: reject [%d]=%02X\n",
		     i,buffer[i]));
    return 0;    
}



/* May be called from signal handler -- on that situation use
   buffer specified as argument -- otherwise result is malloced
*/
char * lock_shift(r,bank,buffer,size)
     int r; 
     enum iso2022_bank bank;
     char *buffer;
     int size;
{
    int len = 3;
    int idx = 0;
    char * ret;

    int maybe_signal = buffer != NULL;
    
    if (maybe_signal) {
	SIGDPRINT(Debug,9,(&Debug,
			   "lock_sift: buffer=%p size=%d\n",
			   buffer,size));
    }

    if (maybe_signal) {
	ret = buffer;
	len = size-1;
    } else {
	ret = safe_malloc(len+1);
    }

#define ADD(x) if (idx >= len) \
  panic("ISO2022 PANIC",__FILE__,__LINE__,"lock_shift","Overlow",\
    maybe_signal);\
  else { ret[idx++]=(x); }

    switch(r) {
    case 0:
	switch (bank) {
	case bank_G0:     ADD(0x0F);   /* SI */ break;
	case bank_G1:     ADD(0x0E);   /* SO */ break;
	case bank_G2:     ADD(0x1B);   ADD(0x6E);  break;
	case bank_G3:     ADD(0x1B);   ADD(0x6F);  break;
	}
	break;
    default:
	switch (bank) {
	case bank_G1:     ADD(0x1B);   ADD(0x7E);   break;
	case bank_G2:     ADD(0x1B);   ADD(0x7D);   break;
	case bank_G3:     ADD(0x1B);   ADD(0x7C);   break;
	}
    }
#undef ADD

    ret[idx] = '\0';

    if (maybe_signal && ret != buffer)
	panic("ISO2022 PANIC",__FILE__,__LINE__,
	      "lock_sift",
	      "buffer != ret when called from signal",1);

    return ret;
}

/* Special return values:    0    Not a bank switch
 *                          -1    Incomplete switch
 *                          > 0   len of switch
 */
int eat_iso2022_bank_switch P_((enum iso2022_bank *bank,
				enum shift_mode *left_right,
				CONST unsigned char *buffer,
				int len));
int eat_iso2022_bank_switch(bank,left_right,buffer,len)			      
     enum iso2022_bank *bank;
     enum shift_mode   *left_right;
     CONST unsigned char *buffer;
     int len;
{
    int i = 0;

    if (len < 1) {
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_bank_switch=-1: Too short %d\n",
			 i));
	return -1;
    } 

    switch(buffer[i]) {

    case 0x0E:
	*bank       = bank_G1;
	*left_right = lock_shift_left;
	break;

    case 0x0F:
	*bank       = bank_G0;
	*left_right = lock_shift_left;
	break;

    case 0x1B:
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_bank_switch: accept [%d]=%02X\n",
			 i,buffer[i]));
	i++;

	if (len <= i) {
	    DPRINT(Debug,60,(&Debug, 
			     "eat_iso2022_bank_switch=-1: Too short %d\n",
			     i));
	    return -1;
	}
	switch(buffer[i]) {

	case 0x7E:
	    *bank       = bank_G1;
	    *left_right = lock_shift_right;
	    break;

	case 0x6E:
	    *bank       = bank_G2;
	    *left_right = lock_shift_left;
	    break;

	case 0x7D:
	    *bank       = bank_G2;
	    *left_right = lock_shift_right;
	    break;

	case 0x6F:
	    *bank       = bank_G3;
	    *left_right = lock_shift_left;
	    break;

	case 0x7C:
	    *bank       = bank_G3;
	    *left_right = lock_shift_right;
	    break;

	case 0x4E:
	    *bank       = bank_G2;
	    *left_right = single_shift;    /* Normally left, but EUC uses right bank */
	    break;

	case 0x4F:
	    *bank       = bank_G3;
	    *left_right = single_shift;
	    break;

	default:
	    goto fail;
	}
	break;

    case 0x8E:
	*bank       = bank_G2;
	*left_right = single_shift;      /* Normally left, but EUC uses right bank */
	break;

    case 0x8F:
	*bank       = bank_G3;
	*left_right = single_shift;      /* Normally left, but EUC uses right bank */
	break;

    default:
	goto fail;
    }
    DPRINT(Debug,60,(&Debug, 
		     "eat_iso2022_bank_switch: accept [%d]=%02X\n",
		     i,buffer[i]));
    i++;

    DPRINT(Debug,60,(&Debug, 
		     "eat_iso2022_bank_switch=%d: accept (bank=%d, left_right=%d)\n",
		     i, *bank,*left_right));
    return i;
    
 fail:
    DPRINT(Debug,60,(&Debug, 
		     "eat_ISO2022_bank_switch=0: reject [%d]=%02X\n",
		     i,buffer[i]));
    return 0;    
}

/* -1 == no space, 0 == not available */
int do_single_shift(buffer,size,bank,is_upper) 
     unsigned char buffer[]; 
     int size;
     enum iso2022_bank bank;
     int is_upper;
{
    int ret = 0;
    if (size < 2)
	return -1;  /* NO SPACE */

    if (is_upper) {
	switch (bank) {
	case  bank_G2:
	    buffer[ret++] = 0x8E;
	    break;
	case bank_G3:
	    buffer[ret++] = 0x8F;
	    break;
	default:
	    return 0;
	}
    } else {

	if (size < 3)
	    return -1;  /* NO SPACE */

	buffer[ret++] = 0x1B;      /* ESC */

	switch (bank) {
	case  bank_G2:
	    buffer[ret++] = 0x4E;
	    break;
	case bank_G3:
	    buffer[ret++] = 0x4E;
	    break;
	default:
	    return 0;
	}
    }
    buffer[ret] = '\0';

    return ret;
}


/* Special return values:    0    Not a ISO2022 ident
 *                          -1    Incomplete ident
 *                          > 0   len of ident
 */

static int eat_iso2022_ident(buffer,len)			      
     CONST unsigned char *buffer;
     int len;
{
    int i = 0;

    while (i < len && buffer[i] >= 0x20 && buffer[i] <= 0x2F) {
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_ident: accept [%d]=%02X\n",
			 i,buffer[i]));
	i++;
    }
    
    /* Final byte 0x30..0x7E
                  0x30..0x3F   is only private use
    */

    if (i < len && buffer[i] >= 0x30 && buffer[i] <= 0x7E) {
	DPRINT(Debug,60,(&Debug, 
			 "eat_iso2022_ident=%d: final [%d]=%02X\n",
			 i+1,i,buffer[i]));
	i++;
	return i;
    }
    if (i == len) {
	DPRINT(Debug,60,(&Debug,  
			 "eat_iso2022_ident=-1: Too short %d\n",
		     i));
	return -1;
    }
    DPRINT(Debug,60,(&Debug, 
		     "eat_iso2022_ident=0: reject [%d]=%02X\n",
		     i,buffer[i]));
    return 0;
}

void iso2022_clear_setlist(X)
     struct setlist *X;
{
    int i;

    for (i = 0; 
	 i < sizeof (X->initial_bank) / sizeof (X->initial_bank[0]); 
	 i++) {
	X->initial_bank[i] = -1;
    }

    for (i = 0; i < sizeof (X->sets) / sizeof (X->sets[0]); i++) {
	X->sets[i] = NULL;
    } 
    X->initial_L = bank_unspecified;
    X->initial_R = bank_unspecified;
}

int parse_gen_spec(val,bytes,size)
     CONST char *val; 
     unsigned char *bytes;
     int size;
{
    int ret = 0;
    int ptr = 0;
    char * temp = safe_strdup(val);
    char *wrk;

    for (wrk = strtok(temp," \t,"); wrk; wrk = strtok(NULL," \t,")) {
	char *end;
	long l = strtol(wrk,&end,10); 
	
	if (ptr == size) {
	    lib_error(CATGETS(elm_msg_cat, MeSet, 
			      MeTooLongident,
			      "Too long ident: %.20s..."),
		      temp);
	    ret = 0;
	    goto fail;
	}

	if ((*end == '\0')  &&
	    l >= 0x01 && l <= 0x7F) {
	    bytes[ptr] = l;
	    DPRINT(Debug,11,(&Debug, 
			     "parse_gen_ident_spec: [%d]=%02X\n",
			     ptr,bytes[ptr]));
	    ptr++;
	} else if (*end == '/' && l >= 0 && l <= 15 &&
		   *(end+1) != '\0') {	    
	    long l1; 

	    wrk = end+1;
	    l1 = strtol(wrk,&end,10);
		
	    if ((*end == '\0') &&
		l1 >= 0 && l1 <= 15 &&
		(l != 0 || l1 != 0)) {	    
		bytes[ptr] = l*16 + l1;
		DPRINT(Debug,11,(&Debug, 
				 "parse_gen_ident_spec: [%d]=%02X\n",
				 ptr,bytes[ptr]));
		ptr++;
	    } else {
		DPRINT(Debug,1,(&Debug, 
				"parse_gen_ident_spec: wrk=%s, *end=%c,l1=%ld\n",
				wrk,*end,l1));
		lib_error(CATGETS(elm_msg_cat, MeSet, 
				  MeBadident,
				  "Bad ident: %.20s..."),
			  wrk);
		ret = 0;
		goto fail;
	    }
	} else {
	    DPRINT(Debug,1,(&Debug, 
			"parse_gen_ident_spec: wrk=%s, *end=%c,l=%ld\n",
			wrk,*end,l));

	    lib_error(CATGETS(elm_msg_cat, MeSet, 
			      MeBadident,
			      "Bad ident: %.20s..."),
		      wrk);
	    ret = 0;
	    goto fail;
	}
    }
    ret = ptr;

 fail:
    free(temp);
    while (ptr < size)
	bytes[ptr++] = '\0';    
    return ret;
}
			      
static int parse_ISO2022_ident_spec(val,bytes,size)
     CONST char *val;
     unsigned char * bytes;
     int size;
{
    int ret = 0, ptr,l;

    DPRINT(Debug,11,(&Debug, 
		     "parse_ISO2022_ident_spec: val=%s\n",val));

    ptr = parse_gen_spec(val,bytes,size);
    
    if (ptr) {
	ret = 1;
	l = eat_iso2022_ident(bytes,ptr);
	if (l != ptr) {
	    DPRINT(Debug,1,(&Debug, 
			    "parse_ISO2022_ident_spec: eat_iso2022_ident=%d, ptr=%d\n",
			    l,ptr));
	    
	    lib_error(CATGETS(elm_msg_cat, MeSet, 
			      MeBadISO2022ident,
			      "Bad ISO2022 ident: %.20s..."),
		      val);
	    ret = 0;
	}
    }

    return ret;
}

static struct iso2022_banks {
    CONST char *          keyword;
    enum iso2022_bank     bank; 
} iso2022_banks[] = {
    { "none",      bank_unspecified },
    { "bank-G0",   bank_G0 },
    { "bank-G1",   bank_G1 },
    { "bank-G2",   bank_G2 },
    { "bank-G3",   bank_G3 },

    {  NULL, bank_unspecified }      
};



void iso2022_merge_old_info(new_setlist,setcount,old_info)
     struct setlist *new_setlist;
     int setcount;
     struct setlist *old_info; 
{
    int i;
    int bank_info[ISO2022_BANK_NUM];

    for (i = 0; i <  ISO2022_BANK_NUM; i++) {
	bank_info[i] = new_setlist->initial_bank[i];	
    }

    for (i = 0; i < setcount; i++) {
	if (new_setlist->sets[i] &&
	    new_setlist->sets[i]->bank >= 0 &&
	    new_setlist->sets[i]->bank < ISO2022_BANK_NUM &&
	    -1 == bank_info[ new_setlist->sets[i]->bank ] )
	    bank_info[ new_setlist->sets[i]->bank ] = i;  
    }
	
    
    /* copy old left= and rigth= specifications if 
       bank is on use
    */

    if (bank_unspecified == new_setlist->initial_L &&
	bank_unspecified != old_info->initial_L &&
	-1 != bank_info [ old_info->initial_L ])
	new_setlist->initial_L = old_info->initial_L;

    if (bank_unspecified == new_setlist->initial_R &&
	bank_unspecified != old_info->initial_R &&
	-1 != bank_info [ old_info->initial_R ])
	new_setlist->initial_R = old_info->initial_R;
}

int parse_iso2022_specification(param,value,count,list)
     CONST char     *param;
     CONST char     *value;
     int            *count;
     struct setlist *list; 
{
    int i;
    struct iso2022_setid  TMP;
    int initial = 0;
    int left_right = -1;

    /* TODO: Hook for extra parameters */

    if (0 == strcmp("left",param)) 
	left_right = 0;
    if (0 == strcmp("right",param)) 
	left_right = 1;

    if (left_right >= 0) {

	for (i= 0; iso2022_banks[i].keyword; i++)
	    if (0 == strcmp(iso2022_banks[i].keyword,value))
		break;

	if (!iso2022_banks[i].keyword)
	    return 0;
	
	switch(left_right) {
	case 0:
	    list->initial_L = iso2022_banks[i].bank;
	    break;
	case 1:
	    if (iso2022_banks[i].bank == bank_G0) {
		lib_error(CATGETS(elm_msg_cat, MeSet, 
				  MeRigthNobank0,
				  "right=bank-G0 is not allowed"));
		return 0;
	    }
	    
	    list->initial_R = iso2022_banks[i].bank;
	    break;
	}
	return 1;
    }


    if (0 == strncmp("initial-",param,8)) {
	param += 8;
	initial++;
    }

    for (i = 0; iso2022_keywords[i].keyword; i++)
	if (0 == strcmp(iso2022_keywords[i].keyword,param))
	    break;

    if (!iso2022_keywords[i].keyword)
	return 0;

    if (initial && ( iso2022_keywords[i].bank < 0 ||
		     iso2022_keywords[i].bank >= 
		     sizeof (list->initial_bank) / 
		     sizeof (list->initial_bank[0])))
	return 0;
    
    TMP.bank = iso2022_keywords[i].bank;
    TMP.type = iso2022_keywords[i].type;

    if (!parse_ISO2022_ident_spec(value,TMP.bytes,sizeof (TMP.bytes)))
	return 0;

    if (initial) {
	int j;

	if (-1 != list->initial_bank[TMP.bank]) {
	    lib_error(CATGETS(elm_msg_cat, MeSet, 
			      MeMultipleInitial,
			      "Multiple initial-%.20s given"),
		      param);
	    return 0;
	}

	for (j = 0; j < (*count); j++) {
	    if (same_setid(* list->sets[j],TMP))
		break;
	}
	
	if (j < (*count)) {
	    list->initial_bank[TMP.bank] = j;
	    return 1;
	}
    }

    if ((*count) >= sizeof (list->sets) / sizeof (list->sets[0])) {
	lib_error(CATGETS(elm_msg_cat, MeSet, 
			  MeTooManyBank,
			  "Too many banks on charset: %.20s"),
		  param);
	return 0;
    }
    
    if (*count > 0 &&
	list->sets[0]->type == iso2022_other) {

	lib_error(CATGETS(elm_msg_cat, MeSet, 
			  MeOtherSetIncompatible,
			  "Param other-set is incompatible with param %s"),
		  param);
	return 0;
    }

    list->sets[(*count)] = loc_setid(TMP);

    if (initial)
        list->initial_bank[TMP.bank] = (*count);

    (*count)++;

    return 1;
}

char * iso2022_codestr(bytes,size)
     unsigned char * bytes;
     int size;
{
    char *ret = NULL;
    int i;

    for (i = 0; i < size && bytes[i]; i++) {
	char temp[10];
	int val = (unsigned char) bytes[i];
	sprintf(temp,"%d/%d",val/16,val%16);
	if (ret)
	    ret = strmcat(ret," ");
	ret = strmcat(ret,temp);
    }
    return ret;
}


void print_setlist(f,l)
     FILE *f;
     struct setlist *l;
{
    int i;

    if (bank_unspecified != l->initial_L) {
	for (i = 0; iso2022_banks[i].keyword; i++)
	    if (iso2022_banks[i].bank == l->initial_L)
		fprintf(f,";left=%s",iso2022_banks[i].keyword);
    }

    if (bank_unspecified != l->initial_R) {
	for (i = 0; iso2022_banks[i].keyword; i++)
	    if (iso2022_banks[i].bank == l->initial_R)
		fprintf(f,";right=%s",iso2022_banks[i].keyword);
    }

    for (i = 0; l->sets[i] && 
	     i < sizeof (l->sets) / sizeof (l->sets[0]); 
	 i++) {
	int j;

	for (j = 0; iso2022_keywords[j].keyword; j++) {
	    if (iso2022_keywords[j].bank == l->sets[i]->bank &&
		iso2022_keywords[j].type == l->sets[i]->type) {
		char * t = iso2022_codestr(l->sets[i]->bytes,
					   sizeof l->sets[i]->bytes);
		if (t) {
		    char *I = "";

		    if (l->sets[i]->bank >= 0 &&
			l->sets[i]->bank < sizeof (l->initial_bank) / 
			sizeof (l->initial_bank[0])) {
   
			if (l->initial_bank[l->sets[i]->bank] == i) {
			    I = "initial-";

			}			     
		    }
		    
		    if (0 == strchr(t,' '))
			elm_fprintf(f,FRM(";%s%s=%s"),
				    I,
				    iso2022_keywords[j].keyword,
				    t);
		    else
			elm_fprintf(f,FRM(";%s%s=%Q"),
				    I,
				    iso2022_keywords[j].keyword,
				    t);
		    free(t);
		}
	    }
	}
    }
}
	
/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */


syntax highlighted by Code2HTML, v. 0.9.1