

-- WHDLoad menu for AROS by Yannick Erb
-- Version 0.2

require "muidefs"
require "muifuncs"
require "muiasl"
require "lfs"

-- Global Identifier for ZUNE interface
GameList_ID      = 50
CurrentGame_ID   = 51
Image_ID         = 52
ReadMe_ID        = 53
Path_ID          = 54
Option_ID        = 55
Launch_ID        = 56
Configure_ID     = 57
Exit_ID          = 58
ListView_ID      = 59
CurGenre_ID      = 60
DispFilt_ID      = 61
Remove_ID        = 62
Delete_ID        = 63
Conf_CloseReq_ID = 100
Conf_Cancel_ID   = 101
Conf_Save_ID     = 102
Conf_Gen_ID      = 103
Conf_DB_ID       = 104
Conf_SP_ID       = 105
Conf_IP_ID       = 106
Conf_UAE_ID      = 107
Conf_RC_ID       = 108
Conf_SYS_ID      = 109
Conf_WRK_ID      = 110
Conf_SS_ID       = 111
Gen_CloseReq_ID  = 200
Gen_Start_ID     = 201
Gen_Cancel_ID    = 202

-- Global Variables from configuration file
ConfigFile = "WHD_MENU.cfg"
DBName     = ""
SearchPath = ""
ImageType  = ""
UAEexe     = ""
UAErc      = ""
UAEsys     = ""
UAEwrk     = ""
UAEss      = ""

-- Global "defines"
GameGenre = strarray.new("Not Classified","Adventure","Arcade","FPS","RPG","Shoot'em UP","Beat'em UP","Racing","Point&Click","Platform","Sports","Simulation","Puzzle")
GameGenreFilt = strarray.new("ALL","Not Classified","Adventure","Arcade","FPS","RPG","Shoot'em UP","Beat'em UP","Racing","Point&Click","Platform","Sports","Simulation","Puzzle")

-- Tables for DB information temp storage
Nb_Entries = 0 -- Initialise Nb of DB entries to 0
SearchDB = {}  -- Only used while searching slaves
DataBase = {}  -- Table containing current DB
Name      = 1
Path      = 2
ToolTypes = 3
Favorite  = 4
Genre     = 5
Year      = 6

DB_Modified = false

function Launch_Game()
-- This function launches j-uae with selected uaerc.config
-- and modified startup-sequence in order to directly launch the game
  local cmd_line
  local ss
  local path_in_uae
  local error_return
  
  if ActiveGame == nil then
    app:request(window, 0 , "Launching Game : ERROR", "OK", "You must select a game first")
  else
    out = app:request(window, 0 , "Launching Game", "OK|CANCEL", DataBase[ActiveGame][Path] .. DataBase[ActiveGame][Name].."\noptions : "..DataBase[ActiveGame][ToolTypes]) 
    if out == 1 then
      -- close all windows
      mui.set(app,mui.MUIA_Application_Iconified,true)
      -- modify WHD_MENU-startup as needed
      path_in_uae = string.gsub(DataBase[ActiveGame][Path],UAEwrk,"WORK:")
      os.execute("c:copy "..UAEss.." tmp_file QUIET")
      cmd_line = "c:cd "..path_in_uae.."\nc:whdload "..DataBase[ActiveGame][Name]..".slave".." "..DataBase[ActiveGame][ToolTypes]
      ss,error_return = io.open("tmp_file","a+")
      if ss == nil then
        print("Error opening tmp_file: "..error_return)
      end
      ss:write(cmd_line)
      ss:close()
      -- copy WHD_MENU-Startup in place   
      cmd_line = "copy tmp_file "..UAEsys.."s/WHD_MENU-startup MOVE"
      os.execute(cmd_line) 
      -- launch j-uae with uaerc.config file from WHD_MENU config file
      cmd_line = UAEexe.." -f "..UAErc.." -v4 -c4 -Z8 -G <NIL: >NIL:"
      os.execute(cmd_line)
      -- Remove WHD_MENU-startup
      cmd_line = "c:delete "..UAEsys.."s/WHD_MENU-startup QUIET"
      os.execute(cmd_line)
      -- open all windows again
      mui.set(app,mui.MUIA_Application_Iconified,false)     
    end
  end
end  


function Get_File_Path(file)
-- returns separately File and Path from file string
  local lFile, lPath
  
  local l = string.len(file)
  local pos = string.find(string.reverse(file),'/')
  if pos==nil then
    return "",file
  else
    return string.sub(file,1,l-pos+1),string.sub(file,-pos+1) 
  end

end

function Get_TOOLTYPES(file)
-- Extract TOOLTYPES from icon file using "processicon" tool.  
  local TT = ""
  local ext_cmd
    
  -- execute processicon
  ext_cmd = "work:Extras/Misc/aminet/C/processicon " .. file.. " VIEW > T:PI.output"
  os.execute(ext_cmd)
  
  -- read processiscon output and get TOOLTYPE
  local existTT = false
  for line in io.lines("T:PI.output") do
    if existTT and string.sub(line,3,3)~=";" and string.sub(line,3,3)~="(" and string.sub(line,3,3)~=" " and string.upper(string.sub(line,3,7))~="SLAVE" then
       TT = TT ..  string.sub(line,3) .. " "
    end
    if string.find(line, "TT") ~= nil and string.find(line, "YES") ~= nil then 
      existTT = true
    end
  end
  
  return TT
end

function SearchSlaves(path)

  local name_loc 
  local path_loc
  local file_comp
  local tt_loc = ""   
  
  if path == "" or string.sub(path,-1) == ":" or string.sub(path,-1) == "/" then
    path_loc = path
  else
    path_loc = path.."/"
  end
  mui.set(Gen_Action_txt, mui.MUIA_Text_Contents, "Searching in "..path_loc)   
  for file in lfs.dir(path) do
    
    file_comp = path_loc..file
    local attr = lfs.attributes (file_comp)
    assert (type(attr) == "table")
    if attr.mode == "directory" then
      SearchSlaves(file_comp)
    elseif string.upper(string.sub(file,-6))==".SLAVE" then
      nb_slaves = nb_slaves+1
      mui.set(Gen_Counter_txt, mui.MUIA_Text_Contents, tostring(nb_slaves))
      name_loc = string.sub(file,1,-7)
      tt_loc = Get_TOOLTYPES(path_loc .. name_loc .. ".info")
      SearchDB[nb_slaves] = string.sub(file,1,-7)..","..path_loc..","..tt_loc..","
    end
  end
end

function Update_DB()
  -- Save modifications made to previous Active            
  if PreviousActive ~= nil then
    -- Save changes in DB
    PreviousActiveRecord = {}
    PreviousActiveRecord[Name]      = DataBase[PreviousActive][Name]
    PreviousActiveRecord[Path]      = DataBase[PreviousActive][Path]
    PreviousActiveRecord[ToolTypes] = mui.getstr(CurrentOption,mui.MUIA_String_Contents)
    PreviousActiveRecord[Favorite]  = tostring(mui.getbool(CurrentIsFavorite,mui.MUIA_Selected))
    PreviousActiveRecord[Genre]     = strarray.get(GameGenre,mui.getint(CurrentGenre,mui.MUIA_Cycle_Active)+1)
    PreviousActiveRecord[Year]      = mui.getstr(CurrentYear,mui.MUIA_String_Contents)
        
    if    PreviousActiveRecord[Name]      ~= DataBase[PreviousActive][Name]
      or PreviousActiveRecord[Path]      ~= DataBase[PreviousActive][Path]
      or PreviousActiveRecord[ToolTypes] ~= DataBase[PreviousActive][ToolTypes]
      or PreviousActiveRecord[Favorite]  ~= DataBase[PreviousActive][Favorite]
      or PreviousActiveRecord[Genre]     ~= DataBase[PreviousActive][Genre]
      or PreviousActiveRecord[Year]      ~= DataBase[PreviousActive][Year] then

      -- Changes were made
      DB_Modified = true 
      DataBase[PreviousActive] = PreviousActiveRecord  
    end
  end   
  PreviousActive = ActiveGame
end

function Generate_db()
-- Generates the DataBase file
  nb_slaves = 0
  
  Gen_Win_run = true
  
  Gen_window:set(mui.MUIA_Window_Open, true)

  while Gen_Win_run do
    id, signals = app:input()
    if id == Gen_CloseReq_ID or id == Gen_Cancel_ID then
      Gen_Win_run = false
    elseif id == Gen_Start_ID then
      -- erase DataBase
      mui.set(Gen_Action_txt, mui.MUIA_Text_Contents, "Erasing existing Database...")
      SearchDB = {}
      mui.set(Gen_Action_txt, mui.MUIA_Text_Contents, "Searching in "..SearchPath)
      SearchSlaves(SearchPath)
      mui.set(Gen_Action_txt, mui.MUIA_Text_Contents, "Sorting Games...")
      table.sort(SearchDB)
      mui.set(Gen_Action_txt, mui.MUIA_Text_Contents, "Saving Database to "..DBName)
      DBfile = io.open(DBName,"w+")
      for i=1,nb_slaves,1 do
        DBfile:write(SearchDB[i].."false,Not Classified,0000,\n")
      end
      DBfile:close()
      mui.set(Gen_Action_txt, mui.MUIA_Text_Contents, "Done")
    end
    if Gen_Win_Run then mui.wait(signals) end
  end  
  Gen_window:set(mui.MUIA_Window_Open, false)
  
end

function SaveConfig()
-- Saves the configuration file
   local cf
   
   cf = io.open(ConfigFile,"w+")
   
   cf:write("DataBase file:\n")
   cf:write(DBName .. "\n")
   cf:write("Game Search Path (root directory:)\n")
   cf:write(SearchPath .. "\n")
   cf:write("Image Type:\n")
   cf:write(ImageType .. "\n")
   cf:write("UAE executable:\n")
   cf:write(UAEexe .. "\n")
   cf:write("UAE config file to be used:\n")
   cf:write(UAErc .. "\n")
   cf:write("Emulated SYS: directory:\n")
   cf:write(UAEsys .. "\n")
   cf:write("Emulated WORK: directory (Games must be in this path):\n")
   cf:write(UAEwrk .. "\n")
   cf:write("Startup-Sequence to be used within emulator:\n")
   cf:write(UAEss .. "\n")
   
   cf:close()
   
end

function Configure()
-- Manage configuration
  local tmp
  local ifile  
  local ipath 


  -- open  configuration window
  mui.set(DB_h, mui.MUIA_String_Contents,  DBName)
  mui.set(SP_h, mui.MUIA_String_Contents,  SearchPath)
  mui.set(UAE_h, mui.MUIA_String_Contents, UAEexe)
  mui.set(RC_h, mui.MUIA_String_Contents,  UAErc)
  mui.set(SYS_h, mui.MUIA_String_Contents, UAEsys)
  mui.set(WRK_h, mui.MUIA_String_Contents, UAEwrk)
  mui.set(SS_h, mui.MUIA_String_Contents,  UAEss)
  local a = tonumber(ImageType)
  if a == nil then a = 0 end
  mui.set(IP_h, mui.MUIA_Cycle_Active, a)
  Conf_window:set(mui.MUIA_Window_Open, true)
  confGUIrun = true
  
  while confGUIrun do
    id, signals = app:input()
	
    if id == Conf_Cancel_ID or id == Conf_CloseReq_ID then
      DBName   = mui.getstr(DB_h, mui.MUIA_String_Contents)
      SearchPath = mui.getstr(SP_h, mui.MUIA_String_Contents)
      UAEexe     = mui.getstr(UAE_h, mui.MUIA_String_Contents)
      UAErc      = mui.getstr(RC_h, mui.MUIA_String_Contents)
      UAEsys     = mui.getstr(SYS_h, mui.MUIA_String_Contents)
      UAEwrk     = mui.getstr(WRK_h, mui.MUIA_String_Contents)
      UAEss      = mui.getstr(SS_h, mui.MUIA_String_Contents)
      ImageType  = mui.getint(IP_h, mui.MUIA_Cycle_Active)
      if DBName == "" or SearchPath == "" or UAEexe == "" or UAErc == "" or UAEsys == "" or UAEwrk == "" or UAEss == "" then
        app:request(Conf_window, 0 , "Configuration Error", "OK", "All configuration fields must be filled in!")
      else
        confGUIrun = false
      end		
    elseif id == Conf_Save_ID then
      DBName   = mui.getstr(DB_h, mui.MUIA_String_Contents)
      SearchPath = mui.getstr(SP_h, mui.MUIA_String_Contents)
      UAEexe     = mui.getstr(UAE_h, mui.MUIA_String_Contents)
      UAErc      = mui.getstr(RC_h, mui.MUIA_String_Contents)
      UAEsys     = mui.getstr(SYS_h, mui.MUIA_String_Contents)
      UAEwrk     = mui.getstr(WRK_h, mui.MUIA_String_Contents)
      UAEss      = mui.getstr(SS_h, mui.MUIA_String_Contents)
      ImageType  = mui.getint(IP_h, mui.MUIA_Cycle_Active)
      if DBName == "" or SearchPath == "" or UAEexe == "" or UAErc == "" or UAEsys == "" or UAEwrk == "" or UAEss == "" then
        app:request(Conf_window, 0 , "Configuration Error", "OK", "All configuration fields must be filled in!")
      else
        SaveConfig()
        confGUIrun = false
      end	      
    elseif id == Conf_Gen_ID then
      Generate_db()     
    elseif id == Conf_DB_ID then
      ipath, ifile = Get_File_Path(DBName)
      if ipath=="" then ipath = lfs.currentdir() end
      tmp = mui.filerequest(
              mui.ASLFR_InitialFile,     ifile,
              mui.ASLFR_InitialDrawer,   ipath
            )             
      if tmp ~= nil then
        DBName = tmp
        mui.set(DB_h, mui.MUIA_String_Contents,  DBName)
      end
    elseif id == Conf_SP_ID then
      ipath = SearchPath
      if ipath=="" then ipath = lfs.currentdir() end
      tmp = mui.filerequest(
              mui.ASLFR_DrawersOnly, true,
              mui.ASLFR_InitialDrawer, ipath
            )
      if tmp ~= nil then
        SearchPath = Get_File_Path(tmp)
        mui.set(SP_h, mui.MUIA_String_Contents,  SearchPath)
      end
    elseif id == Conf_UAE_ID then
      ipath, ifile = Get_File_Path(UAEexe)
      if ipath=="" then ipath = lfs.currentdir() end
      tmp = mui.filerequest(
              mui.ASLFR_InitialFile,     ifile,
              mui.ASLFR_InitialDrawer,   ipath
            )             
      if tmp ~= nil then
        UAEexe= tmp
        mui.set(UAE_h, mui.MUIA_String_Contents,  UAEexe)
      end
    elseif id == Conf_RC_ID then
      ipath, ifile = Get_File_Path(UAErc)
      if ipath=="" then ipath = lfs.currentdir() end
      tmp = mui.filerequest(
              mui.ASLFR_InitialFile,     ifile,
              mui.ASLFR_InitialDrawer,   ipath
            )             
      if tmp ~= nil then
        UAErc = tmp
        mui.set(RC_h, mui.MUIA_String_Contents,  UAErc)
      end      
    elseif id == Conf_SYS_ID then
      ipath = UAEsys
      if ipath=="" then ipath = lfs.currentdir() end
      tmp = mui.filerequest(
              mui.ASLFR_InitialDrawer, ipath
            )             
      if tmp ~= nil then
        UAEsys= Get_File_Path(tmp)
        mui.set(SYS_h, mui.MUIA_String_Contents,  UAEsys)
      end      
    elseif id == Conf_WRK_ID then
      ipath = UAEwrk
      if ipath=="" then ipath = lfs.currentdir() end
      tmp = mui.filerequest(
              mui.ASLFR_InitialDrawer, ipath
            )             
      if tmp ~= nil then
        UAEwrk = Get_File_Path(tmp)
        mui.set(WRK_h, mui.MUIA_String_Contents,  UAEwrk)
      end      
    elseif id == Conf_SS_ID then
      ipath, ifile = Get_File_Path(UAEss)
      if ipath=="" then ipath = lfs.currentdir() end
      tmp = mui.filerequest(
              mui.ASLFR_InitialFile,     ifile,
              mui.ASLFR_InitialDrawer,   ipath
            )             
      if tmp ~= nil then
        UAEss = tmp
        mui.set(SS_h, mui.MUIA_String_Contents,  UAEss)
      end      
    end
    if confGUIrun then mui.wait(signals) end
  end
  
  Conf_window:set(mui.MUIA_Window_Open, false)
  
end

function LoadConf()
-- Loads the configuration file
  local cf
  
  cf = io.open(ConfigFile,"r")
    
  if cf == nil then
    -- Configuration File doesn't exist let's create it
    while DBName == "" or SearchPath == "" or UAEexe == "" or UAErc == "" or UAEsys == "" or UAEwrk == "" or UAEss == "" do
      Configure()
    end
  else
    -- Load Configuration file
    cf:read("*l")
    DBName = cf:read("*l")
    cf:read("*l")
    SearchPath = cf:read("*l")
    cf:read("*l")
    ImageType = tonumber(cf:read("*l"))
    if ImageType == nil then ImageType = 0 end
    cf:read("*l")
    UAEexe= cf:read("*l")
    cf:read("*l")
    UAErc = cf:read("*l")
    cf:read("*l")
    UAEsys = cf:read("*l")
    cf:read("*l")
    UAEwrk = cf:read("*l")
    cf:read("*l")
    UAEss = cf:read("*l")
    cf:close()
  end
end


function Load_ReadMe()
-- Loads the ReadMe file corrsponding to the selected game
  
  local ReadMe_txt = {}
  local nblines = 0
  local line = "" 
  local filename = DataBase[ActiveGame][Path] .. "Readme"
  local fh 
    
  fh = io.open(filename,"r")
  if fh == nil then
    ReadMe_txt[1] = filename
    ReadMe_txt[2] = "not found"    
  else
    for line in fh:lines() do
      nblines = nblines + 1
      ReadMe_txt[nblines] = line
    end
    fh:close()  
  end
  
  return table.maxn(ReadMe_txt),ReadMe_txt
  
end  

function extract_db_line(Line)
-- extract one line (record) from the DB file and returns the information.
  local L = {}
  local fieldstart = 1
  local count = 1
  
  repeat
    local nexti = string.find(Line,",",fieldstart)
    L[count] = string.sub(Line,fieldstart,nexti-1)
    fieldstart = nexti+1
    count = count+1
  until fieldstart > string.len(Line)
  
  return L

end

function loaddb()
-- Loads the information from the DB and stores it inside tables
  local db_file 
  local NewLine

  db_file = io.open(DBName,"r")
  
  if db_file == nil then
    -- db file is not existing, let's generate it!
    app:request(Conf_window, 0 , "No DataBase", "OK", "DataBase "..DBName.." does not exist\nSelect another one or generate it!")
    Configure()
    -- and finally open it for reading
    db_file = io.open(DBName,"r")
  end
  
  for NewLine in io.lines(DBName) do
      Nb_Entries = Nb_Entries+1
      DataBase[Nb_Entries] = extract_db_line(NewLine)
  end
end

function savedb()
-- Saves the information in the DB file
  local db_file 

  db_file = io.open(DBName,"w+")
    
  for i=1,Nb_Entries,1 do
    if DataBase[i] ~=nil then
      db_file:write(DataBase[i][Name]..","..DataBase[i][Path]..","..DataBase[i][ToolTypes]..","..
	            DataBase[i][Favorite]..","..DataBase[i][Genre] ..","..DataBase[i][Year]..",\n")
    end
  end
  db_file:close()
end

function creategui() 

  -- Create Main Window GUI
  
  Launch_button    = mui.SimpleButton("LAUNCH")
  Configure_button = mui.SimpleButton("CONFIGURE")
  Exit_button      = mui.SimpleButton("EXIT")
  Remove_button    = mui.SimpleButton("Remove from DB")
  Delete_button    = mui.SimpleButton("Delete from HD")
  
  CurrentGame = mui.TextObject(
                 mui.MUIA_Text_Contents, "NONE",
                 mui.MUIA_ObjectID, CurrentGame_ID)
                 
  CurrentImage = mui.ImagedisplayObject(
  		   mui.MUIA_FixWidth, 320,
  		   mui.MUIA_FixHeight, 256,
  		   mui.MUIA_Imagedisplay_FreeHoriz, true,
  		   mui.MUIA_Imagedisplay_FreeVert, true,
  		   mui.MUIA_Imagedisplay_UseDefSize, true,
                   mui.MUIA_Imagedisplay_Spec,"5:Default_Screenshot.png",
                   mui.MUIA_ObjectID, Image_ID)
  
  CurrentPath = mui.TextObject(
                  mui.MUIA_Text_Contents, "",
                  mui.MUIA_ObjectID, Path_ID)
                    
  CurrentReadMe = mui.ListObject()
       
  CurrentOption = mui.StringObject(
                    mui.MUIA_Frame, mui.MUIV_Frame_String,
                    mui.MUIA_String_Contents, "",
		    mui.MUIA_String_MaxLen, 128,
                    mui.MUIA_ObjectID, Option_ID) 
					                    
  Game_list = mui.ListObject()
  
  CurrentYear = mui.StringObject(
                  mui.MUIA_Frame, mui.MUIV_Frame_String,
                  mui.MUIA_String_Format, mui.MUIV_String_Format_Right,
                  mui.MUIA_String_Contents, "0000",
  		  mui.MUIA_String_MaxLen, 5)

  CurrentGenre = mui.CycleObject(
                   mui.MUIA_Cycle_Entries, GameGenre,
                   mui.MUIA_Cycle_Active, 0,
                   mui.MUIA_ObjectID, CurGenre_ID)  

  
  CurrentIsFavorite = mui.make(mui.MUIO_Checkmark, "")
  CurrentIsFavorite:setcheckmark(false)
  
  DisplayFavorite = mui.make(mui.MUIO_Checkmark, "")
  DisplayFavorite:setcheckmark(false)
  
--  DisplayFilter = mui.make(mui.MUIO_Checkmark, "")
--  DisplayFilter:setcheckmark(false)  
--  mui.set(DisplayFilter,mui.MUIA_ObjectID,DispFilt_ID)
					  
  DisplayGenre = mui.CycleObject(
                   mui.MUIA_Cycle_Entries, GameGenreFilt,
                   mui.MUIA_Cycle_Active, 0)

  window = mui.WindowObject(
    mui.MUIA_Window_Title , "WHD_MENU",
    mui.MUIA_Window_ID    , mui.makeid("WHDM"),
    mui.MUIA_Window_Width , mui.MUIV_Window_Width_Screen(80),
    mui.MUIA_Window_Height, mui.MUIV_Window_Height_Screen(80),
    mui.WindowContents, mui.HGroup(
    
      mui.Child, mui.VGroup(
    
        mui.MUIA_Frame, mui.MUIV_Frame_Group, 

        mui.Child, mui.VGroup(
          mui.MUIA_Frame, mui.MUIV_Frame_Group,
	  mui.Child, mui.HGroup(
	    mui.Child, mui.Label("Favorites: "),
            mui.Child, DisplayFavorite,
            mui.Child, mui.Label("Genre: "),
            mui.Child, DisplayGenre
          )
        ),

        mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),

        mui.Child, mui.ListviewObject(
          mui.MUIA_Listview_List,Game_list,
          mui.MUIA_ObjectID,ListView_ID
        ),
      
        mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
      
        mui.Child, CurrentGame,
		
        mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),

        mui.Child, mui.HGroup(
          mui.Child, Remove_button,
		  mui.Child, Delete_button
        )	
      ),
      
      mui.Child, mui.VGroup(
        mui.Child, mui.VGroup(
          mui.MUIA_Frame, mui.MUIV_Frame_Group,
        
          mui.Child, mui.HGroup(
            mui.Child, mui.ImageObject(mui.MUIA_Image_Spec,"5:Title.png"),
            mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
            mui.Child, CurrentImage
          ),
        
          mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),

          mui.Child, mui.HGroup(
            mui.MUIA_Frame, mui.MUIV_Frame_Group,
            mui.Child, mui.Label("Favorite: "),
            mui.Child, CurrentIsFavorite,
            mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
            mui.Child, mui.Label("Genre :"),
            mui.Child, CurrentGenre,
            mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
            mui.Child, mui.Label("Year :"),
	    mui.Child, CurrentYear
          ),

          mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
          
          mui.Child, mui.HGroup(
            mui.Child, mui.Label1("OPTION:"),
            mui.Child, CurrentOption
          ),
		  
          mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
                    
          mui.Child, mui.ListviewObject(
            mui.MUIA_Weight, 100,
            mui.MUIA_Listview_List,CurrentReadMe
          ),
                 
          mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
          
          mui.Child, mui.HGroup(
            mui.Child, mui.Label("PATH:"),
            mui.Child, CurrentPath
          )
          
        ),
                                                                              
        mui.Child, mui.HGroup(
          mui.MUIA_Frame, mui.MUIV_Frame_Group,
          mui.Child, Launch_button,
          mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
          mui.Child, Configure_button,
          mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
          mui.Child, Exit_button
        )
      )
    )
  )

  -- creates the GUI for configuration window
  
  Cancel_button   = mui.SimpleButton("CANCEL")
  Save_button     = mui.SimpleButton("SAVE")
  Generate_button = mui.SimpleButton("GENERATE DATABASE")
  DBReq_button    = mui.SimpleButton("Select")
  SPReq_button    = mui.SimpleButton("Select")
  UAEReq_button   = mui.SimpleButton("Select")
  RCReq_button    = mui.SimpleButton("Select")
  SYSReq_button   = mui.SimpleButton("Select")
  WRKReq_button   = mui.SimpleButton("Select")
  SSReq_button    = mui.SimpleButton("Select")
  
    
  DB_h = mui.StringObject(
           mui.MUIA_Frame, mui.MUIV_Frame_String,
           mui.MUIA_Weight, 2000,
           mui.MUIA_String_Contents, "",
           mui.MUIA_String_MaxLen, 128)
             
  SP_h = mui.StringObject(
           mui.MUIA_Frame, mui.MUIV_Frame_String,
           mui.MUIA_String_Contents, "",
           mui.MUIA_String_MaxLen, 128)
             
  UAE_h = mui.StringObject(
           mui.MUIA_Frame, mui.MUIV_Frame_String,
           mui.MUIA_String_Contents, "",
           mui.MUIA_String_MaxLen, 128)

  RC_h = mui.StringObject(
           mui.MUIA_Frame, mui.MUIV_Frame_String,
           mui.MUIA_String_Contents, "",
           mui.MUIA_String_MaxLen, 128)

  SYS_h = mui.StringObject(
           mui.MUIA_Frame, mui.MUIV_Frame_String,
           mui.MUIA_String_Contents, "",
           mui.MUIA_String_MaxLen, 128)

  WRK_h = mui.StringObject(
           mui.MUIA_Frame, mui.MUIV_Frame_String,
           mui.MUIA_String_Contents, "",
           mui.MUIA_String_MaxLen, 128)

  SS_h = mui.StringObject(
           mui.MUIA_Frame, mui.MUIV_Frame_String,
           mui.MUIA_String_Contents, "",
           mui.MUIA_String_MaxLen, 128)

  IP_h = mui.CycleObject(
           mui.MUIA_Frame, mui.MUIV_Frame_String,
           mui.MUIA_Cycle_Entries, strarray.new("From Icon file", "From PNG Files"))

  Conf_window = mui.WindowObject(
    mui.MUIA_Window_Title , "WHD_MENU Configuration",
    mui.MUIA_Window_ID    , mui.makeid("WHDC"),
    mui.MUIA_Window_Width , mui.MUIV_Window_Width_Screen(60),
    mui.MUIA_Window_Height, mui.MUIV_Window_Height_Screen(60),
    mui.WindowContents, mui.VGroup(
    
      mui.Child, mui.GroupObject(
        mui.MUIA_Group_Columns,3,
        mui.Child, mui.Label("DataBase file:"),
        mui.Child, DB_h,
        mui.Child, DBReq_button,
        mui.Child, mui.Label("Game Path:"),
        mui.Child, SP_h,
        mui.Child, SPReq_button,
        mui.Child, mui.Label("UAE exe:"),
        mui.Child, UAE_h,
        mui.Child, UAEReq_button,
        mui.Child, mui.Label("UAE config:"),
        mui.Child, RC_h,
        mui.Child, RCReq_button,
        mui.Child, mui.Label("UAE Sys:"),
        mui.Child, SYS_h,
        mui.Child, SYSReq_button,
        mui.Child, mui.Label("UAE WORK:"),
        mui.Child, WRK_h,
        mui.Child, WRKReq_button,
        mui.Child, mui.Label("WHD Startup:"),
        mui.Child, SS_h,
        mui.Child, SSReq_button
      ),        

      mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
      
      mui.Child, mui.HGroup(
        mui.Child, mui.Label("Screenshot Type:"),
        mui.Child, IP_h
      ),
          
      mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),
      
      mui.Child, Generate_button,
      
      mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),

      mui.Child,mui.HGroup(
        mui.Child, Save_button,
        mui.Child, Cancel_button
      )
    )
  )
  
  -- creates the GUI for DataBase Generation window
  
  Gen_Start_button   = mui.SimpleButton("START")
  Gen_Cancel_button  = mui.SimpleButton("CLOSE")

  Gen_Action_txt = mui.TextObject(mui.MUIA_Text_Contents, "")

  Gen_Counter_txt = mui.TextObject(mui.MUIA_Text_Contents, "")

 
  Gen_window = mui.WindowObject(
    mui.MUIA_Window_Title , "WHD_MENU DataBase Generation",
    mui.MUIA_Window_ID    , mui.makeid("GENW"),
    mui.MUIA_Window_Width , mui.MUIV_Window_Width_Screen(40),
    mui.MUIA_Window_Height, mui.MUIV_Window_Height_Screen(40),
    mui.WindowContents, mui.VGroup(
    
      mui.Child, mui.GroupObject(
        mui.MUIA_Group_Columns,2,
        mui.Child, mui.Label("Action:"),
        mui.Child, Gen_Action_txt,
        mui.Child, mui.Label("Game Found:"),
        mui.Child, Gen_Counter_txt
      ),        
      
      mui.Child, mui.BalanceObject(mui.MUIA_CycleChain, 1),

      mui.Child,mui.HGroup(
        mui.Child, Gen_Start_button,
        mui.Child, Gen_Cancel_button
      )
    )
  )

  -- Create Application

  app = mui.ApplicationObject(
    mui.MUIA_Application_Title      , "WHD_MENU",
    mui.MUIA_Application_Version    , "$VER: WHD_LOAD MENU v0.2 September 2009",
    mui.MUIA_Application_Author     , "Yannick Erb",
    mui.MUIA_Application_Description, "Menu for launching WHDLoad games under AROS",
    mui.MUIA_Application_Base       , "WHD_MENU",
    mui.MUIA_Application_Window     , window,
    mui.MUIA_Application_Window     , Conf_window,
    mui.MUIA_Application_Window     , Gen_window
  )

  -- Start Application

  assert(app:check(), "Failed to create Application.")

  -- Initialise GUI Notifications

  window:doint(mui.MUIM_Notify, mui.MUIA_Window_CloseRequest, true,
    app, 2, mui.MUIM_Application_ReturnID, mui.MUIV_Application_ReturnID_Quit)

  Launch_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Launch_ID)

  Configure_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Configure_ID)

  Exit_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Exit_ID)
    
  Remove_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Remove_ID)
    
  Delete_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Delete_ID)
    
  Game_list:doint(mui.MUIM_Notify, mui.MUIA_Listview_SelectChange,true,
    app, 2, mui.MUIM_Application_ReturnID, GameList_ID)

  DisplayGenre:doint(mui.MUIM_Notify, mui.MUIA_Cycle_Active, mui.MUIV_EveryTime,
    app, 2, mui.MUIM_Application_ReturnID, DispFilt_ID)
	
  DisplayFavorite:doint(mui.MUIM_Notify, mui.MUIA_Selected,true,
    app, 2, mui.MUIM_Application_ReturnID, DispFilt_ID)  
  DisplayFavorite:doint(mui.MUIM_Notify, mui.MUIA_Selected,false,
    app, 2, mui.MUIM_Application_ReturnID, DispFilt_ID)  
    
  Conf_window:doint(mui.MUIM_Notify, mui.MUIA_Window_CloseRequest, true,
    app, 2, mui.MUIM_Application_ReturnID, Conf_CloseReq_ID)

  Generate_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_Gen_ID)

  Save_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_Save_ID)

  Cancel_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_Cancel_ID)

  DBReq_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_DB_ID)

  SPReq_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_SP_ID)

  UAEReq_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_UAE_ID)

  RCReq_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_RC_ID)

  SYSReq_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_SYS_ID)

  WRKReq_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_WRK_ID)

  SSReq_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Conf_SS_ID)
    
  Gen_window:doint(mui.MUIM_Notify, mui.MUIA_Window_CloseRequest, true,
    app, 2, mui.MUIM_Application_ReturnID, Gen_CloseReq_ID) 

  Gen_Start_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Gen_Start_ID)

  Gen_Cancel_button:doint(mui.MUIM_Notify, mui.MUIA_Pressed, false,
    app, 2, mui.MUIM_Application_ReturnID, Gen_Cancel_ID)
end

function main()

  PreviousActive = nil
  PreviousActiveRecord = nil

  Image = "5:Default_Screenshot.png"
  CounterImage = 0

-- Create the Graphical User Interface  
  creategui()
  running = true

-- load configuration file
  LoadConf()

-- Load the DataBase
  loaddb(DBName)
  
-- fill in list with entries from db file  
  for i=1,Nb_Entries,1 do
    Game_list:doint(mui.MUIM_List_InsertSingle,DataBase[i][Name],mui.MUIV_List_Insert_Bottom)
  end

-- Open Main Window
   window:set(mui.MUIA_Window_Open, true)

-- Main loop
  while running do
    id, signals = app:input()
    if id == mui.MUIV_Application_ReturnID_Quit or id == Exit_ID then
      Update_DB()
      if DB_Modified then
        -- Shall we save the changes made to the database?
        out = app:request(window, 0 , "Save DataBase modifications", "YES|NO", "Shall the modifications made to the DataBase be saved?")
        if out == 1 then savedb() end
      end  
      running = false
      
    elseif id == Configure_ID then
      Configure()
      
    elseif id == Launch_ID then
      Launch_Game() 
      
    elseif id == DispFilt_ID then
      --remove all entries that are not corresponding to the filter
      -- get filter
--      local IsFiltered = mui.getbool(DisplayFilter,mui.MUIA_Selected)
      local FiltFav = mui.getbool(DisplayFavorite,mui.MUIA_Selected)
      local FiltGenre = strarray.get(GameGenreFilt,mui.getint(DisplayGenre,mui.MUIA_Cycle_Active)+1)
      -- Set List QUIET to avoid interface flashing
      mui.set(Game_list,mui.MUIA_List_Quiet,true)	  	  
      -- Emtpy List
      Game_list:doint(mui.MUIM_List_Clear)	  
      -- Fill List with entries corresponding to filter DB
      for i=1,Nb_Entries,1 do
        -- Get Fav
        local IsFav = (DataBase[i][Favorite] == "true")
        if (((FiltFav and IsFav) or not(FiltFav)) and (FiltGenre=="ALL" or FiltGenre == DataBase[i][Genre])) then	    
          Game_list:doint(mui.MUIM_List_InsertSingle,DataBase[i][Name],mui.MUIV_List_Insert_Bottom)
        end  
      end
      -- Unset List QUIET
      mui.set(Game_list,mui.MUIA_List_Quiet,false)
      PreviousActive = nil
	  
      elseif id == Remove_ID and ActiveGame ~= nil then
        out = app:request(window, 0 , "Remove entry from DB", "YES|NO", "Are you sure you want to remove "..DataBase[ActiveGame][Name].."from the DataBase?")
        if out == 1 then
          table.remove(DataBase,ActiveGame)
          Game_list:doint(mui.MUIM_List_Remove,mui.getint(Game_list,mui.MUIA_List_Active))
          DB_Modified = true
          PreviousActive = nil
          Nb_Entries = Nb_Entries - 1		
        end	
	
      elseif id == Delete_ID and ActiveGame ~= nil then
        out = app:request(window, 0 , "Remove entry from DB and Delete Game", "YES|NO",
                          "Are you sure you want to remove "..DataBase[ActiveGame][Name].."from the DataBase\nand DELETE it from the Harddisk?")
        if out == 1 then
	  os.execute("delete "..DataBase[ActiveGame][Path].." ALL QUIET")
	  os.execute("delete "..string.sub(DataBase[ActiveGame][Path],1,-2)..".info QUIET")
          table.remove(DataBase,ActiveGame)
          Game_list:doint(mui.MUIM_List_Remove,mui.getint(Game_list,mui.MUIA_List_Active))
          DB_Modified = true
          PreviousActive = nil
          Nb_Entries = Nb_Entries - 1
        end	
   
    elseif id == GameList_ID then
      -- read active list member      
      local ActiveName = Game_list:dostr(mui.MUIM_List_GetEntry,mui.getint(Game_list,mui.MUIA_List_Active))
      if ActiveName ~= nil then
        ActiveGame = 0
        repeat
          ActiveGame = ActiveGame + 1
        until DataBase[ActiveGame][Name] == ActiveName
      
        Update_DB()

        -- Change selected Game Name Field
        mui.set(CurrentGame,mui.MUIA_Text_Contents,DataBase[ActiveGame][Name])     

        -- Change selected Game Path Field
        mui.set(CurrentPath,mui.MUIA_Text_Contents,DataBase[ActiveGame][Path])
 
        -- Change Selected Game Option Field
        mui.set(CurrentOption,mui.MUIA_String_Contents,DataBase[ActiveGame][ToolTypes])

        -- Change Selected Game Favorite Field
        local Fav = (DataBase[ActiveGame][Favorite] == "true")
        CurrentIsFavorite:setcheckmark(Fav)

        -- Change Selected Game Genre Field
        local Gnum = 1
        while DataBase[ActiveGame][Genre] ~= strarray.get(GameGenre,Gnum) do
          if strarray.get(GameGenre,Gnum)==nil then break end
          Gnum = Gnum+1 
        end
        mui.set(CurrentGenre,mui.MUIA_Cycle_Active,Gnum-1)

        -- Change Selected Game Year Field
        mui.set(CurrentYear,mui.MUIA_String_Contents,DataBase[ActiveGame][Year])

        -- Change selected Game ReadMe field
        nblines,ReadMe_text = Load_ReadMe()  
        mui.set(CurrentReadMe,mui.MUIA_List_Quiet,true)
        CurrentReadMe:doint(mui.MUIM_List_Clear)
        for i=1,nblines,1 do
          CurrentReadMe:doint(mui.MUIM_List_InsertSingle,ReadMe_text[i],mui.MUIV_List_Insert_Bottom)
        end
        mui.set(CurrentReadMe,mui.MUIA_List_Quiet,false)
            
        -- Change selected Game Image
        if ImageType == 0 then
        -- use icon for image
          test = io.open(DataBase[ActiveGame][Path] .. DataBase[ActiveGame][Name] .. ".info","r");
          if test == nil then
            Image = "5:Default_Screenshot.png"
          else
            Image = "5:" .. DataBase[ActiveGame][Path] .. DataBase[ActiveGame][Name] .. ".info"
            test:close()
          end
        else
          test = io.open(DataBase[ActiveGame][Path] .. "TitleScreen.png","r");
          if test == nil then
            test = io.open(DataBase[ActiveGame][Path] .. "InGameScreen.png","r");
            if test == nil then 
              Image = "5:Default_Screenshot.png"
            else
              Image = "5:" .. DataBase[ActiveGame][Path] .. "InGameScreen.png"
              test:close()
            end 
          else
            Image = "5:" .. DataBase[ActiveGame][Path] .. "TitleScreen.png"
            test:close()
          end
          CounterImage = os.time()  
        end
        mui.set(CurrentImage,mui.MUIA_Imagedisplay_Spec,Image)
      
      end
    end

    if ImageType == 1 and os.difftime(os.time(),CounterImage) > 2 then
      if string.find(Image,"TitleScreen.png") then
        test = io.open(DataBase[ActiveGame][Path] .. "InGameScreen.png","r");
        if test ~= nil then
          test:close()
          Image = "5:" .. DataBase[ActiveGame][Path] .. "InGameScreen.png"
          mui.set(CurrentImage,mui.MUIA_Imagedisplay_Spec,Image)
          CounterImage = os.time()
        end
      elseif string.find(Image,"InGameScreen.png") then
        test = io.open(DataBase[ActiveGame][Path] .. "TitleScreen.png","r");
        if test ~= nil then
          test:close()
          Image = "5:" .. DataBase[ActiveGame][Path] .. "TitleScreen.png"
          mui.set(CurrentImage,mui.MUIA_Imagedisplay_Spec,Image)
          CounterImage = os.time()
        end
      end
    end  
      
    if running then mui.wait(signals) end
  end
end

_, err = pcall(main)
if err then print("Error: " .. err) end
if app then app:dispose() end

