static char rcsid[] = "@(#)$Id: elm.c,v 1.122 2006/07/01 06:26:52 hurtta Exp $";

/*****************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.122 $   $State: Exp $
 *
 *  Modified by: Kari Hurtta <hurtta+elm@posti.FMI.FI> 
 *                       (was hurtta+elm@ozone.FMI.FI)
 *           or  Kari Hurtta <elm@elmme-mailer.org>
 *****************************************************************************
 *  The Elm Mail System 
 *
 * This file and all associated files and documentation:
 *			Copyright (c) 1988-1992 USENET Community Trust
 *			Copyright (c) 1986,1987 Dave Taylor
 *****************************************************************************/

/* Main program of the ELM mail system! 
*/

#include "patchlevel.h"
#include "elm.h"
#include "mailerlib.h"
#include "mboxlib.h"
#include "s_elm.h"

#ifdef BSD_TYPE
#  include <sys/timeb.h>
#endif

#include "mime.h"
#include "me.h"

DEBUG_VAR(Debug,__FILE__,"ELM");


static unsigned char * s2us P_((char *str));
static unsigned char * s2us(str)
     char *str;
{
    return (unsigned char *)str;
}

static void do_check_only P_((char *argv[],
			      struct AliasView *aview)); 
static void debug_screen P_((struct MailboxView *mailbox,
			     struct screen_parts *LOC));
static void debug_message P_((struct header_rec *hdr, int current,
			      struct folder_view *index));

static void elm_panic_prepare P_((CONST int interrupt, 
				  CONST char * title,
				  CONST char * ms));
static void elm_panic_prepare(interrupt,title,ms)
     CONST int interrupt;
     CONST char * title;
     CONST char * ms;
{
    int do_cursor = RawState();

    if (do_cursor && !interrupt) {
	lib_error(FRM("%s: %s"),title,ms);
	sleep(1);
    }

    if (do_cursor) {
	/* MoveCursor() is not safe on interrupt */

	if (interrupt) {
	    ClearScreen(1);    /* 1 == is called from interrupt */

	    Raw(OFF|RAW_FROM_SIGNAL);
	} else {
	    int LINES, COLUMNS;

	    menu_get_sizes(default_context, &LINES, &COLUMNS);   

	    MoveCursor(LINES-1,0);
	    Raw(OFF);
	}
    }
}

static void elm_panic_exit P_((CONST int interrupt));
static void elm_panic_exit(interrupt)
     CONST int interrupt;
{
    emergency_exit(interrupt);
}

void forget_passphrase() 
{
#ifdef USE_PGP
    if (pgp_void_passphrase())
	lib_error(CATGETS(elm_msg_cat, ElmSet, 
			  ElmPGPPassphraseForgotten,
			  "PGP passphrase forgotten!"));
#endif
#ifdef REMOTE_MBX
    if(close_cached_connections())
	lib_error(CATGETS(elm_msg_cat, ElmSet, 
			  ElmCachedConenctionsClosed,
			  "Cached connections closed!"));
#endif

    error_sleep(1);
}

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

int mailbox_command(mailbox, ch,  LOC, cmdX, aview, 
		    page)
     struct MailboxView *mailbox;
     int ch;   
     struct screen_parts *LOC;
     showmsg_cmd  cmdX;
     struct AliasView *aview;
     struct menu_context  *page;
{
    struct menu_common MENU;
    int LINES, COLUMNS;

    menu_get_sizes(page, &LINES, &COLUMNS);   
    

    set_mcommon_from_mbxview(&MENU,mailbox);

    switch (ch) {

#ifdef ALLOW_SUBSHELL
    case '!'    :  
	menu_Writechar(LOC->prompt_page,'!'); 
	subshell(mailbox, page,LOC->prompt_page);		

	break;
#endif

    case '<'    :  {
	/* scan current message for calendar information */
#ifdef ENABLE_CALENDAR
	int current = get_current(mailbox);

	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, 
				     ElmSet, 
				     ElmScanForCalendar,
				     "Scan message for calendar entries..."));
	
	if  (current < 1) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToScan,
			      "No mail to scan!"));
	    
	} else if (give_message_data(mailbox,current-1,
				     NULL,NULL,NULL,NO_mime_parse)) {
	    /* FIX: mime sctructure is not 
	       currently used */
	    scan_calendar(mailbox);
	} else {
	    DPRINT(Debug,3,(&Debug, 
			    "give_message_data [%d] fails",current-1));
	}
#else
	lib_error(CATGETS(elm_msg_cat, ElmSet, 
			  ElmSorryNoCalendar,
			  "Sorry. Calendar function disabled."));
	
#endif
    }
	break;
	
    case 'a'    :  
	alias(mailbox, aview);
	menu_trigger_redraw(page);

	/* define_softkeys(MAIN); */	
	break;

    case 'b'    :  {
	int current = get_current(mailbox);
	struct header_rec *hdr;
	FILE *F;
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, 
				     ElmSet, ElmBounceMessage,
				     "Bounce message"));
	FlushBuffer();
	if (current < 1) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToBounce,
			      "No mail to bounce!"));
	    
	} else if (give_message_data(mailbox,current-1,
				     &hdr,&F,NULL,
				     NO_mime_parse)) {

	    remail(hdr,F, aview, page, LOC->prompt_page);

	} else {
	    DPRINT(Debug,3,(&Debug, 
			    "give_message_data [%d] fails",current-1));
	}
    }
	break;

#ifdef USE_PGP
    case ctrl('E'): {
	int current = get_current(mailbox);
	struct header_rec *hdr;
	FILE *F;

	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet, ElmExtractPGPKey,
				     "Extract PGP public key"));
	
	if (current < 1) 
	    lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNoMailInFolder,
			      "There is no mail in this folder!"));

	else if (give_message_data(mailbox,current-1,
				     &hdr,&F,NULL,NO_mime_parse)) {
		  
	    if (hdr->pgp & PGP_PUBLIC_KEY) {
		/* FIXME: mime structure is not currently used */
		pgp_extract_public_key(hdr,F,page);
	    } else
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmNoPgpPublicKeys,
				  "This message does not contain PGP public keys!"));
	} else {
	    DPRINT(Debug,3,(&Debug, 
			    "give_message_data [%d] fails",current-1));

	}
    }
	break;	
#endif
	
    case 'E': 
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmExtendedCommand,
				     "Extended command"));
	
	FlushBuffer();
		
	extended_command(mailbox, 
			 aview,
			 page,
			 LOC);
	
	break;

    case ctrl('F'):
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet, 
				ElmPassphraseForget,
				"Forget passphrase"));
	forget_passphrase();
	break;

    case 'f'    : {
	int current = get_current(mailbox);
	struct header_rec *hdr;
	FILE *F;
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet, 
				     ElmForward,
				     "Forward"));
	/* define_softkeys(YESNO); */
	FlushBuffer();
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToForward,
			      "No mail to forward!"));
		  
	else  {
	    forward(current-1,mailbox, aview, 
		    page,
		    LOC->prompt_page,
		    LOC->header_page);
	   
	} 
	/* define_softkeys(MAIN); */
    }
	break;

    case 'g'    :  {
	int current = get_current(mailbox);
	struct header_rec *hdr;
	FILE *F;


	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet, 
				     ElmGroupReply,
				     "Group reply"));
	FlushBuffer();
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToReply,
			      "No mail to reply to!")); 
	else if (give_message_data(mailbox,current-1,
				   &hdr,NULL,NULL,
				   mime_parse_routine)) {
	    
	    if (hdr->status & FORM_LETTER) {
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmCantGroupReplyForm,
				  "Can't group reply to a Form!!"));
		
	    } else {
		int vis;
		/* define_softkeys(YESNO); */
		
		reply_to_everyone(current-1, mailbox, aview,
				  page,
				  LOC->prompt_page,
				  LOC->header_page);	
		/* define_softkeys(MAIN); */

	    }
	} else {
	    DPRINT(Debug,3,(&Debug, 
			    "give_message_data [%d] fails",current-1));

	}
	FlushBuffer();
    }
	break;
	
    case 'h'    :  {
	int current = get_current(mailbox);
		
	if (elm_filter)
	    menu_Write_to_screen(LOC->prompt_page,
				 CATGETS(elm_msg_cat, 
					 ElmSet, 
					 ElmMessageWithHeaders,
					 "Message with headers..."));
	else
	    menu_Write_to_screen(LOC->prompt_page,
				 CATGETS(elm_msg_cat, 
					 ElmSet, 
					 ElmDisplayMessage,
					 "Display message"));
	FlushBuffer();

	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToRead,
			      "No mail to read!"));
	else {		
	    int x = show_message_with_headers(mailbox,cmdX,aview,page,
					      LOC->header_page);
	    
	    if (x != 0)
		return x;   /* "call" parent or EOF */

	    current = get_current(mailbox);
	    
	}
    }
	break;

    case 'I'    : {
	int current = get_current(mailbox);
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmMailingListInfo,
				     "Mailing List Info"));

	FlushBuffer();
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToViewInfo,
			      "No mail to view list info!"));

	else {
	    list_info(current-1,mailbox, aview, page,LOC->prompt_page);	
	    
	} 
	/* softkeys_on(); */
    }
	break;
	
#ifdef USE_PGP
    case ctrl('K'):
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmMailPGPPublicKey,
				     "Mail PGP public key"));
	FlushBuffer();
	
	pgp_mail_public_key(mailbox, aview, 
			    page, 
			    LOC->prompt_page);
	break;
#endif
	
    case 'm'    :   
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmMail,
				     "Mail"));
	FlushBuffer();
	send_msg_l(-1, NULL, NULL, NULL,
		   MAIL_EDIT_MSG,allow_forms,
		   mailbox, aview,page, LOC->prompt_page);
	break;
			   
    case ' '    : 
    case ctrl('J'):
    case ctrl('M'): {
	int current = get_current(mailbox);
		
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmDisplayMessage,
				     "Display message"));  
	FlushBuffer();
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToRead,
			      "No mail to read!"));
	else {
	    int x = show_message_normal(mailbox,cmdX,aview,page,
					      LOC->header_page);
	    
	    if (x != 0)
		return x;   /* "call" parent or EOF */	    

	    current = get_current(mailbox);
	}
    }
	break;
	
    case 'n'    : {
	int current = get_current(mailbox);
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmNextMessage,
				     "Next Message"));
	FlushBuffer();
	/* define_softkeys(READ); */
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToRead,
			      "No mail to read!"));
	else {
	    int x = show_next_message(mailbox,cmdX,aview,page,
				      LOC->header_page);
	    
	    if (x != 0)
		return x;   /* "call" parent or EOF */	    

	    current = get_current(mailbox);
	} 
    }		
	break;

    case ctrl('N'):   {
	int current = get_current(mailbox);
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmNextUMessage,
				     "Next Unread Message"));
	FlushBuffer();
	
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToRead,
			      "No mail to read!"));
	else {
	    int mc;
	    int i = 0;	    
	    
	    struct pager_page * PP = init_pager_page(&MENU);
	    
	    if(ison_status_message(mailbox,current-1,status_basic,UNREAD)) {
		
		i = mbx_show_msg(mailbox,current-1,PP);
		
	    } else 
		i = ctrl('N');

	    while (i >0) {
		i = process_showmsg_cmd(i, mailbox, cmdX, aview, 
					PP);
		
		switch (i) {
		case EOF:

		    exit_pager_page(&PP,page);
		    return EOF;/* Read failed, control tty died? */
		    
		case 'X':      /* Quick Exit */
		case 'x':      /* Exit       */
		    
		    exit_pager_page(&PP,page);
		    return i;   /* "call" parent */

		case 0:
		    break;
		    
		default:
		    DPRINT(Debug,3,(&Debug, 
				    "Looping showmsg command %d (%c)\n",
				    i,i));		    
		}
	    }

	    exit_pager_page(&PP,page);
	    current = get_current(mailbox);


	    menu_trigger_redraw(page);
	    if (++current > (mc = get_message_count(mailbox)))
		current = mc;
	    set_current(mailbox,current);
	    
	    get_page(&MENU, LOC->header_page);
	}
    }
	break;
	
    case 'O' : {
	int current = get_current(mailbox);
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,	  
				     ElmOverrideCharset,
				     "Override charset"));
	FlushBuffer();

	if  (current < 1) 
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToOverride,
			      "No mail to override!"));
	else
	    OverrideCharset(mailbox, page, 
			    LOC->prompt_page,
			    LOC->header_page);

    }
	break;


    case 'P'    : {
	int current = get_current(mailbox);
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,	  
				     ElmPrintTextMail,
				     "Print text of mail"));
	FlushBuffer();
	
	if (current < 1) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToPrint,
			      "No mail to print!"));
	    
	} else if (give_message_data(mailbox,current-1,
				     NULL,NULL,NULL,
				     mime_parse_routine)) {
	    int vis;

	    print_text(TRUE, mailbox, page, LOC->header_page);


	} else {
	    DPRINT(Debug,3,(&Debug, 
			    "give_message_data [%d] fails",current-1));
	}
    }
	break;
	
    case 'R'    : {
	int current = get_current(mailbox);
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmGenericReply,
				     "Generic Reply"));

	FlushBuffer();
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToReplyTo,
			      "No mail to reply to!")); 
	else {
	    generic_reply(current-1,mailbox, aview, 
			  page,LOC->prompt_page);	
	    
	} 
	/* softkeys_on(); */
    }
	break;

    case 'r'    : {
	int current = get_current(mailbox);
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmReplyToMessage,
				     "Reply to message"));
	FlushBuffer();
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToReplyTo,
			      "No mail to reply to!")); 
	else {

	    reply(current-1,mailbox, aview, 
		  page, 
		  LOC->prompt_page,
		  LOC->header_page);	

	} 
	/* softkeys_on(); */
    }
	break;
	
    case '>'    : /** backwards compatibility **/
	
    case 'C'	:
    case 's'    :  {
	int current = get_current(mailbox);
	
	if (ch != 'C')
	    menu_Write_to_screen(LOC->prompt_page,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmSaveToFolder,
					 "Save to folder"));
	else
	    menu_Write_to_screen(LOC->prompt_page,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmCopyToFolder,
					 "Copy to folder"));
	FlushBuffer();
	
	if  (current < 1) {
	    if (ch != 'C')
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmNoMailToSave,
				  "No mail to save!"));
	    else
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmNoMailToCopy,
				  "No mail to copy!"));
	    
	} else if (give_message_data(mailbox,current-1,
				     NULL,NULL,NULL,NO_mime_parse)) {
	    
	    if (save(FALSE, (ch != 'C'), 0,mailbox, aview, 
		     page, 
		     LOC->prompt_page,
		     LOC->header_page)
		&& resolve_mode && ch != 'C') {
		int i;

		if((i=next_message(current-1, TRUE, &MENU)) != -1) {
		    
		    int current        = get_current(mailbox);
		    current = i+1;
		    set_current(mailbox,current);
		    
		    get_page(&MENU, LOC->header_page);
		    
		}
	    }

	} else {
	    DPRINT(Debug,3,(&Debug, 
			    "give_message_data [%d] fails",current-1));
	}
	ClearLine(LINES-3);		
    }
	break;

    case 'S'     :   { 
	int current = get_current(mailbox);
	
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmSaveTextToFileorFolder,
				     "Save (copy) text to file or folder"));
	FlushBuffer();
	
	if  (current < 1) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToCopy,
			      "No mail to copy!"));
	    
	} else if (give_message_data(mailbox,current-1,
				     NULL,NULL,NULL,
				     mime_parse_routine)) {
	    int vis;

	    save(FALSE, 0, 1, mailbox, aview, 
		 page, 
		 LOC->prompt_page,
		 LOC->header_page);


	} else {
	    DPRINT(Debug,3,(&Debug, 
			    "give_message_data [%d] fails",current-1));
	}
	
	ClearLine(LINES-3);		
    }
	break;	                   

    case 'U'    :  {
	if (get_message_count(mailbox) < 1) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet,
			      ElmNoItemToMarkUnread,
			      "No %S to mark as unread!"),
		      mcommon_give_item(&MENU,m_items));
	    
	}
	else
	    unread_msg(mailbox, LOC->header_page);
    }
	break;
       	
    case 'v'    :   {	      
	struct header_rec *hdr;
	FILE *F;
	int current = get_current(mailbox);
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMessages,
			      "There are no messages!"));
	else {
	    menu_Write_to_screen(LOC->prompt_page,
				 CATGETS(elm_msg_cat, ElmSet, 
					 ElmViewParts,
					 "View parts of message"));
	    
	    if (give_message_data(mailbox,current-1,
				  &hdr,&F,NULL,mime_parse_routine)) {
		int vis;

		if ((hdr->status & MIME_MESSAGE)) {
		    
		    mime_warnings(hdr);
		    
		    attach_menu(F,& (hdr->mime_rec),
				NULL, 
				hdr->header_charset, NULL,
				hdr,
				aview,
				& (hdr->header_error));
		    menu_trigger_redraw(page);
		} else
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmNoMIMEMessage,
				      "This is not a MIME message!"));
		/* FIXME ? */
		vis = compute_visible(current, &MENU);
		menu_header_status_update(LOC->header_page,vis-1);

	    } else {
		DPRINT(Debug,3,(&Debug, 
				"give_message_data [%d] fails",current-1));
	    }
	}
    }	   	
	break;

    case 'V': {
	int current = get_current(mailbox);

	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet,
				     ElmViewDigest,
				     "View digest as mailbox"));

	FlushBuffer();
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToView,
			      "No mail to view!")); 
	else if (give_message_data(mailbox,current-1,
				   NULL,NULL,NULL,mime_parse_routine)) {
	    
	    ViewDigest(mailbox,aview,page);

	    current = get_current(mailbox);
	    get_page(&MENU, LOC->header_page);

	} else {
	    int vis;
	    DPRINT(Debug,3,(&Debug, 
			    "give_message_data [%d] fails",current-1));

	    /* FIXME? */
	    vis = compute_visible(current, &MENU);
	    menu_header_status_update(LOC->header_page,vis-1);
	}
    }
	break;

    case EOF : 
	return EOF;/* Read failed, control tty died? */
     
    case '@'    : 
	debug_screen(mailbox,LOC);  
	menu_trigger_redraw(page);	
	break;

    case '#'    : {
	int current = get_current(mailbox);
	menu_Write_to_screen(LOC->prompt_page,
			     CATGETS(elm_msg_cat, ElmSet, 
				     ElmCheckMessage,
				     "Check message"));
	FlushBuffer();
	
	if (current < 1)
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoMailToCheck,
			      "No mail to check."));
	else {
	    struct header_rec * hdr = give_header(mailbox,
						  current-1);
	    if (hdr) {
		struct folder_view index;
		
		give_index_number(mailbox,current-1,
				  &index);
		
		debug_message(hdr, current, &index); 
		menu_trigger_redraw(page);	
	    }
	} 
    }
	break;

    default: 
	/* Maybe motion command */

	ch = motion(ch,&MENU,LOC, page);
    
	/* motion() may already set, menu_trigger_redraw(page),
           we do not examine it */

	return ch;
		
    }

    return 0;   /* Command OK */
}

void new_mail_check (mailbox, page, LOC)
     struct MailboxView *mailbox;
     struct menu_context  *page;
     struct screen_parts *LOC;
{
    int idx, mbxcount;
    struct menu_common MENU;
    int   LINES, COLUMNS;	

    menu_get_sizes(page,&LINES, &COLUMNS);

    set_mcommon_from_mbxview(&MENU,mailbox);
    
    mbxcount = get_storage_count(mailbox);

    for (idx = 0 ; idx < mbxcount; idx++) {
	int bytes;

	struct current_storage * storage = get_storage(mailbox, idx);
	    
	if (!storage ||
	    !storage->current_folder)
	    continue;

	flush_folder(storage->current_folder);

	if (new_mail_on_folder(storage->current_folder,
			       &bytes)) {

	    int current        = get_current(mailbox);
	    int last_in_folder = storage->message_count;
	    int selected       = get_selected(mailbox);
	    int ok;

	    DPRINT(Debug,2,(&Debug, 
			    "Just received %d bytes more mail (elm), storage idx %d\n", 
			    bytes, idx));
	    
	    lib_transient(CATGETS(elm_msg_cat, ElmSet, ElmNewMailHangOn,
				  "New mail has arrived! Hang on..."));
	    
	    ok = read_new_mails(storage, page);

	    if (ok)
		clear_error();
		  
	    if (selected) {               
		/* update count of selected messages */
		selected += storage->message_count - last_in_folder;
		set_selected(mailbox,selected);
	    }		  

	    menu_trigger_redraw(LOC->header_page);	
	    menu_trigger_redraw(LOC->title_page);	
		  
	    ClearLine(LINES-2);	     /* remove reading message... */
	    
	    if (ok) {
		if ((storage->message_count - last_in_folder) == 1)
		    lib_error(CATGETS(elm_msg_cat, ElmSet, ElmNewMessageRecv,
				      "1 new message received."));
		else
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmNewMessageRecvPlural,
				      "%d new messages received."), 
			      storage->message_count - last_in_folder);
	    } else
		show_last_error();
	    
	} else if (bytes < 0) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmALERTMailfileShrinken,
			      "ALERT: Mailfile shrinken %d bytes!"),
		      -bytes);
	    DPRINT(Debug,1,(&Debug, 
			    "ALERT: Mailfile shrinken %d bytes!",
			    -bytes));
	    sleep_message();
	}
    }
    
}

void mailbox_screen_common(page,LOC, LIST)
     struct menu_context  *page;
     struct screen_parts *LOC;
     struct menu_param  *LIST;
{    
    int   LINES, COLUMNS;	
    int  headers_per_page;

    menu_get_sizes(page,&LINES, &COLUMNS);

    /* 3) prompt part */

    if (LOC->prompt_page)
	menu_subpage_relocate(LOC->prompt_page,page,LINES-4,4);
    else 
	LOC->prompt_page = new_menu_subpage(page,LINES-4,4,
					    subpage_simple_noredraw,LIST);


    headers_per_page = LOC->menu_page ? LINES-13 : LINES-9;
    if (headers_per_page < 1) {
	lib_error(CATGETS(elm_msg_cat, ElmSet, ElmWindowSizeTooSmall,
			  "The window is too small to run Elm.  It must have at least %d rows"),
		  LINES - headers_per_page);
	
	headers_per_page = 1;
    }

    /* 4) headers of screen */
    
    if (! LOC->header_page)
	LOC->header_page = new_menu_header(page,4,
					   headers_per_page,
					   hdr_show_header,
					   hdr_show_current,
					   null_header_param_changed,
					   hdr_show_status,
					   LIST);
    else 
	menu_header_relocate(LOC->header_page,page,
			     4,headers_per_page);

}

void free_mailbox_screen(LOC)
     struct screen_parts *LOC;
{
    erase_menu_context (&(LOC->title_page));

    if (LOC->menu_page)
	erase_menu_context (&(LOC->menu_page));

    erase_menu_context (&(LOC->prompt_page));

    if (LOC->header_page)
	erase_menu_context (&(LOC->header_page));
}


#if ANSI_C
static subpage_simple_redraw sb_update_sendtitle;
#endif
static int sb_update_sendtitle(ptr,list)
     struct menu_context  *ptr;
     struct menu_param *list;
{
    menu_ClearScreen(ptr);

    menu_print_format_center(ptr,1,
			     CATGETS(elm_msg_cat, ElmSet, ElmSendOnlyMode,
				     "Send only mode [ELM %s]"), 
			     version_buff);

    return 1;   /* Redraw completely done */
}

static void set_sendmode_screen P_((struct menu_context  *page, 
				   struct screen_parts *LOC,
				   struct menu_param  *LIST));
static void set_sendmode_screen(page,LOC, LIST)
     struct menu_context  *page;
     struct screen_parts *LOC;
     struct menu_param  *LIST;
{    
    int   LINES, COLUMNS;	

    menu_get_sizes(page,&LINES, &COLUMNS);

    /* 1)  Title part of screen */
    
    if (! LOC->title_page)
	LOC->title_page = new_menu_subpage(page,0,4,sb_update_sendtitle,LIST);
    else
	menu_subpage_relocate(LOC->title_page,page,0,4);

    /* 2) menu part */
    LOC->menu_page = NULL;

    /* 3) prompt part */

    if (LOC->prompt_page)
	menu_subpage_relocate(LOC->prompt_page,page,LINES-4,4);
    else 
	LOC->prompt_page = new_menu_subpage(page,LINES-4,4,
					    subpage_simple_noredraw,LIST);

    /* 4) headers of screen */
    LOC->header_page = NULL;
}


int main P_((int argc, char *argv[]));
int main(argc, argv)
     int argc;
     char *argv[];
{
    int  ch;
    char **req_mfile_vector = NULL;    /* Malloced */
    char **to_whom = NULL;
    int  i,j;      		/** Random counting variables (etc)          **/

    struct menu_context  *page = NULL;
  
    struct AliasView     * cur_aliaslist = NULL;
    enum check_mode      check_mode = chk_none;
    char                 * url_mode = NULL;

    set_panic_prepare(elm_panic_prepare);
    set_panic_exit(elm_panic_exit);

#if DEBUG
    init_debugfile("ELM");

    /* HACK .... 
       USER may want enable debug output for locale_init()
       
       This gives wrong result if some options value start
       with "-d"
    */

    for (i = 1; i < argc; i++) {
	if ('-' == argv[i][0] &&
	    'd' == argv[i][1] &&
	    argv[i][2]) {
	    set_debugging(& (argv[i][2]));
	}
    }
#endif	

    locale_init();
	
    req_mfile_vector = parse_arguments(argc, argv, &to_whom,
				       &check_mode, &url_mode);
    initialize(&cur_aliaslist, &page);


    if (url_mode) {
	struct string * s   = new_string2(system_charset,s2us(url_mode));
	struct url    * url = url_from_raw(s,NULL,NULL);
	enum url_type T;

	DPRINT(Debug,2,(&Debug, 
			"Elm: Url-mode\n"));

	/* Be sure that errors are visible */
	error_wait();

	if (!url) {	    
	    	free_string(&s);
		goto fail_1;
	}

	T = get_url_type(url);


	switch (T) {
	    int r;	    

	case url_unknown:
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmUnknownUrl,
			      "Unsupported URL type. Can not open %S"),
		      s);
	    free_url(&url);
	    free_string(&s);

	    goto fail_1;	

	case url_mailing: 
	    DPRINT(Debug,2,(&Debug, 
			    "Mail-only: mailing to URL\n"));
	
	    if(!batch_only) {
		struct screen_parts  LOC  = { NULL, NULL, NULL, NULL };


		set_sendmode_screen(page,&LOC,NULL);  
		sb_update_sendtitle(LOC.title_page,NULL);

		r = send_msg_url(url, batch_subject, 
				 MAIL_EDIT_MSG | 
				 (confirm_url ? MAIL_ASK_SEND : 0),
				 (batch_only ? NO : allow_forms), 
				 cur_aliaslist, page, 
				 LOC.prompt_page);

		free_mailbox_screen(&LOC);

		if (!r) {
		    free_url(&url);
		    free_string(&s);

		    goto fail_1;
		}

	    } else {

		if (confirm_url) {
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmConfirmUrlBatch,
				      "Can't confirm url on batch mode."));
		    free_url(&url);
		    free_string(&s);
		    
		    goto fail_1;

		}

		r = send_msg_url(url, batch_subject, MAIL_EDIT_MSG,
				 (batch_only ? NO : allow_forms), 
				 cur_aliaslist, page, 
				 NULL);
		
		if (!r) {
		    free_url(&url);
		    free_string(&s);

		    goto fail_1;
		}

	    }
	    break;

	case url_mailbox_list:
	    DPRINT(Debug,2,(&Debug, 
			    "Selecting mailbox from URL\n"));

	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmMailboxListUnsUrl,
			      "Mailbox list is unsupported. Can not open %S"),
		      s);
	    free_url(&url);
	    free_string(&s);

	    goto fail_1;	


	case url_mailbox:
	    DPRINT(Debug,2,(&Debug, 
			    "Viewing mailbox from URL\n"));

	    if (batch_only) {

		DPRINT(Debug,2,(&Debug, 
				"Batch-only\n"));
		
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmBatchOnlyMailbox,
				  "Can't browse mailbox on batch-only mode!"));
		goto fail_1;
	    }

	    r = url_messages_menu(page,url,cur_aliaslist, check_mode);

	    if (!r) {
		free_url(&url);
		free_string(&s);
		
		goto fail_1;
	    }
	    break;		 
	}

	
	free_url(&url);
	free_string(&s);

    }  else if (mail_only) {

	DPRINT(Debug,2,(&Debug, 
			"Elm: Mail-only: mailing to\n"));
	
	if(!batch_only) {
	    struct screen_parts  LOC  = { NULL, NULL, NULL, NULL };
	    
	    int r;

	    set_sendmode_screen(page,&LOC,NULL);  
	    sb_update_sendtitle(LOC.title_page,NULL);

	    r = send_msg_argv(to_whom, batch_subject, MAIL_EDIT_MSG,
			      (batch_only ? NO : allow_forms), 
			      cur_aliaslist, page, 
			      LOC.prompt_page);

	    free_mailbox_screen(&LOC);

	    if (!r)
		goto fail_1;

	} else {
	    int r = send_msg_argv(to_whom, batch_subject, MAIL_EDIT_MSG,
				  (batch_only ? NO : allow_forms), 
				  cur_aliaslist, page, 
				  NULL);

	    if (EOF == r)
		goto fail_EOF;

	    if (!r)
		goto fail_1;
	}

    } else if (check_only) {
	DPRINT(Debug,2,(&Debug, 
			"Elm: Check-only\n"));

	do_check_only(to_whom, cur_aliaslist);

    } else if (batch_only) {

	DPRINT(Debug,2,(&Debug, 
			"Elm: Batch-only\n"));

	lib_error(CATGETS(elm_msg_cat, ElmSet, 
			  ElmBatchOnlyMailbox,
			  "Can't browse mailbox on batch-only mode!"));
	goto fail_1;

    } else {
	int r;

	DPRINT(Debug,2,(&Debug, 
			"Elm: Normal mode\n"));

	r = main_messages_menu(page,req_mfile_vector,
				   cur_aliaslist, check_mode);

	if (req_mfile_vector) {
	    int i;
	    
	    for (i = 0; req_mfile_vector[i]; i++) {
		free(req_mfile_vector[i]);
		req_mfile_vector[i] = NULL;
	    }
	    
	    free(req_mfile_vector);
	    req_mfile_vector = NULL;
	}

	if (EOF == r)
	    goto fail_EOF;

	if (!r)
	    goto fail_1;

    }
    
    if (cur_aliaslist) {
	DPRINT(Debug,9, (&Debug, 
			 "main: freeing cur_aliaslist\n"));

	free_aliasview(&cur_aliaslist);
    }

    erase_menu_context(&page);

    leave(0);
    
    return 0;

 fail_1:
 fail_EOF: 

    if (cur_aliaslist) {
	DPRINT(Debug,9, (&Debug, 
			 "main: freeing cur_aliaslist\n"));

	free_aliasview(&cur_aliaslist);
    }

    erase_menu_context(&page);
	
    if(!batch_only)
	Raw_OFF(1); /* Raw(OFF) and reprint error message */

#ifdef REMOTE_MBX
    close_cached_connections();	       
#endif
    return 1;
}

static void debug_screen(mailbox,LOC)
     struct MailboxView *mailbox;
     struct screen_parts *LOC;
{
	/**** spit out all the current variable settings and the table
	      entries for the current 'n' items displayed. ****/

	int i, j;
	int LINES, COLUMNS;
	int li,co;
	struct menu_context *page = new_menu_context();

redraw:
	if (menu_resized(page) ||
	    menu_need_redraw(page))
	/* Nothing */;
        
	menu_get_sizes(page, &LINES, &COLUMNS);   

	menu_ClearScreen(page);

	menu_PutLineX(page,
		      0,0,CATGETS(elm_msg_cat, ElmSet, 
				  ElmDbxCurrMsgNum,
				  "Current message number = %d\t\t%d message(s) total\n"),
		      get_current(mailbox), 
		      get_message_count(mailbox));


	{ 

	    struct folder_info * f = get_main_folder(mailbox);
	    if (f) {
		menu_PutLineX(page,
			      4,0,CATGETS(elm_msg_cat, ElmSet, 
					  ElmDbxCurrMailFile,
					  "\nCurrent mail file is %S.\n\r\n"), 
			      f->cur_folder_disp);
	    }
	}

	i = menu_header_get(LOC->header_page,header_top_line);	/* starting header */
	menu_get_sizes(LOC->header_page, &li, &co);   

	if ((j = i + li-1) >= get_message_count(mailbox)) 
	    j = get_message_count(mailbox)-1;

	/* FIXME -- selected */

	menu_Write_to_screen(page,
			     CATGETS(elm_msg_cat, ElmSet, ElmDebugHeader,
				     "Num      From                    Subject                Lines   Offset  Content\n\r\n\r"));
	
	for (;i <= j; i++) {	  
	    struct header_rec * hdr = give_header(mailbox,i);
	    struct string * x    = NULL;
	    struct string * temp = NULL;
	    

	    if (! hdr)
		continue;
	    
	    x = hdr->subject;
	    if (!x) {
		temp = new_string2(ASCII_SET,s2us("<-- NO SUBJECT -->"));
		x = temp;
	    }

	    if (hdr->from && 
		hdr->from->fullname &&
		string_len(hdr->from->fullname))
		menu_Write_to_screen(page,
				     FRM("%3d %-16.16S %-35.35S %4d %8d %8d\n\r"),
				     i+1,
				     hdr->from->fullname, 
				     x,
				     hdr->lines,
				     hdr->offset,
				     hdr->content_length);
	    else
		menu_Write_to_screen(page,
				     FRM("%3d %-16.16s %-35.35S %4d %8d %8d\n\r"),
				     i+1,
				     hdr->from && 
				     hdr->from->addr &&
				     hdr->from->addr[0] ?
				     hdr->from->addr :
				     hdr->env_from,
				     x,
				     hdr->lines,
				     hdr->offset,
				     hdr->content_length);

	    if (temp)
		free_string(&temp);

	}
	
	menu_PutLineX(page,
		      LINES-1,0,CATGETS(elm_msg_cat, ElmSet, 
					ElmDbxPressAnyKey,"Press any key to return."));
	if (REDRAW_MARK == menu_ReadCh(page, REDRAW_MARK))
	    goto redraw;

	erase_menu_context(&page);
	return;
	
}

static void debug_message(current_header,current,index)
     struct header_rec *current_header;
     int current;
     struct folder_view *index;
{
	/**** Spit out the current message record.  Include EVERYTHING
	      in the record structure. **/
	
	time_t header_time;
	int LINES, COLUMNS;
	struct menu_context *page = new_menu_context();
	
redraw:
	if (menu_resized(page) ||
	    menu_need_redraw(page))
	    /* Nothing */;
        
	menu_get_sizes(page, &LINES, &COLUMNS);   

	menu_ClearScreen(page);

	menu_Write_to_screen(page,
			     FRM("\t\t\t----- Message %d -----\n\r\n\r\n\r\n\r"), 
			     current);
	
	menu_Write_to_screen(page,
			     FRM("Lines: %-17dStatus: A  C  D  E  F  N  P  T  U  V  O  R  M  P  U  N\n\r"), 
			     current_header->lines);
	menu_Write_to_screen(page,
			     FRM("Content-Length: %-16dc  o  e  x  o  e  r  a  r  i  l  e  i  r  s  H\n\r"), 
			     current_header->content_length);
	menu_Write_to_screen(page,
			     FRM("Binary: %-24dt  n  l  p  r  w  i  g  g  s  d  p  m  e  u  d\n\r"), 
			     current_header->binary);
	menu_Write_to_screen(page,
			     FRM("'From ' on body: %-15dn  f  d  d  m     v  d  n  i     l  e  M  p  r\n\r"),
			     current_header->have_from);
	
	menu_Write_to_screen(page,
			     FRM("\n\rOffset: %-22ld%3d%3d%3d%3d%3d%3d%3d%3d%3d%3d%3d%3d%3d%3d%3d%3d\n"),
			     current_header->offset,
			     (current_header->status & ACTION) != 0,
			     (current_header->status & CONFIDENTIAL) != 0,
			     (current_header->status & DELETED) != 0,
			     (current_header->status & EXPIRED) != 0,
			     (current_header->status & FORM_LETTER) != 0,
			     (current_header->status & NEW) != 0,
			     (current_header->status & PRIVATE_MAIL) != 0,
			     (current_header->status & TAGGED) != 0,
			     (current_header->status & URGENT) != 0,
			     (current_header->status & VISIBLE) != 0,
			     (current_header->status & UNREAD) != 0,
			     (current_header->status & REPLIED) != 0,
			     (current_header->status & MIME_MESSAGE) != 0,
			     (current_header->status & PRE_MIME_CONTENT) != 0,
			     (current_header->status & MIME_UNSUPPORTED) != 0,
			     (current_header->status & NOHDRENCODING) != 0);
	
        menu_Write_to_screen(page,
			     FRM("\n\rReceived on: %s\r"),
			     asctime(localtime(&current_header->received_time)));
      
	header_time = current_header->time_sent + current_header->tz_offset;

	menu_Write_to_screen(page,
			     FRM("\rMessage sent on: %s\r\nFrom timezone: %s (%d)\n\r"),
			     asctime(gmtime(&header_time)),
			     current_header->time_zone,
			     current_header->tz_offset);
	
	menu_Write_to_screen(page,
			     FRM("(Env) From: %s\n\r"), 
			     current_header->env_from);

	if (current_header->from) {
	    int first = 1;
	    struct addr_item *p;
	    for (p = current_header->from; 
		 p->fullname && p->addr && p->comment; 
		 p++) {
		if (first)
		    menu_Write_to_screen(page,
					 FRM(     "From: "));
		else
		    menu_Write_to_screen(page,
					 FRM(",\r\n      "));
		menu_Write_to_screen(page,
				     FRM("%-30S <%s>"),p->fullname,p->addr);
		first = 0;
		if (string_len(p->comment)) 
		    menu_Write_to_screen(page,
					 FRM(" (%S)"),p->comment);
	    }
	    menu_Write_to_screen(page,
				 FRM("\r\n"));
	}
	
	

	menu_Write_to_screen(page,
			     FRM("Subject: %S\n\rInternal Index Reference Number = %d/%d (hdr index %d)\n\r"),
			     current_header->subject,
			     index->mailbox_number,
			     index->index,
			     current_header->index_number_X);
	menu_Write_to_screen(page,FRM("Thread number = %d\r\n"),
			     index->thread_number);

	if (current_header->to) {
	    int first = 1;
	    struct addr_item *p;
	    for (p = current_header->to; 
		 p->fullname && p->addr && p->comment; 
		 p++) {
		if (first)
		    menu_Write_to_screen(page,
					 FRM(     "To: "));
		else
		    menu_Write_to_screen(page,
					 FRM(",\r\n    "));
		menu_Write_to_screen(page,
				     FRM("%-30S <%s>"),p->fullname,p->addr);
		first = 0;
		if (string_len(p->comment)) 
		    menu_Write_to_screen(page,
					 FRM(" (%S)"),p->comment);
	    }
	    menu_Write_to_screen(page,
				 FRM("\r\n"));
	}

	if (current_header->cc) {
	    int first = 1;
	    struct addr_item *p;
	    for (p = current_header->cc; 
		 p->fullname && p->addr && p->comment; 
		 p++) {
		if (first)
		    menu_Write_to_screen(page,
					 FRM(     "CC: "));
		else
		    menu_Write_to_screen(page,
					 FRM(",\r\n    "));
		menu_Write_to_screen(page,
				     FRM("%-30S <%s>"),p->fullname,p->addr);
		first = 0;
		if (string_len(p->comment)) 
		    menu_Write_to_screen(page,
					 FRM(" (%S)"),p->comment);	    
	    }
	    menu_Write_to_screen(page,
				 FRM("\r\n"));
	}


	menu_Write_to_screen(page,
			     FRM("Message-ID: %s\n\r"), 
			     strlen(current_header->messageid) > 0 ? 
			     current_header->messageid : "<none>");

	menu_Write_to_screen(page,
			     FRM("Status: %s\n\r"),  
			     current_header->mailx_status);

	menu_Write_to_screen(page,
			     FRM("Content-Transfer-Encoding: %s\n\r"),
			     ENCODING(current_header->mime_rec.encoding));


	menu_PutLineX(page,
		      LINES-1,0,CATGETS(elm_msg_cat, ElmSet, 
					ElmDbxPressAnyKey,
					"Please Press any key to return."));
	if (REDRAW_MARK == menu_ReadCh(page, REDRAW_MARK))
	  goto redraw;

	erase_menu_context(&page);
	return;

}

static void do_check_only(to_whom,aview)
     char *to_whom[];
     struct AliasView *aview;
{
    struct expanded_address A;
    
    zero_expanded_address(&A);
    
    dump_expanded_address(3,"Check-only: checking",A);

    if (to_whom) {
	struct mailer_info *mailer_info = get_mailer_info();
	if (argv_to_expanded(&A,to_whom,mailer_info,aview)) {
	    struct string * addr_string = hdr_to_expval(A);
	    if (addr_string) {
		elm_fprintf(stdout,
			    CATGETS(elm_msg_cat, ElmSet, ElmExpandsTo,
				    "Expands to: %S\n"),
			    addr_string);
		free_string(&addr_string);
	    }
	}
	free_expanded_address(&A);
	free_mailer_info(&mailer_info);
    }
}

void check_range(mc,LOC)
     struct menu_common *mc;
     struct screen_parts *LOC;
{
    int i;
    int current  = mcommon_get_current(mc);
    int selected = mcommon_get_selected(mc);

    i = compute_visible(current, mc);

    if ((current < 1) || (selected && i < 1)) {
	if (mcommon_get_count(mc) > 0) {
	    /* We are out of range! Get to first message! */
	    if (selected)
		current = compute_visible(1,mc);
	    else
		current = 1;
	}
	else
	    current = 0;
    }
    else if ((current > mcommon_get_count(mc))
	      || (selected && i > selected)) {

	if (mcommon_get_count(mc) > 0) {
	    /* We are out of range! Get to last (visible) message! */
	    if (selected)
		current = visible_to_index(selected,mc)+1;
	    else
		current = mcommon_get_count(mc);

	} else
	    current = 0;
    }
    
    mcommon_set_current(mc,current);
    copy_current(mc,LOC->header_page);
}


/* Return key if unknown */
int motion(ch,mc, LOC,  page)
     int ch;
     struct menu_common *mc;    
     struct screen_parts *LOC;
     struct menu_context  *page;
{

    /* Consolidated the standard menu navigation and delete/tag
     * commands to a function.                                   */

    int  i;

    int current = mcommon_get_current(mc);

    switch (ch) {


	case FIND_MARK:
	case '/'    :  /* scan mbox or aliases for string */
	    if  (mcommon_get_count(mc) < 1) {
		lib_error(CATGETS(elm_msg_cat, ElmSet,
				  ElmNoItemToScan, "No %S to scan!"), 
			  mcommon_give_item(mc,m_items));
			
	    }
	    else {

		int x = pattern_match(mc, page, LOC);
		
		if (EOF == x) {
		    return EOF;   /* ERROR */

		}

		if (x) {
		    current = mcommon_get_current(mc);
		    get_page(mc, LOC->header_page);
		} else {
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmPatternNotFound,
				      "pattern not found!"));
		}
	    }
	    break;


	case PAGEDOWN_MARK :
	case RIGHT_MARK :
	case '+'	:  {
	    int selected = mcommon_get_selected(mc);
	    int top      = menu_header_get(LOC->header_page,header_top_line);
	    int li,co;

	    menu_get_sizes(LOC->header_page, &li, &co);   

	    /* move to next page if we're not on the last */
	    
	    if ((selected && (top+li < selected))
		||
		(!selected && (top+li < mcommon_get_count(mc)))) {
		
		top += li;

		menu_header_change(LOC->header_page, header_top_line,top);
		
		if(move_when_paged) {
		    /* move to first message of new page */
		    if(selected)
			current = visible_to_index(top+1,mc) + 1;
		    else
			current = top+1;
		    
		    mcommon_set_current(mc,current);
		    menu_header_change(LOC->header_page, 
				       header_current,top);
		}
	    } else
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmAlreadyOnLastPage,
				  "Already on last page."));
	}
	    break;

	case PAGEUP_MARK :
	case LEFT_MARK  :
	case '-'	:  {
	    int selected = mcommon_get_selected(mc);
	    int top      = menu_header_get(LOC->header_page,header_top_line);
	    int li,co;

	    menu_get_sizes(LOC->header_page, &li, &co);   
		
	    /* move to prev page if we're not on the first */
	    if(top > 0) {
		
		top -= li;
		if (top < 0)
		    top = 0;

		menu_header_change(LOC->header_page, header_top_line,top);

		if(move_when_paged) {
		    /* move to first message of new page */
		    if(selected)
			current = visible_to_index(top + 1, mc) + 1;
		    else
			current = top + 1;
		    mcommon_set_current(mc,current);
		    menu_header_change(LOC->header_page, 
				       header_current,top);
		}
	    } else
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmAlreadyOnFirstPage,
				  
				  "Already on first page."));
	}
	    break;

	case HOME_MARK:
	case '='    :  {
	    int selected = mcommon_get_selected(mc);
	    
	    if (selected)
		current = visible_to_index(1,mc)+1;
	    else
		current = 1;
	    mcommon_set_current(mc,current);
	    menu_header_change(LOC->header_page, header_current,0);
	    
	    get_page(mc, LOC->header_page);
	}
	    break;
	    
	case END_MARK:
	case '*'    :  {
	    int selected = mcommon_get_selected(mc);
	    int i;
	    
	    if (selected) {
		current = (visible_to_index(selected,mc)+1);
	    } else {
		current = mcommon_get_count(mc);
	    }
	    
	    mcommon_set_current(mc,current);
	    copy_current(mc,LOC->header_page);
	    
	    get_page(mc, LOC->header_page);
	}
	    break;
	    
	case EOF    : return EOF;   /* ERROR */


	case ctrl('D') :
	case '^'    :
	case 'd'    :
    case DELETE_MARK:
	    if (mcommon_get_count(mc) < 1) {
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmNoItemToDelete,
				  "No %S to delete!"), 
			  mcommon_give_item(mc,m_item));
		
	    } else {

		if (DELETE_MARK == ch) 
		    ch = 'd';     /* Translate */

		if(ch == ctrl('D')) {
		    
		    /* if current item did not become deleted,
		     * don't to move to the next undeleted item */
		    if(!meta_match(DELETED, mc, page, LOC)) 
			break;
		    
		} else
		    delete_msg((ch == 'd'), mc, LOC);
		
		/* If given '^' command (toggle delete flag)
		   go to next command regagdles is next command
		   marked for deletion or not on resolve mode.
		   In other words works same way than u)undelete
		   command works.
		*/
		
		if (resolve_mode) 	/* move after mail resolved */
		    if((i=next_message(current-1, 
				       (ch == 'd') ? TRUE : FALSE,
				       mc)) != -1) {
			
			current = i+1;
			mcommon_set_current(mc,current);
			copy_current(mc,LOC->header_page);
			
			get_page(mc, LOC->header_page);
		    }
	    }
	    break;
	    
    case 'F': {    /* Actually this works only for messages
		    * and not aliases
		    */
	if (mcommon_get_count(mc) < 1) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet, 
			      ElmNoItemToFlag,
			      "No %S to flag!"), 
		      mcommon_give_item(mc,m_items));
	    
	} else 
	    flag_message(mc, LOC->header_page); 
    }
    break;


	case 'J'    :  
	    if (current > 0) {
		if((i=next_message(current-1, FALSE,
				   mc)) != -1) {
		    int j;
		    
		    DPRINT(Debug,5,(&Debug,  
				    " current %d => %d\n",
				    current,i+1));
		    
		    current = i+1;
		    mcommon_set_current(mc,current);
		    copy_current(mc,LOC->header_page);
		    
		    get_page(mc, LOC->header_page);
		} else
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmNoMoreItemBelow,
				      "No more %S below."), 
			      mcommon_give_item(mc,m_items));
	    } else 
		lib_error(FRM("%S"),
			  mcommon_give_item(mc,m_no_item));
	    
	    break;	       

next_undel_msg:
	case DOWN_MARK :
	case 'j'    :  
	    if (current > 0) {
		if((i=next_message(current-1, TRUE,
				   mc)) != -1) {
		    
		    DPRINT(Debug,5,(&Debug,  
				    " current %d => %d\n",
				    current,i+1));
		    
		    current = i+1;
		    mcommon_set_current(mc,current);
		    copy_current(mc,LOC->header_page);

		    get_page(mc, LOC->header_page);
		} else
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmNoItemUndeletedBelow,
				      "No more undeleted %S below."), 
			      mcommon_give_item(mc,m_items));
	    } else
		lib_error(FRM("%S"),
			  mcommon_give_item(mc,m_no_item));
		
	    break;
	    
	case 'K'    :  
	    if (current > 0) {
		if((i=prev_message(current-1, FALSE,
				   mc)) != -1) {

		    DPRINT(Debug,5,(&Debug,  
				    " current %d => %d\n",
				    current,i+1));
		    
		    current = i+1;
		    mcommon_set_current(mc,current);
		    copy_current(mc,LOC->header_page);

		    get_page(mc, LOC->header_page);
		} else
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmNoMoreItemAbove,
				      "No more %S above."), 
			      mcommon_give_item(mc,m_items));
	    } else 
		lib_error(FRM("%S"),
			  mcommon_give_item(mc,m_no_item));
	    
	    break;

	case UP_MARK :
	case 'k'    :  
	    if (current > 0) {
		if((i=prev_message(current-1, TRUE, 
				   mc)) != -1) {
		    
		    DPRINT(Debug,5,(&Debug,  
				    " current %d => %d\n",
				    current,i+1));
		    
		    current = i+1;
		    mcommon_set_current(mc,current);
		    copy_current(mc,LOC->header_page);

		    get_page(mc, LOC->header_page);
		} else
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmNoMoreUndeletedAbove,
				      "No more undeleted %S above."), 
			      mcommon_give_item(mc,m_items));
	    } else 
		lib_error(FRM("%S"),
			  mcommon_give_item(mc,m_no_item));
	    
	    break;
	    
	case 'l'    :  
	    menu_Write_to_screen(LOC->prompt_page,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmLimitDisplayBy,
					 "Limit displayed %S by..."), 
				 mcommon_give_item(mc,m_items));

	    clear_error();
	    limit(mc, page,LOC);

	    break;
	    

	case ctrl('T') :
	case 'T'       :
	case 't'       :  
	    if (mcommon_get_count(mc) < 1) {
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmNoItemToTag,
				  "No %S to tag!"), 
			  mcommon_give_item(mc,m_items));
		
	    } else if (ch == 't')
		tag_message(mc, LOC->header_page); 
	    else if (ch == 'T') {
		tag_message(mc, LOC->header_page); 
		goto next_undel_msg;
	    } else
		meta_match(TAGGED, mc, page, LOC);
	    break;

	case 'u'    :  
	    if (mcommon_get_count(mc) < 1) {
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmNoItemToMarkUndeleted,
				  "No %S to mark as undeleted!"), 
			  mcommon_give_item(mc,m_items));
		
	    } else {
		undelete_msg(mc, LOC->header_page);

		if (resolve_mode) 	/* move after mail resolved */
		    if((i=next_message(current-1, FALSE, mc)) != -1) {
				   
			current = i+1;
			mcommon_set_current(mc,current);
			copy_current(mc,LOC->header_page);

			get_page(mc, LOC->header_page);

		    }
/*************************************************************************
 **  What we've done here is to special case the "U)ndelete" command to
 **  ignore whether the next message is marked for deletion or not.  The
 **  reason is obvious upon usage - it's a real pain to undelete a series
 **  of messages without this quirk.  Thanks to Jim Davis @ HPLabs for
 **  suggesting this more intuitive behaviour.
 **
 **  The old way, for those people that might want to see what the previous
 **  behaviour was to call next_message with TRUE, not FALSE.
**************************************************************************/
	    }
	    break;

	case ctrl('U') : 
	    if (mcommon_get_count(mc) < 1) {
		lib_error(CATGETS(elm_msg_cat, ElmSet, 
				  ElmNoItemToUndelete,
				  "No %S to undelete!"), 
			  mcommon_give_item(mc,m_items));
		
	    } else 
		meta_match(UNDELETE, mc, page, LOC);
	    break;

	case ctrl('L') : 
	    menu_trigger_redraw(page);
	    break;

	case NO_OP_COMMAND : break;	/* noop for timeout loop */


	default	: 
	    if (ch > '0' && ch <= '9') {
		int selected = mcommon_get_selected(mc);
		
		menu_Write_to_screen(LOC->prompt_page,
				     CATGETS(elm_msg_cat, ElmSet,
					     ElmNewCurrentItem,
					     "New Current %S"), 
				     mcommon_give_item(mc,m_Item));
		
		i = read_number(ch, 
				mcommon_give_item(mc,m_item),
				current, page, LOC->prompt_page);
		
		DPRINT(Debug,5,(&Debug,  
				" current %d => %d (?)\n",
				current,i));
		
		if( i > mcommon_get_count(mc))
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmNotThatMany,
				      "Not that many %S."), 
			      mcommon_give_item(mc,m_items));
		else if(selected
			&& mcommon_isoff_status(mc,i-1,
						status_basic,VISIBLE))
		    lib_error(CATGETS(elm_msg_cat, ElmSet, 
				      ElmNotInLimitedDisplay,
				      "%S not in limited display."),
			      mcommon_give_item(mc,m_Item));
		else {
		    current = i;
		    mcommon_set_current(mc,current);
		    copy_current(mc,LOC->header_page);
		    
		    get_page(mc, LOC->header_page);
		}
		
	    } else {
		return ch;  /* UNKNOWN command */
		
	    }
	    break;
	}

	return 0;   /* COmmand OK */
}

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


syntax highlighted by Code2HTML, v. 0.9.1