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

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.8 $   $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"

DEBUG_VAR(Debug,__FILE__,"charset");

struct charset_state * new_state_1(set)
     charset_t set;
{
    struct charset_state * res = safe_malloc(sizeof (struct charset_state));

    /* defined in hdrs/defs.h */
    bzero((void *)res,sizeof (struct charset_state));


    if (CS_charset_magic != set->magic) 
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"new_state_1",
	      "Bad magic number (set)",0);
    
    res->charset      = set;
    res->caller_flags = 0;    /* Not used here, but maybe by caller */
    res->p = safe_malloc(sizeof (struct state_private_data));
    /* defined in hdrs/defs.h */
    bzero((void *)res->p,sizeof (struct state_private_data));
    res->p->ready = 0;

    res->charset->charset_type->cs_init_s_it(res);

    return res;
}

struct charset_state * new_state(set)
     charset_t set;
{
    struct charset_state * res;

    DPRINT(Debug,60,(&Debug, 		    
	       "new_state(%p)   ('%s'; type=%p '%s')\n",
	       set,
	       set->MIME_name ? 
	       set->MIME_name : "<none>",
	       set->charset_type,
	       set->charset_type->type_name));

    if (CS_charset_magic != set->magic) 
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"new_state_1",
	      "Bad magic number (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 = new_state_1(set);

    DPRINT(Debug,60,(&Debug, 
		     "new_state=%p\n",res));
    return res;
}

void free_state_internal(state)
     struct charset_state **state;
{
    (*state)->charset->charset_type->cs_free_s_it(*state);

    free((*state)->p);
    (*state)->p = NULL;
    (*state)->charset = NULL;

    free(*state);
    *state = NULL;
}

void free_state(state)
     struct charset_state **state;
{
    if (CS_charset_magic != (*state)->charset->magic) 
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"free_state",
	      "Bad magic number (charset)",0);
    
    DPRINT(Debug,60,(&Debug, 
		     "free_state((*state)=%p)   ('%s'; type=%p '%s')\n",
		     (*state),
		     (*state)->charset->MIME_name ? 
		     (*state)->charset->MIME_name : "<none>",
		     (*state)->charset->charset_type,
		     (*state)->charset->charset_type->type_name));
    free_state_internal(state);
}

int state_ready(st)
     struct charset_state *st;
{
    if (CS_charset_magic != st->charset->magic)
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"ready_state",
	      "Bad magic number (charset)",0);

    DPRINT(Debug,60,(&Debug, 
		     "ready_state(%p)=%d   ('%s'; type=%p '%s')\n",
		     st,st->p->ready,
		     st->charset->MIME_name ? 
		     st->charset->MIME_name : "<none>",
		     st->charset->charset_type,
		     st->charset->charset_type->type_name));

    if (st->p->ready) {
	DPRINT(Debug,61,(&Debug," .... character: %C\n",st)); 
    }

    return st->p->ready;
}

/* Unready state */
void reset_state(st, hard)
     struct charset_state *st;
     int hard;
{
    if (CS_charset_magic != st->charset->magic)
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"ready_state",
	      "Bad magic number (charset)",0);

    DPRINT(Debug,60,(&Debug, 
		     "reset_state(%p,hard=%d)   (ready=%d; '%s'; type=%p '%s')\n",
		     st,hard,
		     st->p->ready,
		     st->charset->MIME_name ? 
		     st->charset->MIME_name : "<none>",
		     st->charset->charset_type,
		     st->charset->charset_type->type_name));
    
    if (hard) {
	st->charset->charset_type->cs_free_s_it(st);
	st->charset->charset_type->cs_init_s_it(st);
    } else {
	st->charset->charset_type->cs_soft_reset_s_it(st);
    }
}

int add_streambyte_to_state(st,ch)
     struct charset_state *st; 
     int ch;
{
    int res;
    if (CS_charset_magic != st->charset->magic)
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"ready_state",
	      "Bad magic number (charset)",0);

    DPRINT(Debug,60,(&Debug, 
		     "add_streambyte_to_state(%p)  ('%s'; type=%p '%s')\n",
		     st,
		     st->charset->MIME_name ? 
		     st->charset->MIME_name : "<none>",
		     st->charset->charset_type,
		     st->charset->charset_type->type_name));
    if (st->charset == display_charset) {
	DPRINT(Debug,61,(&Debug, 
		   "add_streambyte_to_state -- ch=%d '%c'\n",ch,ch));    
    } else {
	DPRINT(Debug,61,(&Debug, 
			 "add_streambyte_to_state -- ch=%d\n",ch));    
    }


    res = st->charset->charset_type->cs_add_streambyte_to_s_it(st,ch);

    DPRINT(Debug,60,(&Debug, 
		     "add_streambyte_to_state=%d\n",res));

    return res;
}

int state_same_char(A,B,ignore_case)
     struct charset_state *A;
     struct charset_state *B;
     int ignore_case;
{
    int ret = -1;
    if (CS_charset_magic != A->charset->magic)
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"state_same_char",
	      "Bad magic number (A, charset)",0);
    if (CS_charset_magic != B->charset->magic)
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"state_same_char",
	      "Bad magic number (B, charset)",0);

    DPRINT(Debug,60,(&Debug, 
		     "state_same_state(%p,%p)   ('%s'; type=%p '%s', '%s'; type=%p '%s')\n",
		     A,B,
		     A->charset->MIME_name ? 
		     A->charset->MIME_name : "<none>",
		     A->charset->charset_type,
		     A->charset->charset_type->type_name,
		     B->charset->MIME_name ? 
		     B->charset->MIME_name : "<none>",
		     B->charset->charset_type,
		     B->charset->charset_type->type_name));

    if (!A->p->ready) 
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"state_same_state",
	      "State not ready (A)",0);
    if (!B->p->ready) 
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"state_same_state",
	      "State not ready (B)",0);

    if (A->charset == B->charset)
	ret = A->charset->charset_type->cs_s_it_same_char(A,B,ignore_case);

    /* -1 indicates that unicode values should be used on comparision ... */
    if (ret < 0) {
	int found1, found2;
	uint16 val1 = 
	    A->charset->charset_type->cs_give_unicode_from_s_it(A,&found1);
	uint16 val2 = 
	    A->charset->charset_type->cs_give_unicode_from_s_it(B,&found2);

	if (found1 && found2) {
	    if (ignore_case) {
		/* TODO: Should lowercase ANY unicode value ... */

		val1 = unicode_ch(val1,UOP_lowercase);
		val2 = unicode_ch(val2,UOP_lowercase);

		if (!val1 || !val2) {
		    ret = 0;
		    goto fail;
		}
		    
	    }
	    ret = (val1 == val2);
	} else
	    ret = 0;
    }

 fail:
    DPRINT(Debug,60,(&Debug,        
		     "state_same_char=%d\n",ret));

    return ret;
}

int state_printable(st)
     struct charset_state *st;
{
    int ret;

    if (CS_charset_magic != st->charset->magic)
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"state_printable",
	      "Bad magic number (A, charset)",0);

    DPRINT(Debug,60,(&Debug, 
		     "state_printable(%p)   ('%s'; type=%p '%s')\n",
		     st,
		     st->charset->MIME_name ? 
		     st->charset->MIME_name : "<none>",
		     st->charset->charset_type,
		     st->charset->charset_type->type_name));
    
    if (!st->p->ready) 
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"state_printable",
	      "State not ready",0);

    ret = st->charset->charset_type->cs_s_it_printable(st);
    
    if (ret < 0) { /* Use unicode values ... */
	int found;
	uint16 val = 
	    st->charset->charset_type->cs_give_unicode_from_s_it(st,&found);
	
	if (!found)
	    ret = 0;
	else if (unicode_ch(val,UOP_printable))
	    ret = 1;
	else
	    ret = 0;
    }

    DPRINT(Debug,60,(&Debug,
		     "state_printable=%d\n",ret));

    return ret;
}

int state_is_onebyte(st)
     struct charset_state *st;
{
    int ret;
    /* If character corresponds one byte on stream, returns it.
     * Otherwise returns 0. This is used implement ReadCh().
     * It is assumend that returned character corresponds to
     * code characterter set (and perhaps also US-ASCII)
     */

    if (CS_charset_magic != st->charset->magic)
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"state_is_onebyte",
	      "Bad magic number (A, charset)",0);

    DPRINT(Debug,60,(&Debug, 
		     "state_is_onebyte(%p)   ('%s'; type=%p '%s')\n",
		     st,
		     st->charset->MIME_name ? 
		     st->charset->MIME_name : "<none>",
		     st->charset->charset_type,
		     st->charset->charset_type->type_name));
    
    if (!st->p->ready) 
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,"state_is_onebyte",
	      "State not ready",0);

    ret = st->charset->charset_type->cs_s_it_is_onebyte(st);

    DPRINT(Debug,60,(&Debug,
		     "state_is_onebyte=%d\n",ret));

    return ret;
}

uint16 give_unicode_from_state(st)
     struct charset_state *st;
{
    int found;
    uint16 val; 

    if (CS_charset_magic != st->charset->magic)
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,
	      "give_unicode_from_state",
	      "Bad magic number (charset)",0);

    DPRINT(Debug,60,(&Debug, 			    
		     "give_unicode_from_state(%p)   ('%s'; type=%p '%s')\n",
		     st,
		     st->charset->MIME_name ? 
		     st->charset->MIME_name : "<none>",
		     st->charset->charset_type,
		     st->charset->charset_type->type_name));

    if (!st->p->ready) 
	panic("CHARSET STATE PANIC",__FILE__,__LINE__,
	      "give_unicode_from_state",
	      "State not ready",0);	   

    val = st->charset->charset_type->cs_give_unicode_from_s_it(st,&found);

    DPRINT(Debug,60,(&Debug,
	       "give_unicode_from_state=%d (found=%d)\n",val,found));

    return val;
}


/*
 * Local Variables:
 *  mode:c
 *  c-basic-offset:4
 *  buffer-file-coding-system: iso-8859-1
 * End:
 */




syntax highlighted by Code2HTML, v. 0.9.1