static char rcsid[] = "@(#)$Id: reply.c,v 1.9 2006/06/25 10:41:05 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.9 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
 *      or  Kari Hurtta <elm@elmme-mailer.org>
 *****************************************************************************/

#include "def_list.h"
#include "s_me.h"
#include "mailerlib.h"

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

DEBUG_VAR(Debug,__FILE__,"mail");

static int reply_to_combined P_((struct menu_context  *page,
				  struct menu_context *prompt_area,
				  struct MailboxView *mailbox,
				  int index,
				  struct header_rec *current_header,
				  FILE *F,
				  struct AliasView   *aview,
				  const struct url *url_to,
				  struct addr_item *to_addr, 
				  struct addr_item *cc_addr));

static int reply_to_combined(page,prompt_area,mailbox,index,current_header,
			      F,aview,url_to,to_addr,cc_addr)
     struct menu_context  *page;
     struct menu_context *prompt_area;
     struct MailboxView *mailbox;
     int index;
     struct header_rec *current_header;
     FILE *F;
     struct AliasView   *aview;
     const struct url *url_to;
     struct addr_item *to_addr; 
     struct addr_item *cc_addr;
{
    struct mailer_info *mailer_info   = get_mailer_info();
    struct mailing_headers headers;
    int r = 0;
    
    zero_mailing_headers(&headers);

    if (!mailer_info) {
        DPRINT(Debug,5,(&Debug, 
			"reply_to_combined: No mailer_info\n"));
	return 0;
    }

    if (url_to) {

	/* When replying, possible body given on URL is ignored */
	
	r = set_mailing_headers_from_url(&headers,url_to,mailer_info);
	if (!r) {
	    DPRINT(Debug,5,(&Debug, 
			    "reply_to_combined: set_mailing_headers_from_url failed!\n"));
	    goto fail;
	}
    }
    
    expanded_address_from_items(& headers.to, to_addr);
    expanded_address_from_items(& headers.cc, cc_addr);
    
    if (!headers.subject && current_header->subject) {
	
	struct string * X =  skip_ascii_head_from_string(current_header->
							 subject, 
							 s2us("Re: "),1);
	
	headers.subject = format_string(FRM("Re: %S"),X);
	
	free_string(&X);
    } 
    
    
    r = send_msg_middle2(&headers,index,MAIL_EDIT_MSG | MAIL_REPLYING,
			 NO,mailer_info,mailbox,aview,
			 page,prompt_area,NULL);
    
    if (!r) {
	DPRINT(Debug,5,(&Debug, 
			"reply_to_combined: send_msg_middle2 failed!\n"));
	goto fail;
    }
    
 fail:
    
    free_mailing_headers(&headers);
    free_mailer_info(&mailer_info);

    DPRINT(Debug,5,(&Debug, 
		    "reply_to_combined=%d\n",r));

    return r;
}



static int reply_to_url_mailing P_((struct menu_context  *page,
				    struct menu_context *prompt_area,
				    struct MailboxView *mailbox,
				    int index,
				    struct header_rec *current_header,
				    FILE *F,
				    const struct url *url,
				    struct AliasView   *aview,
				    int ask_send));

static int reply_to_url_mailing(page,prompt_area,mailbox,index,current_header,
				 F,url,aview,ask_send)
     struct menu_context  *page;
     struct menu_context *prompt_area;
     struct MailboxView *mailbox;
     int index;
     struct header_rec *current_header;
     FILE *F;
     CONST struct url *url;
     struct AliasView   *aview;
     int ask_send;
{
    struct mailer_info *mailer_info   = get_mailer_info();
    struct mailing_headers headers;
    int r;
    
    zero_mailing_headers(&headers);
    
    if (!mailer_info) {
        DPRINT(Debug,5,(&Debug, 
			"reply_to_url_mailing: No mailer_info\n"));
	return 0;
    }
    
    /* When replying, possible body given on URL is ignored */
    
    r = set_mailing_headers_from_url(&headers,url,mailer_info);
    if (!r) {
	DPRINT(Debug,5,(&Debug, 
			"reply_to_url_mailing: set_mailing_headers_from_url failed!\n"));
	goto fail;
    }
        
    if (!headers.subject && current_header->subject) {
	
	struct string * X =  skip_ascii_head_from_string(current_header->
							 subject, 
							 s2us("Re: "),1);
	
	headers.subject = format_string(FRM("Re: %S"),X);
	
	free_string(&X);
    } 
    
    
    r = send_msg_middle2(&headers,index,
			 MAIL_EDIT_MSG | MAIL_REPLYING | 
			 (ask_send ? MAIL_ASK_SEND : 0),
			 NO,mailer_info,mailbox,aview,
			 page,prompt_area,NULL);
    
    if (!r) {
	DPRINT(Debug,5,(&Debug, 
			"reply_to_url_mailing: send_msg_middle2 failed!\n"));
	goto fail;
    }
    
 fail:
    
    free_mailing_headers(&headers);
    free_mailer_info(&mailer_info);

    DPRINT(Debug,5,(&Debug, 
		    "reply_to_url_mailing=%d\n",r));
    return r;
}

static int reply_to_url P_((struct menu_context  *page,
			     struct menu_context *prompt_area,
			     struct MailboxView *mailbox,
			     int index,
			     struct header_rec *current_header,
			     FILE *F,
			     const struct url *url,
			     struct AliasView   *aview,
			    int ask_send));

static int reply_to_url(page,prompt_area,mailbox,index,current_header,
			 F,url,aview,ask_send)
     struct menu_context  *page;
     struct menu_context *prompt_area;
     struct MailboxView *mailbox;
     int index;
     struct header_rec *current_header;
     FILE *F;
     CONST struct url *url;
     struct AliasView   *aview;
     int ask_send;
{
    int r = 0;
    enum url_type T = get_url_type(url);

    struct string *url_text = raw_from_url(url);

    switch (T) {
    case url_unknown:
	if (url_text)
	    lib_error(CATGETS(elm_msg_cat, MeSet, 
			      MeUnknownUrlReply,
			      "Unsupported URL type. Can not reply to %S"),
		      url_text);
	goto failure;


    case url_mailing: 
	r = reply_to_url_mailing(page,prompt_area,mailbox,index,current_header,
				 F,url,aview,ask_send);
	
    }

 failure:

    if (url_text)
	free_string(& (url_text));

    return r;
}




/* ----------------------------------------------------------------------- */


struct menu_anon_param {
    struct header_rec * current_header;
};




enum { reply_mp_islist,
       reply_mp_param,
       reply_mp_COUNT };
  

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

S_(subpage_simple_redraw sb_update_reply_title)
static int sb_update_reply_title(ptr,list)
     struct menu_context  *ptr;
     struct menu_param *list;
{
    menu_ClearScreen(ptr);

    menu_print_format_center(ptr,0,
			     CATGETS(elm_msg_cat, MeSet, MeGenericReplyTitle,
				     "Generic reply"));

    return 1;   /* title completed */
}

S_(subpage_simple_redraw sb_update_reply_menu)
static int sb_update_reply_menu(ptr,list)
     struct menu_context  *ptr;
     struct menu_param *list;
{
    int islist   = mp_lookup_integer(list,reply_mp_islist);

    menu_ClearScreen(ptr);

    if (islist)
	menu_print_format_center(ptr,0,
				 CATGETS(elm_msg_cat, MeSet, 
					 MeGenericReplyMenu1,
					 "Reply to a)ll, l)ist, list o)wner, au(t)hor (from address) or go to i)index"));
    else
	menu_print_format_center(ptr,0,
				 CATGETS(elm_msg_cat, MeSet, 
					 MeGenericReplyNoList1,
					 "Reply to a)ll, au(t)hor (from address) or go to i)index"));

    return 1;   /* title completed */
}

S_(subpage_simple_redraw sb_update_reply_info)
static int sb_update_reply_info(ptr,list)
     struct menu_context  *ptr;
     struct menu_param *list;
{

    struct menu_anon_param *A = mp_lookup_anon(list,reply_mp_param);
    int line = 0;

    int LINES, COLUMNS;

    menu_get_sizes(ptr, &LINES, &COLUMNS);

    menu_ClearScreen(ptr);

    if (A->current_header->from) {
	int ph = give_dt_enumerate_as_int(&phrase_display_mode);


	struct addr_item *frm;
	
	for (frm = A->current_header->from; 
	     frm->addr && frm->fullname; frm++) {

	    if (frm == A->current_header->from)
		menu_PutLineX(ptr,line,0,CATGETS(elm_msg_cat, MeSet, 
						 MeListInfoAuthor,
						 "Author          : "));
	    else
		menu_PutLineX(ptr,line,0,FRM(    "                : "));
		
	    if (string_len(frm->fullname) > 0) {
		if (ph)
		    menu_Writechar(ptr,'"');
		menu_Write_to_screen(ptr,FRM("%S"),frm->fullname);
		if (ph)
		    menu_Writechar(ptr,'"');
		menu_Writechar(ptr,' ');
	    }

	    menu_Write_to_screen(ptr,FRM("<%s>"),frm->addr);

	    if (string_len(frm->comment) > 0) {
		menu_Writechar(ptr,' ');

		menu_Writechar(ptr,'(');
		menu_Write_to_screen(ptr,FRM("%S"),frm->comment);
		menu_Writechar(ptr,')');
	    }
	    line++;

	}
	line++;
    }


    if (A->current_header->list_info) {
	if (A->current_header->list_info->list_phrase) {
	    menu_PutLineX(ptr,line,0,CATGETS(elm_msg_cat, MeSet, MeListInfoListName,
					     "List name       : %S"),
			  A->current_header->list_info->list_phrase);
	    line++;
	}
	if (A->current_header->list_info->list_id) {
	    menu_PutLineX(ptr,line,0,CATGETS(elm_msg_cat, MeSet, MeListInfoListID,
					     "List ID         : %s"),
			  A->current_header->list_info->list_id);
	    line++;
	}

	if (A->current_header->list_info->list_post_no) {

	    if (line) 
		line++;
	    
	    if (A->current_header->list_info->list_post_no_comment) {
		menu_print_format_center(ptr,line,CATGETS(elm_msg_cat, MeSet, 
							  MeListInfoListNoPostX,
							  "Mailing list do not accept postings (%S)"),
					 A->current_header->list_info->list_post_no_comment);
	    } else {
		menu_print_format_center(ptr,line,CATGETS(elm_msg_cat, MeSet, 
							  MeListInfoListNoPost,
							  "Mailing list do not accept postings."));
	    }
	    line += 2;
	}

	if (A->current_header->list_info->list_post_len > 0) {
	    int i;
	    
	    if (line) 
		line++;

	    for ( i = 0; i < A->current_header->list_info->list_post_len; i++) {
		struct string * X = raw_from_url (A->current_header->list_info->list_post[i].url);
		
		if (!X)
		    X = format_string(FRM("?ERROR?"));
		
		if (0 == i) {
		    if (A->current_header->list_info->list_post[i].comment)
			menu_PutLineX(ptr,line,0,CATGETS(elm_msg_cat, MeSet, MeListInfoListPost,
							 "List post       : <%S> %S"),
				      X,A->current_header->list_info->list_post[i].comment);
		    else
			menu_PutLineX(ptr,line,0,CATGETS(elm_msg_cat, MeSet, MeListInfoListPost0,
							 "List post       : <%S>"),
				      X);
		} else {
		    if (A->current_header->list_info->list_post[i].comment)
			menu_PutLineX(ptr,line,0,FRM(    "                : <%S> (%S)"),
				      X,A->current_header->list_info->list_post[i].comment);
		    else
			menu_PutLineX(ptr,line,0,FRM(    "                : <%S>"),
				      X);
		}
		
		free_string(&X);
		line++;
	    }
	}
	
	if (A->current_header->list_info->list_owner_len > 0) {
	    int i;
	
	    for ( i = 0; i < A->current_header->list_info->list_owner_len; i++) {
		struct string * X = raw_from_url (A->current_header->list_info->list_owner[i].url);

		if (!X)
		    X = format_string(FRM("?ERROR?"));

		if (0 == i) {
		    if (A->current_header->list_info->list_owner[i].comment)
			menu_PutLineX(ptr,line,0,CATGETS(elm_msg_cat, MeSet, MeListInfoListOwner,
							 "List owner      : <%S> (%S)"),
				      X,A->current_header->list_info->list_owner[i].comment);
		    else
			menu_PutLineX(ptr,line,0,CATGETS(elm_msg_cat, MeSet, MeListInfoListOwner0,
							 "List owner      : <%S>"),
				      X);
		} else {
		    if (A->current_header->list_info->list_owner[i].comment)
			menu_PutLineX(ptr,line,0,FRM(    "                : <%S> (%S)"),
				      X,A->current_header->list_info->list_owner[i].comment);
		    else
			menu_PutLineX(ptr,line,0,FRM(    "                : <%S>"),
				      X);
		}
		
		free_string(&X);
		line++;
	    }
	}	
    }

    return 1;   /* info completed */
}


static void set_reply_screen P_((struct menu_context  *page, 
				  struct screen_parts *LOC,
				  struct menu_param  *LIST));
static void set_reply_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 */

    if (! LOC->title_page)
	LOC->title_page = new_menu_subpage(page,0,2,sb_update_reply_title,
					   LIST);
    else
	menu_subpage_relocate(LOC->title_page,page,0,2);

    /* 2) Info part */

    if (! LOC->header_page)
	LOC->header_page = new_menu_subpage(page,2,LINES-8,
					    sb_update_reply_info,LIST);
    else
	menu_subpage_relocate(LOC->header_page,page,2,LINES-8);

    /* 3) Menu part */

    if (LOC->menu_page)
	menu_subpage_relocate(LOC->menu_page,page,LINES-6,2);
    else 
	LOC->menu_page = new_menu_subpage(page,LINES-6,2,
					  sb_update_reply_menu,LIST);
  
    /* 4) 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);
}

static void check_reply_screen P_((struct screen_parts *LOC,
				   struct menu_param *list));
static void check_reply_screen(LOC,list)
     struct screen_parts *LOC;
     struct menu_param *list;
{
    /* Title area */

    if (menu_resized(LOC->title_page)) {
	DPRINT(Debug,1, (&Debug, "title page resized\n"));

    }
    if (menu_need_redraw(LOC->title_page)) {
	DPRINT(Debug,1, (&Debug, "title page redraw???\n"));
	sb_update_reply_title(LOC->title_page,list);
    }

    /* Menu area */

    if (menu_resized(LOC->menu_page)) {
	DPRINT(Debug,1, (&Debug, "menu page resized\n"));
	
    }
    if (menu_need_redraw(LOC->menu_page)) {
	DPRINT(Debug,1, (&Debug, "menu page redraw\n"));
	sb_update_reply_menu(LOC->menu_page,list);
    }

    /* Prompt area */
    if (menu_resized(LOC->prompt_page)) {
	DPRINT(Debug,1, (&Debug, "prompt page resized\n"));
    }
    if (menu_need_redraw(LOC->prompt_page)) {
	DPRINT(Debug,7, (&Debug, "prompt page redraw\n"));
	menu_ClearScreen(LOC->prompt_page);

	show_last_error();	/* for those operations that have to
				 * clear the footer except for a message.
				 */
    }

    if (menu_resized(LOC->header_page)) {
	DPRINT(Debug,1, (&Debug, "info page resized\n"));

	menu_trigger_redraw(LOC->header_page);
    }

    if (menu_need_redraw(LOC->header_page)) {

	DPRINT(Debug,7, (&Debug, "info page redraw\n"));

	sb_update_reply_info(LOC->header_page,list);
    }
}

static void reply_to_all P_((struct header_rec *current_header,
			      FILE *F,int index,
			      struct MailboxView *mailbox,
			      struct AliasView   *aview,
			      struct menu_context  *page,
			      struct menu_context  *prompt_area));
static void reply_to_all(current_header,F,index,mailbox,
			  aview,page,prompt_area)
     struct header_rec *current_header;
     FILE *F;
     int index;
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct menu_context  *prompt_area;
{
    struct list_info *L = current_header->list_info;
    CONST struct url * url = NULL;
    struct addr_item * rt = NULL;
    struct addr_item * cc = NULL;
    int r;

    if (L) {
	int i;
	
	for (i = 0; i < L->list_post_len; i++) {
	    struct url * url0   = L->list_post[i].url;


	    if (url_mailing == get_url_type(url0)) {
		url = url0;
		break;
	    }
	}
    }

    rt = handle_reply_to(current_header,F);
    cc = get_and_expand_everyone(current_header,rt);

    /* Add author (From address) to CC (rt may include Reply-To address) */
    append_addresses_to_addr_list(&cc,current_header->from);

    r = reply_to_combined(page,prompt_area,mailbox,index,current_header,F,
			  aview,url,rt,cc);

    if (r) {
	if (me_retcode) {

	    DPRINT(Debug,5,(&Debug, 
			    "reply_to_all: Setting replied flag\n"));

	    current_header->status |= REPLIED;
	    current_header->status_chgd = TRUE;
	}
    }

    if (rt)
	free_addr_items(rt);	  
    if (cc)
	free_addr_items(cc);	  

}			      


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

    menu_print_format_center(ptr,0,
			     CATGETS(elm_msg_cat, MeSet, 
				     MeGenericReplyTitleListPost,
				     "List-Post selection for reply"));

    return 1;   /* title completed */
}



static void reply_to_list P_((struct header_rec *current_header,
			      FILE *F,int index,
			      struct MailboxView *mailbox,
			      struct AliasView   *aview,
			      struct menu_context *page,
			      struct menu_context  *prompt_area));
static void reply_to_list(current_header,F,index,mailbox,
			  aview,page,prompt_area)
     struct header_rec *current_header;
     FILE *F;
     int index;
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct menu_context  *prompt_area;
{
    int r;

    struct list_info *L = current_header->list_info;
    CONST struct url * url = NULL;

    if (!L)
	return;

    if (L->list_post_no) {
	lib_error(CATGETS(elm_msg_cat, MeSet,
			  MeGenericReplyNoPosting,		       
			  "Mailing list do not accept postings!"));
	return;
    }

    if (L->list_post_len < 1) {
	lib_error(CATGETS(elm_msg_cat, MeSet,
			  MeGenericReplyNoListPost,		       
			  "No information for posting to list."));
	return;
    }
	

    url = select_post_url(L->list_post, L->list_post_len,
			  page,sb_update_title_list_post_selection);
    if (!url)
	return;

    r = reply_to_url(page,prompt_area,mailbox,index,current_header,
		     F,url,aview,0);

    if (r) {
	if (me_retcode) {

	    DPRINT(Debug,5,(&Debug, 
			    "reply_to_list: Setting replied flag\n"));

	    current_header->status |= REPLIED;
	    current_header->status_chgd = TRUE;
	}
    }
}			      


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

    menu_print_format_center(ptr,0,
			     CATGETS(elm_msg_cat, MeSet, 
				     MeGenericReplyTitleListOwner,
				     "List-Owner selection for reply"));

    return 1;   /* title completed */
}


static void reply_to_list_owner P_((struct header_rec *current_header,
				    FILE *F,int index,
				    struct MailboxView *mailbox,
				    struct AliasView   *aview,
				    struct menu_context  *page,
				    struct menu_context  *prompt_area));
static void reply_to_list_owner(current_header,F,index,mailbox,
				aview,page,prompt_area)
     struct header_rec *current_header;
     FILE *F;
     int index;
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct menu_context  *prompt_area;
{
    int r;
    struct list_info *L = current_header->list_info;
    CONST struct url * url = NULL;

    if (!L)
	return;

    if (L->list_owner_len < 1) {
	lib_error(CATGETS(elm_msg_cat, MeSet,
			  MeGenericReplyNoListOwner,		       
			   "No information for posting to list owner."));
	return;

    }
	

    url = select_post_url(L->list_owner, L->list_owner_len,
			  page,sb_update_title_list_owner_selection);
    if (!url)
	return;


    r= reply_to_url(page,prompt_area,mailbox,index,current_header,
		    F,url,aview,1);

    if (r) {
	if (me_retcode) {

	    DPRINT(Debug,5,(&Debug, 
			    "reply_to_list_owner: Setting replied flag\n"));

	    current_header->status |= REPLIED;
	    current_header->status_chgd = TRUE;
	}
    }
}			      

static void reply_to_author P_((struct header_rec *current_header,
				FILE *F,int index,
				struct MailboxView *mailbox,
				struct AliasView   *aview,
				struct menu_context  *page,
				struct menu_context  *prompt_area));
static void reply_to_author(current_header,F,index,mailbox,
			    aview,page,prompt_area)
     struct header_rec *current_header;
     FILE *F;
     int index;
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct menu_context  *prompt_area;
{
    int r;

    r = reply_to_combined(page,prompt_area,mailbox,index,current_header,F,
			  aview,NULL,current_header->from,NULL);

    if (r) {
	if (me_retcode) {

	    DPRINT(Debug,5,(&Debug, 
			    "reply_to_author: Setting replied flag\n"));

	    current_header->status |= REPLIED;
	    current_header->status_chgd = TRUE;
	}
    }
}			      

/* Returns 'i' if should go index */
int generic_reply(index,mailbox,aview,parent_page, old_prompt)
     int index;
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *parent_page;
     struct menu_context  *old_prompt;
{
    FILE *F = NULL;
    struct header_rec *current_header = NULL;    
    int form_letter;
    int ch;
    int retch = 0;
    int update = 0;

    int screen_initialized = 0;

    struct menu_anon_param A;
    struct menu_context *page = NULL;
    struct screen_parts  LOC  = { NULL, NULL, NULL, NULL };
    struct menu_param  PARAM[reply_mp_COUNT+1] = { 
	{ mp_integer, 0 },
	{ mp_anon_param,0 },
	{ mp_END,0 }
    };

    struct menu_context  *this_page    = NULL;
    struct menu_context  *this_prompt  = NULL;



    if (!give_message_data(mailbox,index,
			   &current_header,&F,NULL,
			   NO_mime_parse))
	return 0;

    if (! current_header || !F)	
	return 0;

    form_letter = (current_header->status & FORM_LETTER);
    if (form_letter)
	return 0;

    mp_list_set_integer(PARAM,reply_mp_islist,
			current_header->list_info != NULL);

    A.current_header  = current_header;
    mp_list_set_anon(PARAM,reply_mp_param,&A);


    /* Make possible type two character commands without printing
       of info screen .. this waits a second for command
    */
    if (old_prompt) {
	int lin,col;
	this_page    = parent_page;
	this_prompt  = old_prompt;

	menu_Write_to_screen(old_prompt,FRM(": "));
	menu_GetXYLocation(old_prompt,&lin,&col);
	menu_CleartoEOS(old_prompt); 
	show_last_error();
	menu_MoveCursor(old_prompt,lin,col);
	
	ch = menu_ReadCh(old_prompt, 
			 REDRAW_MARK|READCH_CURSOR|READCH_resize|
			 READCH_sig_char|READCH_poll);

	if (ch == EOF ||
	    ch == TERMCH_interrupt_char)
	    goto OUT;
	if (ch != TIMEOUT_MARK)
	    goto peek_key;

    }

    for (;;) {

	if (! screen_initialized) {

	    page = new_menu_context();
	    set_reply_screen(page,&LOC,PARAM);

	    this_page    = page;
	    this_prompt  = LOC.prompt_page;

	    screen_initialized = 1;
	}

	if (menu_resized(page)) {
	    set_reply_screen(page,&LOC,PARAM);
	    update = 1;
	}

	if (update || menu_need_redraw(page)) {
	    menu_ClearScreen(page);

	    /* Call refresh routines of children */
	    menu_redraw_children(page);
	    	    
	    update = 0;
	    show_last_error(); 
	} 


	check_reply_screen(&LOC,PARAM);

	{
	    int lin,col;
	    
	    menu_ClearLine(LOC.prompt_page,0);
	    
	    menu_PutLineX (LOC.prompt_page,0, 0, 
			   CATGETS(elm_msg_cat, MeSet, MeGenericReplyPrompt,
				   "Generic reply: "));
	    menu_GetXYLocation(LOC.prompt_page,&lin,&col);
	    
	    menu_CleartoEOS(LOC.prompt_page);   
	    
	    show_last_error();
	    menu_MoveCursor(LOC.prompt_page,lin,col);
	    
	    ch = menu_ReadCh(LOC.prompt_page, 
			     REDRAW_MARK|READCH_CURSOR|READCH_resize|
			     READCH_sig_char);
	    
	    menu_CleartoEOS(LOC.prompt_page);
	    set_error("");	/* clear error buffer */
	}

    peek_key:
	switch (ch) {
	case RESIZE_MARK:
	    DPRINT(Debug,4, (&Debug, " ... resizing\n"));
	    
	    continue;
	    
	case ctrl('L'):
	case REDRAW_MARK:
	    DPRINT(Debug,4, (&Debug, " ... redrawing\n"));

	    menu_ClearScreen(this_page);   /* Clear possible redraw mark */
	    
	    /* Call refresh routines of children */
	    menu_redraw_children(this_page);
	    
	    if (menu_need_redraw(this_prompt))		    
		menu_ClearScreen(this_prompt);   /* Clear redraw mark from prompt_area*/
	    
	    update = 1;
	    continue;

	case ctrl('J'):
	case ctrl('M'):
	    goto OUT;

	case 'a':
	    menu_Write_to_screen(this_prompt,
				 CATGETS(elm_msg_cat, MeSet,
					 MeGenericReplyToAll,
					 "Reply to all"));
	    FlushBuffer();

	    reply_to_all(current_header,F,index,mailbox,aview,
			 this_page,this_prompt);
	    goto OUT;

	case 'l':
	    menu_Write_to_screen(this_prompt,
				 CATGETS(elm_msg_cat, MeSet,
					 MeGenericReplyToList,
					 "Reply to list"));
	    FlushBuffer();

	    if (current_header->list_info)
		reply_to_list(current_header,F,index,mailbox,aview,
			      this_page,this_prompt);
	    else {
		lib_error(CATGETS(elm_msg_cat, MeSet,
				  MeGenericReplyNotAList,		       
				  "Mailing list information is not a available."));
	    }
	    goto OUT;


	case 'o':
	    menu_Write_to_screen(this_prompt,
				 CATGETS(elm_msg_cat, MeSet,
					 MeGenericReplyToListOwner,
					 "Reply to list owner"));
	    FlushBuffer();

	    if (current_header->list_info)
		reply_to_list_owner(current_header,F,index,mailbox,aview,
				    this_page,this_prompt);
	    else {
		lib_error(CATGETS(elm_msg_cat, MeSet,
				  MeGenericReplyNotAList,		       
				  "Mailing list information is not a available."));
	    }
	    goto OUT;


	case 't':
	case 'f':
	    menu_Write_to_screen(this_prompt,
				 CATGETS(elm_msg_cat, MeSet,
					 MeGenericReplyToAuthor,
					 "Reply to author"));
	    FlushBuffer();
	    
	    reply_to_author(current_header,F,index,mailbox,aview,
			    this_page,this_prompt);
	    goto OUT;

	case 'i':
	    menu_Write_to_screen(this_prompt,
				 CATGETS(elm_msg_cat, MeSet,
					 MeGenericReplyIndex,
					 "Go to index"));
	    FlushBuffer();
	    retch = 'i';
	    /* FALLTHRU */
	case 'q':
	case 'x':
	case TERMCH_interrupt_char:
	    goto OUT;

	case EOF:
	    retch = EOF;
	    goto OUT;

	default:
	    lib_error(CATGETS(elm_msg_cat, MeSet,
			      MeGenericReplyUnknownCommand,		       
			      "Unknown command: %c"), 
		      ch);
	    continue;
	}    
    }

 OUT:

    error_wait();

    if (screen_initialized) {
	free_mailbox_screen(&LOC);
	
	erase_menu_context(&page);

	/* Force default return to parent page ... */
	menu_set_default(parent_page); 
	
	menu_trigger_redraw(parent_page);
    } else if (old_prompt)
	menu_trigger_redraw(old_prompt);

    return retch;
}


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



syntax highlighted by Code2HTML, v. 0.9.1