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

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

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

DEBUG_VAR(Debug,__FILE__,"ELM");


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


typedef void  run_command P_((struct MailboxView *mailbox,
			      struct AliasView   *aview,
			      struct menu_context  *parent_page,
			      struct menu_context  *old_prompt));

typedef void  run_command_post P_((struct MailboxView *mailbox,
				  struct AliasView   *aview,
				  struct menu_context  *page,
				  struct screen_parts *LOC));

S_(run_command_post h_nopost_redraw)
static void  h_nopost_redraw P_((struct MailboxView *mailbox,
				 struct AliasView   *aview,
				 struct menu_context  *page,
				 struct screen_parts *LOC));
static void  h_nopost_redraw(mailbox,aview,page,LOC)
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct screen_parts *LOC;
{

}


S_(run_command   dummy_quit)
static void  dummy_quit P_((struct MailboxView *mailbox,
			    struct AliasView   *aview,
			    struct menu_context  *page,
			    struct menu_context  *prompt));
static void  dummy_quit(mailbox,aview,page,prompt)
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct menu_context  *prompt;
{
    menu_Write_to_screen(prompt,
			 CATGETS(elm_msg_cat, MeSet,
				 MeExtendedQuit,
				 "Quit"));

    FlushBuffer();
}


S_(run_command h_duplicate_removal)
static void  h_duplicate_removal P_((struct MailboxView *mailbox,
			    struct AliasView   *aview,
			    struct menu_context  *page,
			    struct menu_context  *prompt));
static void  h_duplicate_removal(mailbox,aview,page,prompt)
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct menu_context  *prompt;
{
    menu_Write_to_screen(prompt,
			 CATGETS(elm_msg_cat, MeSet,
				 MeExtendedDuplicateRemoval,
				 "Duplicate removal mode"));

    FlushBuffer();

    ViewRemoveDuplicate(mailbox,aview,page);
}


S_(run_command h_open_mailbox)
static void  h_open_mailbox P_((struct MailboxView *mailbox,
				struct AliasView   *aview,
				struct menu_context  *page,
				struct menu_context  *prompt));
static void  h_open_mailbox(mailbox,aview,page,prompt)
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct menu_context  *prompt;
{
    menu_Write_to_screen(prompt,
			 CATGETS(elm_msg_cat, MeSet,
				 MeExtendedOpenMailbox,
				 "Open mailbox to current view"));

    FlushBuffer();

    OpenMailbox(mailbox,aview,page);
}

S_(run_command_post h_open_mailbox_post)
static void  h_open_mailbox_post P_((struct MailboxView *mailbox,
				     struct AliasView   *aview,
				     struct menu_context  *page,
				     struct screen_parts *LOC));
static void  h_open_mailbox_post(mailbox,aview,page,LOC)
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct screen_parts *LOC;
{
    OpenMailboxPost(mailbox,page,LOC);
}


S_(run_command h_view_threads)
static void  h_view_threads P_((struct MailboxView *mailbox,
				struct AliasView   *aview,
				struct menu_context  *page,
				struct menu_context  *prompt));
static void  h_view_threads(mailbox,aview,page,prompt)
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *page;
     struct menu_context  *prompt;
{
    menu_Write_to_screen(prompt,
			 CATGETS(elm_msg_cat, MeSet,
				 MeExtendedViewThreads,
				 "View threads"));

    FlushBuffer();

    ViewThreads(mailbox,aview,page);
}



static struct command_selection {
    int cmd;
    
    int      nls_code;
    char   * default_line;

    run_command       * f_command;
    run_command_post  * f_post;
}  commands[] = {
    { 'd',  MeExtendedMenuDeplicateRemoval, "d)uplicate removal mode", 
      h_duplicate_removal, h_nopost_redraw },
    { 'o',  MeExtendedMenuOpenMailbox, "o)pen mailbox to current view", 
      h_open_mailbox, h_open_mailbox_post },
    { 't', MeExtendedMenuViewThreads, "view t)hreads", 
      h_view_threads, h_nopost_redraw },
    { 'q',  MeExtendedMenuQuit, "q)uit extended command", 
      dummy_quit, h_nopost_redraw }
};

static CONST int commands_len = sizeof (commands) / sizeof (commands[0]);


S_(header_line_redraw extended_show_header)
static void extended_show_header P_((struct menu_context  *ptr,
				     struct menu_param *list,
				     int line_number,
				     int index,
				     int is_current));
static void extended_show_header(ptr,list,line_number,index,is_current)
     struct menu_context  *ptr;
     struct menu_param *list;	   
     int line_number;
     int index;
     int is_current;
{

    int LINES, COLUMNS;

    menu_get_sizes(ptr, &LINES, &COLUMNS);

    menu_ClearLine(ptr,line_number);	    
    menu_MoveCursor(ptr,line_number,0);

    if (is_current) {

	if (has_highlighting && ! arrow_cursor) {

	    menu_StartXX(ptr,pg_INVERSE);

	    menu_PutLine0(ptr,line_number,0,"   ");

	} else {
	    menu_PutLine0(ptr,line_number,0,"-> ");

	}

    } else 
	menu_PutLine0(ptr,line_number,0,"   ");

    if (index >= 0 && index < commands_len) {
	char * msg = catgets(elm_msg_cat, MeSet, 
			     commands[index].nls_code,
			     commands[index].default_line);
	
	if (COLUMNS > 3)
	    menu_PutLineX(ptr,line_number,3,FRM("%-*.*s"),
			  COLUMNS-3,COLUMNS-3,msg);
    }

    if (is_current) {
	if (has_highlighting && ! arrow_cursor) {
	    menu_EndXX(ptr,pg_INVERSE);
	}
    }
    menu_Writechar(ptr,'\r');
    menu_Writechar(ptr,'\n');
}

S_(header_line_redraw extended_show_current)
static void extended_show_current P_((struct menu_context  *ptr,
				    struct menu_param *list,
				    int line_number,
				    int index,
				    int is_current));
static void extended_show_current(ptr,list,line_number,index,is_current)
     struct menu_context  *ptr;
     struct menu_param *list;	   
     int line_number;
     int index;
     int is_current;
{
    if (has_highlighting && ! arrow_cursor) {
	extended_show_header(ptr,list,line_number,index,is_current);
    } else {
	if (!is_current)
	    menu_PutLine0(ptr,line_number,0,"  ");  /* remove old pointer... */
	else
	    menu_PutLine0(ptr,line_number,0,"->");
    }
}


S_(subpage_simple_redraw sb_update_extended_title)
static int sb_update_extended_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, MeExtendedTitle,
				     "Extended command selection"));

    return 1;   /* title completed */
}

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

    menu_print_format_center(ptr,0,
			     CATGETS(elm_msg_cat, MeSet, MeExtendedMenuLine1,
				     "To select command, press <return>.  j = move down, k = move up"));
    menu_print_format_center(ptr,1,
			     CATGETS(elm_msg_cat, MeSet, MeExtendedMenuLine2,
				     "Or select letter from command line."));

    return 1;

}


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

    /* 1) Title part */

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

    /* 2) selection part */
    headers_per_page = LINES-8;
    if (headers_per_page < 1) {
	headers_per_page = 1;
    }

    if (! LOC->header_page)
	LOC->header_page = new_menu_header(page,2,
					   headers_per_page,
					   extended_show_header,
					   extended_show_current,
					   null_header_param_changed,
					   extended_show_current,
					   LIST);
    else
	menu_header_relocate(LOC->header_page,page,
			     2,headers_per_page);

    /* 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_extended_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_extended_screen P_((struct screen_parts *LOC,
				   struct menu_param *list));
static void check_extended_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_extended_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_extended_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, "selection page resized\n"));

	menu_trigger_redraw(LOC->header_page);
    }

    if (menu_need_redraw(LOC->header_page)) {

	DPRINT(Debug,1, (&Debug, "selection page redraw\n"));
	menu_ClearScreen(LOC->header_page);
    }
}


static void first_item P_((void));
static void first_item()
{
    lib_error(CATGETS(elm_msg_cat, MeSet, 
		      MeNoMoreCommandsAbove,
		      "No more commands above."));    
}

static void last_item P_((void));
static void last_item()
{
    lib_error(CATGETS(elm_msg_cat, MeSet, 
		      MeNoMoreCommandsBelow,
		      "No more commands below.")); 
}

static struct move_messages M = {
    first_item,
    last_item
};



void extended_command(mailbox,aview,parent_page,parent_LOC)
     struct MailboxView *mailbox;
     struct AliasView   *aview;
     struct menu_context  *parent_page;
     struct screen_parts *parent_LOC;
{
    run_command_post * postpage = h_nopost_redraw;
    
    struct menu_context  *old_prompt = 
	parent_LOC ? 
	parent_LOC->prompt_page :
	NULL;

    int ch = 0;
    int update = 0;
    int screen_initialized = 0;

    struct menu_context *page = NULL;
    struct screen_parts  LOC  = { NULL, NULL, NULL, NULL };

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


    /* Make possible type two character commands without printing
       of selection 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 (;;) {
	int i;

	if (! screen_initialized) {

	    page = new_menu_context();
	    set_extended_screen(page,&LOC,NULL /* PARAM */);

	    this_page    = page;
	    this_prompt  = LOC.prompt_page;

	    screen_initialized = 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_extended_screen(&LOC,NULL /* PARAM */);


	{
	    int lin,col;
	    
	    menu_ClearLine(LOC.prompt_page,0);
	    
	    menu_PutLineX (LOC.prompt_page,0, 0, 
			   CATGETS(elm_msg_cat, MeSet, MeExtendedPrompt,
				   "Extended command: "));
	    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 */
	}



	ch = do_movement(LOC.header_page,ch,commands_len,&M);

	switch (ch) {
	    int cur;
	    
	case 0:
	    continue;

	case '\n':
	    cur = menu_header_get(LOC.header_page,header_current);

	    if (cur >= 0 && cur < commands_len) {
		
		commands[cur].f_command(mailbox,aview,this_page,this_prompt);

		postpage = commands[cur].f_post;

		goto OUT;
	    }
	    continue;

	}

    peek_key:

	for (i = 0; i < commands_len; i++) {
	    if (ch == commands[i].cmd) {
		
		commands[i].f_command(mailbox,aview,this_page,this_prompt);
		
		postpage = commands[i].f_post;

		goto OUT;	       
	    }
	}

	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 'i':
	    menu_Write_to_screen(this_prompt,
				 CATGETS(elm_msg_cat, MeSet,
					 MeExtendedGoIndex,
					 "Go to index"));
	    FlushBuffer();

	    /* FALLTHRU */
	case 'q':
	case 'x':
	case TERMCH_interrupt_char:
	    goto OUT;

	case EOF:
	    goto OUT;




	default:
	    lib_error(CATGETS(elm_msg_cat, MeSet,
			      MeExtendedUnknownCommand,		       
			      "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);

    if (parent_LOC)
	postpage(mailbox,aview,parent_page,parent_LOC);

}

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


syntax highlighted by Code2HTML, v. 0.9.1