static char rcsid[] = "@(#)$Id: newmbox.c,v 1.101 2006/12/06 09:59:45 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.101 $   $State: Exp $
 *
 *  Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI> 
 *                           (was hurtta+elm@ozone.FMI.FI)
 ******************************************************************************
 *  The Elm Mail System 
 *
 *			Copyright (c) 1988-1992 USENET Community Trust
 *			Copyright (c) 1986,1987 Dave Taylor
 *****************************************************************************/

/**  read new folder **/

#include "def_elm.h"
#include "s_elm.h"

DEBUG_VAR(Debug,__FILE__,"mbox");

#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif       

#if  !defined(ANSI_C) && !defined(atol) /* avoid problems with systems that declare atol as a macro */
extern void rewind();
extern long atol();
#endif

/* -1  ... failure */
static int read_headers P_((int adds_only, struct current_storage *storage,
			    struct menu_context *page));   /* Prototype */

int open_folder_lock(direction,folder) 
     int direction;
     struct folder_info *folder;
{
    DPRINT(Debug,10,(&Debug, 
		     "open_folder_lock: folder=%p (%s)\n",
		     folder,folder->cur_folder_sys));

  if (!sessionlock_folder(folder,SESSIONLOCK_CHECK))
      return 0;

  lock(direction, folder);
    
  return 1;
}

int read_new_mails(storage, page) 
     struct current_storage *storage;
     struct menu_context *page;
{
    int ret, r;

    ret = sessionlock_folder(storage->current_folder,
			     SESSIONLOCK_NONE);
    if (!ret)
	return 0;

    r = read_headers(1,storage,page);  /* Returns number of mails readed */

    if (r < 0 ||
	ferror_folder(storage->current_folder,1)) {
	lib_error(CATGETS(elm_msg_cat, ElmSet, ElmErrorWhenReading,
			  "Error when reading: %S"),
		  storage->current_folder->cur_folder_disp);
	return 0;
    }
    return 1;
}

void add_new_mailbox (new_folder,mailbox,page)
     struct folder_info *new_folder;
     struct MailboxView *mailbox;
     struct menu_context *page;
{
    struct current_storage *storage = NULL;

    int mbc = get_storage_count(mailbox);
    int i;
    int ret = 0;
    int same_file = 0;
    int r;

    /* Shold not be same file, but check anyway ... */

    for (i = 0; i < mbc; i++) {
	struct current_storage *s = get_storage(mailbox,i);

	if (!s)
	    continue;

	if (s->current_folder &&
	    new_folder == s->current_folder) {
	    storage   = s;
	    same_file++;
	    break;
	}
    }    


    if (! same_file) {

	storage = new_storage(new_folder);
	
	ret = sessionlock_folder(storage->current_folder,
				 SESSIONLOCK_NORMAL);
      
    } else {
	

	DPRINT(Debug,1,(&Debug, 
			"WARNING -- add_new_mailbox is reopening file which is already open: %s\n",
			storage->current_folder->cur_folder_sys));
	
	
	/* folder (as opposite to mailbox) can be session locked
	 * only when it is opened. That call can do session locking
	 * for both (folders and mailboxes)
	 */
	
	ret = sessionlock_folder(storage->current_folder,
				 SESSIONLOCK_TRUNCATE);
    }
    

    if (!ret) {

	if (!same_file)
	    free_storage(&storage);
	
	DPRINT(Debug,1,(&Debug, 
			"WARNING -- add_new_mailbox failed: %s\n",
			storage->current_folder->cur_folder_sys));
	
	return;
    }

    DPRINT(Debug,10,(&Debug, 
		     "Mailfile opened: %s\n",
		     storage->current_folder->cur_folder_sys));

    clear_error();

    r= read_headers(0,storage, page); /* Returns number of mails readed */
    
    if (r < 0 || 
	ferror_folder(storage->current_folder,1)) {

	DPRINT(Debug,1,(&Debug, 
			"WARNING -- add_new_mailbox failed: %s\n",
			storage->current_folder->cur_folder_sys));

	lib_error(CATGETS(elm_msg_cat, ElmSet, ElmErrorWhenReading,
			  "Error when reading: %S"),
		  storage->current_folder->cur_folder_disp);

	if (!same_file)
	    free_storage(&storage);

	return;
    }

    if(!same_file) 		
	add_storage(mailbox,storage);

    update_view(mailbox);

    resort_mailbox(mailbox, !same_file);
   
    return;
}

/* If new folder is freed / moved to new owner,
   then *new_folder == NULL is NULL
   if *new_folder is not modified (set to NULL)
   caller must free *new_folder 

   reads mailbox
*/
struct MailboxView * enter_mailbox(new_folder,page)
     struct folder_info **new_folder;
     struct menu_context *page;
{
    struct MailboxView * mailbox = NULL;
    struct current_storage *storage = NULL;
    int ret;
    int r;

    ret = sessionlock_folder(*new_folder,SESSIONLOCK_NORMAL);
    if (!ret)
	return NULL;


    storage = new_storage(*new_folder);
    *new_folder = NULL;     /* Storage takes care of freeing */

    r= read_headers(0,storage, page); /* Returns number of mails readed */

    if (r < 0 || 
	ferror_folder(storage->current_folder,1)) {

	DPRINT(Debug,1,(&Debug, 
			"error when reading mailfile: %s\n",
			storage->current_folder->cur_folder_sys));
	lib_error(CATGETS(elm_msg_cat, ElmSet, ElmErrorWhenReading,
			  "Error when reading: %S"),
		  storage->current_folder->cur_folder_disp);

	free_storage(&storage);   /* Frees folder */
	return NULL;
    }

    mailbox = malloc_mailbox_view(storage);

    update_view(mailbox);
    resort_mailbox(mailbox,0);

    return mailbox;
}


void newmbox_1(new_folder, mailbox, append, page)
     struct folder_info *new_folder;
     struct MailboxView **mailbox;
     int append;
     struct menu_context *page;
{
    int ret;
    struct current_storage *storage = NULL;

    /* If we were reading a spool file, we need to
     * truncate the corresponding tempfile.
     */

    int same_file  = 0;
    int r;
  
    if (*mailbox) {
	int mbc = get_storage_count(*mailbox);
	int i;

	for (i = 0; i < mbc; i++) {
	    struct current_storage *s = get_storage(*mailbox,i);

	    if (!s)
		continue;

	    if (s->current_folder &&
		new_folder == s->current_folder) {
		storage   = s;
		same_file++;
		break;
	    }
	}    
    }

    if (! same_file) {

	storage = new_storage(new_folder);
      
	ret = sessionlock_folder(storage->current_folder,
				 SESSIONLOCK_NORMAL);
      
    } else {
	/* folder (as opposite to mailbox) can be session locked
	 * only when it is opened. That call can do session locking
	 * for both (folders and mailboxes)
	 */

	ret = sessionlock_folder(storage->current_folder,
				 SESSIONLOCK_TRUNCATE);
    }
  
    if (!ret) {

	if (!same_file)
	    free_storage(&storage);

	silently_exit();     /* ????  TODO -- is needed? */

    }

    DPRINT(Debug,10,(&Debug, 
		     "Mailfile opened: %s\n",
		     storage->current_folder->cur_folder_sys));

    clear_error();

 reread:
    r= read_headers(0,storage, page); /* Returns number of mails readed */

    if (r < 0 || 
	ferror_folder(storage->current_folder,1)) {
	int LINES, COLUMNS;

	menu_get_sizes(page,&LINES, &COLUMNS);

	DPRINT(Debug,1,(&Debug, 
			"error when reading mailfile: %s\n",
			storage->current_folder->cur_folder_sys));
	lib_error(CATGETS(elm_msg_cat, ElmSet, ElmErrorWhenReading,
			  "Error when reading: %S"),
		  storage->current_folder->cur_folder_disp);
	sleep_message();
	if (*def_ans_yes == want_to ("Error when reading! Reread folder?",
				     *def_ans_yes,LINES-1,1,
				     page)) {
	    
	    DPRINT(Debug,1,(&Debug, 
			    "rereading mailfile: %s\n",
			    storage->current_folder->cur_folder_sys));
	    if (sessionlock_folder(storage->current_folder,
				   SESSIONLOCK_TRUNCATE))
		goto reread;
	}

	if (!same_file)
	    free_storage(&storage);
	
	rm_temps_exit();        /* ????  TODO -- is needed? */
    }
    
   
    if(!same_file) {		

	if (!append) {
	    if (*mailbox)
		free_mailbox(mailbox);
	    *mailbox = malloc_mailbox_view(storage);
	} else
	    add_storage(*mailbox,storage);

    }
    
    /* limit mode off -- we are recreating headers 
       We loose the 'Visible' flag 
    */
    set_selected(*mailbox, 0);    
        

    update_view(*mailbox);

    resort_mailbox(*mailbox, append && !same_file);

    return;
}

#if ANSI_C
parse_header_callback parse_header_routine;
#endif
int parse_header_routine(folder,read_state_ptr,current_header,
				parsed_headers)
     struct folder_info *folder;
     READ_STATE read_state_ptr;
     struct header_rec *current_header;
     header_list_ptr parsed_headers;
{

    
    current_header->exit_disposition = UNSET;
    /* header_parse_helper may set 
       current_header->exit_disposition = HIDE   */

    /* copy_envelope_folder() may have set current_header->content_length */

    current_header->have_from        = FALSE;

    /* copy_envelope_folder() have set current_header->header_charset */

    header_parse_helper(current_header,parsed_headers);

    return 1;
}

struct counter_data {
    int count_x, count_y, lastpercent;
    struct string * truncated_name;
};

enum counter_mode { COUNT_initialize,
		    COUNT_update,
		    COUNT_finalize };

static void reading_updater P_((enum counter_mode mode,
				struct string *name,
				struct counter_data *counter,
				int count, int percent,
				int skipcount, int percent2));
static void reading_updater(mode,
			    name, counter,count,percent,skipcount,
			    percent2)
     enum counter_mode mode;
     struct string *name;
     struct counter_data *counter;
     int count; 
     int percent;
     int skipcount; 
     int percent2;
{
    int initialize = mode == COUNT_initialize;

    int width;
    int LINES, COLUMNS;

    menu_get_sizes(default_context,&LINES, &COLUMNS);

    width = COLUMNS - 53
	        - ((skipcount >= 10000) ? 1 : 0)
	        - ((count >= 10000) ? 1 : 0);

    if (initialize) {
	counter->truncated_name = NULL;
    }

    if (width <= 6) 
	return;


    if (string_len( counter->truncated_name ? 
		    counter->truncated_name : name ) 
	> width) {
	int A = width/2 -2;
	int B = string_len(name);
	int C = B-A;
	struct string *D = clip_from_string(name,&C,A);

	if (counter->truncated_name)
	    free_string(&(counter->truncated_name));

	counter->truncated_name = 
	    format_string(FRM("%.*S...%S"),
			  A,name,D);
		
	free_string(&D);
	initialize++;
    }

    if (need_refresh_low_line())
	initialize++;

    if (initialize) {
	PutLineX(LINES-1, 0, CATGETS(elm_msg_cat, ElmSet, 
				       ElmReadingInMessage,
				       "Reading in %S, message: ."),
		 counter->truncated_name ? counter->truncated_name : name);
	
	GetXYLocation(&(counter->count_x),&(counter->count_y)); 
	counter->count_y--;
	counter->lastpercent = -1;
	CleartoEOLN();
    }

    PutLineX(counter->count_x, counter->count_y, 
	     FRM("%d (%02d%%) "), count,percent);

    if (skipcount > 0 || percent2 >= 0) {
	int add = 12 	- ((skipcount >= 100)  ? 1 : 0)
	                - ((skipcount >= 1000) ? 1 : 0)
                        + ((count >= 10000) ? 1 : 0);


	PutLineX(counter->count_x, counter->count_y+add,
		 CATGETS(elm_msg_cat, ElmSet,
			 ElmSkippingInMessage,
			 " %d (%02d%%) skipped "),
		 skipcount,percent2);		
    }

    if (COUNT_finalize == mode) {
	CarriageReturn();

	if (counter->truncated_name)
	    free_string(&(counter->truncated_name));
    }
    FlushBuffer();
}



#if ANSI_C
parse_body_callback parse_body_routine;
#endif
int parse_body_routine(current_folder,read_state_ptr,current_header,
		       parsed_headers,counter
		       )
     struct folder_info *current_folder;
     READ_STATE read_state_ptr;
     struct header_rec *current_header;
     header_list_ptr parsed_headers;
     struct counter_data *counter;
{
    int content_length_found = current_header->content_length > -1L;

    long content_start = -1L;
    long content_remaining = -1L;
    long tmp;

    char * buffer = NULL;
    int len = 0;

    int last_empty_line = 0;



    if (content_length_found)
	content_remaining = current_header->content_length;
    else
	content_remaining = -1;
    content_start     = copy_fbytes_folder(current_folder,
					   read_state_ptr);


    /* Notice that mark_keep_folder() also uses mime_rec.offset */
    start_body_helper(current_header,content_start,parsed_headers);

 reset_body:

    while (copy_body_folder(current_folder,read_state_ptr,
			    &buffer,&len,&content_remaining)) {
	int skipcount;
	long skipbytes;
	long f = copy_fbytes_folder(current_folder,
				    read_state_ptr);
	int percent;	


	last_empty_line =   len == 1 && '\n' == buffer[0];

	copy_skipcount_folder(current_folder,read_state_ptr,
			      &skipcount,&skipbytes);

	f += skipbytes;

	percent = (int)(f * 100.0 / 
			current_folder->mailfile_size);
	
	/* calculation with integers overflow on big folders! */
	if (counter &&
	    counter->lastpercent / readdatapercentinc != 
	    percent / readdatapercentinc) {

		if (skipbytes > 0 || skipcount > 0) {
		    int percent2 = (int)(skipbytes * 100.0 /
					current_folder->mailfile_size);

		    reading_updater(COUNT_update,
				    current_folder->cur_folder_disp,counter,
				    current_header->index_number_X,
				    percent,skipcount,percent2);

		} else
		    reading_updater(COUNT_update,
				    current_folder->cur_folder_disp,counter,
				    current_header->index_number_X,
				    percent,-1,-1);

		counter->lastpercent = percent;
	}

	DPRINT(Debug,13,(&Debug, "** fbytes=%ld,size=%ld -> %d%%\n",
			 f,current_folder->mailfile_size,percent));

	switch (buffer[0]) {

	case 'F':

	    if (first_word(buffer,"From ")) {
		if (!current_header->have_from) {
		    current_header->have_from = 1;
		    DPRINT(Debug,10,(&Debug, 
				     "-- Message have unescaped From \n"));
		}
	    }

	    break;

	case '[':

	    if (mime_body_keywords && first_word(buffer, START_ENCODE)) {
		current_header->encrypted = 1;
		DPRINT(Debug,10,(&Debug, "-- encrypted: %s\n",buffer));
		
		/* Text/plain can be converted to application/X-ELM-encode
		 */
		if (get_major_type_code(current_header->mime_rec.TYPE) == 
		    MIME_TYPE_TEXT && 
		    (istrcmp(get_subtype_name(current_header->
					      mime_rec.TYPE),"plain")==0)) {
		    current_header->mime_rec.TYPE = 
			give_media_type2(MIME_TYPE_APPLICATION,
					 "X-ELM-encode",0);
		    if (!current_header->mime_rec.TYPE)
			mime_panic(__FILE__,__LINE__,"parse_body_routine",
				   "application/X-ELM-encode is not known");
		    
		    /* Keep current_header->mime_rec.type_opts ! */
		}
		DPRINT(Debug,10,(&Debug, 
				 "-- encrypted, %d/%s\n",
				 get_major_type_code(current_header->
						     mime_rec.TYPE),
			     get_subtype_name(current_header->mime_rec.TYPE)));
		
	    }

	    break;

	case '-':

#ifdef USE_PGP
	    if (strncmp(buffer, "-----BEGIN PGP", 14) == 0) {
		if (strncmp(buffer + 15, "PUBLIC", 6) == 0) {
		    current_header->pgp |= PGP_PUBLIC_KEY;
		    DPRINT(Debug,10,(&Debug, "-- PGP PUBLIC KEY: %s\n",
				     buffer));
		} else {
		    
		    /* Text/plain can be converted to 
		     * application/pgp.  There will a possible
		     * loss of surrounding text, but there is no
		     * way to get around this without having the
		     * sender use the proper MIME type.  
		     */
		    
		    if (get_major_type_code(current_header->mime_rec.TYPE) 
			== MIME_TYPE_TEXT && 
			istrcmp(get_subtype_name(current_header->mime_rec.TYPE),
				"plain")==0) {
			current_header->mime_rec.TYPE = 
			    give_media_type2(MIME_TYPE_APPLICATION,"pgp",1);
			/* Keep current_header->mime_rec.type_opts ! */
		    }
		    
		    if (strncmp(buffer + 15, "SIG", 3) == 0) {
			CONST char *mp;
			
			current_header->pgp |= PGP_SIGNED_MESSAGE;
			DPRINT(Debug,10,(&Debug, "-- PGP signed: %s\n",
					 buffer));
			
			mp = get_mime_param_compat(current_header->
						   mime_rec.TYPE_opts,
						   "x-action");
			if (!mp) {
			    mime_params_add_compat(& (current_header->
						  mime_rec.TYPE_opts),
						   "x-action", "sign");
			    
			}
			DPRINT(Debug,10,(&Debug, 
					 "-- PGP signed, %s/%s; \n",
					 get_major_type_name(current_header->
							     mime_rec.TYPE),
					 get_subtype_name(current_header->
							  mime_rec.TYPE)));
		    } else {
			CONST char *mp;
			
			current_header->pgp |= PGP_MESSAGE;
			
			DPRINT(Debug,10,(&Debug, 
					 "-- PGP message: %s\n",
					 buffer));
			
			mp = get_mime_param_compat(current_header->
						   mime_rec.TYPE_opts,
						   "x-action");
			if (!mp) {
			    mime_params_add_compat(& (current_header->
						      mime_rec.TYPE_opts),
						   "x-action", "encrypt");
			}
			DPRINT(Debug,10,(&Debug, 
					 "-- PGP message, %s/%s\n",
					 get_major_type_name(current_header->
							     mime_rec.TYPE),
					 get_subtype_name(current_header->
							  mime_rec.TYPE)));
		    }
		}
	    }
#endif /* USE_PGP */

	    break;
	}
		
	if (buffer)
	    free(buffer);
    }
    
    current_header->lines =  copy_lines_folder(current_folder,
					       read_state_ptr);
    tmp = current_header->content_length;
    if (content_start >= 0L)
	current_header->content_length = 
	    copy_fbytes_folder(current_folder,read_state_ptr) - 
	    content_start;
    else
	current_header->content_length = 0;
    DPRINT(Debug,12,(&Debug, "-- content-length=%d\n",
		     current_header->content_length));

    /* Work around message
          Message contains bare newlines
       from some IMAP servers. Do not include terminating
       empty line (only LF on line) from end of mail,
       which is part of mailbox format.

       When message is downloaded from IMAP or POP servers
       there are all lines terminated with CR LF. However
       ending line which is part of mailbox format is ended
       by LF  (added by real_end_we_local()).


       Possible real empty lines from IMAP and POP servers
       are ended with CR LF so that do not effect them.
    */

#ifndef MMDF
    if (last_empty_line) {

	if (current_header->content_length < 1)
	    mime_panic(__FILE__,__LINE__,"parse_body_routine",
		       "content-length fixup error");

	current_header->content_length --;

	DPRINT(Debug,12,(&Debug, "-- FIXUP content-length=%d\n",
			 current_header->content_length));

    }
#endif

    if (tmp >= 0 && current_header->content_length != tmp) {
	DPRINT(Debug,10,(&Debug, 
			 "  DIFFERS from header value (%ld)\n",
			 tmp));
    }

    if (!copy_envelope_end_folder(current_folder,read_state_ptr)) {
	    
	if (content_length_found) {
	    content_length_found = 0;
	    
	    if (copy_envelope_reset_body(current_folder,read_state_ptr,
					 &content_remaining))
		goto reset_body;

	}

	DPRINT(Debug,10,(&Debug, "-- Message parsing FAILED.\n"));
	return 0;
    }

    current_header->body_parsed = 1;

    return 1;
}

void resort_mailbox(mailbox, add_new_only)
     struct MailboxView *mailbox;
     int add_new_only;
{
    int current;
    int count   = get_message_count(mailbox);

    /* Sort folder *before* we establish the current message, so that
     * the current message is based on the post-sort order.
     */
    
    sort_mailbox(count, 1, mailbox);         
    
    /* Now lets figure what the current message should be.
     * If we are only reading in newly added messages from a mailfile
     * that already had some messages, current should remain the same.
     * If we have a folder of no messages, current should be zero.
     * Otherwise, if we have point_to_new on then the current message
     * is the first message of status NEW if there is one.
     * If we don't have point_to_new on or if there are no messages of
     * of status NEW, then the current message is the first message.
     */

    current = get_current(mailbox);
    if(!(add_new_only && current != 0)) {
	if(count == 0)
	    current = 0;
	else {
	    current = 1;
	    if (point_to_new) {
		int another_count;

		for(another_count = 0; another_count < count; 
		    another_count++) {
		    struct header_rec *hdr = give_header(mailbox,
							 another_count);

		    if(hdr &&
		       ison(hdr->status, NEW)) {
			current = another_count+1;
			goto found_new;
		    }
		}
		for(another_count = 0; another_count < count; 
		    another_count++) {
		    struct header_rec *hdr = give_header(mailbox,
							 another_count);

		    if(hdr &&
		       ison(hdr->status, UNREAD)) {
			current = another_count+1;
			goto found_new;
		    }
		}
		switch (give_dt_sort_as_int(&sortby)) {
		case SENT_DATE:
		case RECEIVED_DATE:
		case THREAD:
		case MAILBOX_ORDER:
		    current = count;
		}
	    found_new: ;
	    }
	}

	set_current(mailbox,current);

    }
}

static int read_headers(add_new_only, storage, page)
     int add_new_only;
     struct current_storage *storage;    
     struct menu_context *page;
{
    /** Reads the headers into the headers[] array and leaves the
	file rewound for further I/O requests.   If the file being
	read is a mail spool file (ie incoming) then it is copied to
	a temp file and closed, to allow more mail to arrive during 
	the elm session.  If 'add_new_only' is set, the program will copy
	the status flags from the previous data structure to the new 
	one if possible and only read in newly added messages.
    **/

    int percent, count = 0;    
    

    struct counter_data COUNTER;

    struct read_folder_state * read_state_ptr = NULL;
    CONST char *msg;
    int LINES, COLUMNS;

    menu_get_sizes(page,&LINES, &COLUMNS);

    if (!prepare_read_folder(storage->current_folder,
			     add_new_only ? PREPARE_NEW_ONLY : PREPARE_NORMAL,
			     &read_state_ptr)) {
	sleep_message();
	return -1;  /* FAILURE */
    }

    if (add_new_only)
	count = storage->message_count;		/* next available  */

    ClearLine(LINES-2);
    ClearLine(LINES-1);

    /* Initialize */
    reading_updater(COUNT_initialize,
		    storage->current_folder->cur_folder_disp,&COUNTER,
		    count,0,-1,-1);

    if ((msg = is_forwarded_folder(storage->current_folder,
				   read_state_ptr)) != NULL) {
	lib_transient(CATGETS(elm_msg_cat, ElmSet, ElmMailBeingForwardTo,
			      "Mail being forwarded to %s"), 
		      msg);	
    } else {
	int status;
	struct header_rec WRK;
	header_zero(&WRK);
	WRK.index_number_X = count+1;

	while ((status = 
		copy_envelope_folder(storage->current_folder,read_state_ptr,
				     &WRK,
				     parse_header_routine,
				     parse_body_routine,
				     &COUNTER
				     )) > 0) {
	    
	    if (count % readmsginc == 0) {
		int skipcount;
		long skipbytes;
		long f = copy_fbytes_folder(storage->current_folder,
					    read_state_ptr);

		copy_skipcount_folder(storage->current_folder,read_state_ptr,
				      &skipcount,&skipbytes);

		f += skipbytes;


		percent = (int)(f * 100.0 / 
				storage->current_folder->mailfile_size);
		/* calculation with integers overflow on big folders! */

		if (skipbytes > 0 || skipcount > 0) {
		    int percent2 = (int)(skipbytes * 100.0 /
					 storage->current_folder->
					 mailfile_size);

		    reading_updater(COUNT_update,
				    storage->current_folder->cur_folder_disp,
				    &COUNTER,
				    count,percent,skipcount,percent2);

		} else
		    reading_updater(COUNT_update,
				    storage->current_folder->cur_folder_disp,
				    &COUNTER,
				    count,percent,-1,-1);

		COUNTER.lastpercent = percent;
	    }

	    /** allocate new header pointers, if needed... **/
	    realloc_headers(storage,count);


	    /** allocate new header structure, if needed... **/
	    alloc_header(storage,count);

	    header_clear(storage->headers[count]);
	    *(storage->headers[count]) = WRK;
	    header_zero(&WRK);  /* Reset (NOT free) temporary work space */

	    storage->headers[count]->index_number_X = count+1;


	    DPRINT(Debug,10,(&Debug, "-- Message %d parsed.\n",count));
	    count++;

	    WRK.index_number_X = count +1;   /* For messages ... */
	}
	header_clear(&WRK);  /* Should have resetted if parsing was succeed */

	if (status < 0) {
	    sleep_message();
	    end_read_folder(storage->current_folder,&read_state_ptr,1);


	    DPRINT(Debug,7,(&Debug, 
			    "  Updating storage message count %d -> %d on FAILURE\n",
			    storage->message_count,count));
	    storage->message_count = count;

	    return -1;  /* FAILURE */
	}
    }
   	

    {
	/* Final counter */
	int skipcount;
	long skipbytes;
	long f = copy_fbytes_folder(storage->current_folder,
				    read_state_ptr);
	
	copy_skipcount_folder(storage->current_folder,read_state_ptr,
			      &skipcount,&skipbytes);
	
	f += skipbytes;
	
	if (storage->current_folder->mailfile_size >0)
	    percent = (int)(f * 100.0 / 
			    storage->current_folder->mailfile_size);
	else 
	    percent = 100;
	/* calculation with integers overflow on big folders! */
	
	/* Should be 100% now ... */

	if (skipbytes > 0 || skipcount > 0) {
	    int percent2 = (int)(skipbytes * 100.0 /
				 storage->current_folder->mailfile_size);
	    
	    reading_updater(COUNT_finalize,
			    storage->current_folder->cur_folder_disp,&COUNTER,
				    count,percent,skipcount,percent2);

	} else
	    reading_updater(COUNT_finalize,
			    storage->current_folder->cur_folder_disp,&COUNTER,
			    count,percent,-1,-1);
	
	COUNTER.lastpercent = percent;
    }


    if (!end_read_folder(storage->current_folder,&read_state_ptr,0)) {
	sleep_message();

	DPRINT(Debug,7,(&Debug, 
			"  Updating storage message count %d -> %d on FAILURE\n",
			storage->message_count,count));
	storage->message_count = count;

	return -1;  /* FAILURE */
    } 

    /* We need set per storage variable message_count */
    DPRINT(Debug,7,(&Debug, 
		    "  Updating storage message count %d -> %d\n",
		    storage->message_count,count));
    storage->message_count = count;

    clear_error();

    return(count);
}

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


syntax highlighted by Code2HTML, v. 0.9.1