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 (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, "")); 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, "")); 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, "")); 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: 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: */