static char rcsid[] = "@(#)$Id: showmsg.c,v 1.57.10.2 2007/10/12 03:25:02 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.57.10.2 $   $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
 *****************************************************************************/

/** This file contains all the routines needed to display the specified
    message.
**/

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

DEBUG_VAR(Debug,__FILE__,"ui");

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

void OverrideCharset(mailbox, page, prompt_area, header_area)
     struct MailboxView *mailbox;
     struct menu_context  *page;
     struct menu_context  *prompt_area;
     struct menu_context  *header_area;
{
    int tagged = 0;
    int current              = get_current(mailbox);
    struct header_rec * chdr = give_header(mailbox,current-1);

    char override_charset[40];
    int code;
    charset_t res = NULL;
    int mc,i;
    int delay_redraw = 0;
    int line;

    mc = get_message_count(mailbox);
    for (i=0; i < mc; i++) {
	if (ison_status_message(mailbox,i,status_basic,TAGGED)) {
	    tagged++;
	}
    }

    if (!tagged && chdr && chdr->override_charset &&
	chdr->override_charset->MIME_name)
	strfcpy(override_charset,chdr->override_charset->MIME_name,
		sizeof override_charset);
    else if (display_charset->MIME_name)
	strfcpy(override_charset,display_charset->MIME_name,
		sizeof override_charset);
    else
	strfcpy(override_charset,"none", sizeof override_charset);

 redraw:	    
    if (tagged > 1) 
	menu_print_format_center(prompt_area,1,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmOverrideTagged,
					 "Override charset of %d tagged messages. Use \"none\" to cancel override."),
				 tagged);
    else if (1 == tagged) 
	menu_print_format_center(prompt_area,1,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmOverrideTaggedOne,
					 "Override charset of tagged message. Use \"none\" to cancel override."));
    else if (chdr && chdr->override_charset)
	menu_print_format_center(prompt_area,1,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmOverrideCurrentOver,
					 "Override charset of current message. Use \"none\" to cancel override."));
    else
	menu_print_format_center(prompt_area,1,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmOverrideCurrent,
					 "Override charset of current message."));


    /* FIXME --optionally_enter*  should use prompt_area */
    line = menu_GetAbsLine(prompt_area,2);

    menu_PutLineX(page,line,0,CATGETS(elm_msg_cat, ElmSet, ElmOverrideCSprompt,
				      "Override charset: "));
    code = optionally_enter(override_charset,-1,-1,OE_REDRAW_MARK|
			    OE_SIG_CHAR /* Ctrl-C */,
			    sizeof override_charset, page);

    switch(code) {
    case REDRAW_MARK:
	menu_ClearScreen(page);   /* Reset possible redraw flag */
	delay_redraw++;   /* Can't trigger redraw yet... */

	goto redraw;
    case -1:    /* Interrupt */
	if (delay_redraw)
	    menu_trigger_redraw(page);
	menu_trigger_redraw(prompt_area);

	return;
    case 1:     /* EOF */
	if (delay_redraw)
	    menu_trigger_redraw(page);
	menu_trigger_redraw(prompt_area);

	return;
    case 0:
	/* OK */
	break;
    default:
	if (delay_redraw)
	    menu_trigger_redraw(page);
	menu_trigger_redraw(prompt_area);

	DPRINT(Debug,9,(&Debug, "optionally enter returned %d (unexpected)n",
			code));
	return;
    }

    if (delay_redraw)
	menu_trigger_redraw(page);
    menu_trigger_redraw(prompt_area);

    if (! override_charset[0])
	return;

    if (0 == strcmp(override_charset,"none"))
	res = NULL;
    else {
	int j;

	res = MIME_name_to_charset(override_charset,0);

	if (!res) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet, ElmUnknowCharset,
			      "Charset %s is unknown."),
		      override_charset);
	    
	    goto redraw;
	}

	j = charset_properties(res);
	
	if (! (j & CS_printable) ||
	    ! (j & CS_mapping)) {
	    lib_error(CATGETS(elm_msg_cat, ElmSet, ElmCharsetBadOverride,
			      "Can't use charset %s for override."),
		      override_charset);
	    goto redraw;
	}


    }


    if (tagged == 0) {
	tagged = 1;
	setf_status_message(mailbox,current-1,status_basic,TAGGED);
    }

    mc = get_message_count(mailbox);
    for (i=0; i < mc; i++) {	/* get each tagged msg */
	if (ison_status_message(mailbox,i,status_basic,TAGGED)) {
	    struct header_rec * hdr = give_header(mailbox,i);

	    hdr->override_charset = res;

	    /* If charset is overrided, it effects classification */
	    if (hdr->mime_parsed)
		mime_classify_media(&(hdr->mime_rec),hdr);
	    
	    clearf_status_message(mailbox,i,status_basic,TAGGED);

	    if (header_area) {
		struct menu_common MENU;
		int vis;

		set_mcommon_from_mbxview(&MENU,mailbox);

		vis = compute_visible(i+1, &MENU);
		menu_header_status_update(header_area,vis-1);
	    }
	}
    }
}


/* Set *cancel = 1 if no showing message */
static void print_errors_1 P_((struct header_rec *hdr, 
			       int current, int message_count,
			       int *cancel, 
			       struct string *prompt,
			       struct string *view_text,
			       struct menu_context  *page,
			       int start_line,
			       struct header_errors *header_error
			       ));
static void print_errors_1(hdr,current,message_count,cancel,prompt,
			   view_text,page,start_line,header_error)
     struct header_rec *hdr;
     int current; 
     int message_count;
     int *cancel;
     struct string *prompt;
     struct string *view_text;
     struct menu_context  *page;     
     int start_line;
     struct header_errors *header_error;
{

    int li,co;
    int redraw = 1;
    int last_line = 0;

    if (cancel)
	*cancel = 0;
    if (!header_error)
	return;

    menu_get_sizes(page,&li,&co);

    do {
	int defans = 'v';
	int ch = '\0';

    resize_mark:
	if (menu_resized(page)) {
	    menu_get_sizes(page,&li,&co);
	    redraw = 1;
	}

	if (menu_need_redraw(page) ||    
	    redraw) {
	    
	    int X = 1;
	    int mlen =  get_header_errors_count(header_error);
	    int prompt_line = li - 3;
	    int m;

	    redraw = 0;

	    menu_ClearScreen(page);
	    
	    if (hdr && title_messages && current > 0) {
		struct string * T = title_text(hdr,current,message_count,co,
					       display_charset);
		
		menu_PutLineX(page,0,0,FRM("%S"),T);
		free_string(&T);
		
		if (hdr->subject)
		    menu_print_format_center(page,1,FRM("%S"),
					     hdr->subject);
		X = 3;
	    }
	    
	    menu_print_format_center(page,X, 
				     CATGETS(elm_msg_cat,
					     MeSet, MeHaveParsingErrors,
					     "There is parsing errors on message"));
	    X += 2;
	    
	    for (m = start_line; m < mlen; m++) {
		CONST struct string *S = 
		    get_header_errors_msg(header_error,m);
		int Slen = string_len(S);
		int ptr = 0;
				
		if (X+1 >= prompt_line)
		    break;
		
		do {
		    int visible_len;
		    struct string * S1 = curses_printable_clip(S,&ptr,Slen,
							       &visible_len,
							       co);
		    
		    if (S1) {
			menu_PutLineX(page,X,0,FRM("%S"),S1);
			X++;
			
			free_string(&S1);
		    } else 
			break;
		    
		    if (X+1 >= prompt_line)
			break;
		    
		} while (ptr < Slen);
		last_line = m;
		
		X++;
		
	    }

	    menu_PutLineX(page,prompt_line,0,
			  FRM("%S"),prompt);
	}

	menu_CleartoEOLN(page);   /* Clear current answer */
	
	menu_Write_to_screen(page,
			     FRM("%c%c"),defans,BACKSPACE);
	FlushBuffer();


	ch = menu_ReadCh(page,REDRAW_MARK|READCH_CURSOR|
			 READCH_resize|READCH_sig_char);
	
	if (ch == '\n') 
	    ch = defans;
	
	switch (ch) {
	case TERMCH_interrupt_char:	
	    if (cancel)
		*cancel = 1;
	    goto quit;

	case 'i':
	case 'q':
	case 'c':
	    if (cancel) {
		menu_Write_to_screen(page,
				     CATGETS(elm_msg_cat, MeSet,
					     MeErrorCancel,
					     "Cancel"));
		FlushBuffer();
		*cancel = 1;
		goto quit;
	    }
	    break;

	case RESIZE_MARK:
	    
	    DPRINT(Debug,4, (&Debug,"    .... resizing\n"));
	    goto resize_mark;

	case REDRAW_MARK:
	    redraw = 1;
	    menu_ClearScreen(page);
	    break;

	case '-':
	case LEFT_MARK:
	case PAGEUP_MARK: {
	    int L = last_line - start_line +1;

	    start_line -= L;
	    if (start_line < 0)
		start_line = 0;
	    
	    redraw = 1;
	}
	    break;
	
	case '+':
	case RIGHT_MARK:
	case PAGEDOWN_MARK: {
	    start_line = last_line +1;
	    
	    redraw = 1;
	}
	    break;
	    
	case 'v':
	    menu_Write_to_screen(page,FRM("%S"),view_text);

	    FlushBuffer();
	    
	    if (cancel)
		*cancel = 0;
	    goto quit;
	}
    } while(1);

 quit:
    return;
}

/* Set *cancel = 1 if no showing message */
static void print_errors P_((struct header_rec *hdr, 
			     int current, int message_count,
			     int *cancel));
static void print_errors(hdr,current,message_count,cancel)
     struct header_rec *hdr;
     int current; 
     int message_count;
     int *cancel;
{
    struct menu_context  *page = new_menu_context();

    struct string *prompt     = NULL;
    struct string *view_text  = NULL;

   
    if (cancel)
	 prompt = format_string(CATGETS(elm_msg_cat, MeSet, MeErrorPrompt1,
					"Press enter for default, v)iew message or c)ancel: "));
    else
	prompt = format_string(CATGETS(elm_msg_cat, MeSet, MeErrorPrompt2,
				       "Press enter to view message: "));

    view_text = format_string(CATGETS(elm_msg_cat, MeSet,
				      MeErrorView,
				      "View message"));

    print_errors_1(hdr,current,message_count,cancel,prompt,
		   view_text,page,0,hdr->header_error);

    free_string(&view_text);
    free_string(&prompt);
    erase_menu_context(&page);
}

void print_errors_att(header_error,start_line,cancel)
     struct header_errors *header_error;
     int start_line;
     int *cancel;
{
    struct menu_context  *page = new_menu_context();

    struct string *prompt     = NULL;
    struct string *view_text  = NULL;

   
    if (cancel)
	 prompt = format_string(CATGETS(elm_msg_cat, MeSet, MeErrorPrompt3,
					"Press enter for default, v)iew message structure or c)ancel: "));
    else
	prompt = format_string(CATGETS(elm_msg_cat, MeSet, MeErrorPrompt4,
				       "Press enter to view message structure: "));

    view_text = format_string(CATGETS(elm_msg_cat, MeSet,
				      MeErrorViewStructure,
				      "View message structure"));

    print_errors_1(NULL,0,0,cancel,prompt,
		   view_text,page,start_line,header_error);

    free_string(&prompt);
    erase_menu_context(&page);
}


struct screen_parts2 {
    struct menu_context  * title_area;
    struct menu_context  * prompt_area;
};

static void set_prompt_screen P_((struct menu_context  *page, struct screen_parts2 *LOC, int current));
static void set_prompt_screen(page,LOC,current)
     struct menu_context  *page; 
     struct screen_parts2 *LOC;
     int current;
{
    int   LINES, COLUMNS;	
    int C = 5;

    menu_get_sizes(page,&LINES, &COLUMNS);

    if (title_messages && current > 0) {
	C = 7;
    }

    /* 1)  Title part of screen */

    if (! LOC->title_area)
	LOC->title_area = new_menu_subpage(page,0,C,
					   subpage_simple_noredraw,NULL);
    else
	menu_subpage_relocate(LOC->title_area,page,0,C);


    /* 2)  Prompt part of screen */

    if (! LOC->prompt_area)
	LOC->prompt_area = new_menu_subpage(page,C,LINES-C,
					    subpage_simple_noredraw,NULL);
    else
	menu_subpage_relocate(LOC->title_area,page,C,LINES-C);
}

static void free_prompt_screen P_((struct screen_parts2 *LOC));
static void free_prompt_screen(LOC)
     struct screen_parts2 *LOC;
{
    erase_menu_context (&(LOC->title_area));
    erase_menu_context (&(LOC->prompt_area));    
}

static void redraw_prompt_screen P_((struct menu_context  *page));
static void redraw_prompt_screen(page)
     struct menu_context  *page; 
{
    menu_ClearScreen(page);

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


/* Returns 0 on quit */

struct prompt_list {
    struct mimeinfo *structure;
    char   * printable_command;
    int    selected;
    int    col;
};

struct update_params {
    struct prompt_list  ** list; 
    int  *list_len;
    int *current_offset;
};

static void update_prompt P_((struct update_params *P,	   
			      int idx,
			      struct menu_context  *page));


static void prompt_Z P_((struct menu_context  *page,
			 int ask_metamail));
static void prompt_Z(page,ask_metamail)
     struct menu_context  *page;
     int ask_metamail;
{
    int lin,col;

    menu_get_sizes(page, &lin,&col);   

    if (ask_metamail) 
	menu_PutLineX(page,		      
		      lin-2,0,
		      CATGETS(elm_msg_cat, ElmSet, ElmMailcapPage,
			      "Press enter for default, use m)etamail or p)age mail: "));
    else
	menu_PutLineX(page,
		      lin-2,0,
		      CATGETS(elm_msg_cat, ElmSet, ElmMailcapDone,
			      "Press enter for default or use %c/%c, use m)etamail or d)one: "),
		      *def_ans_yes, *def_ans_no);

}

static void check_prompt_screen P_((struct screen_parts2 *LOC,
				    struct update_params *P,
				    int ask_metamail,
				    int current,
				    int message_count,
				    struct header_rec *hdr));
static void check_prompt_screen(LOC,P,ask_metamail,current,message_count,hdr)
     struct screen_parts2 *LOC;
     struct update_params *P;
     int ask_metamail;
     int current;
     int message_count;
     struct header_rec *hdr;
{

    /* 1)  Title part of screen */
    if (menu_resized(LOC->title_area)) {
	DPRINT(Debug,1, (&Debug, "title area resized\n"));

    }

    if (menu_need_redraw(LOC->title_area)) {
	int X = 1;

	DPRINT(Debug,7, (&Debug, "title area redraw\n"));

	menu_ClearScreen(LOC->title_area);

	if (title_messages && current > 0) {
	    int li,co;
	    struct string *T;

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

	    X = 3;

	    T = title_text(hdr,current,message_count,
			   co,
			   display_charset);

	    menu_PutLineX(LOC->title_area,0,0,FRM("%S"),T);
	    free_string(&T);


	    if (hdr->subject)
		menu_print_format_center(LOC->title_area,1,
					 FRM("%S"),
					 hdr->subject);

	}
 
	if (ask_metamail) {
	    menu_print_format_center(LOC->title_area,X,
				     CATGETS(elm_msg_cat, ElmSet, ElmMetamailMenu,
					     "Metamail selection"));

	    menu_PutLineX(LOC->title_area,X+2,0,
			   CATGETS(elm_msg_cat, ElmSet, ElmMetamailMenu1,
				   "Viewing of this message requires metamail. Press 'm' to select metamail."));
	    menu_PutLineX(LOC->title_area,X+3,0,
			  CATGETS(elm_msg_cat, ElmSet, ElmMetamailMenu2,
				  "Or you can p)age message without metamail."));
	    
	} else {
	    menu_print_format_center(LOC->title_area,X,
				     CATGETS(elm_msg_cat, ElmSet, ElmMailcapMenu,
					     "Mailcap program selection"));

	    menu_PutLineX(LOC->title_area,X+2,0,
			  CATGETS(elm_msg_cat, ElmSet, ElmMailcapMenu1,
				  "Viewing of this message requires external programs (press 'y' to confirm.)"));
	    
	    menu_PutLineX(LOC->title_area,X+3,0,
			  CATGETS(elm_msg_cat, ElmSet, ElmMailcapMenu2,
				  "To refuse external program press 'n'. Also you can page message with m)etamail."));

		    
	}
    }

    /* 2)  Prompt part of screen */

    if (menu_resized(LOC->prompt_area)) {
	DPRINT(Debug,1, (&Debug, "prompt area resized\n"));

    }

    if (menu_need_redraw(LOC->prompt_area)) {

	DPRINT(Debug,7, (&Debug, "prompt area redraw\n"));

	update_prompt(P,-1, LOC->prompt_area);	

	prompt_Z(LOC->prompt_area,ask_metamail);
    }
}

static void update_prompt (P,idx,page)
     struct update_params *P;
     int idx;
     struct menu_context  *page; 
{
    int LINES, COLUMNS;
    struct prompt_list  ** list = P->list;
    int  *list_len              = P->list_len;
    int *current_offset         = P->current_offset;


    menu_get_sizes(page,&LINES, &COLUMNS);

    if (idx < 0) {
	int i;

	menu_ClearScreen(page);

	for (i = *current_offset; 
	     i >= 0 && 
		 i < *current_offset + LINES / 3  &&
		 i < *list_len;
	     i++)
	    update_prompt(P,i, page);
		 
    } else if (idx >= 0 &&
	       idx >= *current_offset &&
	       idx < *list_len
	       ) {
	
	int X = (idx - *current_offset) * 3 + 3;
	media_type_t            T =  (*list)[idx].structure->TYPE;
	struct string * S  = NULL;
	struct string * S1 = NULL;
	int pos = 0;
	int visible_len = 0;

	if (X >= LINES-3)
	    return;

	S =  format_string(CATGETS(elm_msg_cat, ElmSet, ElmUseMailcap,
				   "%2d Use '%s' to show %s/%s"),
			   idx,
			   (*list)[idx].printable_command ? 
			   (*list)[idx].printable_command : "???",
			   get_major_type_name(T), get_subtype_name(T));
	S1 = curses_printable_clip(S,&pos,string_len(S),
				   &visible_len,
				   COLUMNS-10);
	
	menu_PutLineX(page,X,0,FRM("%S ? "),S1);
	menu_CleartoEOLN(page);
		 
	(*list)[idx].col = visible_len+3;
	
	if ((*list)[idx].structure->handler_data->use_entry ||
	    (*list)[idx].selected) {
	    
	    if ((*list)[idx].structure->handler_data->use_entry)
		menu_PutLineX(page,X,(*list)[idx].col,
			 CATGETS(elm_msg_cat, ElmSet, ElmYesWord, 
				 "Yes."));
	    else
		menu_PutLineX(page,X,(*list)[idx].col,
			      CATGETS(elm_msg_cat, ElmSet, ElmNoWord, 
				      "No."));
	}
	    
	free_string(&S1);
	free_string(&S);
    }

}

static void prompt_programs_1 P_((struct mimeinfo *structure,
				 struct prompt_list  ** list, 
				 int  *list_len,
				 int *current_offset,
				  struct menu_context  *page));

static void prompt_programs_1(structure, list, list_len, current_offset,
			      page)
     struct mimeinfo *structure;
     struct prompt_list  ** list; 
     int  *list_len;
     int *current_offset;
     struct menu_context  *page;
{
    int LINES, COLUMNS;

    menu_get_sizes(page, &LINES, &COLUMNS);   


    if (structure->mime_flags) {
       
	if (structure->handler_data &&
	    structure->handler_data->entry) {
	    
	    char * cmd = mailcap_view_command(structure->handler_data->entry,
					      structure);

	    if (cmd) {
		
		char **  trusted_programs = 
		    give_dt_path_as_elems(&internal_mailcap_t_programs,
					  "internal-mailcap-trusted-programs");
		
		int IS_OK = 0;

		int i;
		char *x;

		if (trusted_programs) {
		    for (i = 0; trusted_programs[i]; i++) {
			if (0 == strcmp(cmd,
					trusted_programs[i]))
			    IS_OK++;
		     }
		}
		*list = safe_realloc(*list,
				     sizeof ((*list)[0]) * (*list_len +1));
		
		bzero((void *) &( (*list)[*list_len] ),
		      sizeof    ( (*list)[*list_len] ));
		
		if (strlen(cmd) > 15 && (x = strrchr(cmd,'/')) && x != cmd) {

		    char * s = elm_message(FRM("...%s"),x);

		    free(cmd);
		    cmd = s;
		}

		(*list)[*list_len].structure          = structure;
		(*list)[*list_len].printable_command  = cmd;
		(*list)[*list_len].selected           = 0;
		(*list)[*list_len].col                = COLUMNS-7;

		if (IS_OK) {
		    (*list)[*list_len].selected           = 1;
		    (*list)[*list_len].structure->handler_data->use_entry = 1;
		}
		
		i = (*list_len)++;

		{
		    struct update_params P;

		    P.list           = list;
		    P.list_len       = list_len;
		    P.current_offset = current_offset;

		    update_prompt(&P,i,page);
		}

	    }
	}
	
	/* Is alternative -- just process it */
	if (structure->handler_data &&
	    structure->handler_data->selected_alternative) {

	    if (structure->handler_data->selected_alternative->magic != MIME_magic)
		mime_panic(__FILE__,__LINE__,"prompt_programs_1",
			   "Bad magic number (alternatice)");

	    prompt_programs_1(structure->handler_data->selected_alternative,
			      list,list_len,current_offset, page);

	} 

	/* Process subparts recursively */
	else if (structure->parser_data) {
	    int count = mime_parser_subparts(structure->parser_data);
	    int i;

	    for (i = 0; i < count; i++) {
		mime_t *att = 	mime_parser_index(structure->parser_data,i);

		if (att->magic != MIME_magic)
		    mime_panic(__FILE__,__LINE__,"prompt_programs_1",
			       "Bad magic number (subpart)");

		prompt_programs_1(att,
				  list,list_len,current_offset, page);
	    
	    }

	}
	
    }
}


/* return TRUE if metamail is used instead,
   -1 to cancel
 */
static int prompt_programs P_((struct header_rec *hdr, int ask_metamail,
			       int current, int message_count));
static int prompt_programs(hdr, ask_metamail, current, message_count)
     struct header_rec *hdr;
     int ask_metamail;   
     int current;
     int message_count;
{
    int r = TRUE;
    struct mimeinfo *structure = &(hdr->mime_rec);

    struct prompt_list  * list     = NULL;
    int                   list_len = 0;
    int                   offset   = 0;

    struct menu_context  *page = new_menu_context();

    struct screen_parts2 LOC = { NULL, NULL };
    struct update_params P;
    int q = 0;
    int ch = '\0';

    if (ask_metamail)
	ask_metamail = NULL != have_metamail();

    P.list           = &list;
    P.list_len       = &list_len;
    P.current_offset = &offset;

    set_prompt_screen(page,&LOC,current);

    redraw_prompt_screen(page);
	
    prompt_programs_1(structure,&list,&list_len,&offset, LOC.prompt_area);

    check_prompt_screen(&LOC,&P,ask_metamail, current,message_count,hdr);

    /* Check if all programs was trusted ... */
    
    while (q < list_len &&
	   list[q].selected &&
	   list[q].structure &&
	   list[q].structure->handler_data &&
	   list[q].structure->handler_data->use_entry)
	q++;

    r = FALSE;
    if (q >= list_len && !internal_mailcap_t_prompt && list_len > 0) 
	goto out;
    
    do {
	int defans;
	int sel = q;
	
    resize_mark:
	defans = *def_ans_no;
	
	if (menu_resized(page)) {
	    set_prompt_screen(page,&LOC,current);
	}
	
	if (menu_need_redraw(page))
	    goto redraw;
	
	/* Search first not selected entry */
	while (sel < list_len &&
	       list[sel].selected)
	    sel++;

	if (q >= list_len) {
	    
	    prompt_Z(LOC.prompt_area,ask_metamail);
	    
	    defans = ask_metamail ? 'm' : 'd';
	    
	} else {	       		
	    int X = (q - offset) * 3 + 3;
	    int lin,col;
	    menu_get_sizes(LOC.prompt_area, &lin,&col);   
	    
	    if (X <= 1) {
		offset = q-1;
		if (offset < 0)
		    offset = 0;
		
		ch = REDRAW_MARK;
		menu_trigger_redraw(LOC.prompt_area);
		goto redraw1;
	    }
	    
	    if (X >= lin-3) {
		offset = q;
		
		ch = REDRAW_MARK;
		menu_trigger_redraw(LOC.prompt_area);
		goto redraw1;		 
	    }

	    menu_MoveCursor(LOC.prompt_area,X,list[q].col);
	}

	
	menu_CleartoEOLN(LOC.prompt_area);   /* Clear current answer */
	
	menu_Write_to_screen(LOC.prompt_area,
			     FRM("%c%c"),defans,BACKSPACE);
	FlushBuffer();
	
	
	ch = menu_ReadCh(LOC.prompt_area,REDRAW_MARK|READCH_CURSOR|
			 READCH_resize|READCH_sig_char);
	
	if (ch == '\n') 
	    ch = defans;
		
	switch (ch) {
	case TERMCH_interrupt_char:	
	    r=-1;
	    goto failure;
	case 'i':
	case 'q':
	    menu_Write_to_screen(LOC.prompt_area,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmQuit,
					 "Quit"));
	    FlushBuffer();
	    r=-1;
	    goto failure;

	case RESIZE_MARK:
	    
	    DPRINT(Debug,4, (&Debug,"    .... resizing\n"));
	    goto resize_mark;
	    
	case REDRAW_MARK:
	redraw:
	    
	    redraw_prompt_screen(page);		    	      
	    
	    break;
	    
	case '-':
	case LEFT_MARK:
	case PAGEUP_MARK: {
	    int lin,col;
	    menu_get_sizes(LOC.prompt_area, &lin,&col);   
	    
	    offset -= lin / 3 - 2;
	    if (offset < 0)
		offset = 0;
	    q = offset;
	    
	    menu_trigger_redraw(LOC.prompt_area);
	}
	    goto redraw1;
	    
	    
	case '+':
	case RIGHT_MARK:
	case PAGEDOWN_MARK: {
	    int lin,col;
	    menu_get_sizes(LOC.prompt_area, &lin,&col);   
	    
	    offset += lin / 3 - 2;
	    if (offset >= list_len);
	    offset = list_len-1;
	    q = offset;
	    
	    menu_trigger_redraw(LOC.prompt_area);
	}
	    goto redraw1;
	    
	case DOWN_MARK:
	    if (q < list_len) {
		update_prompt(&P,q, LOC.prompt_area);
		q++;
	    }
	    break;
	    
	case UP_MARK:
	    if (q < list_len) 
		update_prompt(&P,q, LOC.prompt_area);
	    if (q > 0)
		q--;
	    break;
	    
	case 'd':
	done:
	    ch = 0;
	    
	    if (q < list_len) 
		update_prompt(&P,q, LOC.prompt_area);
	    
	    prompt_Z(LOC.prompt_area,ask_metamail);
	    
	    menu_Write_to_screen(LOC.prompt_area,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmDone,
					 "Done"));
	    FlushBuffer();
	    break;
	    
	case 'm':
	    if (q < list_len) 
		update_prompt(&P,q, LOC.prompt_area);
	    
	    prompt_Z(LOC.prompt_area,ask_metamail);
	    
	    menu_Write_to_screen(LOC.prompt_area,
				 CATGETS(elm_msg_cat, ElmSet,
					 ElmMetamail,
					 "Metamail"));		
	    if (have_metamail()) {
		ch = 0;
		r = TRUE;
	    }
	    
	    break;
	    
	case 'p':
	    if (q < list_len) 
		update_prompt(&P,q, LOC.prompt_area);
	    
	    if (sel >= list_len)
		goto done;
	    q = sel;
	    ask_metamail = 0;
	    
	    menu_trigger_redraw(LOC.prompt_area);
	    menu_trigger_redraw(LOC.title_area);
	    
	    break;
	    
	    
	}
	
	if (q < list_len) {
	    
	    if (ch == *def_ans_yes) {
		list[q].selected = 1;
		list[q].structure->handler_data->use_entry = 1;
		update_prompt(&P,q, LOC.prompt_area);
		q++;
		
	    } else if (ch == *def_ans_no) {
		
		list[q].selected = 1;
		list[q].structure->handler_data->use_entry = 0;
		update_prompt(&P,q, LOC.prompt_area);
		q++;
		
	    }
	}
	
    redraw1:
	check_prompt_screen(&LOC,&P,ask_metamail,current, message_count,
			    hdr);
	
	FlushBuffer();
	
    } while(ch);
    
    
 out:
 failure:
    
    if (list) {
	int i;
	
	for (i = 0; i < list_len; i++) {
	    if (list[i].printable_command) {
		free(list[i].printable_command);
		list[i].printable_command = NULL;
	    }
	}
	
	free(list);
	list = NULL;
    }
    list_len = 0;
    
    free_prompt_screen(&LOC);
    erase_menu_context(&page);
    
    return r;
}


/* -1 == cancel */
int need_meta (hdr,current,message_count)
     struct header_rec *hdr;
     int current, message_count;
{
    /* Determine whether or not we need to call metamail to display the
     * message contents.
     */
    int result = 0;

    if ((hdr->status & (MIME_MESSAGE)) && (hdr->status & MIME_UNSUPPORTED)) {
	if (have_metamail()) {
	    if (prompt_metamail)
		result = prompt_programs (hdr,1,current,message_count);
	    else 
		result = TRUE;
	} else
	    result = FALSE;
    /* Do not call metamail if Disposition is not inline */
    } else if ((hdr->status & MIME_MESSAGE) && 
	       hdr->mime_rec.disposition != DISP_INLINE)
	result = FALSE;  
    else if (hdr->status & (MIME_MESSAGE | PRE_MIME_CONTENT)) {

	int X = hdr->mime_rec.mime_flags;  /* NOTPLAIN_need_metamail           0x01
					      NOTPLAIN_need_mailcap            0x02
					      NOTPLAIN_canuse_mailcap          0x04
					   */
		
	if (0 != (X & NOTPLAIN_need_metamail) && have_metamail()) {
	    if (prompt_metamail)
		result = prompt_programs (hdr,1,current,message_count);
	    else 
		result = TRUE;
	} else if (0 != (X & NOTPLAIN_canuse_mailcap) ||
		   0 != (X & NOTPLAIN_need_mailcap)) {

	    result = prompt_programs (hdr,0,current,message_count);
	}

    }

    DPRINT(Debug,9,(&Debug, "need_meta=%d\n",result));
    return result;
}

int show_msg(current_header, infile, current,message_count, pager_page)
     struct header_rec *current_header;
     FILE *infile;
     int current, message_count;
     struct pager_page *pager_page;
{
	/*** Display number'th message.  Get starting and ending lines
	     of message from headers data structure, then fly through
	     the file, displaying only those lines that are between the
	     two!

	     Return 0 to return to the index screen or a character entered
	     by the user to initiate a command without returning to
	     the index screen (to be processed via process_showmsg_cmd()).
	***/



    int is_need_meta = 0;
    int LINES, COLUMNS;
    char * metamail_value = NULL;
    int cancel_it = 0;

    menu_get_sizes(pager_page->root,&LINES, &COLUMNS);
    
    /* erase showmsg_c border line and prompt area */

    if (pager_page->border_line)
	erase_menu_context( &(pager_page->border_line));
    if (pager_page->prompt_area)
	erase_menu_context( &(pager_page->prompt_area));

#if 0
    /* Do not erase screen on here, copying mail may take long time
       lefting screen empty before it can be displayed
    */

    menu_ClearScreen(pager_page->root);
#endif


    DPRINT(Debug,4,(&Debug, 
		    "displaying %d lines from message #%d\n", 
		    current_header->lines, 
		    current));
    
    print_errors(current_header,current,message_count,&cancel_it);
    if (cancel_it)
	return 0;
    
    
    is_need_meta = need_meta(current_header,current,message_count);
    if (is_need_meta < 0) {
	DPRINT(Debug,4,(&Debug, "view canceled because of errors.\n"));
	return 0;
    }

    if (is_need_meta &&
	    (metamail_value = 
	     give_dt_estr_as_str(&metamail_path_e, "metamail"))
	    ) {
	        char fname[STRING], Cmd[SLEN];
		int err;
		FILE *fpout;
		char *    tmp = give_dt_estr_as_str(&temp_dir_e,"tmpdir");

		if (!tmp)
		    return 0;


		elm_sfprintf(fname, sizeof fname,
			     FRM("%semm.%d.%d"), tmp, getpid(), getuid());

		if ((fpout = safeopen_rdwr(fname)) == NULL) {
		    err = errno;
		    DPRINT(Debug,1,(&Debug, 
				    "Error: open of temporary file %s, errno %s (show_message)\n",
				    fname, error_description(err)));
		  lib_error(CATGETS(elm_msg_cat, ElmSet, 
				    ElmCantOpenAsOutputFile,
				    "Can't open \"%s\" as output file! (%s)."),
			    fname, error_description(err));
		  return(0);
		}
		/* Let metamail decode it! 
		 * (Now CM_DECODE also decodes MIME and PGP) -KEH
		 *
		 * CM_LF: Metamail can not cope with CRLF
		 */
		if (!copy_message_f(infile,current_header,
				    "", fpout, CM_LF, NULL)) {
		    /* FAIL */
		    fclose (fpout);
		    unlink (fname);
		    return 0;
		}
		(void) fclose (fpout);
		elm_sfprintf(Cmd, sizeof Cmd,
			     FRM("%s -p -z -m Elm %s"), 
			     metamail_value, fname);

		{
		    struct menu_context *xpage;

		    xpage = Raw(OFF);
		
		    menu_ClearScreen(xpage);
		    menu_Write_to_screen(xpage,
					 CATGETS(elm_msg_cat, MeSet, 
						 MeExecuteMetamail,
						 "Executing metamail...\n"));
		    FlushBuffer();
		}

		system_call(Cmd, SY_ENAB_SIGINT|SY_ENV_METAMAIL, NULL);
		(void) unlink (fname);

		if (prompt_after_metamail) {
		    struct menu_context *cpage;

		    cpage = Raw(ON | NO_TITE);	/* Raw on but don't switch screen */
		redraw:
		    menu_get_sizes(cpage,&LINES, &COLUMNS);

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

		    menu_Write_to_screen(cpage,FRM("\r\n"));
		    Raw(OFF | NO_TITE); /* Raw off so raw on takes effect */
		}

		Raw(ON); /* Finally raw on and switch screen */
		return(0);
    } else {
	    
	    return (metapager (infile, current_header, TRUE, 
			       current, message_count, pager_page));
    }
}

int mbx_show_msg (mailbox,msg,pager_page)
     struct MailboxView *mailbox;
     int msg;
     struct pager_page *pager_page;
{
    struct header_rec *hdr;
    FILE *F;

    if (give_message_data(mailbox,msg,
			  &hdr,&F,NULL,
			  mime_parse_routine)) {

	/* it's been read now! */
	if (ison_status_message(mailbox,msg,status_basic,NEW))
	    clearf_status_message(mailbox,msg,status_basic,NEW); 
		
	/* it's been read now! */
	if (ison_status_message(mailbox,msg,status_basic,UNREAD))
	    clearf_status_message(mailbox,msg,status_basic,UNREAD); 

	return(show_msg(hdr,F,msg+1,
			get_message_count(mailbox),
			pager_page));
    } else {
	DPRINT(Debug,3,(&Debug, 
			"give_message_data [%d] fails",msg));
    }
    return 0;
}

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


syntax highlighted by Code2HTML, v. 0.9.1