Re: File Search & Select PGM
- Posted by Jacques Deschjnes <desja at QUEBECTEL.COM> Sep 26, 1996
- 1875 views
Mr. Fred Cole proposed his version of a file select function, Here is my own version. Specifications: -> full navigation this version doesn't use mouse but have full navigation with cursor key, PageUp, PageDown, Home and End keys. -> ESC key can be used to cancel the operation, in which case and empty sequence is returned to caller. -> The file list adapt itself to current screen metrics. -> Directory names are displayed in black, file names in white and the selected one is on green background. -> screen state saved and restored How to use it: include filelist.e in your program srceen is organised in 3 regions: first line is filter and number of files in current list. second line is selected file info (name, size, date, etc) rest of screen is the list The function to call is ChooseFile(filter) the parameter filter is a path or wildcard filter. you can change the filter or drive while viewing the list with the f command. example: include FileList.e sequence FileName FileName = ChooseFile("c:\\euphoria\*.ex") puts(1,name) Consider it public domain. I would appreciated report on bugs and to receive your improve version of it. ************************************************************************ -- FileList: display le list of file for user to pick one and return the -- selected file. -- Creation date: august 26th, 1996 -- By: Jacques Deschenes, Baie-comeau, P.Q. Canada -- e-mail: desja at quebectel.com -- -- caller pass a wildcard path to use as a filter without warning without type_check -- with trace include graphics.e include wildcard.e include machine.e include get.e include image.e include file.e -- Keys constant constant ESC = 27, ENTER = 13, HOME = 327, END = 335, UP = 328, DOWN = 336, LEFT =331, RIGHT =333, PG_UP = 329, PG_DOWN = 337 sequence list,path,filter list = {} path = current_dir() & '\\' -- default path filter = "*.*" -- default filter -- display metrics integer ListLines, -- number of lines to display list ListCol, -- number of columns to display the list PerLine -- number of file name displayed per line constant NAME_FIELD= 14 -- width of name field -- math functions function Min(integer a, integer b) if a < b then return a else return b end if end function -- Min function Max(integer a, integer b) if a > b then return a else return b end if end function -- Max function ToUpper(integer c) -- convert c to upper case if c >= 'a' and c <= 'z' then return c - 'a' + 'A' else return c end if end function -- ToUpper() function f_split(sequence path) -- split path to drive, directory, name and extension -- return sequence {drive,dir,name,ext} sequence slice,drive,dir,name,ext atom c slice = {} drive = {} dir = {} name = {} ext = {} for i =1 to length(path) by 1 do c = ToUpper(path[i]) slice = slice & c if c = ':' then drive = slice slice = {} elsif c = '\\' then dir = dir & slice slice = {} elsif c = '.' then name = slice[1..length(slice)-1] slice = {} end if end for if length(name) = 0 then name = slice else ext = slice end if if length(ext)=0 and not match("*",name) and not match("?",name) then dir = dir & name name = "*" ext = "*" end if if length(dir) then if dir[length(dir)] != '\\' then dir = dir & '\\' end if end if return {drive,dir,name,ext} end function -- f_split() function ParentDir(sequence path) -- return the parent directory sequence parent integer i if path[length(path)] = '\\' then path = path[1..length(path)-1] end if i = length(path) while i > 0 do if path[i] = '\\' or path[i] = ':' then exit end if i = i-1 end while if i = 0 then return {} end if parent = path[1..i] if parent[length(parent)] != '\\' then parent = parent & '\\' end if return parent end function -- ParentDir() function CreateList(sequence filter) -- create the list of files to display. object FileList FileList = dir(filter) if atom(FileList) then return {} end if if length(FileList[1][D_NAME]) = 1 and match(".",FileList[1][D_NAME]) then FileList = FileList[2..length(FileList)] end if return FileList end function -- CreateList function Left(sequence Str, integer width) -- left justify a string in a specified field width. Str = Str & repeat(32,width) return Str[1..width] end function -- Left() procedure WriteFileInfo(integer index) -- write file info line on second line of screen position(2,1) bk_color(BLUE) text_color(WHITE) if index=0 then puts(1,"No files\n") else printf(1,"%14s %5s %8d %4d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d\n", list[index]) end if end procedure --WriteFileInfo() sequence padding padding = repeat(32,NAME_FIELD) procedure WriteFileName(integer i) -- write file name to screen -- directory are displayed in black, files in white sequence name if match("d",list[i][D_ATTRIBUTES]) then text_color(BLACK) else text_color(WHITE) end if name = list[i][D_NAME] & padding puts(1,name[1..NAME_FIELD]) end procedure -- WriteFileName() integer PrevFirst, PrevIndex PrevFirst = 0 PrevIndex = 0 procedure DisplayList(integer index) -- Display the list HiLight the selected one sequence pos integer first,last if index = PrevIndex then return end if first = 1 if index > ListLines*PerLine then first = floor(index/PerLine-ListLines+1)*PerLine+1 end if if first = PrevFirst then position(3+floor((PrevIndex-first)/PerLine), NAME_FIELD*remainder(PrevIndex-first,PerLine)+1) bk_color(BROWN) WriteFileName(PrevIndex) position(3+floor((index-first)/PerLine), NAME_FIELD*remainder(index-first,PerLine)+1) bk_color(GREEN) WriteFileName(index) WriteFileInfo(index) PrevIndex = index return end if bk_color(BROWN) clear_screen() text_color(WHITE) bk_color(BLUE) puts(1,repeat(32,2*ListCol)) position(1,1) printf(1,"%s files: %d\n",{Left(path&filter,60),length(list)}) WriteFileInfo(index) last = Min(first+ListLines*PerLine-1,length(list)) bk_color(BROWN) for i = first to last by 1 do WriteFileName(i) if remainder(i,PerLine)=0 then pos = get_position() if pos[1] < ListLines + 2 then puts(1,"\n") end if end if end for position(3+floor((index-first)/PerLine), NAME_FIELD*remainder(index-first,PerLine)+1) bk_color(GREEN) WriteFileName(index) PrevFirst = first PrevIndex = index end procedure --DisplayList function NewSpec() sequence PathSplit, new_path, new_filter object input_line, new_list -- trace(1) new_list = {} position(2,1) text_color(WHITE) bk_color(BLUE) puts(1,repeat(32,80)) cursor(#0607) position(2,1) puts(1,"NEW FILTER: ") input_line = gets(0) cursor(NO_CURSOR) if atom(input_line) then return list else new_filter = input_line[1..length(input_line)-1] if length(new_filter) = 0 then return list end if end if PathSplit=f_split(new_filter) if length(PathSplit[3]) then new_filter = PathSplit[3]&'.'&PathSplit[4] else new_filter = filter end if if length(PathSplit[1]) then new_path = PathSplit[1]&PathSplit[2] elsif length(PathSplit[2]) then new_path = PathSplit[2] else new_path = path end if if new_path[length(new_path)] != '\\' then new_path = new_path & '\\' end if new_list=dir(new_path&new_filter) if atom(new_list) then return list end if filter = new_filter path = new_path if length(new_list[1][D_NAME])=1 and match(".",new_list[1][D_NAME]) then return new_list[2..length(new_list)] else return new_list end if end function -- NewSpec() function DoSelect() -- navigate the list and return the index of the selected one integer index,car index = 1 while 1 do DisplayList(index) car = wait_key() if car = ESC then return 0 elsif car = LEFT then if index > 1 then index = index - 1 end if elsif car = RIGHT then if index < length(list) then index = index + 1 end if elsif car = UP then if index > PerLine then index = index - PerLine end if elsif car = DOWN then if index <= length(list)-PerLine then index = index + PerLine end if elsif car = HOME then if index > 1 then index = 1 end if elsif car = END then if index < length(list) then index = length(list) end if elsif car = PG_DOWN then if PrevFirst + PerLine*ListLines -1 < length(list) then index = Min(index+ListLines*PerLine,length(list)) end if elsif car = PG_UP then if index > ListLines*PerLine then index = index - ListLines*PerLine end if elsif car = 'F' or car = 'f' then list = NewSpec() index = 1 PrevIndex = 0 PrevFirst = 0 elsif car = ENTER then if match("d",list[index][D_ATTRIBUTES])=0 then return index else if match("..",list[index][D_NAME])=1 then path = ParentDir(path) else path = path&list[index][D_NAME]&'\\' end if list = CreateList(path&filter) index = 1 PrevIndex = 0 PrevFirst = 0 end if end if end while end function -- DoSelect global function ChooseFile(sequence APath) -- display a list of file -- return the selected file or {} if operation canceled sequence saved, FileSpec, vc, CurPos integer pick,OldColor,OldBack CurPos = get_position() OldColor = TextColor OldBack= BkColor FileSpec=f_split(APath) if length(FileSpec[1]) then path = FileSpec[1] & FileSpec[2] end if if length(FileSpec[3]) then filter = FileSpec[3]&"."&FileSpec[4] end if vc = video_config() saved=save_text_image({1,1},{vc[VC_LINES],vc[VC_COLUMNS]}) -- save all screen cursor(NO_CURSOR) ListLines = vc[VC_LINES] - 2 ListCol = vc[VC_COLUMNS] PerLine = floor(ListCol/NAME_FIELD) list = CreateList(filter) pick = DoSelect() display_text_image({1,1},saved) text_color(OldColor) bk_color(OldBack) cursor(#0607) FileSpec = f_split(filter) position(CurPos[1],CurPos[2]) if pick then return FileSpec[1] & FileSpec[2] & list[pick][D_NAME] else return {} end if end function -- ChooseFile