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

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

#include "def_messages.h"

DEBUG_VAR(Debug,__FILE__,"messages");


static struct MailboxView    ** mailbox_list = NULL;
static int                      mailbox_list_len = 0;

struct MailboxView    * give_next_open_mailbox(idx, signal)
     int *idx;
     int signal;
{
    int i = *idx;

    struct MailboxView    *ret = NULL;

    do {
	if (*idx >= mailbox_list_len || *idx < 0)
	    return NULL;


	if (mailbox_list[*idx]) {
	    

	    if (mailbox_list[*idx]->magic !=  MAILBOXVIEW_magic)
		panic("MBX VIEW PANIC",__FILE__,__LINE__,"malloc_view",
		      "Bad type magic number",signal);


	    ret = mailbox_list[*idx];

	}

	(*idx)++;

    } while (!ret);
	

    SIGDPRINT(Debug,7,(&Debug,
		       "give_next_open_mailbox[%d->%d] = %p\n",
		       i,*idx,ret));

    return ret;
}

struct MailboxView * malloc_view(t)
     struct mailbox_type *t;
{
    int idx;

    struct MailboxView *ret, **X;

    ret = safe_malloc(sizeof (*ret));

    /* bzero is defined hdrs/defs.h */
    bzero((void *)ret,sizeof (*ret));

    ret->magic         = MAILBOXVIEW_magic;
    ret->mailbox_type  = t;
    ret->status_type   = &status_common;   /* Caller may override */
    ret->u.dummy       = NULL;

    ret->current       = 0;
    ret->selected      = 0;
    ret->mailbox_title = NULL;

    ret->view          = NULL;
    ret->view_len      = 0;

    ret->thread_view   = NULL;

    if (ret->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"malloc_view",
	      "Bad type magic number",0);

    ret->mailbox_type->mt_init_it(ret);

    for (idx = 0; idx < mailbox_list_len; idx++)
	if (!mailbox_list[idx]) {
	    DPRINT(Debug,7,(&Debug,
			       "malloc_view: Re-using mailbox index %d\n",
			       idx));
	    goto found;
	}

    X = safe_realloc(mailbox_list,(mailbox_list_len+1)* sizeof (*X));
    X[mailbox_list_len] = NULL;
    mailbox_list = X;
    idx = mailbox_list_len++;

    DPRINT(Debug,7,(&Debug,
		       "malloc_view: Allocing new mailbox index %d\n",
		       idx));

 found:
    mailbox_list[idx] = ret;

    return ret;
}

void add_storage(mailbox,storage)
     struct MailboxView *mailbox;
     struct current_storage *storage;
{
    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"add_storage",
	      "Bad magic number",0);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"add_storage",
	      "Bad type magic number",0);

    mailbox->mailbox_type->mt_add_it_storage(mailbox,storage);
}

void add_digest(mailbox,list,received_time,env_from,F,defcharset)
     struct MailboxView *mailbox;
     mime_t *list;
     time_t received_time;
     char *env_from;
     FILE *F;
     charset_t defcharset;
{
    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"add_storage",
	      "Bad magic number",0);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"add_storage",
	      "Bad type magic number",0);

    if (list->magic != MIME_magic)
	mime_panic(__FILE__,__LINE__,"add_digest",
		   "Bad magic number");

    mailbox->mailbox_type->mt_add_it_digest(mailbox,list,received_time,
					    env_from,F, defcharset);
}	

static void free_mailbox1 P_((struct MailboxView **mailbox));

static void free_mailbox1(mailbox)
     struct MailboxView **mailbox;
{
    if ((*mailbox)->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"free_mailbox1",
	      "Bad type magic number",0);
    
    (*mailbox)->mailbox_type->mt_free_it(*mailbox);

    if ((*mailbox)->mailbox_title)
	free_string (& ((*mailbox)->mailbox_title));

    if ((*mailbox)->view) {
	free((*mailbox)->view);
        (*mailbox)->view = NULL;
    }
    (*mailbox)->view_len = 0;

    if ((*mailbox)->thread_view)
	free_thread_view(& ((*mailbox)->thread_view));

    (*mailbox)->magic = 0;    /* Invalidate */
    free(*mailbox);
    *mailbox = NULL;
}

void free_mailbox(mailbox)
     struct MailboxView **mailbox;
{    
    int i;

    if ((*mailbox)->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"free_mailbox",
	      "Bad magic number",0);

    for ( i = 0; i < mailbox_list_len; i++) {
	if (mailbox_list[i] == *mailbox) {

	    SIGDPRINT(Debug,7,(&Debug,
			       "free_mailbox: Mailbox index %d goes free\n",
			       i));
	    
	    mailbox_list[i] = NULL;
	    goto okei;
	}
    }

    panic("MBX VIEW PANIC",__FILE__,__LINE__,"free_mailbox",
	  "mailbox not found from list",0);
	
 okei:
    free_mailbox1(mailbox);
}

void free_all_mailboxes()
{
    if (mailbox_list) {
	int i;
	
	for ( i = 0; i < mailbox_list_len; i++) {
	    if (mailbox_list[i]) {
		
		SIGDPRINT(Debug,7,(&Debug,"free_all_mailboxes: [%d]\n",
				   i));
		
		if (mailbox_list[i]->magic         != MAILBOXVIEW_magic)
		    panic("MBX VIEW PANIC",__FILE__,__LINE__,"free_all_mailboxes",
			  "Bad magic number",0);
		
		free_mailbox1(& (mailbox_list[i]));
	    }
	}
	
	free(mailbox_list);
	mailbox_list = NULL;
    }
    mailbox_list_len = 0;
}

/* Return 1 if redraw required */
int update_view(mailbox)
     struct MailboxView *mailbox;
{
    int ret;
    struct folder_view cur;
    int current_set = 0;

    zero_folder_view(& cur);

    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"update_view",
	      "Bad magic number",0);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"update_view",
	      "Bad type magic number",0);

    if (mailbox->current > 0 && mailbox->current <= mailbox->view_len) {
	cur = mailbox->view[mailbox->current-1];
	current_set++;
    }

    ret = mailbox->mailbox_type->mt_update_view_it(mailbox);

    if (ret && current_set) {
	int i;

	for (i = 0; i < mailbox->view_len; i++)
	    if (cur.mailbox_number == mailbox->view[i].mailbox_number &&
		cur.index == mailbox->view[i].index) {
		DPRINT(Debug,7,(&Debug,
				"update_view: Channing current %d -> %d\n",
				mailbox->current,i+1));
		mailbox->current = i+1;
		break;
	    }
    }

    DPRINT(Debug,7,(&Debug,
		    "update_view=%d\n",ret));
    return ret;
}

struct folder_info * get_main_folder(mailbox)
     struct MailboxView *mailbox;
{

    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"get_main_folder",
	      "Bad magic number",0);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"get_main_folder",
	      "Bad type magic number",0);

    return mailbox->mailbox_type->mt_get_main_it_folder(mailbox);
}

/* Can be called from signal handler */
struct current_storage * get_storage(mailbox,i)
     struct MailboxView *mailbox;
     int i;
{
    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"get_storage",
	      "Bad magic number",1);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"get_storage",
	      "Bad type magic number",1);

    return mailbox->mailbox_type->mt_get_it_storage(mailbox,i);
}

/* Can be called from signal handler */
int get_storage_count(mailbox)
     struct MailboxView *mailbox;
{
    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"get_storage_count",
	      "Bad magic number",1);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"get_storage_count",
	      "Bad type magic number",1);

    return mailbox->mailbox_type->mt_get_it_storage_count(mailbox);
}


void give_index_number(mailbox,index,res) 
     struct MailboxView *mailbox;
     int index; 
     struct folder_view *res;
{   
    zero_folder_view(res);

    if (index < 0 || index >= mailbox->view_len)
	return;

    *res = mailbox->view[index];
}

struct header_rec * give_header(mailbox,index)
     struct MailboxView *mailbox;
     int index;
{
    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"give_header",
	      "Bad magic number",0);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"give_header",
	      "Bad type magic number",0);

    if (index < 0 || index >= mailbox->view_len)
	return NULL;


    return mailbox->mailbox_type->mt_give_header_it(mailbox,index,
						    & mailbox->view[index]);
}


/*  current == index+1     value is used only by caller */
int get_current(mailbox) 
     struct MailboxView *mailbox;
{
    return mailbox->current;
}

/*  current == index+1     value is used only by caller */
void set_current(mailbox,cur)
     struct MailboxView *mailbox;
     int cur;
{
    mailbox->current = cur;
}

int get_selected(mailbox)
     struct MailboxView *mailbox;
{
    return mailbox->selected;
}

void set_selected(mailbox,sel)
     struct MailboxView *mailbox;
     int sel;
{
    mailbox->selected = sel;
}

int get_message_count(mailbox)
     struct MailboxView *mailbox;
{
    return mailbox->view_len;
}

struct header_rec * give_header_s(s)
     struct sort_data *s;
{

    if (s->sort_data_type->magic != SORTDATATYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"give_header_s",
	      "Bad magic number",0);
	   
    return s->sort_data_type->sdt_give_header(s,& s->w);
}

void give_index_number_s(s,res)
     struct sort_data *s;
     struct folder_view *res;
{
    *res = s->w;
}

void sort_mailbox_view(mailbox,func)
     struct MailboxView *mailbox;
     hdr_compare_func   *func;
{

    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"sort_mailbox_view",
	      "Bad magic number",0);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"sort_mailbox_view",
	      "Bad type magic number",0);

    if (mailbox->view_len < 2)
	return;

    mailbox->mailbox_type->mt_sort_it_view(mailbox,func);

}

/* Return 1 if succeed, 0 is fails --
   seeks to {header}->offset   (if ret_F set)
*/
int give_message_data(mailbox,index,ret_header,ret_F,
		      counter,parse_mime)
     struct MailboxView *mailbox;
     int index;
     struct header_rec **ret_header;
     FILE              **ret_F;
     struct counter_data *counter;
     parse_mime_callback *parse_mime;
{
    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"give_message_data",
	      "Bad magic number",0);
    
    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"give_message_data",
	      "Bad type magic number",0);

    if (index < 0 || index >= mailbox->view_len)
	return 0;

    if (ret_header)
	*ret_header = NULL;
    if (ret_F)
	*ret_F      = NULL;

    return mailbox->mailbox_type->
	mt_give_message_data_it(mailbox,index,
				ret_header,ret_F,
				counter,parse_mime,
				& mailbox->view[index]);
}


void write_mailbox_info(fp,mailbox)
     FILE *fp; 
     struct MailboxView *mailbox;
{
    int i,j;
    int count;

    int cur_s   = -1;
    int cur_idx = -1;
    int s;

    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"write_mailbox_info",
	      "Bad magic number",0);

    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"write_mailbox_info",
	      "Bad type magic number",0);
    
    count = mailbox->mailbox_type->mt_get_it_storage_count(mailbox);

    fprintf(fp, "S%d\n", count);
	    
    
    /* HACK */
    if (mailbox->current > 0 && mailbox->current <= mailbox->view_len) {
	cur_s   = mailbox->view[mailbox->current -1].mailbox_number;
	cur_idx = mailbox->view[mailbox->current -1].index;
    }
    
    for (s = 0; s < count; s++) {
	fprintf(fp, "=%d\n",s);

	if (s == cur_s)
	    mailbox->mailbox_type->mt_write_it_info(fp,mailbox,s,cur_idx);
	else
	    mailbox->mailbox_type->mt_write_it_info(fp,mailbox,s,-1);

    }

    fprintf(fp, "V%d\n", mailbox->view_len);
    
    for (i = 0; i < mailbox->view_len; i++) {
	fprintf(fp, "i%d %d %d\n",
		mailbox->view[i].mailbox_number,
		mailbox->view[i].index,
		mailbox->view[i].thread_number);
    }

    /* count up the number of tagged messages */
    count = 0;
    for (i = 0 ; i < mailbox->view_len ; i++)  {
	struct header_rec * hdr = give_header(mailbox,i);
	
	if (hdr &&
	    (hdr->status & TAGGED))
	    ++count;
    }
    
    /* write out selected messages */
    if (count > 0) {
	/* we found tagged messages - write them out */
	fprintf(fp, "C%d\n", count);
	for (i = 0 ; i < mailbox->view_len ; i++) {
	    struct header_rec * hdr = give_header(mailbox,i);

	    if (hdr && (hdr->status & TAGGED))
		fprintf(fp, "S%d\n", i+1);
	}
    } else if (mailbox->current > 0) {
	/* no tagged messages - write out the selected message */
	fprintf(fp, "C1\nS%d\n", mailbox->current);
    } else {
	/* hmmm...must be an empty mailbox */
	fprintf(fp, "C0\n");
    }    
}

/* caller must string_free() result -- calculated if not set */
struct string * mailbox_title(mailbox)
     struct MailboxView *mailbox;
{

    if (mailbox->magic         != MAILBOXVIEW_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"mailbox_title",
	      "Bad magic number",0);

    if (mailbox->mailbox_title) {
	return dup_string(mailbox->mailbox_title);
    }

    if (mailbox->mailbox_type->magic != MAILBOXTYPE_magic)
	panic("MBX VIEW PANIC",__FILE__,__LINE__,"mailbox_title",
	      "Bad type magic number",0);

    return mailbox->mailbox_type->mt_it_title(mailbox);
}

/* must not freed -- shared/stored to structure
   -- set_mailbox_title will free_string()
   it later */
void set_mailbox_title(mailbox,value)
     struct MailboxView *mailbox;
     struct string *value;
{
    if (mailbox->mailbox_title) 
	free_string( & (mailbox->mailbox_title) );
    
    mailbox->mailbox_title = value;
}

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


syntax highlighted by Code2HTML, v. 0.9.1