static char rcsid[] = "@(#)$Id: options.c,v 1.44 2006/04/09 07:37:18 hurtta Exp $";

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

/** This set of routines allows the alteration of a number of paramaters
    in the Elm mailer, including the following;


    a)  arrow-cursor	<on or off>
    b)  border for copy <string for left margin>
    c)  calendar-file	<where to put calendar entries>
    d)  display pager	<how to page messages>
    e)  editor		<name of primary editor or "builtin">
    f)  folder-dir	<folder directory>
    h)  hold sent msgs  <on or off>
  * i) (internal: quit to index screen)
    j)  reply editor    <name of editor for replies>
    k)  pause pager     <on or off>
    l)  alias sort      <how to sort the alias display>
    m)  menu-display    <on or off>
    n)  names-only      <on or off>
    o)  sent-mail	<file to save outbound message copies to>
    p)  printmail	<how to print messages>
  * q) (internal: quit to previous screen)
    r)  reply copy      <on or off>
    s)  sort-by		<how to sort folders>
    t)  text editor     <name of ~e editor>
    u)  user-level	<BEGINNER|INTERMEDIATE|EXPERT>
    v)  visual editor	<name of ~v editor>
    w)  want CC prompt  <on or off>
  * x) (internal: exit ELM now)
    y)  full_username	<your full user name for outgoing mail>
    z)  zap sign dashes <on or off>
	
    And others as they seem useful.

    Formatting parameters:

    _)		Add a blank line
    ^)		Put the title on this line

    A subset of the above parameters may be selected as the
    o)ptions screen using the parameter "configoptions" which is
    a string of letters representing the "key" letter for each
    item as listed above.  The current default is "^_cdefsopyv_am_un".
    The order of the options displayed is as listed in the string.

**/

#include "def_elm.h"
#include "rc_imp.h"
#include "save_opts.h"
#include "s_elm.h"

DEBUG_VAR(Debug,__FILE__,"ui");

#undef onoff
#define   onoff(n)	(n == 1? on_name : off_name)

static void  on_or_off P_((int *var, int x, int y,
			   struct menu_context  *page));
static void one_liner         P_((char *string,
				  struct menu_context *page));
static void sort_one_liner   P_((int sorting_by,
				 struct menu_context *page));
static void alias_sort_one_liner P_((int sorting_by,
				     struct menu_context *page));
static int change_sort P_((struct dt_sort_info *var, int x, int y,
			   struct MailboxView *mailbox,
			   struct AliasView *aview,
			   struct menu_context *page));
static int info_enter P_((char *name, int ypos, int xpos, int append_current, 
			  int passwd, struct MailboxView *mailbox,
			  struct AliasView *aview,
			  struct menu_context *page));

/* new page context assumed */
static void display_options P_((struct menu_context *page));

static void options_help P_((struct menu_context *page));

static char *on_name = NULL;
static char *off_name = NULL;
static int resort = 0;


static int post_sort P_((int f));
static int post_sort(f)
     int f;
{
    if (f) {
	
	resort++;
    }
    return 0;
}


opts_menu cfg_opts[] = {

{'a', "A)rrow cursor",	ElmOptionArrowMenu,  "arrow",	NULL,
"This defines whether the ELM cursor is an arrow or a highlight bar.", ElmOptionArrowHelp},

{'b', "B)order on copy", ElmOptionBorderMenu,	"prefix",	NULL,
"Left margin string (prefix) for reply and forward.", ElmOptionBorderHelp},

#ifdef ENABLE_CALENDAR
{'c', "C)alendar file", ElmOptionCalendarMenu,	"calendar",	NULL,
"This is the file where calendar entries from messages are saved.", ElmOptionCalendarHelp},
#endif

{'d', "D)isplay mail using", ElmOptionDisplayMenu,	"pager",  NULL,
"This is the program invoked to display individual messages (try 'builtin').", ElmOptionDisplayHelp},

{'e', "E)ditor (primary)", ElmOptionEditorMenu,	"editor",	NULL,
"This is the editor used for all outbound messages (may be 'builtin').", ElmOptionEditorHelp},

{'f', "F)older directory", ElmOptionFolderMenu,	"maildir",	NULL,
"This is the folders directory used when '=' (etc) is used in filenames.", ElmOptionFolderHelp},

{'h', "H)old sent message", ElmOptionHoldMenu,	"copy",		NULL,
"Whether to save a copy of outbound messages in O)utbound folder.", ElmOptionHoldHelp},

{'j', "J) reply editor", ElmOptionJreplyMenu,	"alteditor",	NULL,
"This is the editor that will be used for replies (Editor=\"builtin\").", ElmOptionJreplyHelp},

{'k', "K) pause after pager", ElmOptionKpauseMenu, "promptafter",	NULL,
"Whether to pause (prompt) at end of message with display message pager.", ElmOptionKpauseHelp},

{'l', "A(l)ias Sorting", ElmOptionaLiasMenu,	"aliassortby",	post_sort,
"This is used to specify the sorting criteria for the alias display.", ElmOptionaLiasHelp},

{'m', "M)enu display", ElmOptionMenuMenu,	"menu",		NULL,
"This determines if you have the mini-menu displayed or not.", ElmOptionMenuHelp},

{'n', "N)ames only", ElmOptionNameMenu,		"names",	NULL,
"Whether to display the names and addresses on mail, or names only.", ElmOptionNameHelp},

{'o', "O)utbound mail saved", ElmOptionOutboundMenu, "sentmail",	NULL,
"This is where copies of outbound messages are saved automatically.", ElmOptionOutboundHelp},

{'p', "P)rint mail using", ElmOptionPrintMenu,	"print",	NULL,
"This is the command used to print mail messages.", ElmOptionPrintHelp},

{'r', "R)eply copies msg", ElmOptionReplyMenu,	"autocopy",	NULL,
"Whether to copy the message being replied to into the reply.", ElmOptionReplyHelp},

{'s', "S)orting criteria", ElmOptionSortMenu,	"sortby",	post_sort,
"This is used to specify the sorting criteria for the folders.", ElmOptionSortHelp},

{'t', "T)ext editor (~e)", ElmOptionTextMenu,	"easyeditor",	NULL,
"This is the editor that will be used by the ~e command (Editor=\"builtin\").", ElmOptionTextHelp},

{'u', "U)ser level", ElmOptionUserMenu,		"userlevel",	NULL,
"The level of knowledge you have about the ELM mail system.", ElmOptionUserHelp},

{'v', "V)isual Editor (~v)", ElmOptionVisualMenu,	"visualeditor",	NULL,
"This is the editor that will be used by the ~v command (Editor=\"builtin\").", ElmOptionVisualHelp},

{'w', "W)ant Cc: prompt", ElmOptionWantMenu,	"askcc",	NULL,
"Whether to ask for \"Copies to:\" list when sending messages.", ElmOptionWantHelp},

{'y', "Y)our full name", ElmOptionYourMenu,	"fullname",	NULL,
"When mail is sent out, this is what your full name will be recorded as.", ElmOptionYourHelp},

{'z', "Z) signature dashes", ElmOptionZdashMenu,	"sigdashes",	NULL,
"Whether to print dashes before including signature on outbound messages.", ElmOptionZdashHelp},

{ 0 } };

void init_opts_menu()
{
	register char *c;
	register opts_menu *o;

	for (o = cfg_opts; o->parm; o++) {
		c = catgets(elm_msg_cat, ElmSet, o->menu_msg, "~");
		if (*c != '~')
			o->menu = c;

		c = catgets(elm_msg_cat, ElmSet, o->one_liner_msg, "~");
		if (*c != '~')
			o->one_liner = c;
	}
}


opts_menu *
find_cfg_opts(c)
int c;
{
	register opts_menu *o;

	for (o = cfg_opts; o->parm; o++) {
	if (c == o->letter)
	    break;
    }

    return(o->parm ? o : NULL);
}

static char * one_liner_for P_((int c));
static char * one_liner_for(c)
     int c;
{
    opts_menu *o;

    o = find_cfg_opts(c);

    if (o)
	return(o->one_liner);
    else
	return(NULL);
}

static void display_options(page)
     struct menu_context *page;
{
	/** Display all the available options.. **/
	
	int printed_title = FALSE;
	int y;
	opts_menu *o;
	char *s;
	int LINES, COLUMNS;

	menu_get_sizes(page,&LINES, &COLUMNS);
	
	menu_ClearScreen(page);

	for (s = config_options, y = 0; *s; s++, y++) {
	    if (*s == '^') {
		printed_title = TRUE;
		print_format_center(y, 
				    CATGETS(elm_msg_cat, ElmSet, 
					    ElmOptionsEditor,
					    "-- ELM Options Editor --"));
		continue;
	    }
	    if (*s == '_') {
		continue;
	    }
            o = find_cfg_opts(*s);
            if (o != NULL && y<LINES-6) {
	      PutLineX(y, 0, FRM("%-20.20s : %s"), 
		       o->menu,
		       str_opt_nam(o->parm, FULL));
		}
	    }
	if (!printed_title) {
	    print_format_center(LINES-6, 
				CATGETS(elm_msg_cat, ElmSet, 
					ElmOptionsEditor,
					"-- ELM Options Editor --"));
	}
}


static void options_help(page)
     struct menu_context *page;
{
	/** help menu for the options screen... **/

	char	*ptr, *prompt;
	int	c;
	int LINES, COLUMNS;

	menu_get_sizes(page,&LINES, &COLUMNS);

	ClearLine(LINES-3);		/* clear option prompt message */
	print_format_center(LINES-4, 
			    CATGETS(elm_msg_cat, ElmSet, ElmPressKeyHelp,
				    "Press the key you want help for, '?' for a key list, or '.' to exit help"));
	
	/* FIXME */
	lower_prompt(prompt = catgets(elm_msg_cat, ElmSet, ElmKeyPrompt, "Key : "));

	while ((c = menu_ReadCh(page,0|READCH_sig_char|READCH_CURSOR)) != '.') {
	    if (c == EOF)
		leave(0);
	    
	    if (c == TERMCH_interrupt_char)
		break;

#ifdef ASCII_CTYPE
	  if (isascii(c))
#endif
	    c = tolower(c);

	  if (c == '?') {
	     display_helpfile(OPTIONS_HELP);
	     display_options(page);
	     return;
	  }

	  if ((ptr = one_liner_for(c)) != NULL)
	    lib_transient(FRM("%c = %s"), c, ptr);
	  else
	    switch (c) {
	      case ctrl('L'): lib_transient(CATGETS(elm_msg_cat, ElmSet,
						ElmOptionCtrlLHelp,
						"^L = Rewrite the screen."));
	      break;

	      case '>' : lib_transient(CATGETS(elm_msg_cat, ElmSet,
					   ElmOptionGreaterHelp,
					   "> = Save to elmrc file."));
	      break;

	      case 'q' :
	      case 'i' : lib_transient(CATGETS(elm_msg_cat, ElmSet, 
					   ElmOptionReturnHelp,
					   "i,q = Return from option menu."));
	      break;

	      case 'x' : lib_transient(CATGETS(elm_msg_cat, ElmSet, 
					   ElmHelpQuickExit,
					   "X = Exit leaving the folder untouched, unconditionally."));
				break;

	      default: lib_error(CATGETS(elm_msg_cat, ElmSet, ElmKeyIsntUsed,
					 "That key isn't used in this section."));
	    }
	  lower_prompt(prompt);
	}
	ClearLine(LINES-4);		/* clear Press help key message */
	ClearLine(LINES-2);		/* clear lower prompt message */
}


char * level_name(n)
     int n;
{
	/** return the 'name' of the level... **/

	switch (n) {
	  case 0 : return(catgets(elm_msg_cat, ElmSet, ElmBeginningUser,
			"Beginning User   "));
	  case 1 : return(catgets(elm_msg_cat, ElmSet, ElmIntermediateUser,
			"Intermediate User"));
	  default: return(catgets(elm_msg_cat, ElmSet, ElmExpertUser,
			"Expert User      "));
	}
}

int options(mailbox,aview)
     struct MailboxView *mailbox;
     struct AliasView *aview;
{
    /** change options... **/
    /* return:
     *	> 0	if resort was done - to indicate we might need to
     *	 	change the page of our headers as a consequence
     *		of the new sort order
     *	< 0	if user entered 'X' to quit elm immediately
     *	0	otherwise
     */
    
    int	ch,
	y;
    opts_menu *o;

    
    struct menu_context *page = new_menu_context();
    int LINES, COLUMNS;
    
    menu_get_sizes(page,&LINES, &COLUMNS);


    if (on_name == NULL) {
	on_name = catgets(elm_msg_cat, ElmSet, ElmOn, "ON ");
	off_name = catgets(elm_msg_cat, ElmSet, ElmOff, "OFF");
    }
    if (!config_options[0]) {
#ifdef ENABLE_CALENDAR
	strfcpy(config_options,"^_cdefsopyv_am_un",
		sizeof config_options);
#else
	strfcpy(config_options,"^_defsopyv_am_un",
		sizeof config_options);
#endif
    }

 redraw:
 resize_mark:
    if (menu_resized(page)) {
	
	menu_get_sizes(page,&LINES, &COLUMNS);
	  
    } else if (menu_need_redraw(page))
	/* do nothing */

    resort = 0;
    
    display_options(page);
    
    
    while(1) {
	char * x;
	ClearLine(LINES-5);
	
	print_format_center(LINES-5, 
			    CATGETS(elm_msg_cat, ElmSet, 
				    ElmSelectOptionLetter,
				    "Select letter of option line, '>' to save, or 'i' to return to index."));
	
	menu_PutLineX(page,
		      LINES-3, 0, 
		      CATGETS(elm_msg_cat, ElmSet, ElmPrompt, "Command: "));
	
	ch = menu_ReadCh(page, REDRAW_MARK|READCH_resize|READCH_CURSOR);
	if (ch == REDRAW_MARK)
	    goto redraw;
	if (ch == EOF) {
	    erase_menu_context(&page);
	    leave(0); 
	}

	if (ch == RESIZE_MARK) {
	    DPRINT(Debug,4, (&Debug, "     .... resizing\n"));
	    goto resize_mark;
	}

#ifdef ASCII_CTYPE
	if (isascii(ch))
#endif
	    ch = tolower(ch);

	clear_error();	/* remove possible "sorting" message etc... */ 

	if (NULL != (x = index(config_options, ch))) {
	    y = x - config_options;
	    o = find_cfg_opts(ch);
	    if (o != NULL && y < LINES-6) {
		one_liner(o->one_liner,page);
		y = info_enter(o->parm, y, 23, FALSE, FALSE, mailbox, aview,
			       page);
		if (o->post)
		    (o->post)(y);

		if (!y) { /* FAILED -- REDRAW */
		    goto redraw;
		}


	    } else
		lib_error(CATGETS(elm_msg_cat, ElmSet, ElmCommandUnknown,
				  "Command unknown!"));
	} else {
	    one_liner(NULL, page);
	    switch (ch) {
	    case '?' : options_help(page); 

		PutLineX(LINES-3,0, 
			 CATGETS(elm_msg_cat, ElmSet, ElmPrompt, "Command: "));
		break;
		
	    case '>' : lib_error(CATGETS(elm_msg_cat, ElmSet, ElmSaveOptions,
					 "Save options in .elm/elmrc..."));
	        FlushBuffer();    save_options();		break;
	    
	    case 'x' :	
		erase_menu_context(&page);
		return(-1);	/* exit elm */
	    case 'q' :	/* pop back up to previous level, in this case == 'i' */
	    case 'i' :  /* return to index screen */
		erase_menu_context(&page);
		return(resort ? 1 : 0);
	    case ctrl('L'): 
		display_options(page);				
		break;
	    default: lib_error(CATGETS(elm_msg_cat, ElmSet, ElmCommandUnknown,
				       "Command unknown!"));
	      }
	  }
	}
}


static void  on_or_off(var, x, y, page)
     int *var, x,y;
     struct menu_context  *page;
{
	/** 'var' field at x.y toggles between on and off... **/

	int ch;
	int oldvar = *var;

     	menu_PutLineX(page,
		      x, y+6, 
		      CATGETS(elm_msg_cat, ElmSet, ElmUseSpaceToToggle,
			      "(use <space> to toggle, any other key to leave)"));

	menu_MoveCursor(page,x,y+3);	/* at end of value... */
	
	do {
	    ch = menu_ReadCh(page,READCH_sig_char|READCH_CURSOR);
	    
	    if (ch == TERMCH_interrupt_char) {
		*var = oldvar;
		break;
	    }

	    if (ch == SPACE) {
		*var = ! *var;
		menu_PutLine0(page,x,y, onoff(*var));
	    }
	} while (ch == SPACE);
	
	menu_MoveCursor(page,x,y+4); 	
	menu_CleartoEOLN(page);	/* remove help prompt */
}


static void change_enum P_((struct dt_enumerate_info *enumeration,
			    int x, int y,
			    struct menu_context  *page));
static void change_enum(enumeration, x, y, page)
     struct dt_enumerate_info *enumeration;
     int x, y;
     struct menu_context  *page;
{
    int c;
    int val = enumeration->val;

    menu_PutLineX(page,
		  x,y, FRM("%s"), 
		  give_dt_enumerate_as_str(enumeration));
    menu_CleartoEOLN(page);
    
    menu_PutLineX(page,
		  x, y+20, 
		  CATGETS(elm_msg_cat, ElmSet, ElmSpaceToChange,
			  "<space> to change"));

    menu_MoveCursor(page,
		    x,y);	/* at end of value... */

    while ((c = menu_ReadCh(page,0)) == ' ') {

	val = (val +1 ) % enumeration->nlen;

	menu_PutLineX(page,
		      x,y, FRM("%s"), enumeration->list[val]);

	menu_CleartoEOLN(page);
	
	menu_PutLineX(page,
		      x, y+20, 
		      CATGETS(elm_msg_cat, ElmSet, ElmSpaceToChange,
			      "<space> to change"));

	menu_MoveCursor(page,
			x,y);	/* at end of value... */	
    }

    if (c == TERMCH_interrupt_char) {
    fail:
	menu_PutLineX(page,
		      x,y, FRM("%s"), 
		      give_dt_enumerate_as_str(enumeration));
	menu_CleartoEOLN(page);
	return;
    }

    if (c != '\n') {
	char buffer[SLEN+1];
	int code;

	menu_MoveCursor(page,
			x,y);	/* at end of value... */	
	menu_CleartoEOLN(page);

	buffer[0] = c;
	buffer[1] = '\0';

	code = optionally_enter(buffer, x,y,
				OE_SIG_CHAR|OE_REDRAW_MARK|OE_APPEND_CURRENT,
			 sizeof buffer,page);

	if (0 != code)     /* Ctrl-C, error or REDRAW_MARK*/
	    goto fail;

	if (! set_dt_enumerate_as_str(enumeration,buffer))
	    goto fail;
    } else
	enumeration->val = val;	

    menu_PutLineX(page,
		  x,y, FRM("%s"), 
		  give_dt_enumerate_as_str(enumeration));
    menu_CleartoEOLN(page);
    return;    
}


static int change_sort(var, x, y, mailbox, aview, page)
     struct dt_sort_info *var;
     int x,y;
     struct MailboxView *mailbox;
     struct AliasView *aview;
     struct menu_context *page;
{
    /** change the sorting scheme... **/
    /** return !0 if new sort order, else 0 **/
    
    int last_sortby,	/* so we know if it changes... */
	sign = 1;		/* are we reverse sorting??    */
    int ch;			/* character typed in ...      */

    int last_unstable   = unstable_reverse_thread;
	
    int LINES, COLUMNS;
    int z,lastval=0;

    menu_get_sizes(page,&LINES, &COLUMNS);

    /* mailbox sort values are not in order! */
    for (z = 0; var->sortval[z].kw; z++)
	if (lastval < var->sortval[z].sv)
	    lastval = var->sortval[z].sv;


/*	*var = sortby; 	or...	*var == sortby; 	*/
    last_sortby = var->val;	/* remember current ordering   */


    if (var != &sortby ||
	var->val != REVERSE THREAD)
	menu_PutLineX(page,x, COLUMNS-30, 
		      CATGETS(elm_msg_cat, ElmSet, ElmSpaceForNext,
			      " (SPACE for next, or R)everse)"));
    else
	menu_PutLineX(page,x, COLUMNS-30, 
		      CATGETS(elm_msg_cat, ElmSet, ElmReverseUnstable,
			      "(SPACE, R)everse or U)nstable)"));

    if (var == &sortby) {
	PutLine0(x, y, sort_name(PAD));	   
	sort_one_liner(var->val, page);
    } 
    else if (var == &alias_sortby) {
	PutLine0(x, y, alias_sort_name(PAD));	   
	alias_sort_one_liner(var->val,page);
    }
    else {
	PutLine0(x, y, give_dt_sort_as_str(var));	   
	menu_CleartoEOLN(page);
	menu_PutLineX(page,x, COLUMNS-30, 
		      CATGETS(elm_msg_cat, ElmSet, ElmSpaceForNext,
			      " (SPACE for next, or R)everse)"));
    }

    menu_MoveCursor(page,x, y);
    
    do {
	int o = var->val;
	
	ch = menu_ReadCh(page, READCH_sig_char|READCH_CURSOR);
	
	if (ch == TERMCH_interrupt_char) {
	    var->val             = last_sortby;
	    unstable_reverse_thread = last_unstable;
	    break;
	}

#ifdef ASCII_CTYPE
	if (isascii(ch))
#endif
	    ch = tolower(ch);

	switch (ch) {
	case SPACE : 
	    if (var->val < 0) { 
		sign = -1; 
		var->val = - var->val; 
	    } else 
		sign = 1;		/* insurance! */

	    var->val = sign * ((var->val + 1) % (lastval+1));
	    if (var->val == 0 &&
		var->sortval[0].sv != 0) 
		var->val = sign;  /* snicker */
	    
	    if (var == &sortby) {
		PutLine0(x, y, sort_name(PAD));
		sort_one_liner(var->val, page);
	    } else if (var == &alias_sortby) {
		PutLine0(x, y, alias_sort_name(PAD));	   
		alias_sort_one_liner(var->val,page);
	    } else {
		PutLine0(x, y, give_dt_sort_as_str(var));	   
		menu_CleartoEOLN(page);
		menu_PutLineX(page,x, COLUMNS-30, 
			      CATGETS(elm_msg_cat, ElmSet, ElmSpaceForNext,
				      " (SPACE for next, or R)everse)"));
	    }

	    MoveCursor(x, y);
	    break;
	    
	case 'r'   : 
	    var->val = - var->val;

	    if (var == &sortby) {
		PutLine0(x, y, sort_name(PAD));
		sort_one_liner(var->val, page);
	    }
	    else if (var == &alias_sortby) {
		PutLine0(x, y, alias_sort_name(PAD));	   
		alias_sort_one_liner(var->val,page);
	    }	    
	    else
	    {
		PutLine0(x, y, give_dt_sort_as_str(var));	   
		menu_CleartoEOLN(page);
		menu_PutLineX(page,x, COLUMNS-30, 
			      CATGETS(elm_msg_cat, ElmSet, ElmSpaceForNext,
				      " (SPACE for next, or R)everse)"));
	    }
	    
	    MoveCursor(x, y);
	    
	    break;
	    
	  case 'u': 
	      if (var == &sortby &&
		  var->val == REVERSE THREAD) {
		  
		  unstable_reverse_thread = !unstable_reverse_thread;
		  PutLine0(x, y, sort_name(PAD));
		  sort_one_liner(var->val, page);
		  MoveCursor(x, y);
		  		  
	      }
	      break;
	}

	if (var == &sortby &&
	    ( o     == REVERSE THREAD ||
	      var->val == REVERSE THREAD)) {
	    
	    if (var->val != REVERSE THREAD)
		menu_PutLineX(page,x, COLUMNS-30, 
			      CATGETS(elm_msg_cat, ElmSet, ElmSpaceForNext,
				      " (SPACE for next, or R)everse)"));
	    else
		menu_PutLineX(page,x, COLUMNS-30, 
			      CATGETS(elm_msg_cat, ElmSet, ElmReverseUnstable,
				      "(SPACE, R)everse or U)nstable)"));
	    MoveCursor(x, y);
	    
	}

    } while (ch == SPACE || ch == 'r' || ch == 'u');

    menu_MoveCursor(page,x, COLUMNS-30);	
    menu_CleartoEOLN(page);

    ClearLine(LINES-3);		/* clear sort_one_liner()! */
    
    if (var == &sortby && 
	(var->val != last_sortby ||
	 unstable_reverse_thread != last_unstable)) {

    	lib_error(CATGETS(elm_msg_cat, ElmSet, ElmResortingFolder,
			  "Resorting folder..."));
	if (sleepmsg > 0) {
	    error_sleep((sleepmsg + 1) / 2);
	}
	sort_mailbox(get_message_count(mailbox), 0, mailbox);
	
	
	if (unstable_reverse_thread != last_unstable) {
	    mark_local_changed(&unstable_reverse_thread);
	}
	return 1;
    }

    if (var == &alias_sortby && 
	var->val != last_sortby) {
	lib_error(CATGETS(elm_msg_cat, ElmSet, ElmResortingAliases,
			  "Resorting aliases..."));
	if (sleepmsg > 0) {
	    error_sleep((sleepmsg + 1) / 2);
	}
	
	sort_aliases(get_alias_count(aview), FALSE, FALSE, aview);
	
	return 1;
    }

    return(var->val != last_sortby);
}

static void one_liner(string, page)
     char *string;
     struct menu_context *page;
{
	/** A single-line description of the selected item... **/
    int LINES, COLUMNS;

    menu_get_sizes(page,&LINES, &COLUMNS);
    
    ClearLine(LINES-5);
    if (string)
	Centerline(LINES-5, string, page);
}

static void sort_one_liner(sorting_by, page)
     int sorting_by;
     struct menu_context *page;
{
	/** A one line summary of the particular sorting scheme... **/
    int LINES, COLUMNS;
    
    menu_get_sizes(page,&LINES, &COLUMNS);

	ClearLine(LINES-3);

	switch (sorting_by) {
	  
	  case REVERSE SENT_DATE:	
	      print_format_center(LINES-3,
				  CATGETS(elm_msg_cat, ElmSet, 
					  ElmSortRSentDate,
					  "This sort will order most-recently-sent to least-recently-sent"));
				break;
	  case REVERSE THREAD:	
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortRThread,
					  "This sort will order most-recent-thread to least-recent-thread"));
				break;
	  case REVERSE RECEIVED_DATE:	
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, 
					  ElmSortRRecvDate,
					  "This sort will order most-recently-received to least-recently-received"));
				break;
	  case REVERSE MAILBOX_ORDER:	
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortRMailbox,
					  "This sort will order most-recently-added-to-folder to least-recently"));
				break;
	  case REVERSE SENDER:		
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortRSender,
					  "This sort will order by sender name, in reverse alphabetical order"));
				break;
	  case REVERSE SIZE:	      
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortRSize,
					  "This sort will order messages by longest to shortest"));
				break;
	case REVERSE SUBJECT:		
	    print_format_center(LINES-1-2,
				CATGETS(elm_msg_cat, ElmSet, ElmSortRSubject,
					"This sort will order by subject, in reverse alphabetical order"));
				break;
	  case REVERSE STATUS:		
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortRStatus,
					  "This sort will order by reverse status - Deleted through Tagged..."));
	      break;
	  case SENT_DATE:		
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortSentDate,
					  "This sort will order least-recently-sent to most-recently-sent"));
				break;
	  case THREAD:		
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortThread,
					  "This sort will order least-recent-thread to most-recent-thread"));
 				break;
	  case RECEIVED_DATE:		
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortRecvDate,
					  "This sort will order least-recently-received to most-recently-received"));
				break;
	case MAILBOX_ORDER:		
	    print_format_center(LINES-1-2,
				CATGETS(elm_msg_cat, ElmSet, ElmSortMailbox,
					"This sort will order least-recently-added-to-folder to most-recently"));
				break;
	  case SENDER:			
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortSender,
					  "This sort will order by sender name"));
	      break;
	  case SIZE:			
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortSize,
					  "This sort will order messages by shortest to longest"));
	      break;
	  case SUBJECT:		       
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortSubject,
					  "This sort will order messages by subject"));
	      break;
	  case STATUS:		       
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmSortStatus,
					  "This sort will order by status - Tagged through Deleted..."));
	      break;
	}
}


static void alias_sort_one_liner(sorting_by,page)
     int sorting_by;
     struct menu_context *page;
{
	/** A one line summary of the particular sorting scheme... **/
    int LINES, COLUMNS;

    menu_get_sizes(page,&LINES, &COLUMNS);

    ClearLine(LINES-3);

	switch (sorting_by) {
	  
	  case REVERSE ALIAS_SORT:	
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmASortRAlias,
					  "This sort will order by alias name, in reverse alphabetical order"));
	      break;
	  case REVERSE NAME_SORT:	
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmASortRName,
					  "This sort will order by user (real) name, in reverse alphabetical order"));
	      break;
	  case REVERSE TEXT_SORT:	
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmASortRText,
					  "This sort will order aliases in the reverse order as listed in aliases.text"));
	      break;

	  case ALIAS_SORT:		
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmASortAlias,
					  "This sort will order by alias name"));
	      break;
	case NAME_SORT:		
	    print_format_center(LINES-1-2,
				CATGETS(elm_msg_cat, ElmSet, ElmASortName,
"This sort will order by user (real) name"));
	    break;
	  case TEXT_SORT:		
	      print_format_center(LINES-1-2,
				  CATGETS(elm_msg_cat, ElmSet, ElmASortText,
					  "This sort will order aliases in the order as listed in aliases.text"));
	      break;
	}
}

/*
 * This routine is a "shell" to optionally_enter(), etc. so that
 * we can use save_info structure and tag the param as being changed
 * locally (so we know to save it to the .elm/elmrc file).
 */
static int info_enter(name, ypos, xpos, append_current, passwd, mailbox,
		      aview, page)
     char *name;
     int ypos, xpos, append_current, passwd;
     struct MailboxView *mailbox;
     struct AliasView *aview;
     struct menu_context *page;
{
    int x,q = 0;
    char buffer[SLEN+1];
    int number;
    int LINES, COLUMNS;

    menu_get_sizes(page,&LINES, &COLUMNS);

    for (x = 0; x < NUMBER_OF_SAVEABLE_OPTIONS; x++) {
	q = strcmp(name, save_info[x].name);
	if (q <= 0)
	    break;
    }

    if (q)
	return(1);
    
    if (&rc_DT_SORT == save_info[x].dt_type) {
	if (change_sort(save_info[x].val.sort, 
			ypos, xpos, mailbox, aview,page) != 0) {
	    ++q;
	}


    } else if (DT_BOL == save_info[x].dt_type) {
	number = *SAVE_INFO_BOL(x);
	on_or_off(&number, ypos, xpos, page);

	if (number != *SAVE_INFO_BOL(x)) {
	    *SAVE_INFO_BOL(x) = number;
	    ++q;
	}
	
    } else if (&rc_DT_ENUM == save_info[x].dt_type) {

	change_enum(save_info[x].val.enumerate, ypos, xpos, page);

    } else {   /* Hopefully generic routine ... */
	int code;
	char * s;
	
	if (RCTYPE_magic != save_info[x].dt_type->magic)
	    panic("RC PANIC",__FILE__,__LINE__,"info_enter",
		  "Bad config item type",0);

	s = save_info[x].dt_type->get_value(& save_info[x]);

	if (s)
	    strfcpy(buffer,s, sizeof buffer);
	else
	    buffer[0] = '\0';

	code = optionally_enter(buffer, ypos, xpos, 
				(append_current ? OE_APPEND_CURRENT : 0) |
				(passwd ? OE_PASSWD : 0) |
				OE_SIG_CHAR|OE_REDRAW_MARK,
			 sizeof buffer,page);

	if (0 != code)     /* Ctrl-C, error or REDRAW_MARK*/
	    return 0;

	if (!s || !equal(buffer,s)) {

	    if (save_info[x].dt_type->parse_line(& save_info[x],
						 1 /* local */ ,buffer,
						 0,"<config editor>",
						 0))
		q++;
	}	    	
    }

    if (q)
	mark_XX(& (save_info[x]));
    
    return(q != 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