static char rcsid[] = "@(#)$Id: string.c,v 1.50.18.1 2007/08/25 06:35:47 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.50.18.1 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
#include "headers.h"
#include "s_me.h"
#include "cs_imp.h"
#ifdef USE_DLOPEN
#include "shared_imp.h"
#endif
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 CONST char *cus2s P_((const unsigned char *str));
static CONST char *cus2s(str)
CONST unsigned char *str;
{
return (CONST char *)str;
}
#define INVALID_MAP(cs) ((cs)->map_info && \
(cs)->map_info->map_type != (cs)->charset_type)
int verify_string(str)
struct string *str;
{
if (!str) {
DPRINT(Debug,1,(&Debug,"verify_string=0: FAILURE str = NULL\n"));
return 0;
}
if (!str->string_type) {
DPRINT(Debug,1,(&Debug,
"verify_string=0: FAILURE str->string_type = NULL (str=%p)\n",
str));
return 0;
}
if (CS_charset_magic != str->string_type->magic) {
DPRINT(Debug,1,(&Debug,
"verify_string=0: FAILURE Bad magic (str=%p)\n",
str));
return 0;
}
if (INVALID_MAP(str->string_type)) {
DPRINT(Debug,1,(&Debug,
"verify_string=0: FAILURE Bad map (str=%p)\n",
str));
return 0;
}
return 1;
}
static struct string * malloc_string P_((charset_t set));
static struct string * malloc_string(set)
charset_t set;
{
struct string * res = safe_malloc(sizeof (struct string));
/* defined in hdrs/defs.h */
bzero((void *)res,sizeof (struct string));
if (CS_charset_magic != set->magic)
panic("STRING PANIC",__FILE__,__LINE__,"malloc_string",
"Bad magic number (set)",0);
if (INVALID_MAP(set))
panic("STRING PANIC",__FILE__,__LINE__,"malloc_string",
"Bad map (set)",0);
/* Initialize associated map if not done already ... */
if (set->map_info && !set->map_info->map_initialized)
set->map_info->map_init_it(set->map_info);
res->string_type = set;
res->p = safe_malloc(sizeof (struct str_private_data));
/* defined in hdrs/defs.h */
bzero((void *)res->p,sizeof (struct str_private_data));
res->p->magic = CS_str_magic;
res->p->len = 0;
res->p->state = NULL;
res->p->private_flag = 0; /* Mostly not used */
res->p->lang = NULL;
res->string_type->charset_type->cs_init_it(res);
return res;
}
/* ------------------------------------------------------------------------- */
struct string * new_string(set)
charset_t set;
{
struct string *res;
DPRINT(Debug,60,(&Debug,"new_string(set=%p '%s')\n",
set,
set->MIME_name ? set->MIME_name : "<none>"));
res = malloc_string(set);
DPRINT(Debug,60,(&Debug,"new_string=%p (type=%p '%s')\n",
res,
res->string_type->charset_type,
res->string_type->charset_type->type_name));
return res;
}
struct string * new_langstring(set,lang)
charset_t set;
char *lang;
{
struct string *res;
DPRINT(Debug,60,(&Debug,"new_langstring(set=%p '%s', lang=%s)\n",
set,
set->MIME_name ? set->MIME_name : "<none>",
lang));
res = malloc_string(set);
res->p->lang = safe_strdup(lang);
DPRINT(Debug,60,(&Debug,"new_langstring=%p (type=%p '%s')\n",
res,
res->string_type->charset_type,
res->string_type->charset_type->type_name));
return res;
}
struct string * new_string2 P_((charset_t set,
CONST unsigned char *data));
struct string * new_string2(set,data)
charset_t set;
CONST unsigned char *data;
{
struct string * res;
int ERRORS = 0;
DPRINT(Debug,60,(&Debug,
"new_string2: set=%p '%s'\n",
set,
set->MIME_name ? set->MIME_name : "<none>"));
if (set == display_charset || set == system_charset) {
DPRINT(Debug,61,(&Debug,
"new_string2 -- data=%s\n",data));
}
res = malloc_string(set);
res->string_type->charset_type->
cs_add_streambytes_to_it(res,
strlen(cus2s(data)),
data,&ERRORS);
DPRINT(Debug,60,(&Debug,
"new_string2=%p (type=%p '%s'): len=%d ERRORS=%d\n",
res,
res->string_type->charset_type,
res->string_type->charset_type->type_name,
res->p->len,
ERRORS));
return res;
}
void free_string(str)
struct string **str;
{
if (CS_charset_magic != (*str)->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"free_string",
"Bad magic number (string type)",0);
if (INVALID_MAP((*str)->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"free_string",
"Bad map (string type)",0);
DPRINT(Debug,60,(&Debug,"free_string(*str=%p) ('%s'; type=%p '%s')\n",
(*str),
(*str)->string_type->MIME_name ?
(*str)->string_type->MIME_name : "<none>",
(*str)->string_type->charset_type,
(*str)->string_type->charset_type->type_name));
if ((*str)->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"free_string",
"Bad magic number (str_private_data)",0);
if ((*str)->p->state &&
(*str)->p->state->charset != (*str)->string_type)
panic("STRING PANIC",__FILE__,__LINE__,"free_string",
"Bad magic number (state charset)",0);
(*str)->string_type->charset_type->cs_free_it(*str);
if ((*str)->p->state) {
free_state_internal(&((*str)->p->state));
}
if ((*str)->p->lang) {
free((*str)->p->lang);
(*str)->p->lang = NULL;
}
free((*str)->p);
(*str)->p = NULL;
(*str)->string_type = NULL;
free(*str);
*str = NULL;
}
CONST char * get_string_lang(str)
CONST struct string *str;
{
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"get_string_lang",
"Bad magic number (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"get_string_lang",
"Bad magic number (str_private_data)",0);
return str->p->lang;
}
CONST char * get_string_MIME_name(str)
CONST struct string *str;
{
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"get_string_MIME_name",
"Bad magic number (string type)",0);
return str->string_type->MIME_name;
}
int add_streambyte_to_string(str,ch)
struct string *str;
int ch;
{
int r;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_streambyte_to_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"add_streambyte_to_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_streambyte_to_string",
"Bad magic number (str_private_data)",0);
if (str->p->state &&
str->p->state->charset != str->string_type)
panic("STRING PANIC",__FILE__,__LINE__,"add_streambyte_to_string",
"Bad magic number (state charset)",0);
DPRINT(Debug,60,(&Debug,
"add_streambyte_to_string: str=%p ('%s'; type=%p '%s')\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
if (str->string_type == display_charset ||
str->string_type == system_charset) {
DPRINT(Debug,61,(&Debug,
"add_streambyte_to_string -- ch=%d '%c'\n",ch,ch));
} else {
DPRINT(Debug,61,(&Debug,
"add_streambyte_to_string -- ch=%d\n",ch));
}
r = str->string_type->charset_type->cs_add_streambyte_to_it(str,ch);
DPRINT(Debug,60,(&Debug,
"add_streambyte_to_string=%d\n",
r));
return r;
}
int add_streambytes_to_string(str,count,data, errors)
struct string *str;
int count;
CONST unsigned char *data;
int *errors;
{
int r;
int ERRORS = 0;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_streambytes_to_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"add_streambytes_to_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_streambytes_to_string",
"Bad magic number (str_private_data)",0);
if (str->p->state &&
str->p->state->charset != str->string_type)
panic("STRING PANIC",__FILE__,__LINE__,"add_streambytes_to_string",
"Bad magic number (state charset)",0);
DPRINT(Debug,60,(&Debug,
"add_streambytes_to_string: str=%p, count=%d, data=%p ('%s'; type=%p '%s')\n",
str,count,data,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
if (str->string_type == display_charset ||
str->string_type == system_charset) {
DPRINT(Debug,61,(&Debug,
"add_streambytes_to_string -- data='%.*s'\n",
count,data));
}
r = str->string_type->charset_type->cs_add_streambytes_to_it(str, count,data, &ERRORS);
if (errors)
*errors = ERRORS;
DPRINT(Debug,60,(&Debug,"add_streambytes_to_string=%d ERRORS=%d\n",
r,ERRORS));
return r;
}
static CONST unsigned char * csUs P_((const char *str));
static CONST unsigned char * csUs(str)
CONST char *str;
{
return (CONST unsigned char *)str;
}
static CONST char * cUss P_((const unsigned char *str));
static CONST char * cUss(str)
CONST unsigned char *str;
{
return (CONST char *)str;
}
static void add_name_to_string P_((struct string *str,
CONST unsigned char *ascii));
static void add_name_to_string(str,ascii)
struct string *str;
CONST unsigned char *ascii;
{
int l = strlen(cUss(ascii));
int i;
uint16 * vector = safe_malloc ( (l) * sizeof (uint16));
/* Ascii and UNICODE have save codes ... */
for (i = 0; i < l ; i++)
/* ascii string is unsigned ... */
if (ascii[i] < 128)
vector[i] = ascii[i];
else
vector[i] = '?';
str->string_type->charset_type->cs_add_unicodedata_to_it(str,l,vector);
free(vector);
}
void add_unicode_to_string(str,len,vector)
struct string *str;
int len;
CONST uint16 *vector;
{
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_unicode_to_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"add_unicode_to_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_unicode_to_string",
"Bad magic number (str_private_data)",0);
if (len < 0)
panic("STRING PANIC",__FILE__,__LINE__,"add_unicode_to_string",
"Bad vector len",0);
DPRINT(Debug,60,(&Debug,
"add_unicode_to_string(%p,len=%d) ('%s'; type=%p '%s')\n",
str,len,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
str->string_type->charset_type->cs_add_unicodedata_to_it(str,len,vector);
DPRINT(Debug,60,(&Debug,
"add_unicode_to_string: len = %d\n",str->p->len));
}
struct string * cat_strings(str1,str2,printind)
CONST struct string *str1;
CONST struct string *str2;
int printind;
{
struct string *ret = NULL;
if (CS_charset_magic != str1->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"cat_strings",
"Bad magic number (string type)",0);
if (CS_charset_magic != str2->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"cat_strings",
"Bad magic number (string type)",0);
if (INVALID_MAP(str1->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"cat_strings",
"Bad map (string type)",0);
if (INVALID_MAP(str2->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"cat_strings",
"Bad map (string type)",0);
if (str1->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"cat_strings",
"Bad magic number (str_private_data)",0);
if (str2->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"cat_strings",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"cat_strings(%p,%p) ('%s'; type=%p '%s', len=%d), ('%s'; type=%p '%s', len=%d)\n",
str1,str2,
str1->string_type->MIME_name ?
str1->string_type->MIME_name : "<none>",
str1->string_type->charset_type,
str1->string_type->charset_type->type_name,
str1->p->len,
str2->string_type->MIME_name ?
str2->string_type->MIME_name : "<none>",
str2->string_type->charset_type,
str2->string_type->charset_type->type_name,
str2->p->len));
/* Check lengths */
str1->string_type->charset_type->cs_check_length_it(str1);
str2->string_type->charset_type->cs_check_length_it(str2);
/* Either one is empty, produce other,
but not if other is not printable and printind is set.
*/
if (str1->p->len == 0 &&
(!printind ||
0 != (charset_properties(str2 -> string_type) & CS_mapping))) {
ret = malloc_string(str2 -> string_type);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2);
if (str2->p->lang) {
ret->p->lang = safe_strdup(str2->p->lang);
}
} else if (str2->p->len == 0 &&
(!printind ||
0 != (charset_properties(str1 -> string_type) & CS_mapping))) {
ret = malloc_string(str1 -> string_type);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1);
if (str1->p->lang) {
ret->p->lang = safe_strdup(str1->p->lang);
}
} else if (str1 -> string_type == str2 -> string_type) {
/* 1) Same CHARSET */
ret = malloc_string(str1 -> string_type);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2);
if (str1->p->lang && str2->p->lang &&
0 == strcmp(str1->p->lang, str2->p->lang)) {
ret->p->lang = safe_strdup(str1->p->lang);
}
} else if (str1 -> string_type -> charset_type ==
str2 -> string_type -> charset_type &&
charset_superset_of(str1 -> string_type,str2 -> string_type)) {
/* 2) CHARSET of str1 is superset of CHARSET of str2 */
ret = malloc_string(str1 -> string_type);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2);
if (str1->p->lang && str2->p->lang &&
0 == strcmp(str1->p->lang, str2->p->lang)) {
ret->p->lang = safe_strdup(str1->p->lang);
}
} else if (str1 -> string_type -> charset_type ==
str2 -> string_type -> charset_type &&
charset_superset_of(str2 -> string_type,str1 -> string_type)) {
/* 3) CHARSET of str2 is superset of CHARSET of str1 */
ret = malloc_string(str2 -> string_type);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2);
if (str1->p->lang && str2->p->lang &&
0 == strcmp(str1->p->lang, str2->p->lang)) {
ret->p->lang = safe_strdup(str1->p->lang);
}
} else if (printind &&
0 != (charset_properties(str1 -> string_type) & CS_mapping) &&
0 == (charset_properties(str2 -> string_type) & CS_mapping) &&
str2 -> string_type -> MIME_name) {
/* Add just str1 and indicate that 2 is not mappable */
ret = malloc_string(str1 -> string_type);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str1);
add_name_to_string(ret,csUs("[?"));
add_name_to_string(ret,csUs(str2 -> string_type -> MIME_name));
add_name_to_string(ret,csUs("?]"));
} else if (printind &&
0 != (charset_properties(str2 -> string_type) & CS_mapping) &&
0 == (charset_properties(str1 -> string_type) & CS_mapping) &&
str1 -> string_type -> MIME_name) {
/* Add just str2 and indicate that 1 is not mappable */
ret = malloc_string(str2 -> string_type);
add_name_to_string(ret,csUs("[?"));
add_name_to_string(ret,csUs(str2 -> string_type -> MIME_name));
add_name_to_string(ret,csUs("?]"));
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str2);
} else if (0 == str1->p->len && 0 == str2->p->len) {
/* Avoid mallocing null vector */
ret = malloc_string(display_charset);
} else {
/* 4) Unrelated CHARSETs -- so we try use display charset or UTF-8
instead
*/
int i;
int l = 0;
uint16 * vector = safe_malloc ( (str1->p->len + str2->p->len) *
sizeof (uint16));
charset_t target_set = MIME_name_to_charset("UTF-8",0);
if (!target_set)
panic("CHARSET PANIC",__FILE__,__LINE__,"cat_strings",
"UTF-8 not found",0);
/* If display charset is superset of charset of strings
use it
*/
if (0 != (charset_properties(display_charset) & CS_mapping) &&
( charset_superset_of(display_charset, str1 -> string_type) &&
charset_superset_of(display_charset, str2 -> string_type)
||
0 != (charset_properties(display_charset) & CS_universal_set)
))
target_set = display_charset;
if (0 == (charset_properties(target_set) & CS_mapping)) {
DPRINT(Debug,5,(&Debug,
"cat_strings: selected charset do not have mapping info, using ASCII as target set\n"));
target_set = ASCII_SET;
}
ret = malloc_string(target_set);
for (i = 0; i < str1->p->len; i++) {
int found;
uint16 c =
str1->string_type->charset_type->
cs_give_unicode_from_it(str1,i,&found);
vector[l++] = c;
}
for (i = 0; i < str2->p->len; i++) {
int found;
uint16 c =
str2->string_type->charset_type->
cs_give_unicode_from_it(str2,i,&found);
vector[l++] = c;
}
ret->string_type->charset_type->cs_add_unicodedata_to_it(ret,l,vector);
free(vector);
if (str1->p->lang && str2->p->lang &&
0 == strcmp(str1->p->lang, str2->p->lang)) {
ret->p->lang = safe_strdup(str1->p->lang);
}
}
DPRINT(Debug,60,(&Debug,
"cat_strings=%p ('%s'; type=%p '%s'): len=%d\n",
ret,
ret->string_type->MIME_name ?
ret->string_type->MIME_name : "<none>",
ret->string_type->charset_type,
ret->string_type->charset_type->type_name,
ret->p->len));
return ret;
}
int string_len(str)
CONST struct string *str;
{
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_len",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"string_len",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_len",
"Bad magic number (str_private_data)",0);
/* Check length */
str->string_type->charset_type->cs_check_length_it(str);
DPRINT(Debug,60,(&Debug,"string_len(%p)=%d ('%s'; type=%p '%s')\n",
str,str->p->len,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
return str->p->len;
}
int string_cmp(str1,str2,unknown_val)
CONST struct string *str1;
CONST struct string *str2;
int unknown_val;
{
int ret = 0;
int not_found = 0;
int i;
int str1_len;
int str2_len;
cs_give_unicode_from_string *str1_get_unicode;
cs_give_unicode_from_string *str2_get_unicode;
if (CS_charset_magic != str1->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_cmp",
"Bad magic number (string type)",0);
if (CS_charset_magic != str2->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_cmp",
"Bad magic number (string type)",0);
if (INVALID_MAP(str1->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"string_cmp",
"Bad map (string type)",0);
if (INVALID_MAP(str2->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"string_cmp",
"Bad map (string type)",0);
if (str1->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_cmp",
"Bad magic number (str_private_data)",0);
if (str2->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_cmp",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"string_cmp(%p,%p,unknown_val=%d) ('%s'; type=%p '%s', len=%d), ('%s'; type=%p '%s', len=%d)\n",
str1,str2,unknown_val,
str1->string_type->MIME_name ?
str1->string_type->MIME_name : "<none>",
str1->string_type->charset_type,
str1->string_type->charset_type->type_name,
str1->p->len,
str2->string_type->MIME_name ?
str2->string_type->MIME_name : "<none>",
str2->string_type->charset_type,
str2->string_type->charset_type->type_name,
str2->p->len));
/* Check lengths -- do compressions and so on */
str1->string_type->charset_type->cs_check_length_it(str1);
str2->string_type->charset_type->cs_check_length_it(str2);
str1_len = str1->p->len;
str2_len = str2->p->len;
str1_get_unicode = str1->string_type->charset_type->cs_give_unicode_from_it;
str2_get_unicode = str2->string_type->charset_type->cs_give_unicode_from_it;
/* Make unicode compare first to make comparision to stable */
for (i = 0; i < str1_len && i < str2_len; i++) {
int found1,found2;
uint16 c1 = str1_get_unicode(str1,i,&found1);
uint16 c2 = str2_get_unicode(str2,i,&found2);
if (!found1 || !found2) {
ret = 0;
not_found = 1;
break;
} else if (c1 < c2)
ret = -1;
else if (c1 > c2)
ret = 1;
if (ret != 0)
break;
}
DPRINT(Debug,61,(&Debug,
"string_cmp: i=%d, str1 len=%d, str2 len=%d, not_found=%d\n",
i,str1->p->len,str2->p->len,not_found));
if (!not_found) {
if (0 == ret && i < str1->p->len)
ret = 1;
if (0 == ret && i < str2->p->len)
ret = -1;
DPRINT(Debug,61,(&Debug,
"string_cmp: unicode cmp ret=%d\n",ret));
}
if (0 == ret && str1 -> string_type == str2 -> string_type) {
ret = str1 -> string_type->charset_type->cs_cmp_it(str1,str2);
DPRINT(Debug,61,(&Debug,
"string_cmp: cs_cmp_it ret=%d\n",ret));
if (ret < 0)
ret = -1;
else if (ret > 0)
ret = 1;
} else if (0 == ret && not_found) {
DPRINT(Debug,61,(&Debug,"string_cmp: Unable to compare values!\n"));
ret = unknown_val;
}
DPRINT(Debug,60,(&Debug,"string_cmp=%d\n",ret));
return ret;
}
struct string * dup_string(str)
CONST struct string *str;
{
struct string *ret;
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"dup_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,"dup_string: str=%p ('%s'; type=%p '%s')\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
ret = malloc_string(str -> string_type);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str);
if (str->p->lang) {
ret->p->lang = safe_strdup(str->p->lang);
}
DPRINT(Debug,60,(&Debug,"dup_string=%p ('%s'; type=%p '%s')\n",
ret,
ret->string_type->MIME_name ?
ret->string_type->MIME_name : "<none>",
ret->string_type->charset_type,
ret->string_type->charset_type->type_name));
return ret;
}
struct string * convert_string(set,str,printind)
charset_t set;
CONST struct string *str;
int printind;
{
struct string *ret = malloc_string(set);
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"convert_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"convert_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"convert_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"convert_string(set=%p '%s',str=%p) ('%s', type=%p '%s', len=%d)\n",
set,
set->MIME_name ? set->MIME_name : "<none>",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
str->p->len));
/* Check lengths -- do compressions and so on */
str->string_type->charset_type->cs_check_length_it(str);
if (0 == str->p->len) {
/* 0) Empty string is always convertable
because nothing need to be added to result
*/
} else if (set == str->string_type) {
/* 1) Same charset */
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str);
if (str->p->lang) {
ret->p->lang = safe_strdup(str->p->lang);
}
} else if (printind &&
0 != (charset_properties(set) & CS_mapping) &&
0 == (charset_properties(str -> string_type) & CS_mapping) &&
str -> string_type -> MIME_name) {
/* Just indicate that str is not mappable */
add_name_to_string(ret,csUs("[?"));
add_name_to_string(ret,csUs(str -> string_type -> MIME_name));
add_name_to_string(ret,csUs("?]"));
} else {
/* 2) Different charset */
int i;
int l = 0;
uint16 * vector = safe_malloc ( (str->p->len) * sizeof (uint16));
for (i = 0; i < str->p->len; i++) {
int found;
uint16 c =
str->string_type->charset_type->
cs_give_unicode_from_it(str,i,&found);
vector[l++] = c;
}
ret->string_type->charset_type->cs_add_unicodedata_to_it(ret,l,vector);
free(vector);
if (str->p->lang) {
ret->p->lang = safe_strdup(str->p->lang);
}
}
DPRINT(Debug,60,(&Debug,
"convert_string=%p ('%s'; type=%p '%s'): len=%d\n",
ret,
ret->string_type->MIME_name ?
ret->string_type->MIME_name : "<none>",
ret->string_type->charset_type,
ret->string_type->charset_type->type_name,
ret->p->len));
return ret;
}
unsigned char *stream_from_string(str, printable,terminal)
CONST struct string *str;
int printable;
screen_info_p terminal;
{
int reslen;
unsigned char * ret;
char *ret0 = NULL;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"stream_from_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"stream_from_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"stream_from_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,"stream_from_string: ret=%p ('%s'; type=%p '%s')\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
if (terminal && str->string_type->iso2022_info)
ret0 = terminal_charset_post_init(terminal,
str->string_type->iso2022_info);
/* Catenate order is ret == ret0 + ret */
ret = str->string_type->charset_type->cs_stream_from_it(str,
printable,
terminal,
&reslen);
DPRINT(Debug,60,(&Debug,
"stream_from_string -- reslen=%d\n",reslen));
if (str->string_type == display_charset) {
DPRINT(Debug,61,(&Debug,
"stream_from_string -- ret='%s'%s\n",
ret,
ret0 ? " (without post init)" : ""));
}
if (ret0) {
int i;
DPRINT(Debug,8,(&Debug,"Post init terminal charset %s (",
str->string_type->MIME_name ?
str->string_type->MIME_name :
"<no MIME name>"));
for (i = 0; ret0[i]; i++) {
DPRINT(Debug,8,(&Debug,"%s%02X",
i ? " " : "", ret0[i]));
}
DPRINT(Debug,8,(&Debug,")\n"));
/* Catenate order is ret == ret0 + ret */
ret0 = strmcat(ret0,us2s(ret));
free(ret);
ret = s2us(ret0);
}
DPRINT(Debug,60,(&Debug,"stream_from_string=%p\n",
ret));
return ret;
}
/* result is malloced */
void bytestream_from_string(str,res,reslen)
CONST struct string *str;
char **res;
int *reslen;
{
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"bytestream_from_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"bytestream_from_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"bytestream_from_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"bytestream_from_string: str=%p ('%s'; type=%p '%s')\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
*res = us2s(str->string_type->charset_type->cs_stream_from_it(str,0,NULL,
reslen));
DPRINT(Debug,60,(&Debug,
"bytestream_from_string: *res=%p, reslen=%d\n",
*res,reslen));
}
unsigned char *streamclip_from_string(str,pos,len,terminal,printable_len)
CONST struct string *str;
int *pos;
int len;
screen_info_p terminal;
struct cs_printable_len *printable_len;
{
int p = *pos;
unsigned char * ret;
char *ret0 = NULL;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string",
"Bad magic number (str_private_data)",0);
if (printable_len && !terminal)
panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string",
"printable_len argument requires terminal argument",0);
if (printable_len &&
0 == ( CS_printable_len & str->string_type->charset_type->cs_it_properties(str->string_type)))
panic("STRING PANIC",__FILE__,__LINE__,"streamclip_from_string",
"Charset does not support printable_len argument",0);
if (terminal && str->string_type->iso2022_info)
ret0 = terminal_charset_post_init(terminal,
str->string_type->iso2022_info);
/* Catenate order is ret == ret0 + ret */
DPRINT(Debug,60,(&Debug,
"streamclip_from_string(%p,%d,%d) ('%s'; type=%p '%s')\n",
str,p,len,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
ret =
str->string_type->charset_type->cs_streamclip_from_it(str,pos,len,
terminal,
printable_len);
if (str->string_type == display_charset) {
DPRINT(Debug,61,(&Debug,
"streamclip_from_string -- ret='%s'%s\n",
ret,
ret0 ? " (without post init)" : ""));
}
if (ret0) {
int i;
DPRINT(Debug,8,(&Debug,
"Post init terminal charset %s (",
str->string_type->MIME_name ?
str->string_type->MIME_name :
"<no MIME name>"));
for (i = 0; ret0[i]; i++) {
DPRINT(Debug,8,(&Debug,"%s%02X",
i ? " " : "", ret0[i]));
}
DPRINT(Debug,8,(&Debug,")\n"));
/* Catenate order is ret == ret0 + ret */
ret0 = strmcat(ret0,us2s(ret));
free(ret);
ret = s2us(ret0);
}
DPRINT(Debug,60,(&Debug,
"streamclip_from_string [%d(..%d)] =%p ('%s'; type=%p '%s')",
p,*pos,ret,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
if (printable_len) {
DPRINT(Debug,60,(&Debug,
" printable_len: max_len=%d ret_len=%d",
printable_len->max_len,
printable_len->ret_len));
}
DPRINT(Debug,60,(&Debug,"\n"));
return ret;
}
int estimate_clip_string(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;
{
int ret;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string",
"Bad magic number (str_private_data)",0);
if (0 == ( CS_printable_len &
str->string_type->charset_type->cs_it_properties(str->string_type)))
panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string",
"Charset does not support function",0);
if (!printable_len || !terminal)
panic("STRING PANIC",__FILE__,__LINE__,"estimate_clip_string",
"printable_len and terminal required",0);
ret =
str->string_type->charset_type->cs_estimate_clip_it(str,pos,len,
terminal,
printable_len);
DPRINT(Debug,60,(&Debug,
"estimate_clip_it(%p,%d,%d,...) =%d ('%s'; type=%p '%s')",
str,pos,len,ret,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
DPRINT(Debug,60,(&Debug,
" printable_len: max_len=%d ret_len=%d\n",
printable_len->max_len,
printable_len->ret_len));
return ret;
}
struct string *clip_from_string(str,pos,len)
CONST struct string *str;
int *pos;
int len;
{
struct string *ret = malloc_string(str->string_type);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"clip_from_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"clip_from_string(%p,%d,%d) ('%s'; type=%p '%s')\n",
str,*pos,len,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
/* It is assumed that compressions are done
.. ie string_length() function
is called
*/
str->string_type->charset_type->cs_clip_from_it(ret,str,pos,len);
DPRINT(Debug,60,(&Debug,
"clip_from_string=%p ('%s'; type=%p '%s'): len=%d\n",
ret,
ret->string_type->MIME_name ?
ret->string_type->MIME_name : "<none>",
ret->string_type->charset_type,
ret->string_type->charset_type->type_name,
ret->p->len));
return ret;
}
struct string *ascify_string(str)
CONST struct string *str;
{
int can_ascii;
charset_t ascii_ptr = MIME_name_to_charset("US-ASCII",0);
struct string *ret;
if (!ascii_ptr)
panic("STRING PANIC",__FILE__,__LINE__,"ascify_string",
"US-ASCII not found",0);
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"ascify_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"ascify_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"ascify_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"ascify_string(%p) ('%s'; type=%p '%s', len=%d)\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
str->p->len));
/* Check lengths -- do compressions and so on */
str->string_type->charset_type->cs_check_length_it(str);
can_ascii = str->string_type->charset_type->cs_can_ascii_it(str);
if (can_ascii) {
int i;
int l = 0;
uint16 * vector = safe_malloc ( (str->p->len) * sizeof (uint16));
ret = malloc_string(ascii_ptr);
for (i = 0; i < str->p->len; i++) {
int found;
uint16 c =
str->string_type->charset_type->
cs_give_unicode_from_it(str,i,&found);
vector[l++] = c;
}
ret->string_type->charset_type->cs_add_unicodedata_to_it(ret,l,vector);
free(vector);
} else {
ret = malloc_string(str -> string_type);
ret->string_type->charset_type->cs_add_intdata_to_it(ret,str);
}
if (str->p->lang) {
ret->p->lang = safe_strdup(str->p->lang);
}
DPRINT(Debug,60,(&Debug,
"ascify_string=%p ('%s'; type=%p '%s'): len=%d\n",
ret,
ret->string_type->MIME_name ?
ret->string_type->MIME_name : "<none>",
ret->string_type->charset_type,
ret->string_type->charset_type->type_name,
ret->p->len));
return ret;
}
int can_ascii_string(str)
CONST struct string *str;
{
int ret;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"can_ascii_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"can_ascii_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"can_ascii_string",
"Bad magic number (str_private_data)",0);
ret= str->string_type->charset_type->cs_can_ascii_it(str);
DPRINT(Debug,60,(&Debug,
"can_ascii_string(%p)=%d ('%s'; type=%p '%s', len=%d)\n",
str,ret,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
str->p->len));
return ret;
}
void add_ascii_to_string(str,ascii)
struct string *str;
CONST unsigned char *ascii;
{
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_ascii_to_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"add_ascii_to_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_ascii_to_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"add_ascii_to_string(%p) ('%s'; type=%p '%s')\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
DPRINT(Debug,61,(&Debug,
"add_ascii_to_string -- ascii=%s\n",ascii));
add_name_to_string(str,ascii);
DPRINT(Debug,60,(&Debug,
"add_ascii_to_string: len = %d\n",str->p->len));
}
void fill_ascii_to_string(str,count,ascii)
struct string *str;
int count;
unsigned int ascii;
{
int i;
uint16 * vector;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string",
"Bad map (string type)",0);
if (count < 1)
panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string",
"bad count",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string",
"Bad magic number (str_private_data)",0);
if (str->p->state) {
if (str->p->state->charset != str->string_type)
panic("STRING PANIC",__FILE__,__LINE__,"fill_ascii_to_string",
"Bad magic number (state charset)",0);
free_state_internal(&(str->p->state));
}
vector = safe_malloc ( count * sizeof (uint16));
/* Ascii and UNICODE have save codes ... */
for (i = 0; i < count ; i++)
/* ascii is unsigned ... */
if (ascii < 128)
vector[i] = ascii;
else
vector[i] = '?'; /* XXX */
str->string_type->charset_type->cs_add_unicodedata_to_it(str,count,vector);
free(vector);
DPRINT(Debug,60,(&Debug,
"fill_ascii_to_string(%p,%d,%d) ('%s'; type=%p '%s'): len=%d\n",
str,count,ascii,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
str->p->len));
}
struct string *collapse_spaces_from_string(str)
const struct string *str;
{
struct charset_type * cstype;
struct string *ret;
int i, j = 0;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"collapse_spaces_from_string",
"Bad magic number (string type)",0);
cstype = str->string_type->charset_type;
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"collapse_spaces_from_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"collapse_spaces_from_string(%p) ('%s'; type=%p '%s', len=%d)\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
cstype,
cstype->type_name,
str->p->len));
/* Check lengths -- do compressions and so on */
str->string_type->charset_type->cs_check_length_it(str);
ret = malloc_string(str->string_type);
for (i = 0; i < str->p->len; i = j) {
int is_space = 0;
int POS;
int len;
/* Scan to next space */
for (j = i; j < str->p->len; j++) {
int found;
uint16 c = cstype->cs_give_unicode_from_it(str,j,&found);
if (!found) {
DPRINT(Debug,61,(&Debug,
"collapse_spaces_from_string -- failing at %d -- no unicode\n",
i));
} else
is_space = unicode_ch(c,UOP_space);
if (is_space)
break;
}
POS = i;
len = j-i;
if (len > 0) {
struct string *tmp = malloc_string(str->string_type);
DPRINT(Debug,61,(&Debug,
"collapse_spaces_from_string: clipping no space from %d -- len %d\n",
POS,len));
cstype->cs_clip_from_it(tmp,str,&POS,len);
cstype->cs_add_intdata_to_it(ret,tmp);
free_string(&tmp);
}
/* Skip over space */
if (is_space) {
uint16 SPACE_val = 0x0020;
cstype->cs_add_unicodedata_to_it(ret,1,&SPACE_val);
for (; j < str->p->len; j++) {
int found;
uint16 c = cstype->cs_give_unicode_from_it(str,j,&found);
if (!found) {
DPRINT(Debug,61,(&Debug,
"collapse_spaces_from_string -- failing at %d -- no unicode\n",
j));
} else
is_space = unicode_ch(c,UOP_space);
if (!is_space)
break;
}
}
}
DPRINT(Debug,60,(&Debug,
"collapse_spaces_from_string=%p ('%s'; type=%p '%s'): len=%d\n",
ret,
ret->string_type->MIME_name ?
ret->string_type->MIME_name : "<none>",
ret->string_type->charset_type,
ret->string_type->charset_type->type_name,
ret->p->len));
return ret;
}
struct string *skip_ascii_head_from_string(str,ascii,ignore_case)
CONST struct string *str;
CONST unsigned char *ascii;
int ignore_case;
{
struct string *ret = malloc_string(str->string_type);
int X = 0;
int x;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"skip_ascii_head_from_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"skip_ascii_head_from_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"skip_ascii_head_from_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"skip_ascii_head_from_string(%p) ('%s'; type=%p '%s', len=%d)\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
str->p->len));
DPRINT(Debug,60,(&Debug,
"skip_ascii_head_from_string -- ascii=%s\n",ascii));
/* Check lengths -- do compressions and so on */
str->string_type->charset_type->cs_check_length_it(str);
while(1) {
int i;
CONST unsigned char * p = ascii;
DPRINT(Debug,61,(&Debug,
"skip_ascii_head_from_string -- starting pos %d\n",
X));
for (i = X;
/* ascii string is unsigned ... */
*p && *p < 128 && i < str->p->len;
i++, p++) {
int found;
uint16 c =
str->string_type->charset_type->
cs_give_unicode_from_it(str,i,&found);
unsigned char c1 = *p;
if (!found) {
DPRINT(Debug,61,(&Debug,
"skip_ascii_head_from_string -- failing at %d -- no unicode\n",
i));
break;
}
if (ignore_case) {
c = unicode_ch(c,UOP_lowercase);
if (!c) {
DPRINT(Debug,61,(&Debug,
"skip_ascii_head_from_string -- failing at %d -- no lowercasing\n",
i));
break;
}
}
if (ignore_case && c1 >= 0x41 && c1 <= 0x5A) {
c1 = ( c1 - 0x41) + 0x61;
}
if (c1 != c) {
DPRINT(Debug,61,(&Debug,
"skip_ascii_head_from_string -- failing at %d -- mismatch %02X (%c) <> %04X\n",
i,c1,c1,c));
break;
}
}
if (*p) {
DPRINT(Debug,61,(&Debug,
"skip_ascii_head_from_string -- hit end at %d\n",
i));
break;
}
/* Try next sequence */
X = i;
DPRINT(Debug,61,(&Debug,
"skip_ascii_head_from_string -- got %d\n",
X));
}
x = X;
str->string_type->charset_type->cs_clip_from_it(ret,str,&X,str->p->len);
DPRINT(Debug,60,(&Debug,
"skip_ascii_head_from_string=%p ('%s'; type=%p '%s'): len=%d (clip=%d..%d)\n",
ret,
ret->string_type->MIME_name ?
ret->string_type->MIME_name : "<none>",
ret->string_type->charset_type,
ret->string_type->charset_type->type_name,
ret->p->len,x,X));
return ret;
}
/* WARNING: get_word_from_string does everything via Unicode
* may lose information on some situations
*/
int get_word_from_string(str,word,pos,flags,ascii_delim, found_delim)
CONST struct string *str;
struct string **word;
int *pos;
int flags;
CONST unsigned char *ascii_delim;
uint16 *found_delim;
{
int lowercase = flags & GWF_lowercase;
int trim = flags & GWF_trim_space;
int X = *pos;
int last_X;
int X1;
uint16 *data = NULL;
int dx = 0;
int ret = 0;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"get_word_from_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"get_word_from_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"get_word_from_string",
"Bad magic number (str_private_data)",0);
*word = malloc_string(str->string_type);
DPRINT(Debug,60,(&Debug,
"get_word_from_string(%p) ('%s'; type=%p '%s', len=%d), *pos=%d\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
str->p->len,
*pos));
if (found_delim)
*found_delim = 0;
/* Check lengths -- do compressions and so on */
str->string_type->charset_type->cs_check_length_it(str);
if (str->p->len < 1)
goto fail;
/* SKIP delim */
while (X < str->p->len) {
int found;
int sp;
uint16 c = str->string_type->charset_type->
cs_give_unicode_from_it(str,X,&found);
/* ascii string is unsigned ... */
CONST unsigned char *y = NULL;
if (!found) {
DPRINT(Debug,57,(&Debug,
"get_word_from_string -- failing at %d -- no unicode\n",
X));
break;
}
/* Is space? (returns 0 or original character) */
sp = unicode_ch(c,UOP_space);
if (sp) {
if (trim) {
X++;
continue;
}
c = 0x0020; /* Treat all unicode space characters as ascii space */
}
for (y = ascii_delim; *y; y++)
if (*y == c || *y == sp)
break;
/* Delim not found ? */
if (! *y)
break;
X++;
}
X1 = X;
data = safe_malloc(str->p->len * sizeof (data[0]));
dx = 0;
last_X = 0;
/* Read first word */
while (X < str->p->len) {
int found;
uint16 c = str->string_type->charset_type->
cs_give_unicode_from_it(str,X,&found);
int sp;
/* ascii string is unsigned ... */
CONST unsigned char *y = NULL;
if (!found) {
DPRINT(Debug,57,(&Debug,
"get_word_from_string -- failing at %d -- no unicode\n",
X));
ret = 0;
goto fail;
}
/* Is space? (returns 0 or original character) */
sp = unicode_ch(c,UOP_space);
if (sp)
c = 0x0020; /* Treat all unicode space characters as ascii space */
for (y = ascii_delim; *y; y++)
if (*y == c || *y == sp)
break;
/* Delim found */
if (*y) {
if (found_delim)
*found_delim = c;
break;
}
data[dx++] = lowercase ? unicode_ch(c,UOP_lowercase) : c;
if (!sp)
last_X = dx;
X++;
}
if (trim && last_X < dx)
dx = last_X;
(*word)->string_type->charset_type->cs_add_unicodedata_to_it(*word,dx,data);
ret = X -*pos;
*pos = X;
fail:
if (data)
free(data);
DPRINT(Debug,58,(&Debug,
"get_word_from_string=%d, *pos=%d",ret,*pos));
if (found_delim) {
DPRINT(Debug,60,(&Debug,", *found_delim=%04x",*found_delim));
}
DPRINT(Debug,58,(&Debug,"\n"));
return ret;
}
int locate_unicode_from_string(str,unicode)
CONST struct string *str;
int unicode;
{
/* NOTE: We can not trim string !!! */
int i;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"locate_unicode_from_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"locate_unicode_from_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"locate_unicode_from_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"locate_unicode_from_string(%p) ('%s'; type=%p '%s', len=%d)\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
str->p->len));
for (i = 0; i < str->p->len; i++) {
int found;
uint16 c = str->string_type->charset_type->
cs_give_unicode_from_it(str,i,&found);
if (found && c == unicode) {
DPRINT(Debug,60,(&Debug,
"locate_unicode_from_string=%d\n",i));
return i;
}
}
DPRINT(Debug,60,(&Debug,
"locate_unicode_from_string=-1 (not found)\n"));
return -1;
}
int find_pattern_from_string(str,pattern,ignore_case)
CONST struct string *str;
CONST struct string *pattern;
int ignore_case;
{
int ret = -1;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string",
"Bad magic number (string type)",0);
if (CS_charset_magic != pattern->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string",
"Bad map (string type)",0);
if (INVALID_MAP(pattern->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string",
"Bad magic number (str_private_data)",0);
if (pattern->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"find_pattern_from_string",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"find_pattern_from_string(%p,%p,%d) ('%s'; type=%p '%s', len=%d), ('%s'; type=%p '%s', len=%d)\n",
str,pattern,ignore_case,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
str->p->len,
pattern->string_type->MIME_name ?
pattern->string_type->MIME_name : "<none>",
pattern->string_type->charset_type,
pattern->string_type->charset_type->type_name,
pattern->p->len));
/* Check lengths -- do compressions and so on */
str->string_type->charset_type->cs_check_length_it(str);
pattern->string_type->charset_type->cs_check_length_it(pattern);
if (0 == str->p->len) {
/* Nothing can be found from empty string */
DPRINT(Debug,63,(&Debug,
"cs_find_pattern_from_string=0 -- empty string\n"));
ret = 0;
} else if (0 == pattern->p->len) {
/* Empty pattern can found from anywhere */
DPRINT(Debug,63,(&Debug,
"cs_find_pattern_from_string=1 -- empty pattern\n"));
ret = 1;
} else if (str -> string_type == pattern -> string_type)
ret = str->string_type->charset_type->
cs_find_pattern_from_it(str,pattern,ignore_case);
/* -1 indicates that unicode values should be used on comparision ... */
if (ret < 0) {
int l1 = 0;
uint16 * vector1 = safe_malloc ( (str->p->len) * sizeof (uint16));
int l2 = 0;
uint16 * vector2 = safe_malloc ( (pattern->p->len) * sizeof (uint16));
int i,j;
ret = 0;
for (i = 0; i < str->p->len; i++) {
int found;
uint16 c =
str->string_type->charset_type->
cs_give_unicode_from_it(str,i,&found);
/* TODO: Should lowercase ANY unicode value ... */
if (!found)
c = MAPPING_NONE;
else if (ignore_case) {
c = unicode_ch(c,UOP_lowercase);
if (!c)
c = MAPPING_NONE;
}
vector1[l1++] = c;
}
for (i = 0; i < pattern->p->len; i++) {
int found;
uint16 c =
pattern->string_type->charset_type->
cs_give_unicode_from_it(pattern,i,&found);
if (!found)
c = MAPPING_NONE;
else if (ignore_case) {
c = unicode_ch(c,UOP_lowercase);
if (!c)
c = MAPPING_NONE;
}
vector2[l2++] = c;
}
for (i = 0; i < l1; ) {
CONST int s = i + 1;
for (j = 0; j < l2 && i < l1; j++,i++) {
if (vector1[i] != vector2[j])
break;
/* MAPPING_NONE matches newer ... */
if (MAPPING_NONE == vector1[i] ||
MAPPING_NONE == vector2[j])
break;
}
if (j >= l2) {
DPRINT(Debug,63,(&Debug,
"cs_find_pattern_from_string=1 MATCH\n"));
ret = 1;
break;
}
i = s;
}
if (!ret) {
DPRINT(Debug,63,(&Debug,
"cs_find_pattern_from_string=0 NO MATCH\n"));
}
free(vector1);
free(vector2);
}
DPRINT(Debug,60,(&Debug,
"find_pattern_from_string=%d\n",ret));
return ret;
}
static int string_match_part P_((const struct string * name, int name_X,
const struct string * pat, int pat_X));
static int string_match_part(name,name_X,pat,pat_X)
CONST struct string * name;
int name_X;
CONST struct string * pat;
int pat_X;
{
int r = 1;
/* It is assumed that compressions are already done ... */
while (pat_X < pat->p->len) {
int pat_found = 0;
uint16 code_pat =
pat->string_type->charset_type->
cs_give_unicode_from_it(pat,
pat_X,
&pat_found);
if (pat_found &&
0x002A /* '*' */ == code_pat) {
if (name_X < name->p->len) {
if (string_match_part(name,name_X,pat,pat_X+1)) {
/* Tail matches */
goto succeed;
}
/* Try match to next starting position */
name_X++;
} else {
/* '*' matches to empty string */
pat_X++;
}
} else if (name_X < name->p->len) {
int name_found = 0;
uint16 code_name =
name->string_type->charset_type->
cs_give_unicode_from_it(name,
name_X,
&name_found);
if (pat_found &&
0x003F /* '?' */ == code_pat) {
/* Accept any character */
name_X++;
pat_X++;
} else if (pat_found && name_found &&
code_pat == code_name) {
/* Accept character */
name_X++;
pat_X++;
} else {
r = 0;
DPRINT(Debug,55,(&Debug,
"-- Match fail on pat_X=%d (%04X) name_X=%d (%04X)\n",
pat_X,code_pat,name_X,code_name));
break;
}
} else {
r = 0;
DPRINT(Debug,55,(&Debug,
"-- Match fail on pat_X=%d name_X=%d (end of name)\n",
pat_X,name_X));
break;
}
}
if (name_X != name->p->len ||
pat_X != pat->p->len) {
DPRINT(Debug,55,(&Debug,
"-- Match fail on pat_X=%d name_X=%d (failure?)\n",
pat_X,name_X));
r = 0;
}
succeed:
return r;
}
/* return 1 on succeed and 0 on failure */
int string_match(name,pat)
CONST struct string * name;
CONST struct string * pat;
{
int r = 0;
if (CS_charset_magic != name->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_match",
"Bad magic number (string type)",0);
if (CS_charset_magic != pat->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_match",
"Bad magic number (string type)",0);
if (INVALID_MAP(name->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"string_match",
"Bad map (string type)",0);
if (INVALID_MAP(pat->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"string_match",
"Bad map (string type)",0);
if (name->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_match",
"Bad magic number (str_private_data)",0);
if (pat->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_match",
"Bad magic number (str_private_data)",0);
DPRINT(Debug,60,(&Debug,
"string_match(%p,%p) ('%s'; type=%p '%s', len=%d), ('%s'; type=%p '%s', len=%d)\n",
name,pat,
name->string_type->MIME_name ?
name->string_type->MIME_name : "<none>",
name->string_type->charset_type,
name->string_type->charset_type->type_name,
name->p->len,
pat->string_type->MIME_name ?
pat->string_type->MIME_name : "<none>",
pat->string_type->charset_type,
pat->string_type->charset_type->type_name,
pat->p->len));
/* Check lengths -- do compressions and so on */
name->string_type->charset_type->cs_check_length_it(name);
pat->string_type->charset_type->cs_check_length_it(pat);
r = string_match_part(name,0,pat,0);
DPRINT(Debug,60,(&Debug,
"string_match=%d\n",r));
return r;
}
uint16 give_unicode_from_string(str,pos)
CONST struct string *str;
int pos;
{
int found;
uint16 ret;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"give_unicode_from_string",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"give_unicode_from_string",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"give_unicode_from_string",
"Bad magic number (str_private_data)",0);
/* It is assumed that compressions are done
.. ie string_length() function
is called
*/
ret = str->string_type->charset_type->
cs_give_unicode_from_it(str,pos, &found);
DPRINT(Debug,60,(&Debug,
"give_unicode_from_string(%p,%d)=%d ('%s'; type=%p '%s')%s\n",
str,pos,ret,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
found ? "" : " [NOT FOUND]"));
return ret;
}
void remove_control(str)
CONST struct string *str;
{
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"remove_control",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"remove_control",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"remove_control",
"Bad magic number (str_private_data)",0);
if (str->p->state) {
if (str->p->state->charset != str->string_type)
panic("STRING PANIC",__FILE__,__LINE__,"remove_control",
"Bad magic number (state charset)",0);
free_state_internal(&(str->p->state));
}
DPRINT(Debug,60,(&Debug,
"remove_control(%p) ('%s'; type=%p '%s')\n",
str,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name));
str->string_type->charset_type->cs_remove_control_it(str);
}
void add_state_to_string(str,ch)
struct string *str;
struct charset_state *ch;
{
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string",
"Bad magic number (string type)",0);
if (CS_charset_magic != ch->charset->magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string",
"Bad magic number (charset)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string",
"Bad map (string type)",0);
if (INVALID_MAP(ch->charset))
panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string",
"Bad map (charset)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string",
"Bad magic number (str_private_data)",0);
if (str->p->state) {
if (str->p->state->charset != str->string_type)
panic("STRING PANIC",__FILE__,__LINE__,"add_state_to_string",
"Bad magic number (state charset)",0);
free_state_internal(&(str->p->state));
}
DPRINT(Debug,60,(&Debug,
"add_state_to_it(%p,%p) ('%s'; type=%p '%s', '%s'; type=%p '%s')\n",
str,ch,
str->string_type->MIME_name ?
str->string_type->MIME_name : "<none>",
str->string_type->charset_type,
str->string_type->charset_type->type_name,
ch->charset->MIME_name ?
ch->charset->MIME_name : "<none>",
ch->charset->charset_type,
ch->charset->charset_type->type_name));
if (ch->charset == str->string_type)
str->string_type->charset_type->cs_add_state_to_it(str,ch);
else {
int found;
uint16 val =
ch->charset->charset_type->cs_give_unicode_from_s_it(ch,&found);
str->string_type->charset_type->
cs_add_unicodedata_to_it(str,1,&val);
}
}
int charset_properties(ptr)
charset_t ptr;
{
int prop = 0;
if (CS_charset_magic != ptr->magic)
panic("STRING PANIC",__FILE__,__LINE__,"charset_properties",
"Bad magic number (charset)",0);
if (INVALID_MAP(ptr))
panic("STRING PANIC",__FILE__,__LINE__,"charset_properties",
"Bad map (charset)",0);
prop = ptr->charset_type->cs_it_properties(ptr);
DPRINT(Debug,11,(&Debug,
"charset_properties(%p '%s'; type=%p)=%d\n",
ptr,
ptr->MIME_name ? ptr->MIME_name : "<none>",
ptr->charset_type,
prop));
return prop;
}
/* bad_pos is -1 if string is OK */
long string_to_long(str,bad_pos)
CONST struct string *str;
int *bad_pos;
{
long val = 0L;
int found;
int pos = 0;
uint16 c;
int plus_minus = 1;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_to_long",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"string_to_long",
"Bad magic number (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_to_long",
"Bad magic number (str_private_data)",0);
*bad_pos = -1;
pos = 0;
if (str->p->len < 1)
goto fail;
c = str->string_type->charset_type->
cs_give_unicode_from_it(str,pos,&found);
if (!found)
goto fail;
if (0x002B /* + */ == c) {
plus_minus = 1;
pos++;
} else if (0x002D /* - */ == c) {
plus_minus = -1;
pos++;
}
while (pos < str->p->len) {
int num;
long l1;
c = str->string_type->charset_type->
cs_give_unicode_from_it(str,pos,&found);
if (!found)
goto fail;
if (c < 0x0030 /* 0 */ ||
c > 0x0039 /* 9 */)
goto fail;
num = c - 0x0030;
l1 = val * 10 + num;
if (l1 < val) { /* Overflow */
goto fail;
}
val = l1;
pos++;
}
val = val * plus_minus;
DPRINT(Debug,30,(&Debug,
"string_to_long: %S gives value %ld\n",
str,val));
return val;
fail:
*bad_pos = pos;
val = val * plus_minus;
DPRINT(Debug,30,(&Debug,
"string_to_long: %S gives value %ld, error on position %d\n",
str,val,pos));
return val;
}
/* Return 1 is matches, otherwise 0 */
int string_matches_ascii(str,ascii)
CONST struct string *str;
CONST unsigned char *ascii;
{
int i;
if (CS_charset_magic != str->string_type->magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_matches_ascii",
"Bad magic number (string type)",0);
if (INVALID_MAP(str->string_type))
panic("STRING PANIC",__FILE__,__LINE__,"string_matches_ascii",
"Bad map (string type)",0);
if (str->p->magic != CS_str_magic)
panic("STRING PANIC",__FILE__,__LINE__,"string_matches_ascii",
"Bad magic number (str_private_data)",0);
for (i = 0; i < str->p->len; i++) {
uint16 c;
int found;
c = str->string_type->charset_type->
cs_give_unicode_from_it(str,i,&found);
if (!found) {
DPRINT(Debug,30,(&Debug,
"string_matches_ascii=0 on pos %d (unicode not found)\n",
i));
return 0;
}
if (!ascii[i]) {
DPRINT(Debug,30,(&Debug,
"string_matches_ascii=0 on pos %d (ascii string ended)\n",
i));
return 0;
}
if (c != ascii[i]) {
DPRINT(Debug,30,(&Debug,
"string_matches_ascii=0 on pos %d (mismatch)\n",
i));
return 0;
}
}
if (ascii[i]) {
DPRINT(Debug,30,(&Debug,
"string_matches_ascii=0 on pos %d (ascii string not ended)\n",
i));
return 0;
}
DPRINT(Debug,30,(&Debug,
"string_matches_ascii=1 on pos %d (matches)\n",
i));
return 1;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1