static char rcsid[] = "@(#)$Id: state.c,v 1.4 2006/05/07 08:35:31 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.4 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
 *      or  Kari Hurtta <elm@elmme-mailer.org>
 *
 *  These routines are mainly copied from lib/state.c 
 *
 *  Although state.c is initially written written by Michael Elkins 
 *  these copied routines are newer and not written by Michael Elkins 
 *****************************************************************************/

#include "def_mbox.h"
#include "state_imp.h"

DEBUG_VAR(Debug,__FILE__,"stateio");


#if ANSI_C
#define S_(x) static x;
#else
#define S_(x)
#endif

#define DIRSTATE_out_magic      0xFE01

typedef struct dirstate_out {
    unsigned short          magic;   /* DIRSTATE_out_magic */
    struct folder_browser * dir;
    WRITE_STATE             write_state_ptr;
} out_state_dir;


S_(ex_init_so_func init_so_dir)
static void init_so_dir P_((out_state_t *s)); 
static void init_so_dir(s)
     out_state_t *s;
{
    s->u.dir = safe_malloc(sizeof (* s->u.dir));

    bzero((void *)s->u.dir,sizeof (* s->u.dir));

    s->u.dir->magic           = DIRSTATE_out_magic;
    s->u.dir->dir             = NULL;
    s->u.dir->write_state_ptr = NULL;
}

S_(ex_dest_so_func dest_so_dir)
static void dest_so_dir P_((out_state_t *s)); 
static void dest_so_dir(s)
     out_state_t *s;
{
    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"dest_so_dir",
	      "Bad magic number",0);

    if (DIRSTATE_out_magic != s->u.dir->magic)
	panic("STATE PANIC",__FILE__,__LINE__,"dest_so_dir",
	      "Bad magic number (dirstate)",0);
	          
    s->u.dir->dir             = NULL;
    s->u.dir->write_state_ptr = NULL;
    s->u.dir->magic           = 0;  /* Invalidate */

    free(s->u.dir);
    s->u.dir = NULL;
}

S_(ex_seekable_so_func seekable_so_dir)
static int seekable_so_dir P_((out_state_t *s)); 
static int seekable_so_dir(s)
     out_state_t *s;
{
    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"seekable_so_dir",
	      "Bad magic number",0);

    if (DIRSTATE_out_magic != s->u.dir->magic)
	panic("STATE PANIC",__FILE__,__LINE__,"seekable_so_dir",
	      "Bad magic number (dirstate)",0);
    
    if (tell_dir_write_state(s->u.dir->dir,s->u.dir->write_state_ptr) > 0)
	return 1;
    return 0;
}

S_(ex_FILE_so_func FILE_so_dir)
static FILE * FILE_so_dir P_((out_state_t *s)); 
static FILE * FILE_so_dir(s)
     out_state_t *s;
{
    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"FILE_so_dir",
	      "Bad magic number",0);

    return NULL;
}

S_(ex_seek_so_func seek_so_dir)
static int seek_so_dir P_((out_state_t *s, long pos)); 
static int seek_so_dir(s,pos)
     out_state_t *s;
     long pos;
{
    int r;

    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"seek_so_dir",
	      "Bad magic number",0);

    if (DIRSTATE_out_magic != s->u.dir->magic)
	panic("STATE PANIC",__FILE__,__LINE__,"seek_so_dir",
	      "Bad magic number (dirstate)",0);

    /* Note reversed return value on functions! */

    if (seek_dir_write_state(s->u.dir->dir,
			     s->u.dir->write_state_ptr,
			     pos))
	r = 0; /* SUCCEES */
    else
	r = -1; /* FAILURE */

    return r;
}

S_(ex_ftell_so_func ftell_so_dir)
static long ftell_so_dir P_((out_state_t *s)); 
static long ftell_so_dir(s)
     out_state_t *s;
{
    long r;

    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"ftell_so_dir",
	      "Bad magic number",0);

    if (DIRSTATE_out_magic != s->u.dir->magic)
	panic("STATE PANIC",__FILE__,__LINE__,"ftell_so_dir",
	      "Bad magic number (dirstate)",0);

    r = tell_dir_write_state(s->u.dir->dir,s->u.dir->write_state_ptr);

    return r;
}

S_(ex_flush_filter_so_func flush_filter_so_dir)
static void flush_filter_so_dir P_((out_state_t *s, int munge_eoln)); 
static void flush_filter_so_dir(s,munge_eoln)
     out_state_t *s;
     int munge_eoln;
{
    char * s1 = NULL;
    int l = 0;

    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"flush_filter_so_dir",
	      "Bad magic number",0);

    if (RAW_BUFFER == s->display_charset[0]) {
	DPRINT(Debug,10,(&Debug,
			 "flush_filter_so_dir: Raw copy (data charset %s)%s\n",
			 s->filter_line->string_type->MIME_name ?
			 s->filter_line->string_type->MIME_name :
			 "<not set>",
			 munge_eoln ? " -- convert EOLN" : "")); 
	bytestream_from_string(s->filter_line,&s1,&l); 
    } else {
	struct string * tmp = convert_string(s->display_charset[0],
					     s->filter_line,0);
	/* Can't ask just printable characters because we need
	   NLs also ...
	*/
	DPRINT(Debug,10,(&Debug,
			 "flush_filter_so_dir: Conversion %s->%s%s\n",
			 s->filter_line->string_type->MIME_name ?
			 s->filter_line->string_type->MIME_name :
			 "<not set>",
			 tmp->string_type->MIME_name ? 
			 tmp->string_type->MIME_name :
			 "<not set>",
			 munge_eoln ? " -- convert EOLN" : "")); 
	bytestream_from_string(tmp,&s1,&l); 
	free_string(&tmp);
    }
    
    if (munge_eoln) {
	int size = l + 4;
	
	s1 = safe_realloc(s1,size);
	
	/* Take care of CRLF => LF conversion or
	   LF -> CRLF conversion 
	*/
	state_convert_EOLN(s1,&l,size,s);	    
    }

    if (DIRSTATE_out_magic != s->u.dir->magic)
	panic("STATE PANIC",__FILE__,__LINE__,"flush_filter_so_dir",
	      "Bad magic number (dirstate)",0);
    
    if (!write_dir_write_state(s->u.dir->dir,s->u.dir->write_state_ptr,
			       l,s1)) {
	DPRINT(Debug,1,(&Debug,
			"flush_filter_so_dir: start_fd_write_state failed\n"));
    }
    
    free(s1);
}

S_(ex_policy_so_func policy_so_dir)
static int policy_so_dir P_((out_state_t *s, enum state_policy question)); 
static int policy_so_dir(s,question)
     out_state_t *s;
     enum state_policy question;
{
    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"policy_so_dir",
	      "Bad magic number",0);

    switch(question) {
    case state_policy_putc_use_filter: return 1;
    case state_policy_flush_via_put:   return 0;

    default:
	panic("STATE PANIC",__FILE__,__LINE__,"policy_so_dir",
	      "Bad question",0);
    }

    return 0;
}

S_(ex_putc_so_func putc_so_dir)
static int putc_so_dir P_((out_state_t *s, int ch)); 
static int putc_so_dir(s,ch)
     out_state_t *s;
     int ch;
{
    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"putc_so_dir",
	      "Bad magic number",0);

    panic("STATE PANIC",__FILE__,__LINE__,"putc_so_dir",
	  "putc_so_dir called",0);

    return EOF;
}

S_(ex_put_so_func put_so_dir)
static int put_so_dir P_((out_state_t *s, const char *string, int len)); 
static int put_so_dir(s,string,len)
     out_state_t *s;
     CONST char *string;
     int len;
{
    if (s->magic        != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"put_so_dir",
	      "Bad magic number",0);

    panic("STATE PANIC",__FILE__,__LINE__,"put_so_dir",
	  "put_so_dir called",0);

    return EOF;
}


struct out_state_type state_out_dir = {
    STATE_out_magic,
    STATE_out_dir,          /* registered type */
    init_so_dir,
    dest_so_dir,
    seekable_so_dir,
    FILE_so_dir,
    seek_so_dir,
    ftell_so_dir,
    flush_filter_so_dir,
    policy_so_dir,
    putc_so_dir,
    put_so_dir
};

void set_out_state_dir(dir,write_state_ptr,s)
     struct folder_browser *dir;
     WRITE_STATE  write_state_ptr;
     out_state_t *s;  
{
    if (s->magic != STATE_out_extern)
	panic("STATE PANIC",__FILE__,__LINE__,"set_out_state_dir",
		    "Bad magic number",0);

    if (s->external_type != &state_out_dir)
	panic("STATE PANIC",__FILE__,__LINE__,"set_out_state_dir",
		    "Bad external type",0);

    if (DIRSTATE_out_magic != s->u.dir->magic)
	panic("STATE PANIC",__FILE__,__LINE__,"set_out_state_dir",
	      "Bad magic number (dirstate)",0);
	
    if (s->u.dir->dir || s->u.dir->write_state_ptr) 
	panic("STATE PANIC",__FILE__,__LINE__,"set_out_state_dir",
	      "Already called",0);
	
    if (!dir || !write_state_ptr)
	panic("STATE PANIC",__FILE__,__LINE__,"set_out_state_dir",
	      "Bad argument",0);

    if (!s->display_charset) 
	panic("STATE PANIC",__FILE__,__LINE__,"set_out_state_dir",
	      "Display_charset -vector must have been set (possible to RAW_BUFFER)",0);

    
    s->u.dir->dir             = dir;
    s->u.dir->write_state_ptr = write_state_ptr;
}

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


syntax highlighted by Code2HTML, v. 0.9.1