static char rcsid[] = "@(#)$Id: cs_iso2022.c,v 1.42 2006/04/09 07:37:08 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.42 $ $State: Exp $ * * Author: Kari Hurtta (was hurtta+elm@ozone.FMI.FI) *****************************************************************************/ #include "headers.h" #include "s_me.h" #include "cs_imp.h" #include "cs_terminal.h" DEBUG_VAR(Debug,__FILE__,"charset"); static unsigned char *s2us P_((char *str)); static unsigned char *s2us(str) char *str; { return (unsigned char *)str; } static char *us2s P_((unsigned char *str)); static char *us2s(str) unsigned char *str; { return(char *)str; } /* ------------------------------------------------------------------------- */ static void map_init_bad P_((struct map_info *map)); static void map_init_bad(map) struct map_info *map; { panic("STRING PANIC",__FILE__,__LINE__,"map_init_bad", "map_init_bad called",0); } /* ISO 2022 maps */ static struct map_info * open_iso2022_mapset P_((const char * map_name)); static struct map_info * open_iso2022_mapset(map_name) CONST char * map_name; { /* Indexes to iso2022_map_list[] */ int setlist[ISO2022_SET_COUNT]; int count = 0; static struct map_info * ret = NULL; char * WALK = NULL; int i; char * X = safe_strdup(map_name), *X1; for (X1 = mime_parse_content_opts(X, &WALK); X1 && *X1; X1 = mime_parse_content_opts(NULL, &WALK)) { if (count >= ISO2022_SET_COUNT) { lib_error(CATGETS(elm_msg_cat, MeSet, MeTooManyMaps, "Too many maps on %s"), map_name); break; } setlist[count] = find_iso2022_map_spec(X1); if (-1 == setlist[count]) { free(X); return NULL; } count++; } free(X); ret = safe_malloc(sizeof (struct map_info)); ret -> map_type = &cs_iso2022; ret -> map_name = safe_strdup(map_name); ret -> b.setlist = safe_malloc(sizeof (* (ret -> b.setlist))); ret -> map_initialized = 1; ret -> map_init_it = map_init_bad; for (i = 0; i < sizeof (ret->b.setlist->setlist) / sizeof (ret->b.setlist->setlist[0]); i++) { ret->b.setlist->setlist[i] = i < count ? setlist[i] : -1; } return ret; } /* EUC maps */ static struct map_info * open_euc_mapset P_((const char * map_name)); static struct map_info * open_euc_mapset(map_name) CONST char * map_name; { /* Indexes to iso2022_map_list[] */ int setlist[ISO2022_SET_COUNT]; int count = 0; static struct map_info * ret = NULL; char * WALK = NULL; int i; char * X = safe_strdup(map_name), *X1; for (X1 = mime_parse_content_opts(X, &WALK); X1 && *X1; X1 = mime_parse_content_opts(NULL, &WALK)) { if (count >= ISO2022_SET_COUNT) { lib_error(CATGETS(elm_msg_cat, MeSet, MeTooManyMaps, "Too many maps on %s"), map_name); break; } setlist[count] = find_iso2022_map_spec(X1); if (-1 == setlist[count]) return NULL; count++; } free(X); ret = safe_malloc(sizeof (struct map_info)); ret -> map_type = &cs_euc; ret -> map_name = safe_strdup(map_name); ret -> b.setlist = safe_malloc(sizeof (* (ret -> b.setlist))); ret -> map_initialized = 1; ret -> map_init_it = map_init_bad; for (i = 0; i < sizeof (ret->b.setlist->setlist) / sizeof (ret->b.setlist->setlist[0]); i++) { ret->b.setlist->setlist[i] = i < count ? setlist[i] : -1; } return ret; } static void find_with_list P_((struct iso2022_setid **p, struct map_info *map)); static void find_with_list(p,map) struct iso2022_setid **p; struct map_info *map; { int count = 0; DPRINT(Debug,61,(&Debug, "find_with_list iso2022 indexes for %s:", map->map_name ? map->map_name : "???")); for (count = 0; p[count]; count++) { int i; if (count >= sizeof (map->b.setlist->setlist) / sizeof (map->b.setlist->setlist[0])) panic("STRING PANIC",__FILE__,__LINE__,"find_with_list", "Too many maps",0); for (i = 0; i < iso2022_map_list_count; i++) { if (iso2022_map_list[i].setid == p[count]) break; } if (i >= iso2022_map_list_count) panic("STRING PANIC",__FILE__,__LINE__,"find_with_list", "Set not found",0); if (!iso2022_map_list[i].map) panic("STRING PANIC",__FILE__,__LINE__,"find_with_list", "No map for set",0); map->b.setlist->setlist[count] = i; DPRINT(Debug,61,(&Debug," %d",map->b.setlist->setlist[count])); } DPRINT(Debug,61,(&Debug,"\n")); while (count < sizeof (map->b.setlist->setlist) / sizeof (map->b.setlist->setlist[0])) map->b.setlist->setlist[count++] = -1; } /* ASCII -------------------------------------------------------------- */ static void map_init_ASCII P_((struct map_info *map)); static void map_init_ASCII(map) struct map_info *map; { struct iso2022_setid *XX[2] = { NULL, NULL }; map -> b.setlist = safe_malloc(sizeof (* (map -> b.setlist))); XX[0] = ASCII_BANK; find_with_list(XX,map); map->map_initialized = 1; DPRINT(Debug,5,(&Debug, "Map %s (%s) initialized\n", map->map_name,map->map_type->type_name)); } struct map_info map_ISO2022_ascii = { &cs_iso2022, "US-ASCII", 0, map_init_ASCII, 0 }; struct map_info map_EUC_ascii = { &cs_euc, "US-ASCII", 0, map_init_ASCII, 0 }; /* ASCII / ISO-8859-1 ---------------------------------------------------- */ static void map_init_ASCII_latin1 P_((struct map_info *map)); static void map_init_ASCII_latin1(map) struct map_info *map; { struct iso2022_setid *XX[3] = { NULL, NULL, NULL }; map -> b.setlist = safe_malloc(sizeof (* (map -> b.setlist))); XX[0] = ASCII_BANK; XX[1] = LATIN1_BANK; find_with_list(XX,map); map->map_initialized = 1; DPRINT(Debug,5,(&Debug, "Map %s (%s) initialized\n", map->map_name,map->map_type->type_name)); } struct map_info map_ISO2022_ascii_latin1 = { &cs_iso2022, "ISO-8859-1", 0, map_init_ASCII_latin1, 0 }; struct map_info map_EUC_ascii_latin1 = { &cs_euc, "ISO-8859-1", 0, map_init_ASCII_latin1, 0 }; /* ====================================================================== */ #define CS_ISO2022_magic 0xF301 struct charset_type cs_iso2022; struct mb_data { unsigned short magic; /* CS_ISO2022_magic */ struct mb_data_part { int set_index; /* Refers to iso2022_info (struct setlist) ... -1 if control characters (also space with 94, 94x94 sets) -2 if bad iso2022 bank */ int iso2022_map_index; /* index to iso2022_map_list[] */ enum iso2022_settype type; /* iso2022_other for controls */ uint16 *words; /* range: 1 - 94 (bank 94) 0 - 95 (bank 96) 0 == 'space' 1 - (96*96)-1 (bank 94x94) 0 - (96*96)-1 (bank 96x96) 0 - 32,128-160 (if control) */ int word_count; } * parts; int part_count; }; #define STATE_ISO2022_magic 0xF302 /* NOTE: state_iso2022 is used for for input state struct display_settings is used for for output state */ struct state_iso2022 { unsigned short magic; /* STATE_ISO2022_magic */ enum iso2022_bank bank; /* initially bank_unspecified (-1), also bank_unspecified if control character (or perhaps space) */ struct { enum iso2022_settype type; int iso2022_info_index; /* index to iso2022_info (setlist) of charset -1 if not on list */ unsigned char bytes[ISO2022_SETID_LEN]; } banks[ISO2022_BANK_NUM]; enum iso2022_bank CL_bank; /* Bank for 32 - 127 */ enum iso2022_bank CR_bank; /* Bank for 160 - 255 */ /* raw_byte is used during parsing */ unsigned char raw_bytes[ISO2022_SETID_LEN + 4]; int raw_bytes_count; uint16 word; /* code position on gived bank / type */ }; #if ANSI_C #define S_(x) static x; #else #define S_(x) #endif static struct mb_data * alloc_mb_data P_((void)); static struct mb_data * alloc_mb_data() { struct mb_data *ret = safe_malloc(sizeof (* ret)); /* defined in hdrs/defs.h */ bzero((void *) ret, sizeof (* ret)); ret->magic = CS_ISO2022_magic; ret->parts = NULL; ret->part_count = 0; return ret; } S_(cs_init_string cs_init_iso2022_gen) static void cs_init_iso2022_gen(str) struct string *str; { str->p->len = 0; str->p->private_flag = 0; str->p->a.data = alloc_mb_data(); } static void free_parts P_((struct mb_data * X1)); static void free_parts(X1) struct mb_data * X1; { if (X1->parts) { int i; for (i = 0; i < X1->part_count; i++) { if (X1->parts[i].words) { free (X1->parts[i].words); X1->parts[i].words = NULL; } X1->parts[i].word_count = 0; } free(X1->parts); X1->parts = NULL; } X1->part_count = 0; } static void free_mb_data P_((struct mb_data ** ptr)); static void free_mb_data(ptr) struct mb_data **ptr; { if (*ptr) { if (CS_ISO2022_magic != (*ptr)->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"free_mb_data", "Bad magic number",0); free_parts(*ptr); (*ptr)->magic = 0; /* Invalidate magic */ /* defined in hdrs/defs.h */ bzero((void *) *ptr, sizeof (* (*ptr))); free(*ptr); *ptr = NULL; } } S_(cs_free_string cs_free_iso2022_gen) static void cs_free_iso2022_gen(str) struct string *str; { free_mb_data ( & (str->p->a.data)); str->p->len = 0; } static struct mb_data_part * get_part P_((struct mb_data * X1, int index, enum iso2022_settype type)); static struct mb_data_part * get_part(X1,index,type) struct mb_data * X1; int index; enum iso2022_settype type; { struct mb_data_part * X3 = NULL; if (X1->part_count < 1 || X1->parts[X1->part_count-1].set_index != index || X1->parts[X1->part_count-1].type != type) { X1->parts = safe_realloc(X1->parts, ( X1->part_count+1) * sizeof (X1->parts[0])); X1->parts[X1->part_count].set_index = index; X1->parts[X1->part_count].iso2022_map_index = -1; /* Filled later */ X1->parts[X1->part_count].type = type; X1->parts[X1->part_count].words = NULL; X1->parts[X1->part_count].word_count = 0; #ifdef DEBUG DPRINT(Debug,59,(&Debug, "get_part: %d: type=%d set_index=%d (new part)\n", X1->part_count,type,index)); #endif X1->part_count++; } X3 = & (X1->parts[X1->part_count-1] ); return X3; } static void fill_iso2022_map_index P_((struct setlist *iso2022_info, struct mb_data *X1, struct map_info *map)); static void fill_iso2022_map_index(iso2022_info,X1,map) struct setlist * iso2022_info; struct mb_data * X1; struct map_info *map; { int i; if (map -> map_type != &cs_iso2022 && map -> map_type != &cs_euc) { panic("ISO2022 PANIC",__FILE__,__LINE__,"fill_iso2022_map_index", "Bad map type",0); } if (!map->map_initialized) map->map_init_it(map); for (i = 0; i < X1->part_count; i++) { if (X1->parts[i].set_index >= 0 && -1 == X1->parts[i].iso2022_map_index) { if (X1->parts[i].set_index < sizeof (iso2022_info->sets) / sizeof (iso2022_info->sets[0]) && iso2022_info->sets[X1->parts[i].set_index]) { X1->parts[i].iso2022_map_index = give_iso2022_index(map->b.setlist->setlist, sizeof (map->b.setlist->setlist) / sizeof (map->b.setlist->setlist[0]), iso2022_info->sets[X1->parts[i]. set_index]); } else panic("ISO2022 PANIC",__FILE__,__LINE__, "fill_iso2022_map_index", "Bad data set_index",0); } } } static int find_index P_((struct setlist *list,enum iso2022_settype type, unsigned char bytes[ISO2022_SETID_LEN])); static int find_index(list,type,bytes) struct setlist *list; enum iso2022_settype type; unsigned char bytes[ISO2022_SETID_LEN]; { int i; for (i = 0; i < sizeof(list->sets) / sizeof(list->sets[0]); i++) { if (! list->sets[i]) break; if (type == list->sets[i]->type && 0 == memcmp(bytes,list->sets[i]->bytes,sizeof (list->sets[i]->bytes))) return i; } return -2; /* unknown */ } static int convert_index P_((int d_index, struct setlist *d_list, struct setlist *list,enum iso2022_settype type)); static int convert_index(d_index,d_list,list,type) int d_index; struct setlist *d_list; struct setlist *list; enum iso2022_settype type; { int index = -2; if (d_index >= 0 && d_index < sizeof (d_list->sets) / sizeof (d_list->sets[0]) && d_list->sets[d_index]) { unsigned char bytes[ISO2022_SETID_LEN]; if (type != d_list->sets[d_index]->type) panic("ISO2022 PANIC",__FILE__,__LINE__,"convert_index", "Bank type mismatch",0); if (sizeof(bytes) != sizeof(d_list->sets[d_index]->bytes)) panic("ISO2022 PANIC",__FILE__,__LINE__,"convert_index", "size mismatch on ISO2022_SETID",0); memcpy(bytes,d_list->sets[d_index]->bytes, sizeof(bytes)); index = find_index(list,type,bytes); } else panic("ISO2022 PANIC",__FILE__,__LINE__,"convert_index", "Bad data set_index",0); return index; } /* FIXME: This call should be replaced with more effective */ /* iso2022_word can not be uint16 becaus ethat causes error message about promotion */ static void add_iso2022_word P_((struct mb_data_part * X3, unsigned iso2022_word)); static void add_iso2022_word(X3,iso2022_word) struct mb_data_part * X3; unsigned iso2022_word; { X3->words = safe_realloc(X3->words, (X3->word_count+1) * sizeof (X3->words[0])); X3->words[X3->word_count++] = iso2022_word; } #ifdef DEBUG static void debug_iso2022_info_index P_((int level,int index, struct setlist *iso2022_info)); static void debug_iso2022_info_index(level, index,iso2022_info) int level; int index; struct setlist *iso2022_info; { if (index >= 0 && index < sizeof (iso2022_info->sets) / sizeof (iso2022_info->sets[0]) && iso2022_info->sets[index]) { char *x = iso2022_codestr(iso2022_info->sets[index]->bytes, sizeof (iso2022_info->sets[index])); DPRINT(Debug,level,(&Debug, "bank=%d type=%d", iso2022_info->sets[index]->bank, iso2022_info->sets[index]->type)); if (x) { DPRINT(Debug,level,(&Debug," bytes=%s",x)); free(x); } } } #endif static void iso2022_add_char P_((struct string *str, struct charset_state *state)); static void iso2022_add_char(str,state) struct string *str; struct charset_state *state; { int index = -1; enum iso2022_settype type = iso2022_other; struct state_iso2022 * X = state->p->a.iso2022; struct mb_data * X1 = str->p->a.data; struct mb_data_part * X3 = NULL, *debug_ptr; if (STATE_ISO2022_magic != X->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"iso2022_add_char", "Bad magic number (state)",0); if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"iso2022_add_char", "Bad magic number (string)",0); if (bank_unspecified == X->bank) { index = -1; type = iso2022_other; } else if (X->bank >= 0 && X->bank < ISO2022_BANK_NUM) { if (-1 == X->banks[X->bank].iso2022_info_index) { index = -2; /* BAD */ type = X->banks[X->bank].type; } else if (str->string_type->iso2022_info) { if (str->string_type != state->charset) { /* If different character set then we must search about bank */ if (state->charset->iso2022_info) { int d_index = X->banks[X->bank].iso2022_info_index; if (str->string_type->iso2022_info) index = convert_index (d_index, state->charset->iso2022_info, str->string_type->iso2022_info, type); else index = -2; /* Bad bank */ } else index = -2; /* Bad set */ } else { index = X->banks[X->bank].iso2022_info_index; /* Assume correct index */ if (index >= 0 && index < sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) && str->string_type->iso2022_info->sets[index]) { type = X->banks[X->bank].type; if (str->string_type->iso2022_info->sets[index]->type != X->banks[X->bank].type) panic("ISO2022 PANIC",__FILE__,__LINE__,"iso2022_add_char", "Bank type mismatch",0); } else panic("ISO2022 PANIC",__FILE__,__LINE__,"iso2022_add_char", "Bad iso2022_info_index",0); } } else { index = -2; /* Default: Bad bank */ type = X->banks[X->bank].type; } } else panic("ISO2022 PANIC",__FILE__,__LINE__,"iso2022_add_char", "Bad bank number",0); debug_ptr = NULL; if (X1->part_count > 0) debug_ptr = & (X1->parts[X1->part_count-1]); X3 = get_part(X1,index,type); #ifdef DEBUG if (Debug.active > 58 && X3 != debug_ptr) { DPRINT(Debug,59,(&Debug, "iso2022_add_char: %d: type=%d set_index=%d <", X1->part_count-1, type, index)); if (str->string_type->iso2022_info) debug_iso2022_info_index(59,index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); } #endif add_iso2022_word(X3, X->word); str->p->len++; } /* sets state to be ready and pops raw_byte, 1 if popped does not parse escape sequences */ static int streambyte_make_code_1 P_((struct charset_state *st, enum iso2022_bank single_shift_bank)); static int streambyte_make_code_1(st,single_shift_bank) struct charset_state *st; enum iso2022_bank single_shift_bank; { struct state_iso2022 * X = st->p->a.iso2022; unsigned char ch1; int upper; enum iso2022_bank bank; if (X->raw_bytes_count < 1) return 0; /* raw_bytes is unsigned */ if (X->raw_bytes[0] < 32) { goto add_control; } upper = X->raw_bytes[0] & 128; ch1 = X->raw_bytes[0] & 127; if (single_shift_bank >= 0) /* Normally left, but EUC uses rigth bank */ bank = single_shift_bank; else bank = upper ? X->CR_bank : X->CL_bank; if (ch1 > 32 && ch1 < 127 && bank >= 0 && bank < ISO2022_BANK_NUM && iso2022_94 == X->banks[bank].type) { X->bank = bank; X->word = ISO2022_1byte_to_word(ch1); X->raw_bytes_count--; if (X->raw_bytes_count > 0) memmove(X->raw_bytes, X->raw_bytes+1, X->raw_bytes_count); DPRINT(Debug,61,(&Debug, "got [94] bank=%d ISO2022 word=%02x ch=%c upper=%d\n", X->bank,X->word, ch1,upper)); st->p->ready = 1; return 1; } if (ch1 >= 32 && bank >= 0 && bank < ISO2022_BANK_NUM && iso2022_96 == X->banks[bank].type) { X->bank = bank; X->word = ISO2022_1byte_to_word(ch1); X->raw_bytes_count--; if (X->raw_bytes_count > 0) memmove(X->raw_bytes, X->raw_bytes+1, X->raw_bytes_count); DPRINT(Debug,61,(&Debug, "got [96] bank=%d ISO2022 word=%02x ch=%c upper=%d\n", X->bank,X->word, ch1,upper)); st->p->ready = 1; return 1; } if (X->raw_bytes_count > 1) { unsigned char ch2; if (upper != X->raw_bytes[1] & 128) { /* BAD */ goto add_control; } ch2 = X->raw_bytes[1] & 127; if (ch1 > 32 && ch1 < 127 && ch2 > 32 && ch2 < 127 && bank >= 0 && bank < ISO2022_BANK_NUM && iso2022_94x94 == X->banks[bank].type) { X->bank = bank; X->word = ISO2022_2byte_to_word(ch1,ch2); X->raw_bytes_count -= 2; if (X->raw_bytes_count > 0) memmove(X->raw_bytes, X->raw_bytes+2, X->raw_bytes_count); DPRINT(Debug,61,(&Debug, "got [94x94] bank=%d ISO2022 word=%04x ch=%c%c upper=%d\n", X->bank,X->word, ch1,ch2,upper)); st->p->ready = 1; return 1; } if (ch1 >= 32 && ch2 >= 32 && bank >= 0 && bank < ISO2022_BANK_NUM && iso2022_96x96 == X->banks[bank].type) { X->bank = bank; X->word = ISO2022_2byte_to_word(ch1,ch2); X->raw_bytes_count -= 2; if (X->raw_bytes_count > 0) memmove(X->raw_bytes, X->raw_bytes+2, X->raw_bytes_count); DPRINT(Debug,61,(&Debug, "got [96x96] bank=%d ISO2022 word=%04x ch=%c%c upper=%d\n", X->bank,X->word, ch1,ch2,upper)); st->p->ready = 1; return 1; } } if (bank >= 0 && bank < ISO2022_BANK_NUM && (iso2022_96x96 == X->banks[bank].type || iso2022_94x94 == X->banks[bank].type) && X->raw_bytes_count < 2) { return 0; } /* This is not really supported because we do not know number of bytes per characters */ if (bank >= 0 && bank < ISO2022_BANK_NUM && iso2022_other == X->banks[bank].type) { /* Like controls */ X->bank = bank; X->word = X->raw_bytes[0]; X->raw_bytes_count--; if (X->raw_bytes_count > 0) memmove(X->raw_bytes, X->raw_bytes+1, X->raw_bytes_count); DPRINT(Debug,61,(&Debug, "got [other] bank=%d ISO2022 word=%02x\n", X->bank,X->word)); st->p->ready = 1; return 1; } add_control: X->bank = bank_unspecified; X->word = X->raw_bytes[0]; X->raw_bytes_count--; if (X->raw_bytes_count > 0) memmove(X->raw_bytes, X->raw_bytes+1, X->raw_bytes_count); DPRINT(Debug,61,(&Debug, "got [ctrl] bank=%d ISO2022 word=%02x\n", X->bank,X->word)); st->p->ready = 1; return 1; } /* 0 == overflow or bad char, 1 == OK */ static int state_add_raw P_((struct state_iso2022 * X , int ch)); static int state_add_raw(X,ch) struct state_iso2022 * X; int ch; { if (ch < 0 || ch > 0xFF) panic("ISO2022 PANIC",__FILE__,__LINE__, "state_add_raw", "Value not in range 0-255",0); if (X->raw_bytes_count >= sizeof (X->raw_bytes)) { DPRINT(Debug,4,(&Debug, "state_add_raw: Overlow (already %d bytes)\n", X->raw_bytes_count)); return 0; /* Overflow */ } X->raw_bytes[X->raw_bytes_count++] = ch; /* store it */ return 1; } /* -1 == not enough 0 == not ok 1 == processed */ static int streambyte_make_code_2 P_((struct charset_state *st, struct state_iso2022 * X)); static int streambyte_make_code_2(st,X) struct charset_state *st; struct state_iso2022 * X; { int T; if (X->raw_bytes_count < 1) { DPRINT(Debug,1,(&Debug, "streambyte_make_code_2: len=%d\n", X->raw_bytes_count)); return -1; } T = X->raw_bytes[0] & 127; if (T < 32) { /* Is on control area ... ( 0 - 31 or 128 - 159) */ enum iso2022_bank Bank; enum shift_mode LR; struct iso2022_setid Setid; int l; /* Try then if this is bank switch */ l = eat_iso2022_bank_switch(&Bank,&LR, X->raw_bytes, X->raw_bytes_count); if (l > 0) { char buffer[sizeof (X->raw_bytes)]; int buffer_len; /* For backup of single-shift */ memcpy(buffer,X->raw_bytes,X->raw_bytes_count); buffer_len = X->raw_bytes_count; X->raw_bytes_count -= l; if (X->raw_bytes_count > 0) memmove(X->raw_bytes, X->raw_bytes+l, X->raw_bytes_count); switch (LR) { case lock_shift_left: X->CL_bank = Bank; DPRINT(Debug,61,(&Debug, "got bank shift lower bank=%d\n", X->CL_bank)); break; case lock_shift_right: X->CR_bank = Bank; DPRINT(Debug,61,(&Debug, "got bank shift upper bank=%d\n", X->CR_bank)); break; case single_shift: DPRINT(Debug,61,(&Debug, "looking for single shift .. bank=%d\n", Bank)); if (streambyte_make_code_1(st,Bank) > 0) break; /* OK */ memcpy(X->raw_bytes,buffer,buffer_len); X->raw_bytes_count = buffer_len; DPRINT(Debug,8,(&Debug, "streambyte_make_code_2: single shift not complete (len=%d)\n", buffer_len)); return -1; } return 1; /* try eat next code */ } if (l < 0) { DPRINT(Debug,8,(&Debug, "streambyte_make_code_2: incomplete bank switch (len=%d)\n", X->raw_bytes_count)); return -1; } /* Try then if this is setid */ l = eat_iso2022_setid(&Setid,X->raw_bytes,X->raw_bytes_count); if (l > 0) { if (Setid.bank >= 0 && Setid.bank < ISO2022_BANK_NUM) { X->banks[Setid.bank].type = Setid.type; memcpy(X->banks[Setid.bank].bytes, Setid.bytes,sizeof X->banks[Setid.bank].bytes); DPRINT(Debug,61,(&Debug, "got bank %d type=%d bytes=%.*s\n", Setid.bank, X->banks[Setid.bank].type, sizeof X->banks[Setid.bank].bytes, X->banks[Setid.bank].bytes)); X->banks[Setid.bank].iso2022_info_index = find_index(st->charset->iso2022_info, X->banks[Setid.bank].type, X->banks[Setid.bank].bytes); if ( X->banks[Setid.bank].iso2022_info_index < 0) { X->banks[Setid.bank].iso2022_info_index = -1; DPRINT(Debug,8,(&Debug, "streambyte_make_code_2: setid is not part of charset\n")); } DPRINT(Debug,61,(&Debug, " ... iso2022_info_index %d\n", X->banks[Setid.bank].iso2022_info_index)); X->raw_bytes_count -= l; if (X->raw_bytes_count > 0) memmove(X->raw_bytes, X->raw_bytes+l, X->raw_bytes_count); return 1; /* try eat next code */ } DPRINT(Debug,8,(&Debug, "streambyte_make_code_2: bad bank %d on setid\n", Setid.bank)); } if (l < 0) { DPRINT(Debug,8,(&Debug, "streambyte_make_code_2: incomplete setting of bank (setid, len=%d)\n", X->raw_bytes_count)); return -1; } } if (!streambyte_make_code_1(st,bank_unspecified)) { DPRINT(Debug,8,(&Debug, "streambyte_make_code_2: Incomplete character (len=%d)\n", X->raw_bytes_count)); return -1; } return 1; } static void cs_soft_reset_s_iso2022_gen P_((struct charset_state *str)); S_(cs_add_streambyte_to_string cs_add_streambyte_to_iso2022_gen) static int cs_add_streambyte_to_iso2022_gen(str,ch) struct string *str; int ch; { int c; struct state_iso2022 * X ; if (!str->p->state) str->p->state = new_state_1(str->string_type); if (str->p->state->charset != str->string_type) panic("STRING PANIC",__FILE__,__LINE__,"cs_add_streambyte_to_iso2022_gen", "Bad state",0); X = str->p->state->p->a.iso2022; if (STATE_ISO2022_magic != X->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_add_streambyte_to_iso2022_gen", "Bad magic number (state)",0); if (X->raw_bytes_count > 0) { DPRINT(Debug,8,(&Debug, "cs_add_streambyte_to_iso2022: %d bytes already\n", X->raw_bytes_count)); /* Try first read extra characters from buffer */ if (streambyte_make_code_2(str->p->state,X) > 0) { if (str->p->state->p->ready) { /* Got it */ iso2022_add_char(str,str->p->state); cs_soft_reset_s_iso2022_gen(str->p->state); } } } if (!state_add_raw(X,ch)) { DPRINT(Debug,8,(&Debug, "cs_add_streambyte_to_iso2022_gen: failed to add code\n")); return 0; } while ((c = streambyte_make_code_2(str->p->state,X)) > 0) { /* Handle case where several characters generated */ if (str->p->state->p->ready) { /* Got it */ iso2022_add_char(str,str->p->state); cs_soft_reset_s_iso2022_gen(str->p->state); } } if (0 == c) { DPRINT(Debug,8,(&Debug, "cs_add_streambyte_to_iso2022_gen: failed to parse code\n")); return 0; } return 1; } S_(cs_add_intdata_to_string cs_add_intdata_to_iso2022_gen) static void cs_add_intdata_to_iso2022_gen(str,data) struct string *str; CONST struct string *data; { int i; struct mb_data * X1 = str->p->a.data; struct mb_data * Xd = data->p->a.data; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_add_intdata_to_iso2022_gen", "Bad magic number (string)",0); if (CS_ISO2022_magic != Xd->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_add_intdata_to_iso2022_gen", "Bad magic number (data string)",0); for (i = 0; i < Xd->part_count; i++) { int index = -1; enum iso2022_settype type = Xd->parts[i].type; struct mb_data_part * X3 = NULL, *debug_ptr; int j; #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_add_intdata_to_iso2022_gen: %d: type=%d set_index=%d <", i,type, Xd->parts[i].set_index)); if (Debug.active > 58 && data->string_type->iso2022_info) debug_iso2022_info_index(59,Xd->parts[i].set_index, data->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,"> (source)\n")); #endif if (-1 == Xd->parts[i].set_index) { index = -1; if (iso2022_other != type) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_add_intdata_to_iso2022_gen", "Bad type for control data",0); } else if (-2 == Xd->parts[i].set_index) { index = -2; /* bad iso2022 bank */ } else { index = -2; /* bad iso2022 bank */ if (data->string_type->iso2022_info) { int d_index = Xd->parts[i].set_index; if (str->string_type->iso2022_info) index = convert_index(d_index,data->string_type->iso2022_info, str->string_type->iso2022_info,type); else index = -2; /* Bad bank */ } else index = -2; /* bad iso2022 bank */ } if (Xd->parts[i].word_count < 1) continue; /* OOPS -- nothing to do */ debug_ptr = NULL; if (X1->part_count > 0) debug_ptr = & (X1->parts[X1->part_count-1]); X3 = get_part(X1,index,type); #ifdef DEBUG if (Debug.active > 58 && X3 != debug_ptr) { DPRINT(Debug,59,(&Debug, "cs_add_intdata_to_iso2022_gen: %d: type=%d set_index=%d <", X1->part_count-1, type, index)); if (str->string_type->iso2022_info) debug_iso2022_info_index(59,index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,"> (target)\n")); } #endif X3->words = safe_realloc(X3->words, (X3->word_count + Xd->parts[i].word_count) * sizeof (X3->words[0])); for (j = 0; j < Xd->parts[i].word_count; j++) X3->words[X3->word_count++] = Xd->parts[i].words[j]; str->p->len += Xd->parts[i].word_count; } } /* Does compression, recalculation and so on ... so 'const' is not very const */ S_(cs_check_length_string cs_check_length_iso2022_gen) static void cs_check_length_iso2022_gen(str) CONST struct string *str; { int len = 0; int i; struct mb_data * X1 = str->p->a.data; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_check_length_iso2022_gen", "Bad magic number (string)",0); for (i = 0; i < X1->part_count; i++) { len += X1->parts[i].word_count; } if (len != str->p->len) { DPRINT(Debug,6,(&Debug, "cs_check_length_iso2022_gen: Fixing length %d => %d\n", str->p->len,len)); str->p->len = len; } } /* Returns 1 if position exists */ static int pos_to_block P_((struct mb_data * X1, int pos, int *block_number, int *block_index)); static int pos_to_block(X1,pos,block_number,block_index) struct mb_data * X1; int pos; int *block_number; int *block_index; { *block_number = 0; *block_index = pos; while (*block_number < X1->part_count && X1->parts[*block_number].word_count <= *block_index) { *block_index -= X1->parts[*block_number].word_count; (*block_number)++; } if (*block_number >= X1->part_count || *block_index >= X1->parts[*block_number].word_count) return 0; DPRINT(Debug,61,(&Debug, " pos=%d => block/index=%d/%d\n", pos,*block_number,*block_index)); return 1; } S_(cs_give_unicode_from_string cs_give_unicode_from_iso2022_gen) static uint16 cs_give_unicode_from_iso2022_gen(str,pos,found) CONST struct string *str; int pos; int *found; { struct mb_data * X1 = str->p->a.data; int block_number = 0; int block_index = pos; uint16 code; int set_index; /* Refers to iso2022_info (struct setlist) ... -1 if control characters (also space with 94, 94x94 sets) -2 if bad iso2022 bank */ enum iso2022_settype type; /* iso2022_other for controls */ uint16 ret; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_give_unicode_from_iso2022_gen", "Bad magic number (string)",0); if (pos < 0 || pos >= str->p->len) panic("STRING PANIC",__FILE__,__LINE__,"cs_give_unicode_from_iso2022_gen", "Index out of array",0); if (!pos_to_block(X1,pos,&block_number,&block_index)) panic("STRING PANIC",__FILE__,__LINE__,"cs_give_unicode_from_iso2022_gen", "Index position not found",0); /* Fill indexes if current not filled */ if (-1 == X1->parts[block_number].iso2022_map_index && str->string_type->map_info && str->string_type->iso2022_info) fill_iso2022_map_index(str->string_type->iso2022_info, X1, str->string_type->map_info); code = X1->parts[block_number].words[block_index]; set_index = X1->parts[block_number].set_index; type = X1->parts[block_number].type; *found = 0; ret = 0x003F; /* '?' */ if (-1 == set_index) { /* Controls maps to unicode directly */ if (iso2022_other != type) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_give_unicode_from_iso2022_gen", "Type is not iso2022_other for controls",0); ret = code; *found = 1; } else { int iso2022_map_index; /* index to iso2022_map_list[] */ iso2022_map_index = X1->parts[block_number].iso2022_map_index; if (-1 != iso2022_map_index) *found = map_ISO2022_word_to_unicode(code,type,iso2022_map_index, &ret); else { DPRINT(Debug,62,(&Debug, "pos %d -- block/index=%d/%d (code %04x set_index %d type %d) -- no iso2022_map_index\n", pos,block_number,block_index,code,set_index,type)); } } return ret; } static int map_unicode_to_ISO2022_word P_((unsigned unicode, struct setlist * iso2022_info, int * index, enum iso2022_settype * type, uint16 * iso2022_word, struct map_info *map)); static int map_unicode_to_ISO2022_word(unicode,iso2022_info, iso2022_info_index, type,iso2022_word, map) unsigned unicode; struct setlist * iso2022_info; int * iso2022_info_index; enum iso2022_settype * type; uint16 * iso2022_word; struct map_info * map; { int found = 0; int i; *iso2022_info_index = -3; /* MARKER !!!!!!! */ for (i = 0; i < sizeof (iso2022_info->sets) / sizeof (iso2022_info->sets[0]); i++) { if (iso2022_info->sets[i]) { /* (space (32) and del (127) with 94, 94x94 sets is on control area ... */ if ((iso2022_94 == iso2022_info->sets[i]->type || iso2022_94x94 == iso2022_info->sets[i]->type) && ( 32 == unicode || 127 == unicode)) { *iso2022_info_index = -1; /* Control area */ *iso2022_word = unicode; *type = iso2022_other; /* we do not use iso2022_94 hre, because we interpret word as character 32-127 then */ found = 1; break; } } } if (!found && map) { int s; if (map -> map_type != &cs_iso2022 && map -> map_type != &cs_euc) panic("ISO2022 PANIC",__FILE__,__LINE__, "map_unicode_to_ISO2022_word", "Bad map type",0); if (!map->map_initialized) map->map_init_it(map); for (s = 0; s < sizeof (map->b.setlist->setlist) / sizeof (map->b.setlist->setlist[0]); s++) { int iso2022_map_index = map->b.setlist->setlist[s]; if (-1 != iso2022_map_index && map_unicode_to_ISO2022_word_1(unicode,type,iso2022_map_index, iso2022_word)) { DPRINT(Debug,52,(&Debug, "map_unicode_to_ISO2022_word: %04x => iso2022_map_index=%d (setlist %d), type=%d word=%04x\n", unicode,iso2022_map_index,s,*type,*iso2022_word)); /* Search iso2022_info_index */ *iso2022_info_index = -2; /* bad iso2022 bank */ if (iso2022_info) { unsigned char bytes[ISO2022_SETID_LEN]; fill_iso2022_map_setlist_bytes(iso2022_map_index,*type,bytes, sizeof bytes); *iso2022_info_index = find_index(iso2022_info,*type,bytes); } found = 1; break; } } } if (!found) { /* Not actually used ... */ *iso2022_info_index = -2; /* Bad bank */ *iso2022_word = unicode; *type = iso2022_other; /* we do not use iso2022_94 here, because we interpret word as character 32-127 then */ } DPRINT(Debug,52,(&Debug, "map_unicode_to_ISO2022_word=%d: %04x %s == iso2022_info_index %d, type=%d word=%04x\n", found, unicode, found ? "FOUND" : "NOT FOUND", *iso2022_info_index, *type, *iso2022_word)); return found; } S_(cs_add_unicodedata_to_string cs_add_unicodedata_to_iso2022_gen) static void cs_add_unicodedata_to_iso2022_gen(str,len,data) struct string *str; int len; CONST uint16 *data; { int i; struct mb_data * X1 = str->p->a.data; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_add_unicodedata_to_iso2022_gen", "Bad magic number (string)",0); /* TODO: This should be optimized */ for (i = 0; i < len; i++) { /* Values < 32 are on control block and also correspond 8-bit values */ if (data[i] < 32 || data[i] > 127 && data[i] < 160 ) { struct mb_data_part * X3 = get_part(X1,-1,iso2022_other); add_iso2022_word(X3, data[i]); str->p->len++; } else { int index; enum iso2022_settype type; uint16 iso2022_word; struct mb_data_part * X3, *debug_ptr; /* map_unicode_to_ISO2022_word() also puts 32 and 127 to control area if needed */ if (! str->string_type->iso2022_info || ! map_unicode_to_ISO2022_word(data[i], str->string_type->iso2022_info, &index,&type,&iso2022_word, str->string_type->map_info )) { /* Put as bad data ... add_char1_stream() will print that as question mark */ index = -2; /* Bad bank */ type = iso2022_other; /* Also controls */ iso2022_word = data[i]; } debug_ptr = NULL; if (X1->part_count > 0) debug_ptr = & (X1->parts[X1->part_count-1]); X3 = get_part(X1,index,type); #ifdef DEBUG if (Debug.active > 58 && X3 != debug_ptr) { DPRINT(Debug,59,(&Debug, "cs_add_unicodedata_to_iso2022_gen: %d: type=%d set_index=%d <", X1->part_count-1, type, index)); if (str->string_type->iso2022_info) debug_iso2022_info_index(59,index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); } #endif add_iso2022_word(X3,iso2022_word); str->p->len++; } } } S_(cs_cmp_string cs_cmp_iso2022_gen) static int cs_cmp_iso2022_gen(str1,str2) CONST struct string *str1; CONST struct string *str2; { struct mb_data * X1 = str1->p->a.data; struct mb_data * X2 = str1->p->a.data; int i; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_cmp_iso2022_gen", "Bad magic number (string 1)",0); if (CS_ISO2022_magic != X2->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_cmp_iso2022_gen", "Bad magic number (string 2)",0); for (i = 0; i < X1->part_count && i < X2->part_count; i++) { int j; for (j = 0; j < X1->parts[i].word_count && j < X1->parts[i].word_count; j++) { if (X1->parts[i].words[j] < X2->parts[i].words[j]) return -1; if (X1->parts[i].words[j] > X2->parts[i].words[j]) return 1; } /* not necessary correct */ if (j < X1->parts[i].word_count) return 1; if (j < X2->parts[i].word_count) return -1; } if (i < X1->part_count) return 1; if (i < X2->part_count) return -1; return 0; } static void add_bytes_stream P_((unsigned char **ret, int *len, int *alloced, unsigned char *c, int l)); static void add_bytes_stream(ret,len,alloced,c,l) unsigned char **ret; int *len; int *alloced; unsigned char *c; int l; { if (*alloced < *len + l) { *alloced = *len + l + 15; *ret = safe_realloc(*ret,*alloced); } memcpy((*ret)+(*len),c,l); *len += l; } static int select_upper_lower P_((unsigned char **ret, int *len, int *alloced, struct iso2022_setid *ID, screen_info_p output_state, int *width)); static int select_upper_lower(ret,len,alloced,ID,output_state,width) unsigned char **ret; int *len; int *alloced; struct iso2022_setid *ID; screen_info_p output_state; int *width; { int is_upper = 0; int setpos = iso2022_give_setpos(ID,output_state); int printit = 0; if (-1 == setpos) { char * c; if (output_state->set_count < sizeof (output_state->sets) / sizeof (output_state->sets[0])) { setpos = output_state->set_count++; } else if (iso2022_94 == ID->type) { setpos = 0; DPRINT(Debug,7,(&Debug, "select_upper_lower: Too many sets on output state, replacing set %d\n", setpos)); printit++; } else { setpos = 1; DPRINT(Debug,7,(&Debug, "select_upper_lower: Too many sets on output state, replacing set %d\n", setpos)); printit++; } output_state->sets[setpos] = *ID; output_state->width[setpos] = -1; /* No terminal information so no width */ DPRINT(Debug,58,(&Debug, "select_upper_lower: set %d selected\n", setpos)); /* iso2022_change_helper_1 does both iso2022_setid_stream() and lock_shift(), but does nothing if bank is already occupied. This function sets output_state->bank[ID->bank] = setpos; */ c = iso2022_change_helper_1(output_state,*ID,setpos,NULL,0); if (c) { int l = strlen(c); add_bytes_stream(ret,len,alloced,s2us(c),l); #ifdef DEBUG { int x; DPRINT(Debug,58,(&Debug, "select_upper_lower: Setting %d to bank %d: ", setpos,ID->bank)); for (x = 0; x < l; x++) { DPRINT(Debug,58,(&Debug," %02x",c[x])); } DPRINT(Debug,58,(&Debug,"\n")); } if (Debug.active > 57) printit++; #endif free(c); } } /* If on bank have currently other set selected, change it */ if (ID->bank != bank_unspecified && output_state->bank[ID->bank] != setpos) { char * c; output_state->bank[ID->bank] = -1; /* Forget previous assignment */ c = iso2022_setid_stream(*ID,NULL,0); if (c) { int l = strlen(c); /* iso2022_setid_stream() does not set this */ output_state->bank[ID->bank] = setpos; add_bytes_stream(ret,len,alloced,s2us(c),l); #ifdef DEBUG { int x; DPRINT(Debug,58,(&Debug, "select_upper_lower: Changing %d to bank %d: ", setpos,ID->bank)); for (x = 0; x < l; x++) { DPRINT(Debug,58,(&Debug," %02x",c[x])); } DPRINT(Debug,58,(&Debug," (width %d)\n", output_state->width[setpos] )); if (Debug.active > 57) printit++; } #endif free(c); } } if (output_state->current_L == ID->bank) is_upper = 0; else if (output_state->current_R == ID->bank) is_upper = 1; else { /* If either left nor right is selected for this bank currently, select left bank because iso2022 sets are usually 7-bit only */ char buffer1[10]; char * c; is_upper = 0; output_state->current_L = ID->bank; c = lock_shift(is_upper,output_state->current_L, buffer1,sizeof buffer1); if (c) { int l = strlen(c); add_bytes_stream(ret,len,alloced,s2us(c),l); #ifdef DEBUG { int x; DPRINT(Debug,58,(&Debug, "select_upper_lower: setting %s to bank %d: ", is_upper ? "upper" : "lower", setpos)); for (x = 0; x < l; x++) { DPRINT(Debug,58,(&Debug," %02x",c[x])); } DPRINT(Debug,58,(&Debug,"\n")); if (Debug.active > 57) printit++; } #endif } } if (printit) debug_display_settings(output_state,0,1); *width = output_state->width[setpos]; return is_upper; } static void add_char_stream_helper P_((unsigned char **ret, int *len, int *alloced, unsigned char *temp, int temp_l, int temp_size, enum iso2022_settype type, unsigned iso2022_word, int is_upper )); static void add_char_stream_helper(ret,len,alloced,temp,temp_l,temp_size,type, iso2022_word,is_upper) unsigned char **ret; int *len; int *alloced; unsigned char *temp; int temp_l; int temp_size; enum iso2022_settype type; unsigned iso2022_word; int is_upper; { switch(type) { case iso2022_94: if (iso2022_word < 1 || iso2022_word > 94) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream_helper", "Bad iso2022_94 character",0); /* FALLTHRU */ case iso2022_96: if (iso2022_word > 95) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream_helper", "Bad iso2022_96 character",0); if (temp_l+1 > temp_size) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream_helper", "Overflow",0); temp[temp_l++] = iso2022_word + 32 + (is_upper ? 128 : 0); DPRINT(Debug,63,(&Debug, "add_char_stream_helper: Adding 1-byte: %02x (%s) [iso2022_word %04x]\n", temp[temp_l-1], is_upper ? "upper" : "lower", iso2022_word )); add_bytes_stream(ret,len,alloced,temp,temp_l); break; case iso2022_94x94: case iso2022_96x96: if (iso2022_word > 96*96-1) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream_helper", "Bad iso2022_94x94 or iso2022_96x96 character",0); if (temp_l+2 > temp_size) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream_helper", "Overflow",0); temp[temp_l++] = iso2022_word/96 + 32 + (is_upper ? 128 : 0); temp[temp_l++] = iso2022_word%96 + 32 + (is_upper ? 128 : 0); DPRINT(Debug,63,(&Debug, "add_char_stream_helper: Adding 2-byte: %02x %02x (%s) [iso2022_word %04x]\n", temp[temp_l-2],temp[temp_l-1], is_upper ? "upper" : "lower", iso2022_word)); add_bytes_stream(ret,len,alloced,temp,temp_l); break; case iso2022_other: if (iso2022_word < 256) { if (temp_l+1 > temp_size) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream_helper", "Overflow",0); temp[temp_l++] = iso2022_word; /* Not actually work correctly */ DPRINT(Debug,63,(&Debug, "add_char_stream_helper: Adding other: %02x [iso2022_word %04x]\n", temp[temp_l-1], iso2022_word)); add_bytes_stream(ret,len,alloced,temp,temp_l); break; } /* FALLTHRU */ default: panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream_helper", "Unsupported iso2022 settype",0); } } /* iso2022_word can't be uint16 because that causes error messages about promotion ... */ typedef int add_char_stream_t P_((unsigned char **ret, int *len, int *alloced, struct iso2022_setid *set, screen_info_p output_state, unsigned iso2022_word, struct iso2022_setid *ctrlset, struct cs_printable_len *printable_len)); /* Return 0 if overflow printable_len else 1 */ S_(add_char_stream_t add_char_stream_euc) static int add_char_stream_euc(ret,len,alloced,set, output_state,iso2022_word, ctrlset,printable_len) unsigned char **ret; int *len; int *alloced; struct iso2022_setid *set; /* NULL, if control characters */ screen_info_p output_state; unsigned iso2022_word; struct iso2022_setid *ctrlset; /* 'set' used when outputing control characters */ struct cs_printable_len *printable_len; { int width = -1; enum iso2022_bank bank = bank_unspecified; struct iso2022_setid ID; if (set) { int i; ID = *set; i = iso2022_give_setpos(&ID,output_state); bank = ID.bank; if (i < 0 || bank_unspecified == bank) { /* BAD */ DPRINT(Debug,9,(&Debug, "add_char_stream_euc: Bad bank or set? (printing space instead)\n")); iso2022_word = 32; set = NULL; goto restart; } width = output_state->width[i]; } else { /* iso2022_word is character itself */ restart: if (32 == iso2022_word) { /* SPACE */ width = 1; } else { /* Control characters have no width */ width = 0; } } if (printable_len && width < 0) { DPRINT(Debug,9,(&Debug, "add_char_stream_euc: Can't print character because width is not available (printing space instead) [width=%d]\n", width)); iso2022_word = 32; set = NULL; goto restart; } if (printable_len && printable_len->max_len < printable_len->ret_len + width) { DPRINT(Debug,9,(&Debug, "add_char_stream_euc: No space for character ret_len=%d width=%d max_len=%d\n", printable_len->ret_len,width,printable_len->max_len)); return 0; } if (set) { int l = 0; unsigned char temp[5]; int is_upper = -1; if (bank == bank_unspecified) { DPRINT(Debug,9,(&Debug, "add_char_stream_euc: No bank (printing space instead)\n")); iso2022_word = 32; set = NULL; goto restart; } if (bank == output_state->current_L) is_upper = 0; else if (bank == output_state->current_R) is_upper = 1; else { is_upper = 1; if ((l = do_single_shift(temp,sizeof temp,bank,is_upper)) < 1) { DPRINT(Debug,9,(&Debug, "add_char_stream_euc: Can't single shift to bank %d (printing space instead), ret=%d\n", bank,l)); iso2022_word = 32; set = NULL; goto restart; } } add_char_stream_helper(ret,len,alloced, temp,l,sizeof temp,ID.type, iso2022_word,is_upper); } else { unsigned char temp[1]; /* We are printing control characters or space iso2022_word is character itself -- BAD characters are also stored as control characters therefore all codes between 0 - 255 are possible. */ if (iso2022_word > 255) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream_euc", "Bad control character",0); temp[0] = iso2022_word; DPRINT(Debug,63,(&Debug, "add_char_stream_euc: Adding ctrl: %02x [iso2022_word %04x]\n", temp[0],iso2022_word)); add_bytes_stream(ret,len,alloced,temp,1); } if (printable_len) printable_len->ret_len += width; return 1; } /* Return 0 if overflow printable_len else 1 */ S_(add_char_stream_t add_char_stream) static int add_char_stream(ret,len,alloced,set, output_state,iso2022_word, ctrlset,printable_len) unsigned char **ret; int *len; int *alloced; struct iso2022_setid *set; /* NULL, if control characters */ screen_info_p output_state; unsigned iso2022_word; struct iso2022_setid *ctrlset; /* 'set' used when outputing control characters */ struct cs_printable_len *printable_len; { int is_upper; struct iso2022_setid ID; int have_id; int width; restart: have_id = 0; is_upper = 0; ID.bank = bank_unspecified; ID.type = iso2022_other; if (!set) { /* If set is NULL, then we have ouputting control characters (or space). Most ISO-2022-x mime sets require that we switch ascii before outputting control characters (or space) -- in that case iso2022_word is control character itself. */ /* ASCII must be first set declared so that works correctly */ if (ctrlset) { ID = *ctrlset; /* ASCII? */ have_id++; } } else { ID = *set; have_id++; } width = 1; if (have_id) is_upper = select_upper_lower(ret,len,alloced,&ID,output_state,&width); if (!set) { /* iso2022_word is character itself */ if (32 == iso2022_word) { /* SPACE */ if (width < 1) width = 1; } else { /* COntrol characters have no width */ width = 0; } } if (printable_len && width < 0) { DPRINT(Debug,9,(&Debug, "add_char_stream: Can't print character because width is not available (printing space instead) [width=%d]\n", width)); iso2022_word = 32; set = NULL; goto restart; } if (printable_len && printable_len->max_len < printable_len->ret_len + width) { DPRINT(Debug,9,(&Debug, "add_char_stream: No space for character ret_len=%d width=%d max_len=%d\n", printable_len->ret_len,width,printable_len->max_len)); return 0; } if (!set) { unsigned char temp[1]; /* We are printing control characters or space iso2022_word is character itself -- BAD characters are also stored as control characters therefore all codes between 0 - 255 are possible. */ if (iso2022_word > 255) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream", "Bad control character",0); temp[0] = iso2022_word; DPRINT(Debug,63,(&Debug, "add_char_stream: Adding ctrl: %02x [iso2022_word %04x]\n", temp[0],iso2022_word)); add_bytes_stream(ret,len,alloced,temp,1); } else if (!have_id) panic("STRING PANIC",__FILE__,__LINE__,"add_char_stream", "have_id is not set",0); else { unsigned char temp[2]; add_char_stream_helper(ret,len,alloced, temp,0,sizeof temp,ID.type, iso2022_word,is_upper); } if (printable_len) printable_len->ret_len += width; return 1; } /* Find ASCII bank (or other similar) */ static struct iso2022_setid *find_ctrlset P_((struct setlist * iso2022_info)); static struct iso2022_setid *find_ctrlset(iso2022_info) struct setlist * iso2022_info; { int i; struct iso2022_setid *ctrlset = NULL; for (i = 0; i < sizeof (iso2022_info->sets) / sizeof (iso2022_info->sets[0]); i++) { if (iso2022_info->sets[i]) { /* Find ASCII bank (or other similar) */ if (iso2022_94 == iso2022_info->sets[i]->type && bank_G0 == iso2022_info->sets[i]->bank) { ctrlset = iso2022_info->sets[i]; break; } } } return ctrlset; } typedef void charset_reset_routine P_((unsigned char **ret, int *len, int *alloced, screen_info_p output_state, struct setlist * iso2022_info)); S_(charset_reset_routine reset_iso2022) static void reset_iso2022(ret,len,alloced,output_state,iso2022_info) unsigned char **ret; int *len; int *alloced; screen_info_p output_state; struct setlist * iso2022_info; { int i; output_state->current_L = bank_unspecified; output_state->current_R = bank_unspecified; for (i = 0; i < sizeof (output_state->bank) / sizeof (output_state->bank[0]); i++) output_state->bank[i] = -1; SIGDPRINT(Debug,8,(&Debug, "reset_iso2022: Doing initial ISO 2022 assignments\n")); if (bank_unspecified != iso2022_info->initial_L) { char *c; output_state->current_L = iso2022_info->initial_L; c = lock_shift(0,output_state->current_L,NULL,0); if (c) { int l = strlen(c); add_bytes_stream(ret,len,alloced,s2us(c),l); #ifdef DEBUG { int x; DPRINT(Debug,58,(&Debug, "reset_iso2022: setting left to bank %d: ", output_state->current_L)); for (x = 0; x < l; x++) { DPRINT(Debug,58,(&Debug," %02x",c[x])); } DPRINT(Debug,58,(&Debug,"\n")); } #endif free(c); } } if (bank_unspecified != iso2022_info->initial_R) { char *c; output_state->current_R = iso2022_info->initial_R; c = lock_shift(1,output_state->current_R,NULL,0); if (c) { int l = strlen(c); add_bytes_stream(ret,len,alloced,s2us(c),l); #ifdef DEBUG { int x; DPRINT(Debug,58,(&Debug, "reset_iso2022: setting rigth to bank %d: ", output_state->current_R)); for (x = 0; x < l; x++) { DPRINT(Debug,58,(&Debug," %02x",c[x])); } DPRINT(Debug,58,(&Debug,"\n")); } #endif free(c); } } for (i = 0; i < sizeof (iso2022_info->initial_bank) / sizeof (iso2022_info->initial_bank[0]); i++) { int x = iso2022_info->initial_bank[i]; if (-1 != x) { struct iso2022_setid ID; char *c = NULL; if (x < 0 || x >= sizeof (iso2022_info->sets) / sizeof (iso2022_info->sets[0]) || ! iso2022_info->sets[x]) panic("STRING PANIC",__FILE__,__LINE__, "reset_iso2022", "Bad initial_bank (set)", 0); ID = * (iso2022_info->sets[x]); if (ID.bank != i) panic("STRING PANIC",__FILE__,__LINE__, "reset_iso2022", "Bad initial_bank (bank number)", 0); set_initial_bank(&c,ID,output_state,NULL,0,0); if (c) { int l = strlen(c); add_bytes_stream(ret,len,alloced,s2us(c),l); #ifdef DEBUG { int x; DPRINT(Debug,58,(&Debug, "reset_iso2022: setting initial bank %d: ", i)); for (x = 0; x < l; x++) { DPRINT(Debug,58,(&Debug," %02x",c[x])); } DPRINT(Debug,58,(&Debug,"\n")); } #endif free(c); } } } } S_(charset_reset_routine reset_euc) static void reset_euc(ret,len,alloced,output_state,iso2022_info) unsigned char **ret; int *len; int *alloced; screen_info_p output_state; struct setlist * iso2022_info; { /* NO reset on EUC ! */ return; } /* Return -1 when must quit */ static int add_char1_stream_GEN P_((add_char_stream_t *ADD_CHAR_STREAM, unsigned char **ret, int *len, int *alloced, screen_info_p output_state, struct setlist * iso2022_info, struct map_info * map_info, struct iso2022_setid * ctrlset, int printable, struct mb_data_part * part, int j, int * need_reset, struct cs_printable_len *printable_len, charset_reset_routine *RESET_ROUTINE )); static int add_char1_stream_GEN(ADD_CHAR_STREAM, ret,len,alloced,output_state,iso2022_info,map_info, ctrlset,printable,part,j,need_reset,printable_len, RESET_ROUTINE ) add_char_stream_t * ADD_CHAR_STREAM; unsigned char ** ret; int * len; int * alloced; screen_info_p output_state; struct setlist * iso2022_info; struct map_info * map_info; struct iso2022_setid * ctrlset; int printable; struct mb_data_part * part; int j; int * need_reset; struct cs_printable_len * printable_len; charset_reset_routine *RESET_ROUTINE; { int char_added = 0; if (*need_reset) { RESET_ROUTINE(ret,len,alloced,output_state,iso2022_info); *need_reset = 0; } switch (part->set_index) { case -1: /* control characters , (also space with 94, 94x94 sets) */ if (printable && 32 != part->words[j]) goto bad_char; if (ADD_CHAR_STREAM(ret,len,alloced,NULL,output_state, part->words[j],ctrlset,printable_len) < 1) { return -1; } char_added++; if (part->words[j] < 32) { /* Reapply lock shifts and bank assigments after controls so that these appear on every line (at least) */ *need_reset = 1; } break; case -2: /* bad iso2022 bank */ bad_char: if (iso2022_info && map_info) { int index; enum iso2022_settype type; uint16 iso2022_word; if (map_unicode_to_ISO2022_word(0x003F /* '?' */, iso2022_info, &index,&type,&iso2022_word, map_info) && index >= 0) { if (index > sizeof (iso2022_info->sets) / sizeof (iso2022_info->sets[0]) || ! iso2022_info->sets[index]) panic("ISO2022 PANIC",__FILE__,__LINE__,"add_char1_stream_GEN", "Bad index",0); if (ADD_CHAR_STREAM(ret,len,alloced, iso2022_info->sets[index], output_state, iso2022_word, ctrlset,printable_len) < 1) { return -1; } char_added++; break; } } if (ctrlset) { /* We can add space instead */ if (ADD_CHAR_STREAM(ret,len,alloced,NULL,output_state,32,ctrlset,printable_len) < 1) { return -1; } char_added++; } break; default: if (printable) { /* Require printable character */ int iso2022_map_index = part->iso2022_map_index; if (-1 != iso2022_map_index) { uint16 code; int found = map_ISO2022_word_to_unicode(part->words[j], part->type, iso2022_map_index, &code); if (!found) goto bad_char; /* No mapping available */ if (!unicode_ch(code,UOP_printable)) goto bad_char; /* Not printable */ } else goto bad_char; /* No mapping available */ } if (ADD_CHAR_STREAM(ret,len,alloced, iso2022_info->sets[part->set_index], output_state, part->words[j],ctrlset,printable_len) < 1) { return -1; } char_added++; break; } return char_added; } /* Return -1 when must quit */ static int add_char1_stream P_((unsigned char **ret, int *len, int *alloced, screen_info_p output_state, struct setlist * iso2022_info, struct map_info * map_info, struct iso2022_setid * ctrlset, int printable, struct mb_data_part * part, int j, int * need_reset, struct cs_printable_len *printable_len)); static int add_char1_stream(ret,len,alloced,output_state,iso2022_info,map_info, ctrlset,printable,part,j,need_reset,printable_len) unsigned char **ret; int *len; int *alloced; screen_info_p output_state; struct setlist * iso2022_info; struct map_info * map_info; struct iso2022_setid * ctrlset; int printable; struct mb_data_part * part; int j; int * need_reset; struct cs_printable_len *printable_len; { return add_char1_stream_GEN(add_char_stream, ret,len,alloced,output_state,iso2022_info,map_info, ctrlset,printable,part,j,need_reset,printable_len, reset_iso2022 ); } static void fill_euc_state P_((screen_info_p output_state, struct setlist *iso2022_info)); static void fill_euc_state(output_state,iso2022_info) screen_info_p output_state; struct setlist *iso2022_info; { int i; if (bank_unspecified != iso2022_info->initial_L) output_state->current_L = iso2022_info->initial_L; else output_state->current_L = bank_G0; if (bank_unspecified != iso2022_info->initial_R) output_state->current_R = iso2022_info->initial_R; else output_state->current_R = bank_G1; output_state->set_count = 0; for (i =0; i < sizeof (iso2022_info->sets) / sizeof (iso2022_info->sets[0]) && iso2022_info->sets[i]; i++) { enum iso2022_bank bank = iso2022_info->sets[i]->bank; int num = -1; int j; if (bank_unspecified == bank) { if (iso2022_94 == iso2022_info->sets[i]->type && -1 == output_state->bank[0]) bank = bank_G0; } for (j = 0; j < output_state->set_count; j++) { if (output_state->sets[j].type == iso2022_info->sets[i]->type && 0 == strncmp(us2s(output_state->sets[j].bytes), us2s(iso2022_info->sets[i]->bytes), sizeof (output_state->sets[j].bytes))) { DPRINT(Debug,6,(&Debug, "fill_euc_state: same set given several times\n")); num = j; break; } } if (-1 == num) { if (output_state->set_count +1 >= sizeof(output_state->sets) / sizeof(output_state->sets[0])) panic("ISO2022 PANIC",__FILE__,__LINE__,"fill_euc_state", "Too many sets",0); num = output_state->set_count; output_state->sets[num].bank = bank; /* Not needed */ output_state->sets[num].type = iso2022_info->sets[i]->type; memcpy(output_state->sets[num].bytes, iso2022_info->sets[i]->bytes, sizeof (output_state->sets[num].bytes)); output_state->set_count++; } if (bank >= 0 && bank < ISO2022_BANK_NUM) { if (-1 != output_state->bank[bank]) panic("ISO2022 PANIC",__FILE__,__LINE__,"fill_euc_state", "Multiple sets on bank",0); output_state->bank[bank] = num; } } DPRINT(Debug,9,(&Debug, "fill_euc_state: %d sets\n",output_state->set_count)); } S_(cs_stream_from_string cs_stream_from_euc) static unsigned char * cs_stream_from_euc(str,printable,terminal,reslen) CONST struct string *str; int printable; screen_info_p terminal; int *reslen; { screen_info_p output_state = terminal; int alloced = str->p->len+1; unsigned char * ret = safe_malloc(alloced); int RESLEN = 0; int i; int need_reset = 0; struct mb_data * X1 = str->p->a.data; struct iso2022_setid *ctrlset = NULL; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_stream_from_euc", "Bad magic number (string)",0); if (!output_state) { output_state = create_terminal_info(); if (str->string_type->iso2022_info) fill_euc_state(output_state,str->string_type->iso2022_info); } if (DISPLAY_STATE_magic != output_state->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_stream_from_euc", "Bad magic number (output state)",0); /* Fill indexes if current not filled */ if (printable && str->string_type->map_info && str->string_type->iso2022_info) fill_iso2022_map_index(str->string_type->iso2022_info, X1, str->string_type->map_info); /* Find ASCII bank (or other similar) */ if (str->string_type->iso2022_info) ctrlset = find_ctrlset(str->string_type->iso2022_info); for (i = 0; i < X1->part_count; i++) { int j; #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_stream_from_euc: %d: type=%d set_index=%d <", i,X1->parts[i].type, X1->parts[i].set_index)); if (Debug.active > 58 && str->string_type->iso2022_info) debug_iso2022_info_index(59,X1->parts[i].set_index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); #endif switch (X1->parts[i].set_index) { case -1: DPRINT(Debug,58,(&Debug, "cs_stream_from_euc: %d control characters\n", X1->parts[i].word_count)); if (iso2022_other != X1->parts[i].type) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_stream_from_euc", "Bad type for control characters",0); break; case -2: DPRINT(Debug,58,(&Debug, "cs_stream_from_iso2022: %d bad characters\n", X1->parts[i].word_count)); break; default: DPRINT(Debug,58,(&Debug, "cs_stream_from_euc: %d characters from set %d\n", X1->parts[i].word_count, X1->parts[i].set_index)); if (X1->parts[i].set_index < 0 || !str->string_type->iso2022_info || X1->parts[i].set_index > sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) || ! str->string_type->iso2022_info->sets[X1->parts[i].set_index]) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_stream_from_euc", "Bad set_index",0); break; } for (j = 0; j < X1->parts[i].word_count; j++) { int r = add_char1_stream_GEN(add_char_stream_euc, &ret,&RESLEN,&alloced,output_state, str->string_type->iso2022_info, str->string_type->map_info, ctrlset,printable,& (X1->parts[i]),j, &need_reset,NULL, reset_euc ); if (r < 0) { goto out; } } } out: #if 0 /* NOT needed on EUC? */ /* Reset to 94 bank */ if (ctrlset) { struct iso2022_setid ID = *ctrlset; /* ASCII? */ int width; DPRINT(Debug,63,(&Debug, "cs_stream_from_iso2022: Returning to 94 bank\n")); select_upper_lower(&ret,&RESLEN,&alloced,&ID,output_state,&width); } #endif if (output_state != terminal) free_terminal_info(&output_state); *reslen = RESLEN; /* Do not count final \0 to reslen */ { unsigned char temp[1]; temp[0] = '\0'; add_bytes_stream(&ret,&RESLEN,&alloced,temp,1); } return ret; } S_(cs_stream_from_string cs_stream_from_iso2022) static unsigned char * cs_stream_from_iso2022(str,printable,terminal,reslen) CONST struct string *str; int printable; screen_info_p terminal; int *reslen; { screen_info_p output_state = terminal; int alloced = str->p->len+1; unsigned char * ret = safe_malloc(alloced); int RESLEN = 0; int i; int need_reset = 0; struct mb_data * X1 = str->p->a.data; struct iso2022_setid *ctrlset = NULL; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_stream_from_iso2022", "Bad magic number (string)",0); if (!output_state) { output_state = create_terminal_info(); } if (DISPLAY_STATE_magic != output_state->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_stream_from_iso2022", "Bad magic number (output state)",0); /* Fill indexes if current not filled */ if (printable && str->string_type->map_info && str->string_type->iso2022_info) fill_iso2022_map_index(str->string_type->iso2022_info, X1, str->string_type->map_info); /* Find ASCII bank (or other similar) */ if (str->string_type->iso2022_info) ctrlset = find_ctrlset(str->string_type->iso2022_info); for (i = 0; i < X1->part_count; i++) { int j; #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_stream_from_iso2022: %d: type=%d set_index=%d <", i,X1->parts[i].type, X1->parts[i].set_index)); if (Debug.active > 58 && str->string_type->iso2022_info) debug_iso2022_info_index(59,X1->parts[i].set_index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); #endif switch (X1->parts[i].set_index) { case -1: DPRINT(Debug,58,(&Debug, "cs_stream_from_iso2022: %d control characters\n", X1->parts[i].word_count)); if (iso2022_other != X1->parts[i].type) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_stream_from_iso2022", "Bad type for control characters",0); break; case -2: DPRINT(Debug,58,(&Debug, "cs_stream_from_iso2022: %d bad characters\n", X1->parts[i].word_count)); break; default: DPRINT(Debug,58,(&Debug, "cs_stream_from_iso2022: %d characters from set %d\n", X1->parts[i].word_count, X1->parts[i].set_index)); if (X1->parts[i].set_index < 0 || !str->string_type->iso2022_info || X1->parts[i].set_index > sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) || ! str->string_type->iso2022_info->sets[X1->parts[i].set_index]) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_stream_from_iso2022", "Bad set_index",0); break; } for (j = 0; j < X1->parts[i].word_count; j++) { int r = add_char1_stream(&ret,&RESLEN,&alloced,output_state, str->string_type->iso2022_info, str->string_type->map_info, ctrlset,printable,& (X1->parts[i]),j, &need_reset,NULL); if (r < 0) { goto out; } } } out: /* Reset to 94 bank */ if (ctrlset) { struct iso2022_setid ID = *ctrlset; /* ASCII? */ int width; DPRINT(Debug,63,(&Debug, "cs_stream_from_iso2022: Returning to 94 bank\n")); select_upper_lower(&ret,&RESLEN,&alloced,&ID,output_state,&width); } if (output_state != terminal) free_terminal_info(&output_state); *reslen = RESLEN; /* Do not count final \0 to reslen */ { unsigned char temp[1]; temp[0] = '\0'; add_bytes_stream(&ret,&RESLEN,&alloced,temp,1); } return ret; } S_(cs_can_ascii_string cs_can_ascii_iso2022_gen) static int cs_can_ascii_iso2022_gen(str) CONST struct string *str; { struct mb_data * X1 = str->p->a.data; int i; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_can_ascii_iso2022_gen", "Bad magic number (string)",0); /* Fill indexes if current not filled */ if (str->string_type->map_info && str->string_type->iso2022_info) fill_iso2022_map_index(str->string_type->iso2022_info, X1, str->string_type->map_info); for (i = 0; i < X1->part_count; i++) { int j; #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_can_ascii_iso2022_gen: %d: type=%d set_index=%d <", i,X1->parts[i].type, X1->parts[i].set_index)); if (Debug.active > 58 && str->string_type->iso2022_info) debug_iso2022_info_index(59,X1->parts[i].set_index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); #endif switch (X1->parts[i].set_index) { case -1: if (iso2022_other != X1->parts[i].type) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_can_ascii_iso2022_gen", "Bad type for control characters",0); break; case -2: return 0; /* Unknown bank -- can not convert to ascii (well, we can not output this either ... so is this correct? we anyway output '?' on here...) */ default: if (X1->parts[i].set_index < 0 || !str->string_type->iso2022_info || X1->parts[i].set_index > sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) || ! str->string_type->iso2022_info->sets[X1->parts[i].set_index]) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_can_ascii_iso2022_gen", "Bad set_index",0); break; } for (j = 0; j < X1->parts[i].word_count; j++) { switch (X1->parts[i].set_index) { int iso2022_map_index; /* index to iso2022_map_list[] */ case -1: /* control characters , (also space with 94, 94x94 sets) */ if (X1->parts[i].words[j] > 127) return 0; /* If C1 control area */ break; default: iso2022_map_index = X1->parts[i].iso2022_map_index; if (-1 != iso2022_map_index) { uint16 code; int found = map_ISO2022_word_to_unicode(X1->parts[i].words[j], X1->parts[i].type, iso2022_map_index, &code); if (!found || code > 127) return 0; /* Not ASCII */ } else return 0; /* No mapping available */ break; } } } return 1; /* No NON-ASCII character found */ } static int may_add P_((int width, struct cs_printable_len *printable_len)); static int may_add(width,printable_len) int width; struct cs_printable_len *printable_len; { if (printable_len->max_len < printable_len->ret_len + width) return 0; printable_len->ret_len += width; return 1; } static int may_add_from_set P_((struct iso2022_setid *set, screen_info_p output_state, struct cs_printable_len *printable_len)); static int may_add_from_set(set,output_state,printable_len) struct iso2022_setid *set; screen_info_p output_state; struct cs_printable_len *printable_len; { struct iso2022_setid ID = *set; int setpos = iso2022_give_setpos(&ID,output_state); int r; if (setpos < 0) { DPRINT(Debug,49,(&Debug, "may_add_from_set: setpos = %d no information for estimating of width\n", setpos)); return -1; } if (output_state->width[setpos] < 0) { DPRINT(Debug,49,(&Debug, "may_add_from_set: setpos = %d, width = %d no information for estimating of width\n", setpos,output_state->width[setpos])); return -1; } r = may_add(output_state->width[setpos],printable_len); return r; } /* Return number of characters consumed */ S_(cs_estimate_clip_string cs_estimate_clip_iso2022) static int cs_estimate_clip_iso2022(str,pos,len,terminal,printable_len) CONST struct string *str; int pos; int len; /* UPPER LIMIT */ screen_info_p terminal; struct cs_printable_len *printable_len; { struct mb_data * X1 = str->p->a.data; int block_number = 0; int block_index = pos; int counter = 0; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_estimate_clip_iso2022", "Bad magic number (string)",0); printable_len->ret_len = 0; /* Fill indexes if current not filled */ if (str->string_type->map_info && str->string_type->iso2022_info) fill_iso2022_map_index(str->string_type->iso2022_info, X1, str->string_type->map_info); if (!pos_to_block(X1,pos,&block_number,&block_index)) return 0; /* No characters consumed */ while (block_number < X1->part_count && counter < len) { #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_estimate_clip_iso2022: %d: type=%d set_index=%d <", block_number,X1->parts[block_number].type, X1->parts[block_number].set_index)); if (Debug.active > 58 && str->string_type->iso2022_info) debug_iso2022_info_index(59,X1->parts[block_number].set_index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); #endif switch (X1->parts[block_number].set_index) { case -1: DPRINT(Debug,58,(&Debug, "cs_estimate_clip_iso2022: %d control characters\n", X1->parts[block_number].word_count - block_index)); if (iso2022_other != X1->parts[block_number].type) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_estimate_clip_iso2022", "Bad type for control characters",0); break; case -2: DPRINT(Debug,58,(&Debug, "cs_estimate_clip_iso2022: %d bad characters\n", X1->parts[block_number].word_count - block_index)); goto bail_out; default: DPRINT(Debug,58,(&Debug, "cs_estimate_clip_iso2022: %d characters from set %d\n", X1->parts[block_number].word_count - block_index, X1->parts[block_number].set_index)); if (X1->parts[block_number].set_index < 0 || !str->string_type->iso2022_info || X1->parts[block_number].set_index > sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) || ! str->string_type->iso2022_info->sets[X1->parts[block_number].set_index]) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_estimate_clip_iso2022", "Bad set_index",0); break; } while (block_index < X1->parts[block_number].word_count && counter < len) { switch (X1->parts[block_number].set_index) { case -1: /* control characters , (also space with 94, 94x94 sets) */ /* However do not handle controls */ if (32 != X1->parts[block_number].words[block_index]) goto bail_out; /* Asumed that space have width 1 always */ if (!may_add(1,printable_len)) { DPRINT(Debug,49,(&Debug, "cs_estimate_clip_iso2022: %d: ended at at %d, counter=%d (ctrl)\n", block_number,block_index,counter)); goto out; } counter++; break; case -2: /* Not occur */ break; default: if (-1 == X1->parts[block_number].iso2022_map_index || !str->string_type->iso2022_info) { DPRINT(Debug,49,(&Debug, "cs_estimate_clip_iso2022: iso2022_map_index=%d or no iso2022_info\n", X1->parts[block_number].iso2022_map_index)); goto bail_out; } else { uint16 code; int r; int found = map_ISO2022_word_to_unicode(X1->parts[block_number].words[block_index], X1->parts[block_number].type, X1->parts[block_number].iso2022_map_index, &code); if (!found) { DPRINT(Debug,49,(&Debug, "cs_estimate_clip_iso2022: %d: at %d, counter=%d -- iso2022 character %04x type %d with map index %d not found\n", block_number,block_index,counter, X1->parts[block_number].words[block_index], X1->parts[block_number].type, X1->parts[block_number].iso2022_map_index)); goto bail_out; /* No mapping available */ } if (!unicode_ch(code,UOP_printable)) { DPRINT(Debug,49,(&Debug, "cs_estimate_clip_iso2022: %d: at %d, counter=%d -- unicode character %04x not printable\n", block_number,block_index,counter,code)); goto bail_out; /* Not printable */ } r = may_add_from_set(str->string_type->iso2022_info-> sets[X1->parts[block_number].set_index], terminal, printable_len); if (r < 0) goto bail_out; if (!r) { DPRINT(Debug,49,(&Debug, "cs_estimate_clip_iso2022: %d: ended at at %d, counter=%d (no space)\n", block_number,block_index,counter)); goto out; } counter++; } break; } block_index++; } block_number++; block_index = 0; } out: return counter; bail_out: DPRINT(Debug,49,(&Debug, "cs_estimate_clip_iso2022: %d: bailing out at %d, counter=%d\n", block_number,block_index,counter)); if (counter > 0) return counter; return -1; } S_(cs_streamclip_from_string cs_streamclip_from_euc) static unsigned char * cs_streamclip_from_euc(str,pos,len,terminal,printable_len) CONST struct string *str; int *pos; int len; screen_info_p terminal; struct cs_printable_len *printable_len; { screen_info_p output_state = terminal; struct mb_data * X1 = str->p->a.data; int block_number = 0; int block_index = *pos; int start_pos = *pos; int alloced = 0; unsigned char * ret = NULL; int RESLEN = 0; struct iso2022_setid *ctrlset = NULL; int need_reset = 0; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_streamclip_from_euc", "Bad magic number (string)",0); if (*pos < 0) panic("STRING PANIC",__FILE__,__LINE__,"cs_streamclip_from_euc", "Index out of array",0); if (len < 0) panic("STRING PANIC",__FILE__,__LINE__,"cs_streamclip_from_euc", "Negative size",0); if (printable_len) printable_len->ret_len = 0; if (!pos_to_block(X1,*pos,&block_number,&block_index)) { unsigned char * S = safe_malloc(1); *S = '\0'; return S; } alloced = len+1; ret = safe_malloc(alloced); if (!output_state) { output_state = create_terminal_info(); if (str->string_type->iso2022_info) fill_euc_state(output_state,str->string_type->iso2022_info); } /* Fill indexes if current not filled */ if (str->string_type->map_info && str->string_type->iso2022_info) fill_iso2022_map_index(str->string_type->iso2022_info, X1, str->string_type->map_info); /* Find ASCII bank (or other similar) */ if (str->string_type->iso2022_info) ctrlset = find_ctrlset(str->string_type->iso2022_info); while (block_number < X1->part_count && *pos - start_pos < len) { #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_streamclip_from_euc: %d: type=%d set_index=%d <", block_number,X1->parts[block_number].type, X1->parts[block_number].set_index)); if (Debug.active > 58 && str->string_type->iso2022_info) debug_iso2022_info_index(59,X1->parts[block_number].set_index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); #endif switch (X1->parts[block_number].set_index) { case -1: DPRINT(Debug,58,(&Debug, "cs_streamclip_from_euc: %d control characters\n", X1->parts[block_number].word_count - block_index, X1->parts[block_number].set_index)); if (iso2022_other != X1->parts[block_number].type) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_streamclip_from_euc", "Bad type for control characters",0); break; case -2: DPRINT(Debug,58,(&Debug, "cs_streamclip_from_euc: %d bad characters\n", X1->parts[block_number].word_count - block_index, X1->parts[block_number].set_index)); break; default: DPRINT(Debug,58,(&Debug, "cs_streamclip_from_euc: %d characters from set %d\n", X1->parts[block_number].word_count - block_index, X1->parts[block_number].set_index)); if (X1->parts[block_number].set_index < 0 || !str->string_type->iso2022_info || X1->parts[block_number].set_index > sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) || ! str->string_type->iso2022_info->sets[X1->parts[block_number].set_index]) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_streamclip_from_euc", "Bad set_index",0); break; } while (block_index < X1->parts[block_number].word_count && *pos - start_pos < len) { int r = add_char1_stream_GEN(add_char_stream_euc, &ret,&RESLEN,&alloced,output_state, str->string_type->iso2022_info, str->string_type->map_info, ctrlset,1,& (X1->parts[block_number]), block_index,&need_reset,printable_len, reset_euc ); if (r < 0) goto out; if (r > 0) { /* nothing to count */ } else { DPRINT(Debug,1,(&Debug, "cs_streamclip_from_euc: FAILED to add char to steam\n")); } block_index++; (*pos)++; } block_index = 0; block_number++; } out: #if 0 /* NOT needed on EUC? */ /* Reset to 94 bank */ if (ctrlset) { struct iso2022_setid ID = *ctrlset; /* ASCII? */ int width; DPRINT(Debug,63,(&Debug, "cs_streamclip_from_euc: Returning to 94 bank\n")); select_upper_lower(&ret,&RESLEN,&alloced,&ID,output_state,&width); } #endif if (output_state != terminal) free_terminal_info(&output_state); { unsigned char temp[1]; temp[0] = '\0'; add_bytes_stream(&ret,&RESLEN,&alloced,temp,1); } return ret; } S_(cs_streamclip_from_string cs_streamclip_from_iso2022) static unsigned char * cs_streamclip_from_iso2022(str,pos,len,terminal,printable_len) CONST struct string *str; int *pos; int len; screen_info_p terminal; struct cs_printable_len *printable_len; { screen_info_p output_state = terminal; struct mb_data * X1 = str->p->a.data; int block_number = 0; int block_index = *pos; int start_pos = *pos; int alloced = 0; unsigned char * ret = NULL; int RESLEN = 0; struct iso2022_setid *ctrlset = NULL; int need_reset = 0; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_streamclip_from_iso2022", "Bad magic number (string)",0); if (*pos < 0) panic("STRING PANIC",__FILE__,__LINE__,"cs_streamclip_from_iso2022", "Index out of array",0); if (len < 0) panic("STRING PANIC",__FILE__,__LINE__,"cs_streamclip_from_iso2022", "Negative size",0); if (printable_len) printable_len->ret_len = 0; if (!pos_to_block(X1,*pos,&block_number,&block_index)) { unsigned char * S = safe_malloc(1); *S = '\0'; return S; } alloced = len+1; ret = safe_malloc(alloced); if (!output_state) { output_state = create_terminal_info(); } /* Fill indexes if current not filled */ if (str->string_type->map_info && str->string_type->iso2022_info) fill_iso2022_map_index(str->string_type->iso2022_info, X1, str->string_type->map_info); /* Find ASCII bank (or other similar) */ if (str->string_type->iso2022_info) ctrlset = find_ctrlset(str->string_type->iso2022_info); while (block_number < X1->part_count && *pos - start_pos < len) { #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_streamclip_from_iso2022: %d: type=%d set_index=%d <", block_number,X1->parts[block_number].type, X1->parts[block_number].set_index)); if (Debug.active > 58 && str->string_type->iso2022_info) debug_iso2022_info_index(59,X1->parts[block_number].set_index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); #endif switch (X1->parts[block_number].set_index) { case -1: DPRINT(Debug,58,(&Debug, "cs_streamclip_from_iso2022: %d control characters\n", X1->parts[block_number].word_count - block_index, X1->parts[block_number].set_index)); if (iso2022_other != X1->parts[block_number].type) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_streamclip_from_iso2022", "Bad type for control characters",0); break; case -2: DPRINT(Debug,58,(&Debug, "cs_streamclip_from_iso2022: %d bad characters\n", X1->parts[block_number].word_count - block_index, X1->parts[block_number].set_index)); break; default: DPRINT(Debug,58,(&Debug, "cs_streamclip_from_iso2022: %d characters from set %d\n", X1->parts[block_number].word_count - block_index, X1->parts[block_number].set_index)); if (X1->parts[block_number].set_index < 0 || !str->string_type->iso2022_info || X1->parts[block_number].set_index > sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) || ! str->string_type->iso2022_info->sets[X1->parts[block_number].set_index]) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_streamclip_from_iso2022", "Bad set_index",0); break; } while (block_index < X1->parts[block_number].word_count && *pos - start_pos < len) { int r = add_char1_stream(&ret,&RESLEN,&alloced,output_state, str->string_type->iso2022_info, str->string_type->map_info, ctrlset,1,& (X1->parts[block_number]), block_index,&need_reset,printable_len); if (r < 0) goto out; if (r > 0) { /* nothing to count */ } else { DPRINT(Debug,1,(&Debug, "cs_streamclip_from_iso2022: FAILED to add char to steam\n")); } block_index++; (*pos)++; } block_index = 0; block_number++; } out: /* Reset to 94 bank */ if (ctrlset) { struct iso2022_setid ID = *ctrlset; /* ASCII? */ int width; DPRINT(Debug,63,(&Debug, "cs_streamclip_from_iso2022: Returning to 94 bank\n")); select_upper_lower(&ret,&RESLEN,&alloced,&ID,output_state,&width); } if (output_state != terminal) free_terminal_info(&output_state); { unsigned char temp[1]; temp[0] = '\0'; add_bytes_stream(&ret,&RESLEN,&alloced,temp,1); } return ret; } S_(cs_clip_from_string cs_clip_from_iso2022_gen) static void cs_clip_from_iso2022_gen(ret,str,pos,len) struct string *ret; CONST struct string *str; int *pos; int len; { struct mb_data * X1 = str->p->a.data; struct mb_data * X2 = ret->p->a.data; int block_number = 0; int block_index = *pos; int start_pos = *pos; if (ret->string_type->charset_type != str->string_type->charset_type) panic("STRING PANIC",__FILE__,__LINE__,"cs_clip_from_iso2022_gen", "String type mismatch",0); if (*pos < 0) panic("STRING PANIC",__FILE__,__LINE__,"cs_clip_from_iso2022_gen", "Index out of array",0); if (len < 0) panic("STRING PANIC",__FILE__,__LINE__,"cs_clip_from_iso2022_gen", "Negative size",0); if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_clip_from_iso2022_gen", "Bad magic number (string)",0); if (CS_ISO2022_magic != X2->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_clip_from_iso2022_gen", "Bad magic number (ret)",0); free_parts(X2); /* Quarantee */ ret->p->len = 0; if (!pos_to_block(X1,*pos,&block_number,&block_index)) { return ; } /* FIXME: Optimeze this */ while (block_number < X1->part_count && *pos - start_pos < len) { int l1 = X1->parts[block_number].word_count - block_index; int new_len; struct mb_data_part * X3; if (l1 < 1) continue; /* Avoid job */ #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_clip_from_iso2022_gen: %d: type=%d set_index=%d <", block_number,X1->parts[block_number].type, X1->parts[block_number].set_index)); if (Debug.active > 58 && str->string_type->iso2022_info) debug_iso2022_info_index(59,X1->parts[block_number].set_index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); #endif X3 = get_part(X2, X1->parts[block_number].set_index, X1->parts[block_number].type); new_len = X3->word_count + l1; X3->words = safe_realloc(X3->words, (new_len) * sizeof (X3->words[0])); while (block_index < X1->parts[block_number].word_count && X3->word_count < new_len && *pos - start_pos < len) { X3->words[X3->word_count++] = X1->parts[block_number].words[block_index]; ret->p->len++; block_index++; (*pos)++; } block_index = 0; block_number++; } } S_(cs_find_pattern_from_string cs_find_pattern_from_iso2022_gen) static int cs_find_pattern_from_iso2022_gen(str,pattern,ignore_case) CONST struct string *str; CONST struct string *pattern; int ignore_case; { /* FIXME: pattern match should be done on here */ DPRINT(Debug,63,(&Debug, "cs_find_pattern_from_iconv_gen=-1\n")); return -1; /* Use UNICODE comparision on upper level instead */ } /* Returns number of bytes added */ S_(cs_add_streambytes_to_string cs_add_streambytes_to_iso2022_gen) static int cs_add_streambytes_to_iso2022_gen(str,count,data,errors) struct string *str; int count; CONST unsigned char *data; int *errors; { int i = 0; struct state_iso2022 * X ; *errors = 0; if (!str->p->state) str->p->state = new_state_1(str->string_type); if (str->p->state->charset->charset_type != &cs_iso2022 && str->p->state->charset->charset_type != &cs_euc ) panic("STRING PANIC",__FILE__,__LINE__,"cs_add_streambytes_to_iso2022_gen", "Bad state",0); X = str->p->state->p->a.iso2022; if (STATE_ISO2022_magic != X->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_add_streambytes_to_iso2022_gen", "Bad magic number (state)",0); while (1) { if (str->p->state->p->ready) { iso2022_add_char(str,str->p->state); cs_soft_reset_s_iso2022_gen(str->p->state); } else { int c = -1; if (X->raw_bytes_count > 0) { DPRINT(Debug,8,(&Debug, "cs_add_streambytes_to_iso2022_gen: %d bytes collected\n", X->raw_bytes_count)); c = streambyte_make_code_2(str->p->state,X); } if (c < 0) { /* need more characters */ if (i < count) { if (!state_add_raw(X,data[i])) { DPRINT(Debug,8,(&Debug, "cs_add_streambytes_to_iso2022_gen: failed to add code\n")); /* Failed to add character */ (*errors)++; cs_soft_reset_s_iso2022_gen(str->p->state); X->raw_bytes_count = 0; } i++; } else { break; /* All characters entered */ } } if (0 == c) { DPRINT(Debug,8,(&Debug, "cs_add_streambytes_to_iso2022_gen: bad code\n")); (*errors)++; cs_soft_reset_s_iso2022_gen(str->p->state); } } } return i; } S_(cs_find_map_type cs_find_euc) static struct map_info *cs_find_euc(map_name) CONST char * map_name; { int i; struct map_info *ret; static struct map_info ** dyn_maps = NULL; static int dyn_map_count = 0; static struct map_info * maps[] = { &map_EUC_ascii, &map_EUC_ascii_latin1, NULL }; for (i = 0; maps[i]; i++) if (0 == strcmp(map_name,maps[i]->map_name)) return maps[i]; for (i =0; i < dyn_map_count; i++) if (0 == strcmp(dyn_maps[i]->map_name,map_name)) return dyn_maps[i]; ret = open_euc_mapset(map_name); if (ret) { dyn_maps = safe_realloc(dyn_maps, (dyn_map_count + 1) * sizeof (struct map_info *)); dyn_maps[dyn_map_count++] = ret; } return ret; } S_(cs_find_map_type cs_find_iso2022) static struct map_info *cs_find_iso2022(map_name) CONST char * map_name; { int i; struct map_info *ret; static struct map_info ** dyn_maps = NULL; static int dyn_map_count = 0; static struct map_info * maps[] = { &map_ISO2022_ascii, &map_ISO2022_ascii_latin1, NULL }; for (i = 0; maps[i]; i++) if (0 == strcmp(map_name,maps[i]->map_name)) return maps[i]; for (i =0; i < dyn_map_count; i++) if (0 == strcmp(dyn_maps[i]->map_name,map_name)) return dyn_maps[i]; ret = open_iso2022_mapset(map_name); if (ret) { dyn_maps = safe_realloc(dyn_maps, (dyn_map_count + 1) * sizeof (struct map_info *)); dyn_maps[dyn_map_count++] = ret; } return ret; } S_(cs_remove_control cs_remove_control_iso2022_gen) static void cs_remove_control_iso2022_gen(str) CONST struct string *str; { struct mb_data * X1 = str->p->a.data; struct mb_data * new_X1 = alloc_mb_data(); int i; if (CS_ISO2022_magic != X1->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_remove_control_iso2022_gen", "Bad magic number (string)",0); /* Fill indexes if current not filled */ if (str->string_type->map_info && str->string_type->iso2022_info) fill_iso2022_map_index(str->string_type->iso2022_info, X1, str->string_type->map_info); /* FIXME: This is very inefficient -- we rebuild string internally */ for (i = 0; i < X1->part_count; i++) { int j; #ifdef DEBUG DPRINT(Debug,59,(&Debug, "cs_remove_control_iso2022_gen: %d: type=%d set_index=%d <", i,X1->parts[i].type, X1->parts[i].set_index)); if (Debug.active > 58 && str->string_type->iso2022_info) debug_iso2022_info_index(59,X1->parts[i].set_index, str->string_type->iso2022_info); DPRINT(Debug,59,(&Debug,">\n")); #endif switch (X1->parts[i].set_index) { case -1: if (iso2022_other != X1->parts[i].type) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_remove_control_iso2022_gen", "Bad type for control characters",0); break; case -2: break; default: if (X1->parts[i].set_index < 0 || !str->string_type->iso2022_info || X1->parts[i].set_index > sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) || ! str->string_type->iso2022_info->sets[X1->parts[i].set_index]) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_remove_control_iso2022_gen", "Bad set_index",0); break; } for (j = 0; j < X1->parts[i].word_count; j++) { switch (X1->parts[i].set_index) { struct mb_data_part * X3; int iso2022_map_index; case -1: /* control characters , (also space with 94, 94x94 sets) */ if (32 != X1->parts[i].words[j]) goto bad_char; X3 = get_part(new_X1, X1->parts[i].set_index, X1->parts[i].type); add_iso2022_word(X3, X1->parts[i].words[j]); break; case -2: bad_char: if (str->string_type->iso2022_info && str->string_type->map_info) { int index; enum iso2022_settype type; uint16 iso2022_word; if (map_unicode_to_ISO2022_word(0x003F /* '?' */, str->string_type-> iso2022_info, &index,&type,&iso2022_word, str->string_type-> map_info) && index >= 0) { if (index > sizeof (str->string_type->iso2022_info->sets) / sizeof (str->string_type->iso2022_info->sets[0]) || ! str->string_type->iso2022_info->sets[index]) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_remove_control_iso2022_gen", "Bad index",0); X3 = get_part(new_X1,index,type); add_iso2022_word(X3,iso2022_word); break; } } /* We can add space instead */ X3 = get_part(new_X1,-1,iso2022_other); add_iso2022_word(X3,32); break; default: iso2022_map_index = X1->parts[i].iso2022_map_index; if (-1 != iso2022_map_index) { uint16 code; int found = map_ISO2022_word_to_unicode(X1->parts[i].words[j], X1->parts[i].type, iso2022_map_index, &code); if (!found) goto bad_char; /* No mapping avaiulable */ if (!unicode_ch(code,UOP_printable)) goto bad_char; /* Not printable */ } else goto bad_char; /* No mapping available */ X3 = get_part(new_X1, X1->parts[i].set_index, X1->parts[i].type); add_iso2022_word(X3, X1->parts[i].words[j]); break; } } } free_mb_data(&X1); str->p->a.data = new_X1; { int l = str->p->len; str->p->len = 0; for (i = 0; i < new_X1->part_count; i++) { str->p->len += new_X1->parts[i].word_count; } if (l != str->p->len) { DPRINT(Debug,6,(&Debug, "cs_remove_control_iso2022_gen: length changed %d => %d\n", l,str->p->len)); } } } S_(cs_add_state_to_string cs_add_state_to_iso2022_gen) static void cs_add_state_to_iso2022_gen(str,ch) struct string *str; struct charset_state *ch; { if (str->string_type->charset_type != ch->charset->charset_type) panic("STRING PANIC",__FILE__,__LINE__,"cs_add_state_to_iso2022_gen", "String/state type mismatch",0); iso2022_add_char(str,ch); } static void set_initial_state P_((struct charset_state *st)); static void set_initial_state(st) struct charset_state *st; { if (STATE_ISO2022_magic != st->p->a.iso2022->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "set_initial_state", "Bad magic number",0); if (st->charset->iso2022_info) { int i; if (sizeof (st->charset->iso2022_info->initial_bank) / sizeof (st->charset->iso2022_info->initial_bank[0]) != sizeof (st->p->a.iso2022->banks) / sizeof (st->p->a.iso2022->banks[0])) panic("ISO2022 PANIC",__FILE__,__LINE__, "set_initial_state", "Array sizes should be same",0); for (i = 0; i < sizeof (st->charset->iso2022_info->initial_bank) / sizeof (st->charset->iso2022_info->initial_bank[0]); i++) { int x = st->charset->iso2022_info->initial_bank[i]; if (-1 != x) { if (x < 0 || x >= sizeof (st->charset->iso2022_info->sets) / sizeof (st->charset->iso2022_info->sets[0]) || ! st->charset->iso2022_info->sets[x]) panic("STRING PANIC",__FILE__,__LINE__, "set_initial_state", "Bad initial_bank (set)", 0); if (sizeof (st->p->a.iso2022->banks[i].bytes) != sizeof (st->charset->iso2022_info->sets[x]->bytes)) panic("STRING PANIC",__FILE__,__LINE__, "set_initial_state", "Bad size", 0); st->p->a.iso2022->banks[i].iso2022_info_index = x; st->p->a.iso2022->banks[i].type = st->charset->iso2022_info->sets[x]->type; memcpy(st->p->a.iso2022->banks[i].bytes, st->charset->iso2022_info->sets[x]->bytes, sizeof st->p->a.iso2022->banks[i].bytes); } } } } S_(cs_init_state cs_init_s_iso2022) static void cs_init_s_iso2022(st) struct charset_state *st; { int i; st->p->a.iso2022 = safe_malloc(sizeof (*st->p->a.iso2022)); /* defined in hdrs/defs.h */ bzero((void *)st->p->a.iso2022, sizeof (*st->p->a.iso2022)); st->p->a.iso2022->magic = STATE_ISO2022_magic; st->p->a.iso2022->bank = bank_unspecified; for (i = 0; i < sizeof (st->p->a.iso2022->banks) / sizeof (st->p->a.iso2022->banks[0]); i++) { st->p->a.iso2022->banks[i].type = iso2022_other; st->p->a.iso2022->banks[i].iso2022_info_index = -1; bzero(st->p->a.iso2022->banks[i].bytes, sizeof (st->p->a.iso2022->banks[i].bytes)); } st->p->a.iso2022->CL_bank = bank_G0; /* G0 assumed initially */ st->p->a.iso2022->CR_bank = bank_unspecified; /* no assumption for 8-bit characters */ st->p->a.iso2022->raw_bytes_count = 0; st->p->a.iso2022->word = 0; set_initial_state(st); } S_(cs_init_state cs_init_s_euc) static void cs_init_s_euc(st) struct charset_state *st; { int i; st->p->a.iso2022 = safe_malloc(sizeof (*st->p->a.iso2022)); /* defined in hdrs/defs.h */ bzero((void *)st->p->a.iso2022, sizeof (*st->p->a.iso2022)); st->p->a.iso2022->magic = STATE_ISO2022_magic; st->p->a.iso2022->bank = bank_unspecified; for (i = 0; i < sizeof (st->p->a.iso2022->banks) / sizeof (st->p->a.iso2022->banks[0]); i++) { st->p->a.iso2022->banks[i].type = iso2022_other; st->p->a.iso2022->banks[i].iso2022_info_index = -1; bzero(st->p->a.iso2022->banks[i].bytes, sizeof (st->p->a.iso2022->banks[i].bytes)); } st->p->a.iso2022->CL_bank = bank_G0; /* G0 is left on EUC */ st->p->a.iso2022->CR_bank = bank_G1; /* G1 is for 8-bit characters on EUC */ st->p->a.iso2022->raw_bytes_count = 0; st->p->a.iso2022->word = 0; set_initial_state(st); if (st->charset->iso2022_info) { for (i = 0; i < sizeof (st->charset->iso2022_info->sets) / sizeof (st->charset->iso2022_info->sets[0]) && st->charset->iso2022_info->sets[i]; i++) { enum iso2022_bank bank = st->charset->iso2022_info->sets[i]->bank; if (bank == bank_unspecified && iso2022_94 == st->charset->iso2022_info->sets[i]->type && iso2022_other == st->p->a.iso2022->banks[bank_G0].type) bank = bank_G0; if (bank >= 0 && bank < ISO2022_BANK_NUM) { st->p->a.iso2022->banks[bank].iso2022_info_index = i; st->p->a.iso2022->banks[bank].type = st->charset->iso2022_info->sets[i]->type; memcpy(st->p->a.iso2022->banks[bank].bytes, st->charset->iso2022_info->sets[i]->bytes, sizeof st->p->a.iso2022->banks[bank].bytes); } } } } S_(cs_free_state cs_free_s_iso2022_gen) static void cs_free_s_iso2022_gen(st) struct charset_state *st; { if (st->p->a.iso2022) { if (STATE_ISO2022_magic != st->p->a.iso2022->magic) panic("ISO2022 PANIC",__FILE__,__LINE__,"cs_free_s_iso2022", "Bad magic number",0); st->p->a.iso2022->magic = 0; /* Invalidate magic */ free(st->p->a.iso2022); st->p->a.iso2022 = NULL; } } S_(cs_add_streambyte_to_state cs_add_streambyte_to_s_iso2022_gen) static int cs_add_streambyte_to_s_iso2022_gen(st,ch) struct charset_state *st; int ch; { struct state_iso2022 * X = st->p->a.iso2022; if (STATE_ISO2022_magic != X->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_add_streambyte_to_s_iso2022_gen", "Bad magic number (state)",0); if (!state_add_raw(X,ch)) return 0; while (X->raw_bytes_count > 0) { int code; if (st->p->ready) { DPRINT(Debug,4,(&Debug, "cs_add_streambyte_to_s_iso2022_gen: characters lost!\n" )); } code = streambyte_make_code_2(st,X); if (code < 0) { DPRINT(Debug,8,(&Debug, "cs_add_streambyte_to_s_iso2022_gen: too few characters (len = %d)\n", X->raw_bytes_count)); return 1; } if (0 == code) { DPRINT(Debug,8,(&Debug, "cs_add_streambyte_to_s_iso2022_gen: bad code\n")); return 0; } } return 1; } S_(cs_soft_reset_state cs_soft_reset_s_iso2022_gen) static void cs_soft_reset_s_iso2022_gen(st) struct charset_state *st; { struct state_iso2022 * X = st->p->a.iso2022; if (STATE_ISO2022_magic != X->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_soft_reset_s_iso2022_gen", "Bad magic number (state)",0); X->raw_bytes_count = 0; st->p->ready = 0; } S_(cs_give_unicode_from_state cs_give_unicode_from_s_iso2022) static uint16 cs_give_unicode_from_s_iso2022(st,found) struct charset_state *st; int *found; { uint16 ret = 0x003F; /* '?' */ struct state_iso2022 * X = st->p->a.iso2022; if (STATE_ISO2022_magic != X->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_give_unicode_from_s_iso2022", "Bad magic number (state)",0); *found = 0; if (bank_unspecified == X-> bank) { /* Control characters map directrly to unicode */ ret = X->word; *found = 1; } else if (X->bank >= 0 && X->bank < ISO2022_BANK_NUM) { if (0 <= X->banks[X->bank].iso2022_info_index && st->charset->iso2022_info && st->charset->map_info) { int iso2022_map_index; if (X->banks[X->bank].iso2022_info_index >= sizeof (st->charset->iso2022_info->sets) / sizeof (st->charset->iso2022_info->sets[0]) || ! st->charset->iso2022_info->sets [X->banks[X->bank].iso2022_info_index]) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_give_unicode_from_s_iso2022", "Bad iso2022_info_index",0); if (!st->charset->map_info->map_initialized) st->charset->map_info->map_init_it(st->charset->map_info); iso2022_map_index = give_iso2022_index(st->charset->map_info->b.setlist->setlist, sizeof (st->charset->map_info->b.setlist-> setlist) / sizeof (st->charset->map_info-> b.setlist->setlist[0]), st->charset->iso2022_info-> sets[X->banks[X->bank].iso2022_info_index]); if (-1 != iso2022_map_index) *found = map_ISO2022_word_to_unicode(X->word, X->banks[X->bank].type, iso2022_map_index, &ret); } } else panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_give_unicode_from_s_iso2022", "Bad bank number",0); return ret; } S_(cs_state_same_char cs_s_iso2022_same_char_gen) static int cs_s_iso2022_same_char_gen(A,B,ignore_case) struct charset_state *A; struct charset_state *B; int ignore_case; { int r = -1; struct state_iso2022 * XA = A->p->a.iso2022; struct state_iso2022 * XB = B->p->a.iso2022; if (STATE_ISO2022_magic != XA->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_soft_reset_s_iso2022", "Bad magic number (state A)",0); if (STATE_ISO2022_magic != XB->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_soft_reset_s_iso2022", "Bad magic number (state B)",0); /* If control character */ if (bank_unspecified == XA->bank && bank_unspecified == XB->bank) r = XA->word == XB->word; else if (bank_unspecified == XA->bank || bank_unspecified == XB->bank) r = -1; /* Use UNICODE values for comparision */ else if (XA->bank >= 0 && XB->bank >= 0 && XA->bank <= ISO2022_BANK_NUM && XB->bank <= ISO2022_BANK_NUM) { if (-1 == XA->banks[XA->bank].iso2022_info_index && -1 == XB->banks[XB->bank].iso2022_info_index && 0 == memcmp(XA->banks[XA->bank].bytes, XB->banks[XB->bank].bytes, sizeof (XA->banks[XA->bank].bytes))) r = XA->word == XB->word; else if (0 <= XA->banks[XA->bank].iso2022_info_index && XA->banks[XA->bank].iso2022_info_index == XB->banks[XB->bank].iso2022_info_index) r = XA->word == XB->word; else r = -1; /* Use UNICODE values for comparision */ } else panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_s_iso2022_same_char_gen", "Bad bank number",0); if (0 == r && ignore_case) r = -1; /* Use UNICODE values for comparision */ return r; } S_(cs_state_printable cs_s_iso2022_printable_gen) static int cs_s_iso2022_printable_gen(st) struct charset_state *st; { int r = -1; struct state_iso2022 * X = st->p->a.iso2022; if (STATE_ISO2022_magic != X->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_s_iso2022_printable_gen", "Bad magic number (state)",0); if (bank_unspecified == X->bank) r = 32 == X->word; /* Assume that space is only printable control character */ else r = -1; /* Use UNICODE to look printable characters */ return r; } /* If character corresponds one byte on stream, returns it. * Otherwise returns 0. This is used implement ReadCh(). * It is assumed that returned character corresponds to * code character set (and perhaps also US-ASCII) */ S_(cs_state_is_onebyte cs_s_iso2022_is_onebyte_gen) static int cs_s_iso2022_is_onebyte_gen(st) struct charset_state *st; { int r = 0; struct state_iso2022 * X = st->p->a.iso2022; if (STATE_ISO2022_magic != X->magic) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_s_iso2022_is_onebyte_gen", "Bad magic number (state)",0); if (bank_unspecified == X-> bank) { if (X->word < 128) r = X->word; } else if (X->bank >= 0 && X->bank < ISO2022_BANK_NUM) { /* NOTE: I think that it is better not to test iso2022_96 == X->banks[X->bank].type although it is one byte set. One byte sets (without escape switching use range 160-255) for that normally */ if (iso2022_94 == X->banks[X->bank].type) { if (X->word >= 96) panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_s_iso2022_is_onebyte_gen", "Bad word on iso2022_94 or iso2022_96",0); r = X->word + 32; } } else panic("ISO2022 PANIC",__FILE__,__LINE__, "cs_s_iso2022_is_onebyte_gen", "Bad bank number",0); return r; } S_(cs_set_properties cs_iso2022_properties_gen) static int cs_iso2022_properties_gen(st) charset_t st; { int prop = 0; if (st->map_info && st->iso2022_info) prop |= CS_mapping | CS_printable | CS_printable_len; return prop; } S_(cs_iso2022_info_set cs_iso2022_info_set_iso2022) static int cs_iso2022_info_set_iso2022(new_vals, new_setlist,setcount) struct charcode_info *new_vals; struct setlist *new_setlist; int setcount; { int i; /* No requirements? */ for (i = setcount; i < sizeof (new_setlist->sets) / sizeof (new_setlist->sets[0]); i++) new_setlist->sets[i] = NULL; new_vals->iso2022_info = loc_setlist(*new_setlist); new_vals->flags &= ~SET_nodata; return 1; } S_(cs_iso2022_info_set cs_iso2022_info_set_euc) static int cs_iso2022_info_set_euc(new_vals, new_setlist,setcount) struct charcode_info *new_vals; struct setlist *new_setlist; int setcount; { int banks[ISO2022_BANK_NUM]; int i; for (i = 0; i < ISO2022_BANK_NUM; i++) banks[i] = -1; for (i = 0; i < setcount; i++) { if (new_setlist->sets[i]->bank >= 0 && new_setlist->sets[i]->bank <= ISO2022_BANK_NUM) { if (-1 == banks[new_setlist->sets[i]->bank]) banks[new_setlist->sets[i]->bank] = i; else { lib_error(CATGETS(elm_msg_cat, MeSet, MeNoSeveralBank, "Charset type %s does not allow several bank-G%d specifications"), new_vals->charset_type->type_name, new_setlist->sets[i]->bank); return 0; /* Discard bank defination */ } } } for (i = setcount; i < sizeof (new_setlist->sets) / sizeof (new_setlist->sets[0]); i++) new_setlist->sets[i] = NULL; new_vals->iso2022_info = loc_setlist(*new_setlist); new_vals->flags &= ~SET_nodata; return 1; } struct charset_type cs_iso2022 = { "iso2022", cs_init_iso2022_gen, cs_free_iso2022_gen, cs_add_streambyte_to_iso2022_gen, cs_add_intdata_to_iso2022_gen, cs_check_length_iso2022_gen, cs_give_unicode_from_iso2022_gen, cs_add_unicodedata_to_iso2022_gen, cs_cmp_iso2022_gen, cs_stream_from_iso2022, cs_can_ascii_iso2022_gen, cs_streamclip_from_iso2022, cs_clip_from_iso2022_gen, cs_find_pattern_from_iso2022_gen, cs_add_streambytes_to_iso2022_gen, cs_find_iso2022, cs_remove_control_iso2022_gen, cs_add_state_to_iso2022_gen, cs_init_s_iso2022, cs_free_s_iso2022_gen, cs_add_streambyte_to_s_iso2022_gen, cs_soft_reset_s_iso2022_gen, cs_give_unicode_from_s_iso2022, cs_s_iso2022_same_char_gen, cs_s_iso2022_printable_gen, cs_s_iso2022_is_onebyte_gen, cs_iso2022_properties_gen, cs_estimate_clip_iso2022, cs_iso2022_info_set_iso2022, &cs_euc, }; struct charset_type cs_euc = { "euc", cs_init_iso2022_gen, cs_free_iso2022_gen, cs_add_streambyte_to_iso2022_gen, cs_add_intdata_to_iso2022_gen, cs_check_length_iso2022_gen, cs_give_unicode_from_iso2022_gen, cs_add_unicodedata_to_iso2022_gen, cs_cmp_iso2022_gen, cs_stream_from_euc, cs_can_ascii_iso2022_gen, cs_streamclip_from_euc, cs_clip_from_iso2022_gen, cs_find_pattern_from_iso2022_gen, cs_add_streambytes_to_iso2022_gen, cs_find_euc, cs_remove_control_iso2022_gen, cs_add_state_to_iso2022_gen, cs_init_s_euc, cs_free_s_iso2022_gen, cs_add_streambyte_to_s_iso2022_gen, cs_soft_reset_s_iso2022_gen, cs_give_unicode_from_s_iso2022, cs_s_iso2022_same_char_gen, cs_s_iso2022_printable_gen, cs_s_iso2022_is_onebyte_gen, cs_iso2022_properties_gen, cs_estimate_clip_iso2022, cs_iso2022_info_set_euc, NULL }; /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */