static char rcsid[] = "@(#)$Id: browser.c,v 1.46 2006/06/11 17:21:53 hurtta Exp $";

/******************************************************************************
 *  The Elm (ME+) Mail System  -  $Revision: 1.46 $   $State: Exp $
 *
 *  Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
 *****************************************************************************/

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

DEBUG_VAR(Debug,__FILE__,"ui");

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

#define GB_REDRAW    1
#define GB_MENU      2
#define GB_FILL      4
#define GB_HELP      8
#define GB_SAVE_COPY 16
#define GB_HELP2     32
#define GB_EXTENSION 64
#define GB_FILENAME  128

#define GB_FLAGS     py
#define GB_PAGE      counter
#define GB_LINE      px

static void draw_line P_((struct enter_info *I,
			  int i,int lines_per_page));
static void draw_line(I,i,lines_per_page)
     struct enter_info *I;
     int i;
     int lines_per_page;
{
    int flags = 0;

    /* return reference to array -- do not free_string !!! */
    struct string * buffer = 
	give_line_dir(I->dir_p,i,&flags);
    int current = i == I->GB_LINE; 
    int c = '?';
    int LINES,COLUMNS;
    int size;

    menu_get_sizes(I->current_page,&LINES,&COLUMNS);

    size = COLUMNS-5;
    
    switch (flags & (BROWSER_NODIR|BROWSER_NOFOLDER)) {
    case 0:                c = 'd'; break;
    case BROWSER_NODIR:    c = ' '; break;
    case BROWSER_NOFOLDER: c = 'D'; break;
    }
		
    if (current && !arrow_cursor)
	menu_StartXX(I->current_page,pg_INVERSE);
    menu_PutLineX(I->current_page,5 + i % lines_per_page,0,
		  FRM("%.2s%c%c %-*.*S"),
		  current && arrow_cursor ? "->" : "  ",
		  flags & BROWSER_MARKED ? 'N' : ' ',
		  c,size,size,buffer);
    if (current && !arrow_cursor)
	menu_EndXX(I->current_page,pg_INVERSE);
}

static void write_prompt P_((struct enter_info *I));
static void write_prompt(I)
     struct enter_info *I;
{
    int LINES,COLUMNS;
    
    menu_get_sizes(I->current_page,&LINES,&COLUMNS);

    show_last_error();

    menu_PutLineX(I->current_page,LINES-3,0, FRM("%S"),I->pvector[1]);
    if (I->pvector[0])
	menu_Write_to_screen(I->current_page,FRM("%S"),I->pvector[0]);
    menu_CleartoEOLN(I->current_page);
}

int browser_expand(XXX,name,prev_folder,aview)
     struct folder_browser * XXX;
     struct string **name;
     struct string ** prev_folder;
     struct AliasView *aview;
{
    int ret = 0;
    int s_len;

    if (*name && (s_len=string_len(*name)) > 0) {
	switch (give_unicode_from_string(*name,0)) {
	    struct addr_item * address;
	    char *str;
	    int too_long;
		
	case 0x0040: /* '@' -- @alias ... */
	    
	    /* Lousy -- charset not converted... */
	    str = us2s(stream_from_string(*name,0,NULL));
	    address = get_alias_address_l(&(str[1]),
					  FALSE,&too_long,
					  NULL,aview);             
	    free(str); str = NULL;
	    
	    if (address && address[0].addr ) {
		char buffer[LONG_STRING];
		struct string *S1;
		
		/* get filename from address */
		get_return_name(address[0].addr, buffer, 
				TRUE, sizeof buffer);
		
		if (buffer[0]) {
		    S1 = format_string(FRM("=%s"),buffer);
		
		    if (select_dir_item(XXX,&S1)) {
			free_string(&S1);
			if (address)
			    free_addr_items(address);
		    
			ret = 1;
			DPRINT(Debug,4,
			       (&Debug, 
				"-- browser_expand (@alias) OK\n"));
			goto out;
		    }
		    free_string(&S1);
		}
	    }
	    if (address)
		free_addr_items(address);
	    goto out;     /* Alias FAILED */
	    
	case 0x002E: /* '.' */
	    if (1 == s_len) {
		if (prev_folder && *prev_folder &&
		    select_dir_item(XXX, prev_folder)) {
		    
		    ret = 1;
		    DPRINT(Debug,4,
			   (&Debug, 			    
			    "-- browser_expand (. == previous folder) OK\n"));
		    goto out;
		}
		goto out;     /* previous folder */
	    }
	    break;  
	}
	if (select_dir_item(XXX,name))
	    ret = 1;
    }

 out:
	
    DPRINT(Debug,7, (&Debug, 
		     "browser_expand=%d\n",ret));
    
    return ret;    
}

static int cf_english P_((struct enter_info *I));
static int cf_english(I)
     struct enter_info *I;
{
    int s_len;
    int LINES,COLUMNS;

    menu_get_sizes(I->current_page,&LINES,&COLUMNS);

    if (I->pvector[0] && 
	0 == string_len(I->pvector[0])) {
	free_string(&(I->pvector[0]));
    }

    if (!I->pvector[0]) {

	menu_PutLineX(I->current_page,LINES-3,0, FRM("%S"),I->pvector[1]);
	menu_Write_to_screen(I->current_page,
			     CATGETS(elm_msg_cat, ElmSet, ElmNoSave, 
				     "<no save>"));
	menu_CleartoEOLN(I->current_page);
	menu_MoveCursor(I->current_page,
			LINES-3,string_len(I->pvector[1]));
	return 1;

    } else if ((s_len=string_len(I->pvector[0])) > 0) {

	switch (give_unicode_from_string(I->pvector[0],0)) {

	case 0x003D:  /* '='  Handle save copy prompt! */
	    if (1 == s_len) {

		menu_PutLineX(I->current_page,
			      LINES-3,0, FRM("%S"),I->pvector[1]);
		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, 
					     ElmUncondSaveByName, 
					     "<unconditionally save by name>"));
		menu_CleartoEOLN(I->current_page);
		menu_MoveCursor(I->current_page,
				LINES-3,string_len(I->pvector[1]));
		return 1;		

	    } else if (2 == s_len &&
		       give_unicode_from_string(I->pvector[0],1) 
		       == 0x003F /* '?' */) {

		menu_PutLineX(I->current_page,
			      LINES-3,0, FRM("%S"),I->pvector[1]);

		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, 
					     ElmCondSaveByName, 
					     "<conditionally save by name>"));
		menu_CleartoEOLN(I->current_page);
		menu_MoveCursor(I->current_page,
				LINES-3,string_len(I->pvector[1]));
		return 1;		

	    }
	    break;
	case 0x003C: /* '<' */
	    if (1 == s_len) {

		menu_PutLineX(I->current_page,
			      LINES-3,0, FRM("%S"),I->pvector[1]);
		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, 
					     ElmSentFolder, "<\"sent\" folder>"));
		menu_CleartoEOLN(I->current_page);
		menu_MoveCursor(I->current_page,
				LINES-3,string_len(I->pvector[1]));
		return -1;  /* Special prompt but normal expansion */	    
	    }
	    break;
	}
    }
    return 0;
}

static void gb_initial_text P_((struct enter_info *I));
static void gb_initial_text(I)
     struct enter_info *I;
{
    int LINES,COLUMNS;
    int l,l1;
    struct string * S = format_string(CATGETS(elm_msg_cat, ElmSet, 
					      ElmUseForHelp,
					      "(Use '?' for help)"));	    


    /* FIXME: not complete correct -- this do not take account
              double wide characters
    */
    l1 = string_len(S);
    if (l1 < 15)
	l1 = 15;

    menu_get_sizes(I->current_page,&LINES,&COLUMNS);

    l = COLUMNS - l1-5;

    if (l < 45) {
	

	menu_MoveCursor(I->current_page,
			LINES-4, 0);
	menu_CleartoEOS(I->current_page);

	if (l < -5)
	    l = -5;

    } else {
	menu_MoveCursor(I->current_page,
			LINES-4, l);
	menu_CleartoEOS(I->current_page);
	
    }

    show_last_error();
    	
    menu_PutLineX(I->current_page,
		  LINES-4, l+5, FRM("%S"),
		  S);

    free_string(&S);
}

static void gb_initial_non_append P_((struct enter_info *I));
static void gb_initial_non_append(I)
     struct enter_info *I;
{
    int LINES,COLUMNS;

    menu_get_sizes(I->current_page,&LINES,&COLUMNS);

    menu_PutLineX(I->current_page,
		  LINES-3,0, FRM("%S"),I->pvector[1]);

    if (I->pvector[0]) {

	menu_Write_to_screen(I->current_page,
			     FRM("%S"),I->pvector[0]);
	menu_CleartoEOLN(I->current_page);
	menu_MoveCursor(I->current_page,
			LINES-3,string_len(I->pvector[1]));

    }
}

static void gb_initial_title P_((struct enter_info *I,struct string * buffer));
static void gb_initial_title(I,buffer)
     struct enter_info *I;
     struct string * buffer;
{

    menu_ClearScreen(I->current_page);
    menu_print_center(I->current_page,1,buffer);

}

static void browser_help P_((struct enter_info *I));
static void browser_help(I)
     struct enter_info *I;
{

    menu_Write_to_screen(I->current_page,
			 CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg7N,
				 "You may get directory listing by giving directory name and pressing TAB key.\n\r"));
	    
    menu_Write_to_screen(I->current_page,
			 CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg8N,
				 "Pressing LEFT key fills buffer with current directory name and \n\r"));
    menu_Write_to_screen(I->current_page,
			 CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg9N,
				 "pressing RIGTH key fills buffer with current selection. \n\r"));
    menu_Write_to_screen(I->current_page,
			 CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg10N,
				 "UP and DOWN keys changes current selection on directory listing.\n\r"));
    
}

static void gb_dir_title P_((struct enter_info *I,int *entries));
static void gb_dir_title(I,entries)
     struct enter_info *I;
     int *entries;
{
    struct string * buffer = give_title_dir(I->dir_p,entries);

    menu_PutLineX(I->current_page,3,0,FRM("%S"),buffer);  
    menu_CleartoEOLN(I->current_page);

    menu_MoveCursor(I->current_page,4,0);                 
    menu_CleartoEOLN(I->current_page);
	
    free_string(&buffer);    
}

static void sort_message P_((struct string *message));
static void sort_message(message)
     struct string *message;
{
    if (message)
	lib_transient(FRM("%S"),message);
    else
	clear_error();
}

static struct string **gb_browser P_((struct enter_info *I,
				      enum enter_mode em,
				      struct menu_context *base_page));

static struct string **gb_browser(I,em, base_page)
     struct enter_info *I;
     enum enter_mode em;
     struct menu_context *base_page;
{
    int sort_it = 0;
    int append_current = 0 != (I->flags & OE_APPEND_CURRENT);
    int LINES,COLUMNS;

    menu_get_sizes(I->current_page,&LINES,&COLUMNS);

    switch(em) {
    case em_redraw:
	I->GB_FLAGS |= GB_REDRAW ;     
    }

    switch(em) {
	int s_len;
    case em_redraw_initial:
	
	/* POP/IMAP client code will prompt messages to same area
	   so we re-print prompt every time ... */

	if (0 != (GB_SAVE_COPY & I->GB_FLAGS)) {
	    menu_MoveCursor(I->current_page,LINES-3,0);
	    menu_CleartoEOS(I->current_page);

	    show_last_error();	    

	} else {
	    gb_initial_text(I);
	}

	if (!append_current) {
	    if (0 == (GB_SAVE_COPY & I->GB_FLAGS) ||
		cf_english(I) == 0) {
		gb_initial_non_append(I);
	    }
	    I->ch_count = 0;

	    DPRINT(Debug,4,
		   (&Debug, 
		    "-- gb_browser(..,%d)=non null  (initial prompt)\n",
		    em));
	    return &(I->pvector[0]);
	}
	/* FALLTHRU */

    case em_redraw: 
    repage:

	if (0 != (I->GB_FLAGS & GB_MENU))
	    I->GB_FLAGS |= GB_REDRAW;

	if (0 != (I->GB_FLAGS & GB_HELP))
	    I->GB_FLAGS |= GB_REDRAW;


	if (0 != (I->GB_FLAGS & GB_REDRAW)) {

	    struct string * buffer = 
		format_string(CATGETS(elm_msg_cat, ElmSet,
				      ElmFolderSelection,
				      "Folder selection"));

	    if (I->current_page == base_page)
		I->current_page = new_menu_context();

	    gb_initial_title(I,buffer);
	    free_string(&buffer);
	}

 	if (0 != (I->GB_FLAGS & GB_HELP2) &&
 	    0 != (I->GB_FLAGS & GB_HELP)) {	        
 
	    menu_MoveCursor(I->current_page,3,0);    
	    menu_CleartoEOS(I->current_page);
 
 	    browser_help(I);
  
 	    I->GB_FLAGS &= ~GB_HELP2;
 
 	} else if (0 != (I->GB_FLAGS & GB_HELP)) {	        
 	    int line,col;
	        

	    menu_MoveCursor(I->current_page,3,0);    
	    menu_CleartoEOS(I->current_page);

	    if (0 != (GB_SAVE_COPY & I->GB_FLAGS)) {
		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, ElmListFoldersHelp1,
"Enter: <nothing> to not save a copy of the message,\n\
\r       '<'       to save in your \"sent\" folder ("));

		{
		    char * sent_val = give_dt_estr_as_str(&sent_mail_e,"sentmail");

		    menu_Write_to_screen(I->current_page,
					 FRM("%s"), 
					 sent_val ? sent_val : "none");
		}

		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, 
					     ElmListFoldersHelp2,
					"),\n\
\r       '='       to save by name (the folder name depends on whom the\n\
\r                     message is to, in the end),\n\
\r       '=?'      to save by name if the folder already exists,\n\
\r                     and if not, to your \"sent\" folder,\n\
\r       or a filename (a leading '=' denotes your folder directory).\n\r\n\r"
					));
	    } else {

		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg1,
					     "You must specify a file or folder to "));
	    
		menu_Write_to_screen(I->current_page,
				     FRM("%S"),I->pvector[2]);
	    	    	   		    
		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg2,
					     " to.  Several options\n\rare available:\n\r\
\n\r  '!'  will use your incoming mailbox ("));
		
		{
		    char * default_val = give_dt_estr_as_str(&defaultfile_e,"incoming-mailbox");
		    
		    if (default_val)
			menu_Write_to_screen(I->current_page,
					     FRM("%s"),default_val);
		}

		{
		    char * recvd_val = 
			give_dt_estr_as_str(&recvd_mail_e,"receivedmail");
		    if (recvd_val) {
			menu_Write_to_screen(I->current_page,
					     CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg3,
						     ")\n\r  '>'  will use your \"received\" folder ("));


			menu_Write_to_screen(I->current_page,
					     FRM("%s"),recvd_val);
		    }
		}

		{
		    char * sent_val = give_dt_estr_as_str(&sent_mail_e,"sentmail");

		    if (sent_val) {
			menu_Write_to_screen(I->current_page,
					     CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg4,
						     ")\n\r  '<'  will use your \"sent\" folder ("));




			
			menu_Write_to_screen(I->current_page,
					     FRM("%s"), sent_val);
		    }
		}

		if (I->pvector[3]) {
		    menu_Write_to_screen(I->current_page,
					 CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg5,
						 ")\n\r  '.' will use the previous folder ("));
		    menu_Write_to_screen(I->current_page,
					 FRM("%S"), I->pvector[3]);
		}

		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg6,
					     ")\n\r  '@alias' will use the default folder for \"alias\"\n\r\n\r\
If you enter a filename elm will use that file.  If the file name begins\n\r\
with a '=', elm will look for the file in your folder directory\n\r\
(your folder directory is "));

		{
		    /* give_dt_estr_as_str adds / to end */
		    char * folders_val = give_dt_estr_as_str(&folders_e,"maildir");

		    menu_Write_to_screen(I->current_page,
					 FRM("%s)\r\n\n"),
					 folders_val ? folders_val : "???");
		}

		if (browser_wildcards) {
		    menu_Write_to_screen(I->current_page,
					 CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg7,
						 "You may use wildcards (*?) in the name, similary as you do in the shell.\n\r"));
		}
	    }	    	    

	    /* FIXME */
 	    GetXYLocation(&line,&col);
 	    if (line < (LINES-3) - 4)
		browser_help(I);
 	    else
 		I->GB_FLAGS |= GB_HELP2;

	} 

	if (0 != (I->GB_FLAGS & GB_MENU)) {
	    int entries = 0;
	    int i;
	    int lines_per_page = LINES-10;

	    gb_dir_title(I,&entries);

	    if (sort_it) {
		sort_it = 0;
		folder_sort_dir(I->dir_p, sort_message);
		
		/* Refill edit buffer 
		 * FIXME:   should instead just modify I->GB_LINE 
		 */

		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		}
	    }

	    if (I->GB_PAGE > entries / lines_per_page)
		I->GB_PAGE = entries / lines_per_page;
	    if (I->GB_LINE > entries-1 && entries > 0)
		I->GB_LINE = entries-1;

	    for (i = I->GB_PAGE * lines_per_page;
		 i < entries && 
		     i < I->GB_PAGE * lines_per_page + lines_per_page;
		 i++) {
		draw_line(I,i,lines_per_page);
	    }

	    for (; i < I->GB_PAGE * lines_per_page + lines_per_page;
                 i++) {
		menu_MoveCursor(I->current_page,
				5 + i % lines_per_page,0);
		menu_CleartoEOLN(I->current_page);
	    }	    
	}

	break;

    case em_enter:
	clear_error();			   

	if (I->pvector[0] && (s_len=string_len(I->pvector[0])) > 0) {
	    int flags;

	    switch (give_unicode_from_string(I->pvector[0],0)) {
	    case 0x003F: /* '?' */  
		if (1 == s_len) {
		    I->GB_FLAGS |= GB_HELP;
		    I->GB_FLAGS &= ~GB_MENU;
		    
		    goto repage;
		}
		break;
	    }
	    if (0 != (GB_SAVE_COPY & I->GB_FLAGS)) {
		int cf_r;
		if ((cf_r = cf_english(I)) > 0) {
		    DPRINT(Debug,4, (&Debug,  "-- gb_browser(..,%d)=NULL (save folder prompt)\n",
			       em));
		    error_sleep((sleepmsg + 1) / 2);

		    return NULL;
		}
		if (cf_r < 0) {     /* Show text of cf_english() little time */
		    error_sleep((sleepmsg + 1) / 2);
		}
	    }
	    if (browser_wildcards /* do wildcard match? */
		&& 
		dir_is_wildcard(I->dir_p,&(I->pvector[0]))) {
		DPRINT(Debug,4, (&Debug,  
				 "-- gb_browser(..,%d): wildcarding\n",
				 em));
		
		I->GB_FLAGS &= ~GB_HELP;
		I->GB_FLAGS |= GB_MENU | GB_REDRAW | GB_FILL;
		
		I->GB_LINE = 0;
		I->GB_PAGE = 0;
		
		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,
				   '\007');
		}
	       
		sort_it++;

		goto repage;
	    }

	    if (!browser_expand(I->dir_p,&(I->pvector[0]),&(I->pvector[3]),
				I->aview)) {
		break;     /* Selection FAILED -- reject ENTER */
	    }

	    flags = give_dir_flags(I->dir_p);
	    
	    DPRINT(Debug,4, (&Debug, 
			     "*** %S have flags:%s%s%s%s%s%s%s%s\n",
			     I->pvector[0],
			     flags & BROWSER_NODIR    ?   " NODIR":    "",
			     flags & BROWSER_NOFOLDER ?   " NOFOLDER": "",
			     flags & BROWSER_MARKED   ?   " MARKED":   "",
				 
			     flags & BROWSER_MAILFILE ?   " MAILFILE": "",
			     flags & BROWSER_SELECTED ?   " SELECTED": "",
			     flags & BROWSER_EXIST    ?   " EXIST"   : "",
			     flags & BROWSER_DIRPREFIX ?   " DIRPREFIX"   : "",
			     !flags                   ?   " none"    : ""));

	    
	    if (flags & BROWSER_DIRPREFIX) {
		
		if ((I->GB_FLAGS & GB_FILENAME) == 0) {
		    I->GB_FLAGS |= GB_FILENAME;
		    
		    lib_transient(CATGETS(elm_msg_cat, ElmSet,
					  ElmBrowserFolderName,
					  "Enter folder name or press enter again to confirm directory prefix."));
		    
		    break;     /*  reject ENTER */
		}
	    }



	}
	DPRINT(Debug,4, (&Debug,  
			 "-- gb_browser(..,%d)=NULL\n",
			 em));
	return NULL;

    case em_prev:
	I->GB_FLAGS &= ~GB_FILENAME;

	clear_error();
	if (0 != (I->GB_FLAGS & GB_MENU)) {
	    int lines_per_page = LINES-10;
	     int oldline = I->GB_LINE;

	     int entries = 0;
	     /* Needs number of entries ... */
	     struct string * buffer = give_title_dir(I->dir_p,&entries);

	     free_string(&buffer);
	     
	     I->GB_LINE--;
	     if (I->GB_LINE < 0)
		 I->GB_LINE = 0;

	     if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				   &(I->pvector[0]),
				   I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		 /* Ring a bell */
		 menu_Writechar(I->current_page,'\007');
		 goto repage;
	     }

	     if (I->GB_LINE / lines_per_page != I->GB_PAGE) {
		 I->GB_PAGE = I->GB_LINE / lines_per_page;
		 goto repage;
	     }

	     if (oldline < entries)
		 draw_line(I,oldline,lines_per_page);
	     else {
		 menu_MoveCursor(I->current_page,
				 5 + oldline % lines_per_page,0);
		 menu_CleartoEOLN(I->current_page);
	     }	    
	     if (I->GB_LINE < entries)
		 draw_line(I,I->GB_LINE,lines_per_page);
	}
	break;

    case em_next:
	I->GB_FLAGS &= ~GB_FILENAME;

	clear_error();
	if (0 != (I->GB_FLAGS & GB_MENU)) {
	    int lines_per_page = LINES-10;
	    int oldline = I->GB_LINE;

	    int entries = 0;
	    /* Needs number of entries ... */
	    struct string * buffer = give_title_dir(I->dir_p,&entries);

	    free_string(&buffer);
	    	     
	    if (entries > 0) {
		I->GB_LINE++;
		if (I->GB_LINE >= entries)
		    I->GB_LINE = entries-1;
		
		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		    goto repage;
		}
	    }

	     if (I->GB_LINE / lines_per_page != I->GB_PAGE) {
		 I->GB_PAGE = I->GB_LINE / lines_per_page;
		 goto repage;
	     }
	     
	     if (oldline < entries)
		 draw_line(I,oldline,lines_per_page);
	     else {
		 menu_MoveCursor(I->current_page,5 + oldline % lines_per_page,0);
		 menu_CleartoEOLN(I->current_page);
	     }	    
	     if (I->GB_LINE < entries)
		 draw_line(I,I->GB_LINE,lines_per_page);
	}
	break;

    case em_tabaction:
	I->GB_FLAGS &= ~GB_FILENAME;

	DPRINT(Debug,8, (&Debug,  
			 "-- gb_browser - tabaction: append_current=%d ch_count=%d\n",
			 append_current,I->ch_count));
	if (!append_current && I->ch_count == 0) {
	    if (I->pvector[0])
		free_string(&(I->pvector[0]));
	    I->ch_count++;
	}

	clear_error();

	if (browser_wildcards /* do wildcard match? */
	    && 
	    dir_is_wildcard(I->dir_p,&(I->pvector[0]))) {
	    DPRINT(Debug,4, (&Debug,  
			     "-- gb_browser(..,%d): wildcarding\n",
			     em));
	    
	    I->GB_FLAGS &= ~GB_HELP;
	    I->GB_FLAGS |= GB_MENU | GB_REDRAW | GB_FILL;

	    I->GB_LINE = 0;
	    I->GB_PAGE = 0;

	    if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				  &(I->pvector[0]),
				  I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		/* Ring a bell */
		menu_Writechar(I->current_page,'\007');
	    }
	    
	    sort_it++;
	    
	    goto repage;
	}

	if (change_dir(I->dir_p,&(I->pvector[0]))) {
	    I->GB_FLAGS |= GB_MENU | GB_REDRAW | GB_FILL;
	    I->GB_FLAGS &= ~GB_HELP;

	    I->GB_LINE = 0;
	    I->GB_PAGE = 0;

	    if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				  &(I->pvector[0]),
				  I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		/* Ring a bell */
		menu_Writechar(I->current_page,'\007');
	    }

	    sort_it++;

	    goto repage;
	} else {
	    /* Ring a bell */
	    menu_Writechar(I->current_page,'\007');
	    goto repage;
	}
	/* NOT REACHED */

    case em_left:
	I->GB_FLAGS &= ~GB_FILENAME;

	clear_error();

	if (0 != (I->GB_FLAGS & GB_MENU)) {

	    if (0 == (I->GB_FLAGS & GB_FILL)) {

		if (!change_dir_up(I->dir_p,&(I->pvector[0]))) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		} else {
		    I->GB_LINE = 0;
		    I->GB_PAGE = 0;	       

		    sort_it++;
		}
		goto repage;
	    } else {
		I->GB_FLAGS &= ~GB_FILL;

		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		    goto repage;
		}
	    }
	}
	break;
    case em_right:
	I->GB_FLAGS &= ~GB_FILENAME;

	clear_error();
	if (0 != (I->GB_FLAGS & GB_MENU)) {

	    if (0 != (I->GB_FLAGS & GB_FILL)) {

		I->GB_FLAGS &= ~GB_FILL;
		
		if (!change_dir_to_entry(I->dir_p,I->GB_LINE,
					 &(I->pvector[0]))) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		} else {
		    I->GB_LINE = 0;
		    I->GB_PAGE = 0;

		    sort_it++;
		}

		goto repage;

	    } else {
		I->GB_FLAGS |= GB_FILL;

		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		    goto repage;
		}
	    }
	}
	break;
    }


    write_prompt(I);	 
    
    DPRINT(Debug,4, (&Debug,  
		     "-- gb_browser(..,%d)=non null\n",
		     em));
    return &(I->pvector[0]);
}


static int run_browser P_((struct menu_context *page,
			   struct folder_browser *p,
			   struct string **buffer,
			   int save_copy,
			   struct string *word, 
			   struct string * prev_fold,
			   struct AliasView *aview,
			   const char *format, const char *msg,
			   va_list args));
static int run_browser(page,
		       p,buffer,save_copy,
		       word,prev_fold,
		       aview,
		       format,msg,args)
     struct menu_context *page;
     struct folder_browser *p;
     struct string **buffer;
     int save_copy;
     struct string *word;
     struct string * prev_fold;
     struct AliasView *aview;
     const char *format; 
     const char *msg;
     va_list args;
{
    int ret = 0;
    int code;

    struct string *text;
    struct string *vector[5];
    struct enter_info INFO;
    int LINES,COLUMNS;
    int delay_redraw = 0;
    
    DPRINT(Debug,4,
	   (&Debug, "run_browser: Entering [%s]\n",format));

    text = elm_smessage(0,format,msg,args);

    vector[0] = *buffer;
    vector[1] = text;
    vector[2] = word;
    vector[3] = prev_fold;   
    vector[4] = NULL;        /* default_extension */

    INFO.counter     =  0;             /* Page number here */
    INFO.pvector     = vector;
    INFO.px          = 0;              /* line number here */
    INFO.py          = 0;              /* flags       here */
    INFO.give_buffer = gb_browser;
    if (save_copy)
	INFO.flags       = OE_REDRAW_MARK | OE_TABACTION |
	    OE_SIG_CHAR /* Ctrl-C */;
    else
	INFO.flags       = (*buffer ? 0 : OE_APPEND_CURRENT ) |
	    OE_REDRAW_MARK | OE_TABACTION | OE_SIG_CHAR /* Ctrl-C */;
    INFO.ch_count    = 0;
    INFO.builtin     = NULL;
    INFO.dir_p       = p;
    INFO.aview    = aview;
    INFO.current_page = page;
						
    if (save_copy)
	INFO.GB_FLAGS |= GB_SAVE_COPY;

    clear_selection_dir(p);
    do {
	code = enter_helper(&INFO,page);

	if (code == REDRAW_MARK) {
	    menu_ClearScreen(page);   
	    
	    menu_redraw_children(page);
	    
	    delay_redraw++;
	}

    } while (code == REDRAW_MARK);
    
    menu_get_sizes(page,&LINES,&COLUMNS);

    menu_MoveCursor(page,LINES-4,0);
    menu_CleartoEOS(page);
    show_last_error();

    if (0 != code) {
	DPRINT(Debug,4, (&Debug, "run_browser: Ctrl-C or error\n"));
	ret = 0;
    } else {
	int flags = give_dir_flags(p);

	if (0 != (BROWSER_SELECTED & flags))
	    ret = 1;
    }

    *buffer = vector[0];

    free_string(&text);

    if (delay_redraw || (INFO.GB_FLAGS & GB_REDRAW)) {
	DPRINT(Debug,10, (&Debug,  "run_browser: redraw set\n"));
	menu_trigger_redraw(page);	
    }

    DPRINT(Debug,10, (&Debug,  
		      "run_browser=%d\n",ret));

    return ret;
}


struct folder_info * folder_browser(
#if ANSI_C
				    struct menu_context *page,
				    struct folder_browser *p,
				    struct string **buffer,
				    struct AliasView *aview,
				    const char *format, const char *msg, ...
#else
				    page,
				    p,buffer,redraw,aview,format, msg, va_alist
#endif
)
#if !ANSI_C
     struct menu_context *page;
     struct folder_browser *p;
     struct string **buffer;
     struct AliasView *aview;
     CONST char *format; 
     CONST char *msg;
     va_dcl
#endif
{
    struct folder_info *ret = NULL;
    struct string * word;
    va_list vl;


    word=format_string(CATGETS(elm_msg_cat, ElmSet, ElmChange, 
			       "change"));

    Va_start(vl, msg);           /* defined in defs.h */
    if (run_browser(page,p,buffer,0,word,NULL,aview,format,msg,vl)) 
	ret = folder_from_dir_item(p);
    va_end(vl);

    free_string(&word);

    if (ret) {
	DPRINT(Debug,5,
	       (&Debug,"folder_browser=%p\n",ret));
    } else {
	DPRINT(Debug,5,
	       (&Debug,"folder_browser=NULL\n"));
    }
    
    return ret;
}

static void draw_fileline P_((struct enter_info *I,
			      int i,int lines_per_page));
static void draw_fileline(I,i,lines_per_page)
     struct enter_info *I;
     int i;
     int lines_per_page;
{
    int flags = 0;
    int LINES,COLUMNS;

    /* return reference to array -- do not free_string !!! */
    struct string * buffer = 
	give_line_dir(I->dir_p,i,&flags);
    int current = i == I->GB_LINE; 
    int c = '?';
    int size;

    menu_get_sizes(I->current_page,&LINES,&COLUMNS);

    size = COLUMNS-5;

    if (0 == (flags & BROWSER_NODIR))
	c = 'D';
		
    if (current && !arrow_cursor)
	menu_StartXX(I->current_page,pg_INVERSE);

    menu_PutLineX(I->current_page,
		  5 + i % lines_per_page,0,
		  FRM("%.2s%c%c  %-*.*S"),
		  current && arrow_cursor ? "->" : "  ",
		  flags & BROWSER_MARKED ? 'N' : ' ',
		  c,size,size,buffer);
    if (current && !arrow_cursor)
	menu_EndXX(I->current_page,pg_INVERSE);    
}


static struct string **gb_filebrowser P_((struct enter_info *I,
					  enum enter_mode em,
					  struct menu_context *base_page));
static struct string **gb_filebrowser(I,em,base_page)
     struct enter_info *I;
     enum enter_mode em;
     struct menu_context *base_page;
{
    int sort_it = 0;
    int append_current = 0 != (I->flags & OE_APPEND_CURRENT);
    int LINES,COLUMNS;

    menu_get_sizes(I->current_page,&LINES,&COLUMNS);

    /* Clear screen ... */
    if (em_redraw == em)           
	I->GB_FLAGS |= GB_REDRAW ;     
    
    switch(em) {
	int s_len;
    case em_redraw_initial:
	
	/* POP/IMAP client code will prompt messages to same area
	   so we re-print prompt every time ... */

	gb_initial_text(I);

	if (!append_current) {
	    gb_initial_non_append(I);
	    
	    I->ch_count = 0;
	    
	    DPRINT(Debug,4,
		   (&Debug, 
		    "-- gb_filebrowser(..,%d)=non null  (initial prompt)\n",
		    em));
	    return &(I->pvector[0]);
	}
	/* FALLTHRU */

    case em_redraw: repage:

	if (0 != (I->GB_FLAGS & GB_MENU))
	    I->GB_FLAGS |= GB_REDRAW;
	
	if (0 != (I->GB_FLAGS & GB_HELP))
	    I->GB_FLAGS |= GB_REDRAW;

	if (0 != (I->GB_FLAGS & GB_REDRAW)) {
	    struct string * buffer = 
		format_string(CATGETS(elm_msg_cat, ElmSet,
				      ElmFileSelection,
				      "File selection"));

	    if (I->current_page == base_page)
		I->current_page = new_menu_context();

	    gb_initial_title(I,buffer);
	    free_string(&buffer);
	}

	if (0 != (I->GB_FLAGS & GB_HELP)) {	        
	    menu_MoveCursor(I->current_page,3,0);    
	    menu_CleartoEOS(I->current_page);    

	    menu_Write_to_screen(I->current_page,
				 CATGETS(elm_msg_cat, ElmSet, ElmFileSpecify1,
					 "\n\r\n\rYou must specify a file to "));
	    
	    menu_Write_to_screen(I->current_page,
				 FRM("%S"),I->pvector[2]);

	    menu_Write_to_screen(I->current_page,
				 FRM(".\n\r"));

	    if (browser_wildcards) {
		menu_Write_to_screen(I->current_page,
				     CATGETS(elm_msg_cat, ElmSet, ElmFileHelpmsg7,
					     "You may use wildcards (*?) in the name, similary as you do in the shell.\n\r"));
	    }

	    browser_help(I);
	}

	if (0 != (I->GB_FLAGS & GB_MENU)) {
	    int entries = 0;
	    int i;
	    int lines_per_page = LINES-10;

	    gb_dir_title(I,&entries);

	    if (sort_it) {
		sort_it = 0;
		folder_sort_dir(I->dir_p, sort_message);

		/* Refill edit buffer 
		 * FIXME:   should instead just modify I->GB_LINE 
		 */

		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		}
	    }

	    if (I->GB_PAGE > entries / lines_per_page)
		I->GB_PAGE = entries / lines_per_page;
	    if (I->GB_LINE > entries-1 && entries > 0)
		I->GB_LINE = entries-1;

	    for (i = I->GB_PAGE * lines_per_page;
		 i < entries && 
		     i < I->GB_PAGE * lines_per_page + lines_per_page;
		 i++) {
		draw_fileline(I,i,lines_per_page);
	    }

	    for (; i < I->GB_PAGE * lines_per_page + lines_per_page;
                 i++) {
		menu_MoveCursor(I->current_page,
				5 + i % lines_per_page,0);
		menu_CleartoEOLN(I->current_page);
	    }	    
	}

	break;
    case em_enter:
	clear_error();			   

	if (I->pvector[0] && (s_len=string_len(I->pvector[0])) > 0) {
	    int flags;

	    switch (give_unicode_from_string(I->pvector[0],0)) {
	    case 0x003F: /* '?' */  
		if (1 == s_len) {
		    I->GB_FLAGS |= GB_HELP;
		    I->GB_FLAGS &= ~GB_MENU;
		    
		    goto repage;
		}
		break;
	    }

	    if (browser_wildcards /* do wildcard match? */
		&& 
		dir_is_wildcard(I->dir_p,&(I->pvector[0]))) {

		DPRINT(Debug,4, (&Debug,  
				 "-- gb_filebrowser(..,%d): wildcarding\n",
				 em));
		
		I->GB_FLAGS &= ~GB_HELP;
		I->GB_FLAGS |= GB_MENU | GB_REDRAW | GB_FILL;
		
		I->GB_LINE = 0;
		I->GB_PAGE = 0;
		
		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		}
	       
		sort_it++;

		goto repage;
	    }
	    
	    if (!select_dir_item(I->dir_p,&(I->pvector[0]))) {
		break;     /* Selection FAILED -- reject ENTER */
	    }

	    flags = give_dir_flags(I->dir_p);

	    DPRINT(Debug,4, (&Debug, 
			     "*** %S have flags:%s%s%s%s%s%s%s%s\n",
			     I->pvector[0],
			     flags & BROWSER_NODIR    ?   " NODIR":    "",
			     flags & BROWSER_NOFOLDER ?   " NOFOLDER": "",
			     flags & BROWSER_MARKED   ?   " MARKED":   "",
				 
			     flags & BROWSER_MAILFILE ?   " MAILFILE": "",
			     flags & BROWSER_SELECTED ?   " SELECTED": "",
			     flags & BROWSER_EXIST    ?   " EXIST"   : "",
			     flags & BROWSER_DIRPREFIX ?   " DIRPREFIX"   : "",
			     !flags                   ?   " none"    : ""));

	    
	    if (flags & BROWSER_DIRPREFIX) {

		if ((I->GB_FLAGS & GB_FILENAME) == 0) {
		    I->GB_FLAGS |= GB_FILENAME;
		    
		    lib_transient(CATGETS(elm_msg_cat, ElmSet,
					  ElmBrowserFilename,
					  "Enter filename or press enter again to confirm directory prefix."));

		    break;     /*  reject ENTER */
		}
	    }


	    if ((I->GB_FLAGS & GB_EXTENSION) == 0 &&
		I->pvector[4] && I->pvector[0]) {

		int L  = string_len(I->pvector[4]);     /* default extension */
		int L1 = string_len( I->pvector[0]);    /* filename */
		int ok = 1;

		if (L >= L1)
		    ok = 0;
		else {
		    int pos = L1-L;


		    if (give_unicode_from_string(I->pvector[0],pos-1)
			!= 0x002E /* . */)
			ok = 0;
		    else {
			int i;

			for (i = 0; i < L; i++) {
			    if (give_unicode_from_string(I->pvector[0],pos+i) 
				!=
				give_unicode_from_string(I->pvector[4],i)) {
				ok = 0;
				break;
			    }
			}
		    }
		    
		    if (ok) {
			DPRINT(Debug,4, (&Debug,  
					 "-- gb_filebrowser(..,%d): filename %S includes extension %S\n",
					 em,I->pvector[0],I->pvector[4]));
		    } else {
			struct string *X;

			DPRINT(Debug,4, (&Debug,  
					 "-- gb_filebrowser(..,%d): filename %S do not include extension %S\n",
					 em,I->pvector[0],I->pvector[4]));
			

			I->GB_FLAGS |= GB_EXTENSION;

			X = format_string(FRM("%S.%S"),
					  I->pvector[0],
					  I->pvector[4]);

			free_string(& (I->pvector[0]));
			I->pvector[0] = X;
			
			lib_transient(CATGETS(elm_msg_cat, ElmSet,
					      ElmBrowserExtension,
					      "Press enter again to confirm appended extension: %S"),
				      I->pvector[4]);

			break;     /*  reject ENTER */
		    }

		    

		}


	    }


	}
	DPRINT(Debug,4, (&Debug,  
			 "-- gb_filebrowser(..,%d)=NULL\n",
			 em));
	return NULL;

    case em_prev:
	I->GB_FLAGS &= ~GB_EXTENSION;
	I->GB_FLAGS &= ~GB_FILENAME;

	clear_error();
	if (0 != (I->GB_FLAGS & GB_MENU)) {
	    int lines_per_page = LINES-10;
	     int oldline = I->GB_LINE;

	     int entries = 0;
	     /* Needs number of entries ... */
	     struct string * buffer = give_title_dir(I->dir_p,&entries);

	     free_string(&buffer);
	     
	     I->GB_LINE--;
	     if (I->GB_LINE < 0)
		 I->GB_LINE = 0;

	     if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				   &(I->pvector[0]),
				   I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		 /* Ring a bell */
		 menu_Writechar(I->current_page,'\007');
		 goto repage;
	     }

	     if (I->GB_LINE / lines_per_page != I->GB_PAGE) {
		 I->GB_PAGE = I->GB_LINE / lines_per_page;
		 goto repage;
	     }

	     if (oldline < entries)
		 draw_fileline(I,oldline,lines_per_page);
	     else {
		 menu_MoveCursor(I->current_page,
				 5 + oldline % lines_per_page,0);
		 menu_CleartoEOLN(I->current_page);
	     }	    
	     if (I->GB_LINE < entries)
		 draw_fileline(I,I->GB_LINE,lines_per_page);
	}
	break;
    case em_next:
	I->GB_FLAGS &= ~GB_EXTENSION;
	I->GB_FLAGS &= ~GB_FILENAME;

	clear_error();
	if (0 != (I->GB_FLAGS & GB_MENU)) {
	    int lines_per_page = LINES-10;
	    int oldline = I->GB_LINE;

	    int entries = 0;
	    /* Needs number of entries ... */
	    struct string * buffer = give_title_dir(I->dir_p,&entries);

	    free_string(&buffer);
	    	     
	    if (entries > 0) {
		I->GB_LINE++;
		if (I->GB_LINE >= entries)
		    I->GB_LINE = entries-1;
		
		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		    goto repage;
		}
	    }

	     if (I->GB_LINE / lines_per_page != I->GB_PAGE) {
		 I->GB_PAGE = I->GB_LINE / lines_per_page;
		 goto repage;
	     }
	     
	     if (oldline < entries)
		 draw_fileline(I,oldline,lines_per_page);
	     else {
		 menu_MoveCursor(I->current_page,
				 5 + oldline % lines_per_page,0);
		 menu_CleartoEOLN(I->current_page);
	     }	    
	     if (I->GB_LINE < entries)
		 draw_fileline(I,I->GB_LINE,lines_per_page);
	}
	break;
	
    case em_tabaction:
	I->GB_FLAGS &= ~GB_EXTENSION;
	I->GB_FLAGS &= ~GB_FILENAME;

	DPRINT(Debug,10, (&Debug,  
		    "-- gb_filebrowser - tabaction: append_current=%d ch_count=%d\n",
		    append_current,I->ch_count));
	if (!append_current && I->ch_count == 0) {
	    if (I->pvector[0])
		free_string(&(I->pvector[0]));
	    I->ch_count++;
	}

	clear_error();

	if (browser_wildcards /* do wildcard match? */
	    && 
	    dir_is_wildcard(I->dir_p,&(I->pvector[0]))) {
	    DPRINT(Debug,4, (&Debug,  "-- gb_filebrowser(..,%d): wildcarding\n",
		       em));
	    
	    I->GB_FLAGS &= ~GB_HELP;
	    I->GB_FLAGS |= GB_MENU | GB_REDRAW | GB_FILL;

	    I->GB_LINE = 0;
	    I->GB_PAGE = 0;

	    if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				  &(I->pvector[0]),
				  I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		/* Ring a bell */
		menu_Writechar(I->current_page,'\007');
	    }
	    
	    sort_it++;

	    goto repage;
	}

	if (change_dir(I->dir_p,&(I->pvector[0]))) {
	    I->GB_FLAGS |= GB_MENU | GB_REDRAW | GB_FILL;
	    I->GB_FLAGS &= ~GB_HELP;

	    I->GB_LINE = 0;
	    I->GB_PAGE = 0;

	    if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				  &(I->pvector[0]),
				  I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		/* Ring a bell */
		menu_Writechar(I->current_page,'\007');
	    }

	    sort_it++;

	    goto repage;
	} else {
	    /* Ring a bell */
	    menu_Writechar(I->current_page,'\007');
	    goto repage;
	}
	/* NOT REACHED */

      
    case em_left:
	I->GB_FLAGS &= ~GB_EXTENSION;
	I->GB_FLAGS &= ~GB_FILENAME;

	clear_error();
	if (0 != (I->GB_FLAGS & GB_MENU)) {

	    if (0 == (I->GB_FLAGS & GB_FILL)) {

		if (!change_dir_up(I->dir_p,&(I->pvector[0]))) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		} else {
		    I->GB_LINE = 0;
		    I->GB_PAGE = 0;	       

		    sort_it++;
		}
		goto repage;
	    } else {
		I->GB_FLAGS &= ~GB_FILL;

		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		    goto repage;
		}
	    }
	}
	break;
    case em_right:
	I->GB_FLAGS &= ~GB_EXTENSION;
	I->GB_FLAGS &= ~GB_FILENAME;

	clear_error();

	if (0 != (I->GB_FLAGS & GB_MENU)) {

	    if (0 != (I->GB_FLAGS & GB_FILL)) {

		I->GB_FLAGS &= ~GB_FILL;
		
		if (!change_dir_to_entry(I->dir_p,I->GB_LINE,
					 &(I->pvector[0]))) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		} else {
		    I->GB_LINE = 0;
		    I->GB_PAGE = 0;

		    sort_it++;
		}

		goto repage;

	    } else {
		I->GB_FLAGS |= GB_FILL;

		if (!give_edit_buffer(I->dir_p,I->GB_LINE,
				      &(I->pvector[0]),
				      I->GB_FLAGS & GB_FILL ? 1 : 0)) {
		    /* Ring a bell */
		    menu_Writechar(I->current_page,'\007');
		    goto repage;
		}
	    }
	}
	break;
    }

    write_prompt(I);	 
    
    DPRINT(Debug,4, (&Debug,  
		     "-- gb_filebrowser(..,%d)=non null\n",
		     em));
    return &(I->pvector[0]);
}

int gen_browser(
#if ANSI_C
		 struct menu_context *page,
		 struct folder_browser *p,
		 struct string **buffer,
		 enum word_sel w,
		 struct string * prev_fold,
		 struct AliasView *aview,
		 const char *format, const char *msg, ...
#else
		 page,p,buffer,redraw,w,prev_fold,
		 aview,format, msg, va_alist
#endif
)
#if !ANSI_C
     struct menu_context *page;
     struct folder_browser *p;
     struct string **buffer;
     enum word_sel w;
     struct string * prev_fold;
     struct AliasView *aview;
     CONST char *format; 
     CONST char *msg;
     va_dcl
#endif
{
    va_list vl;
    struct string * word = NULL;
    int save_copy = 0;
    int r;

    switch (w) {
    case word_change: 
	word = format_string(CATGETS(elm_msg_cat, ElmSet, 
				     ElmChange, "change"));
	break;
    case word_save:
	word = format_string(CATGETS(elm_msg_cat, ElmSet, 
				     ElmSave, "save"));
	break;
    case word_copy:
	word = format_string(CATGETS(elm_msg_cat, ElmSet, ElmCopy, "copy"));
	break;
    case word_save_copy:
	word = format_string(CATGETS(elm_msg_cat, ElmSet, 
				     ElmSaveCopy, "save copy"));
	save_copy = 1;
	break;
    case word_read:
	word = format_string(CATGETS(elm_msg_cat, ElmSet, 
				     ElmRead, "read"));
	break;
    }

    Va_start(vl, msg);           /* defined in defs.h */

    r = run_browser(page,p,buffer,save_copy,word,prev_fold,
		    aview,format,msg,vl);
    va_end(vl);
   

    free_string(&word);

    DPRINT(Debug,4, (&Debug, "gen_browser=%d\n",
		     r));

    return r;
}

int file_browser(
#if ANSI_C
		 struct menu_context *page,
		 struct folder_browser *p,
		 struct string **buffer,
		 enum word_sel w,
		 struct AliasView *aview,
		 struct string * default_extension,
		 const char *format, const char *msg, ...
#else
		 page,p,buffer,redraw,w,aview,
		 default_extension,
		 format, msg, va_alist
#endif
)
#if !ANSI_C
     struct menu_context *page;
     struct folder_browser *p;
     struct string **buffer;
     enum word_sel w;
     struct AliasView *aview;
     struct string * default_extension;
     CONST char *format; 
     CONST char *msg;
     va_dcl
#endif
{
    int ret = 0;
    int code;
    va_list vl;

    struct string *text;
    struct string *vector[5];     /* We use same vector than on folder browser
				     so that we can share routines ....
				  */
    struct enter_info INFO;
    struct string * word = NULL;
    int delay_redraw = 0;

    int LINES,COLUMNS;

    Va_start(vl, msg);           /* defined in defs.h */


    DPRINT(Debug,5,
	   (&Debug, "file_browser: Entering [%s]\n",format));

    switch (w) {
    case word_change: 
	word = format_string(CATGETS(elm_msg_cat, ElmSet, 
				     ElmChange, "change"));
	break;
    case word_save:
	word = format_string(CATGETS(elm_msg_cat, ElmSet, 
				     ElmSave, "save"));
	break;
    case word_copy:
	word = format_string(CATGETS(elm_msg_cat, ElmSet, ElmCopy, "copy"));
	break;
    case word_save_copy:
	word = format_string(CATGETS(elm_msg_cat, ElmSet, 
				     ElmSaveCopy, "save copy"));
	break;
    case word_read:
	word = format_string(CATGETS(elm_msg_cat, ElmSet, 
				     ElmRead, "read"));
	break;
    }

    text = elm_smessage(0,format,msg,vl);

    vector[0] = *buffer;
    vector[1] = text;
    vector[2] = word;
    vector[3] = NULL;       /* prev_fold */
    vector[4] = default_extension;

    INFO.counter     =  0;             /* Page number here */
    INFO.pvector     = vector;
    INFO.px          = 0;              /* line number here */
    INFO.py          = 0;              /* flags       here */
    INFO.give_buffer = gb_filebrowser;

    INFO.flags       = (*buffer ? 0 : OE_APPEND_CURRENT ) |
	OE_REDRAW_MARK | OE_TABACTION | OE_SIG_CHAR;

    INFO.ch_count    = 0;
    INFO.builtin     = NULL;
    INFO.dir_p       = p;
    INFO.aview    = aview;
    INFO.current_page = page;

    clear_selection_dir(p);
    do {
	code = enter_helper(&INFO,page);

	menu_ClearScreen(page);   

	menu_redraw_children(page);

	delay_redraw++;
    } while (code == REDRAW_MARK);

    menu_get_sizes(page,&LINES,&COLUMNS);
    
    MoveCursor(LINES-4,0);
    CleartoEOS();
    show_last_error();

    va_end(vl);
   
    MoveCursor(LINES-4,0);
    CleartoEOS();
    show_last_error();

    if (0 != code) {
	DPRINT(Debug,4, (&Debug, "file_browser: Ctrl-C or error\n"));
	ret = 0;
    } else {
	int flags = give_dir_flags(p);

	if (0 != (BROWSER_SELECTED & flags))
	    ret = 1;
    }

    *buffer = vector[0];

    free_string(&text);
    free_string(&word);

    if (delay_redraw || (INFO.GB_FLAGS & GB_REDRAW)) {
	DPRINT(Debug,10, (&Debug,  "file_browser: redraw set\n"));
	menu_trigger_redraw(page);	
    }

    DPRINT(Debug,10, (&Debug,  "file_browser=%d\n",ret));
    
    return ret;
}

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


syntax highlighted by Code2HTML, v. 0.9.1