1. inprved filelist.e

--=====================_848990548==_

to all,

  This message is a postage of the last  revision of FILELIST.E I posted ealier

  added feature are:
   1) a drive list
   2) the filelist is now sorted.
   3) The names betwen angle brackets on the last line of display act as
mouse buttons.    4) to change drive using keyboard, press corresponding key.
   5) to change filter you should use alt-f instead of 'F'.





--=====================_848990548==_

-- 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
--
-- globals:
--  function ChooseFile(sequence APath)
--    APath = [drive][directory][name wildcard]
--
--  procedure SetFListColors(sequence colors)
-- color is a sequence of 7 colors as:
--   colors = {iInfoBack,  -- information lines back color
--             iInfoText,  -- informations lines text color
--             iListBack,  -- list back color
--             iFileName,  -- file name text color
--             iDirName,   -- directory name text color
--             iSelected   -- selected item back color
--            }
--
-- *********************USAGE **************
-- include FileList.e
-- sequence FileName
-- FileName = ChooseFile(filter)
-- filter is a directory specification  that can include a wild card file
-- name.
--
-- caller pass a wildcard path to use as a filter
--
-- revision October 16th , 1996
-- 1) function NewSpec() was not working. Corrected this bug.
-- 2) now last line of display same color as top 2.
-- 3) Added SetFListColors() procedure to set menu colors.
-- 4)
-- revision:  October 13th, 1996
-- corrected bugs:
--   1) DisplayList() crash when list was empty.
--   2) PrevIndex and PrevFirst were not initialised at each call so display
--      was not updating correctly.
--   3) directories were not included in list when using a file filter.
--
-- revision date: October 30th, 1996
-- modified code to use mouse.

-- revision date: November 4th, 1996.
-- corrected bugs:
--      1) no response from mouse on next call to ChooseFile()
--      2) End of second line was not cleared on next call to ChooseFile()
--
-- revision date: November 25th, 1996
--  1) added a drive list
--  2) display an ordered list of directories an files
--  3) added mouse buttons on the last line of display

without warning

--with trace
--constant test = 1    -- set to 1 during test and debug phase.

include graphics.e
include wildcard.e
include machine.e
include get.e
include image.e
include file.e
include mouse.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,
         ALT_F=289


sequence drives,list,path,filter
list = {}
path = current_dir() & '\\'
filter = "*.*"

integer -- colors
  iInfoBack,  -- information lines back colors
  iInfoText,  -- information lines text colors
  iListBack,  -- file list back color
  iFileName,  -- file list name text color
  iDirName,   -- files list directory name text color
  iSelected   -- selected item back color

integer iUseMouse   --  set to 1 if mouse detected.

-- 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
        ScrLines,   -- number of screen lines
        ScrCol      -- number of screen colomns

constant NAME_FIELD= 14 -- width of name field

procedure ScrollDown(integer NbLines, integer color)
-- NbLines = How mamy lines to scroll down
-- color = color of empty lines.
sequence r
   r = repeat(0,10)
   r[REG_AX] = #700 + NbLines  -- NbLines = 0 clear screen.
   r[REG_CX] = #0101
   r[REG_DX] = ScrLines*256 + ScrCol
   r[REG_BX] = color*256
   r = dos_interrupt(#10,r)
end procedure -- ScrollDown()

procedure ScrollUp(integer NbLines, integer color)
-- NbLines = How mamy lines to scroll up
-- color = color of empty lines.
sequence r
   r = repeat(0,10)
   r[REG_AX] = #600 + NbLines  -- NbLines = 0 clear screen.
   r[REG_CX] = #0101
   r[REG_DX] = ScrLines*256 + ScrCol
   r[REG_BX] = color*256
   r = dos_interrupt(#10,r)
end procedure -- ScrollUp()

procedure Clreol()
-- clear end of line
sequence CurPos, FirstLine
   CurPos = get_position()
   if CurPos[1] = ScrLines then
     FirstLine = save_text_image({1,1},{1,ScrCol}) -- save first line
     puts(1,repeat(32,ScrCol-CurPos[2]+1))
     ScrollDown(1,7)
     display_text_image({1,1},FirstLine)
   else
     puts(1,repeat(32,ScrCol-CurPos[2]+1))
   end if
   position(CurPos[1],CurPos[2])
end procedure -- Clreol()

-- 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 MousePresent()
-- return 1 if mouse detected
integer MouseVector
sequence r
   MouseVector = (256*peek(207)+peek(206)) *16 + 256*peek(205)+peek(204)
   if MouseVector  = 0 or peek(MouseVector) = #CF then
     return 0  -- no mouse
   end if
   r = repeat(0,10)
   r[REG_AX] =  0
   r = dos_interrupt(#33,r)
   return r[REG_AX] = #FFFF  -- r[REG_AX] = #FFFF if mouse present
end function -- MousePresent

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)
-- remove last sub directory from path if there is one and return it.
-- if root return empty sequence
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 sort(sequence fl)
-- quick sort a file list by ascending file name
sequence swap, m
integer l,r,p

    if length(fl) < 2 then
        return fl
    end if
    if length(fl) = 2 then
        if compare(fl[1][D_NAME],fl[2][D_NAME]) = 1 then
           return {fl[2],fl[1]}
        else
           return fl
        end if
    end if
    p = floor(length(fl)/2)
    m = fl[p][D_NAME]
    l = 1  r = length(fl)
    while l < r do
      while compare(fl[l][D_NAME],m) = -1 do
          l = l + 1
      end while
      while compare(m,fl[r][D_NAME]) = -1 do
          r = r - 1
      end while
      if l < r then
          swap = fl[r]
          fl[r] = fl[l]
          fl[l] = swap
      end if
    end while
    return sort(fl[1..r]) & sort(fl[r+1..length(fl)])
end function -- sort()

function FilterList(sequence FileList, sequence filter)
-- filter list to remove unwanted files.
sequence dirs,files
    if length(FileList[1][D_NAME]) = 1 and match(".",FileList[1][D_NAME]) then
        FileList = FileList[2..length(FileList)]
    end if
    dirs ={}
    files = {}
    for i = 1 to length(FileList) do
        if match("d",FileList[i][D_ATTRIBUTES]) then
          dirs = append(dirs,FileList[i])
        else
          if wildcard_file(filter,FileList[i][D_NAME]) then
             files = append(files,FileList[i])
          end if
        end if
    end for
    return sort(dirs) & sort(files)
end function -- FilterList()

function CreateList(sequence filter)
-- create a list of file from filter
 object FileList
    FileList = dir(path & "*.*")
    if atom(FileList) then
        return {}
    end if
    return FilterList(FileList,filter)
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)
    position(2,1)
    bk_color(iInfoBack)
    text_color(iInfoText)
    if length(list) = 0 or index=0 then
       puts(1,"No files")
     else
       printf(1,"%14s   %5s  %8d   %4d/%2.2d/%2.2d  %2.2d:%2.2d:%2.2d",
            list[index])
    end if
    Clreol()
    puts(1,'\n')
end procedure --WriteFileInfo()

procedure WriteDriveList()
    position(3,1)
    bk_color(iInfoBack)
    text_color(iInfoText)
    for i = 1 to length(drives) do
        puts(1,drives[i] & ": ")
    end for
    Clreol()
    puts(1,'\n')
end procedure --WriteDriveList()

sequence padding
padding = repeat(32,NAME_FIELD)

procedure WriteFileName(integer i)
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

constant buttons=" <Filter> <"&17&"> <"&16&"> <"&24&"> <"&25&
          "> <PgUp> <PgDn> <Home> <End> <CANCEL>"


constant buttonsX={{3,8},{12,12},{16,16},{20,20},{24,24},{28,31},{35,38},
                   {42,45},{49,51},{55,60}}

constant ButtonsToKey={ALT_F,LEFT,RIGHT,UP,DOWN,PG_UP,PG_DOWN,HOME,END,
                       ESC}

procedure DisplayList(integer index)
-- Display the list HiLight the selected one
   sequence pos
   integer first,last
   if index = PrevIndex then
      return
   end if
   mouse_pointer(0)
   first = 1
   if index > ListLines*PerLine then
     first = floor(index/PerLine-ListLines+1)*PerLine+1
   end if
   if first = PrevFirst then
     position(4+floor((PrevIndex-first)/PerLine),
     NAME_FIELD*remainder(PrevIndex-first,PerLine)+1)
     bk_color(iListBack)
     WriteFileName(PrevIndex)
     position(4+floor((index-first)/PerLine),
              NAME_FIELD*remainder(index-first,PerLine)+1)
     bk_color(iSelected)
     WriteFileName(index)
     WriteFileInfo(index)
     PrevIndex = index
     mouse_pointer(1)
     return
   end if
   bk_color(iListBack)
   clear_screen()
   position(ScrLines,1)
   bk_color(iInfoBack)
   text_color(iInfoText)
   puts(1,buttons)
   Clreol()
   position(1,1)
   text_color(iInfoText)
   bk_color(iInfoBack)
   puts(1,repeat(32,2*ListCol))
   position(1,1)
   printf(1,"%s       files: %d\n",{Left(path&filter,60),length(list)})
   WriteFileInfo(index)
   WriteDriveList()
   if not length(list) then
      mouse_pointer(1)
      return  -- empty list
   end if
   last = Min(first+ListLines*PerLine-1,length(list))
   bk_color(iListBack)
   for  i = first to last by 1 do
        WriteFileName(i)
        if remainder(i,PerLine)=0 then
            pos = get_position()
            if pos[1] < ListLines + 3 then
              puts(1,"\n")
            end if
        end if
    end for
    position(4+floor((index-first)/PerLine),
              NAME_FIELD*remainder(index-first,PerLine)+1)
    bk_color(iSelected)
    WriteFileName(index)
    PrevFirst = first
    PrevIndex = index
    mouse_pointer(1)
end procedure --DisplayList


function NewSpec()
-- ask user for a new filter specification. Can be a new drive.
  sequence PathSplit, new_path, new_filter
  object input_line, new_list

    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 input_line[1] = 10   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
    if atom(dir(new_path&new_filter)) then -- check if valid filter.
        return list   -- if not return old list.
    end if
    path = new_path
    filter = new_filter
    new_list=CreateList(filter)
    if atom(new_list) then
        return list
    else
        return new_list
    end if
end function -- NewSpec()

constant NO_EVENT = 0, KEY_EVENT = 1, MOUSE_EVENT = 2  -- type of events

function GetEvent()
-- loop and wait for a mouse or key event.
integer key object mouse
    while 1 do
        key = ToUpper(get_key())
        if key > -1 then
            return {KEY_EVENT,key}
        end if
        mouse = get_mouse()
        if sequence(mouse) then
           if mouse[1] = LEFT_DOWN or mouse[1] = RIGHT_DOWN then
                return {MOUSE_EVENT,mouse}
           end if
        end if
    end while
end function -- GetEvent

function ConvertMouseToKey(sequence MouseEvent, integer index)
-- convert a mouse event to a key event.
integer  x,y, TmpIdx
    --trace(1)
    x = floor(MouseEvent[2]/8) + 1
    y = floor(MouseEvent[3]/8) + 1
       if y = 1 then
         if x <= length(path&filter) then
           return {ALT_F,index}
         else
           return {0,index}
         end if
       elsif y = 2 then
         return {ENTER,index}
       elsif y = 3 then
         TmpIdx = floor((x-1)/3) + 1
         if TmpIdx <= length(drives) then
            return {drives[TmpIdx],index}
         else
            return {0,index}
         end if
       elsif y = ScrLines then -- buttons
         TmpIdx = 0
         for i = 1 to length(buttonsX)  do
            if x >= buttonsX[i][1] and x <= buttonsX[i][2] then
                TmpIdx = ButtonsToKey[i]
                exit
            end if
         end for
         return {TmpIdx,index}
       elsif floor(x/NAME_FIELD)+1 <= PerLine then
          TmpIdx = PerLine*(y-4)+floor(x/NAME_FIELD) + 1
          if TmpIdx <= length(list) then
            if MouseEvent[1] = LEFT_DOWN then
               return {ENTER,TmpIdx}
            else
              return {0,TmpIdx}
            end if
          else
            return{0,index}
          end if
       else
          return {0,index}
       end if
end function -- convertMouseToKey()

function DoSelect()
-- navigate the list and return the index of the selected one
    integer index,char sequence event, KeyIndex
    index = 1
    while 1 do
      DisplayList(index)
      if iUseMouse then
        event = GetEvent()
        if event[1] = MOUSE_EVENT then
           KeyIndex = ConvertMouseToKey(event[2],index)
           char = KeyIndex[1]
           index = KeyIndex[2]
        else
           char = event[2]
        end if
      else
        char = ToUpper(get_key())
      end if
      if char = ESC then
          return 0
        elsif find(char,drives) then
           path = char&":\\"
           list = CreateList(filter)
           index = 1
           PrevIndex = 0   PrevFirst = 0
        elsif char = LEFT then
          if index > 1 then
            index = index - 1
          end if
        elsif char = RIGHT then
          if index < length(list) then
            index = index + 1
          end if
        elsif char = UP then
           if index > PerLine then
              index = index - PerLine
           end if
        elsif char = DOWN then
           if index <= length(list)-PerLine then
              index = index + PerLine
           end if
        elsif char = HOME then
            if index > 1 then
                index = 1
            end if
        elsif char = END then
            if index < length(list) then
                index = length(list)
            end if
        elsif char = PG_DOWN then
            if PrevFirst + PerLine*ListLines -1 < length(list)  then
                index = Min(index+ListLines*PerLine,length(list))
            end if
        elsif char = PG_UP then
            if index > ListLines*PerLine then
                index = index - ListLines*PerLine
            end if
        elsif char = ALT_F then
            list = NewSpec()
            index = 1
            PrevIndex = 0   PrevFirst = 0
        elsif char = 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(filter)
            index = 1
            PrevIndex = 0   PrevFirst = 0
          end if
       end if  -- case char
    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 screen
  cursor(NO_CURSOR)
  ScrLines = vc[VC_LINES]
  ScrCol = vc[VC_COLUMNS]
  ListLines = vc[VC_LINES] - 4
  ListCol = vc[VC_COLUMNS]
  PerLine = floor(ListCol/NAME_FIELD)
  list = CreateList(filter)
  PrevFirst = 0  PrevIndex = 0
  if MousePresent() then
     iUseMouse = 1  -- use mouse
     mouse_pointer(1) -- show mouse cursor
     mouse_events(LEFT_DOWN + RIGHT_DOWN)
  else
     iUseMouse = 0
  end if
  pick = DoSelect()
  if iUseMouse then
    mouse_pointer(0)  -- hide mouse cursor
  end if
  display_text_image({1,1},saved)
  -- text_color(OldColor) bk_color(OldBack)
  cursor(#0607)
  position(CurPos[1],CurPos[2])
  if pick then
     return path & list[pick][D_NAME]
   else
     return {}
  end if
end function -- ChooseFile

global procedure SetFListColors(sequence colors)
-- Set the color for the file list display
-- sequence structure:
-- { InfoLines_back_color, InfoLines_textColor, list_back_color,
--  list_file_name_color, list_directory_color, list_selected_back_color}
  iInfoBack = colors[1]
  iInfoText = colors[2]
  iListBack = colors[3]
  iFileName = colors[4]
  iDirName  = colors[5]
  iSelected = colors[6]
end procedure -- SetFListColors()

-- This will return a list of PHYSICAL floppy and hard drives
global function GetDriveList()
  integer hdn,fdn
  sequence fl,hl,cdl, cdId
  object d

  fdn = floor(peek(#410) / 64)
  if fdn = 0 then
    fl = "A"
  elsif fdn = 1 then
    fl = "AB"
  end if

  hdn = peek(#475)
  if hdn = 1 then
     hl = "C"
     cdId = "D:"
  elsif hdn = 2 then
     hl = "CD"
     cdId = "E:"
  end if
--check for CD-ROM
  d = {}
  cdl = ""
  while not atom(d) do
      d = dir(cdId)
      if sequence(d) then
          cdl = cdl & cdId[1]
          cdId[1] = cdId[1] + 1
      end if
  end while
  return fl & hl & cdl
end function -- GetDriveList()

-------------------------------------------------------------------------------

-- initialisation

drives = GetDriveList()

SetFListColors({BLUE, WHITE, BROWN, WHITE, BLACK, GREEN}) -- default colors

--if test then
--  puts(1,"Selected file is " & ChooseFile("*.*")&'\n')
--end if


--=====================_848990548==_

Jacques Deschenes
Baie-Comeau, Quebec
Canada
desja at quebectel.com

--=====================_848990548==_--

new topic     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu