Add Source From Template.fh_lua

--[[
@Title: Add Source From Template
@Author: Shelley Crawford
@Version: 1.0
@LastUpdated: 2 August 2015
@Description: Add source records based on user-defined templates.
Field prompts are created by entering the desired prompt in curly brackets {} 
within the template text. Default values can be set or changed when 
adding a source. 
]]

require("iuplua")
require("lfs")

-- requires FH 5.0.8 due to use of folder option in fhGetPluginDataFile


--[[
   Save Table to File
   Load Table from File
   v 1.0
   
   Lua 5.2 compatible
   
   Only Saves Tables, Numbers and Strings
   Insides Table References are saved
   Does not save Userdata, Metatables, Functions and indices of these
   ----------------------------------------------------
   table.save( table , filename )
   
   on failure: returns an error msg
   
   ----------------------------------------------------
   table.load( filename or stringtable )
   
   Loads a table that has been saved via the table.save function
   
   on success: returns a previously saved table
   on failure: returns as second argument an error msg
   ----------------------------------------------------
   
   Licensed under the same terms as Lua itself.
]]--
do
   -- declare local variables
   --// exportstring( string )
   --// returns a "Lua" portable version of the string
   local function exportstring( s )
      return string.format("%q", s)
   end

   --// The Save Function
   function table.save(  tbl,filename )
      local charS,charE = "   ","\n"
      local file,err = io.open( filename, "wb" )
      if err then return err end

      -- initiate variables for save procedure
      local tables,lookup = { tbl },{ [tbl] = 1 }
      file:write( "return {"..charE )

      for idx,t in ipairs( tables ) do
         file:write( "-- Table: {"..idx.."}"..charE )
         file:write( "{"..charE )
         local thandled = {}

         for i,v in ipairs( t ) do
            thandled[i] = true
            local stype = type( v )
            -- only handle value
            if stype == "table" then
               if not lookup[v] then
                  table.insert( tables, v )
                  lookup[v] = #tables
               end
               file:write( charS.."{"..lookup[v].."},"..charE )
            elseif stype == "string" then
               file:write(  charS..exportstring( v )..","..charE )
            elseif stype == "number" then
               file:write(  charS..tostring( v )..","..charE )
            end
         end

         for i,v in pairs( t ) do
            -- escape handled values
            if (not thandled[i]) then
            
               local str = ""
               local stype = type( i )
               -- handle index
               if stype == "table" then
                  if not lookup[i] then
                     table.insert( tables,i )
                     lookup[i] = #tables
                  end
                  str = charS.."[{"..lookup[i].."}]="
               elseif stype == "string" then
                  str = charS.."["..exportstring( i ).."]="
               elseif stype == "number" then
                  str = charS.."["..tostring( i ).."]="
               end
            
               if str ~= "" then
                  stype = type( v )
                  -- handle value
                  if stype == "table" then
                     if not lookup[v] then
                        table.insert( tables,v )
                        lookup[v] = #tables
                     end
                     file:write( str.."{"..lookup[v].."},"..charE )
                  elseif stype == "string" then
                     file:write( str..exportstring( v )..","..charE )
                  elseif stype == "number" then
                     file:write( str..tostring( v )..","..charE )
                  end
               end
            end
         end
         file:write( "},"..charE )
      end
      file:write( "}" )
      file:close()
   end
   
   --// The Load Function
   function table.load( sfile )
      local ftables,err = loadfile( sfile )
      if err then return _,err end
      local tables = ftables()
      if tables then
        for idx = 1,#tables do
           local tolinki = {}
           for i,v in pairs( tables[idx] ) do
              if type( v ) == "table" then
                 tables[idx][i] = tables[v[1]]
              end
              if type( i ) == "table" and tables[i[1]] then
                 table.insert( tolinki,{ i,tables[i[1]] } )
              end
           end
           -- link indices
           for _,v in ipairs( tolinki ) do
              tables[idx][v[2]],tables[idx][v[1]] =  tables[idx][v[1]],nil
           end
        end
        return tables[1]
      else
        iup.Message("Table load fail","No data returned")
      end
   end
-- close do
end

-- ChillCode


-- FHUG code snippet
function dirtree(dir)
    assert(dir and dir ~= "", "directory parameter is missing or empty")
    if string.sub(dir, -1) == "/" then
        dir=string.sub(dir, 1, -2)
    end
    local function yieldtree(dir)
        for entry in lfs.dir(dir) do
            if entry ~= "." and entry ~= ".." then
                entry=dir.."\\"..entry
                local attr,err=lfs.attributes(entry)
                if attr == nil then attr = {mode='attrfail',error=err} end
                coroutine.yield(entry,attr)
                if attr.mode == "directory" then
                    yieldtree(entry)
                end
            end
        end
    end
    return coroutine.wrap(function() yieldtree(dir) end)
end

-- add all template files in the plugin directory to a list
function ListTemplates(pluginDir)
   local tblTemplateList = {}
   for filename,attr in dirtree(pluginDir) do   
    	if attr.error then
          print('filename:'..filename..' caused error '..attr.error)
      else
          if attr.mode == 'file' then
			     local strFile = string.match(filename, ".*\\(.-)\.dat")        
              tblTemplateList[#tblTemplateList+1] = strFile
          end
      end
   end
   return tblTemplateList
end

function SetTemplateLists()
   tblTemplateList = ListTemplates(pluginDir)
   if tblTemplateList ~= nil then
      iup.SetAttribute (listChooseTemplate, "REMOVEITEM", "ALL")
      iup.SetAttribute (listUseTemplate, "REMOVEITEM", "ALL")
      for i = 1,#tblTemplateList do
         iup.SetAttribute (listChooseTemplate, "APPENDITEM", tblTemplateList[i])
         iup.SetAttribute (listUseTemplate, "APPENDITEM", tblTemplateList[i])
      end
   end
end


-- TEMPLATES
-- write template fields to table
function GetTemplateFromDialog()
  tblTemplate = {}
  for k,v in ipairs(TemplateParts) do
    tblTemplate[#tblTemplate+1] = v.value
  end 
end

function LoadTemplateToDialog()
   for k,v in ipairs(TemplateParts) do
     iup.SetAttribute(v, "VALUE", tblTemplate[k])
  end
  local strRepo = ""
  if txtiRepository.value ~= nil and txtiRepository.value ~= "" then
     local ptr = fhNewItemPtr()
     ptr:MoveToRecordById('REPO',tonumber(txtiRepository.value))
     strRepo = fhGetDisplayText(ptr)
  end
  iup.SetAttribute(txtRepository, "TITLE", strRepo)  
end

-- FIELDS
-- Only needed for dialog display. Extracted from the template
-- write field names to field table
function GetFieldsFromTemplate()
   if tblFields == nil then tblFields = {} end
   for k,v in ipairs(tblFields) do
      tblFields[k].include = false                  -- doing this to avoid losing field defaults while editing
   end
   local function GetField(a)
      if a then
         exists = false
         for i = 1,#tblFields do
            if tblFields[i].label == a then
               exists = true
               tblFields[i].include = true
            end
         end
         if exists == false then
            i = #tblFields+1
            if tblFields[i] == nil then tblFields[i] = {} end
            tblFields[i].label = a
            tblFields[i].include = true
         end
      end
   end -- end function 
   for k,v in ipairs(tblTemplate) do
       string.gsub(v,"{(.-)}", function(a)  GetField(a) end )
   end
end

-- SAVE FILE

function CreateSaveTable()
   -- Combine template and defaults into one table
   local tbl = {}
   tbl[1] = tblTemplate
   if tblDefaults then 
      tbl[2] = tblDefaults
   end
   return tbl
end

function savelocation(templatetitle)
  local saveloc = pluginDir.."\\"..templatetitle.."\.dat"
  return saveloc
end         

-- DEFAULTS

function GetDefaultsFromDialog()
  -- Gets values from dialog tab1 to save as default values 
  if tblDefaults == nil then tblDefaults = {} end
  if tblFields then
    for k,v in ipairs(tblFields) do
      strDefault = v.flddefault.value
      if strDefault ~= nil then
         tblDefaults[v.label] = strDefault
      else strDefault = "" 
      end
    end
    if RepositoryNumber.value ~= nil then             
      tblTemplate[7] = RepositoryNumber.value       -- set the template repository field
    end
  end

end   

function WriteDefaultsToDialog()
  if tblDefaults ~= nil then
    for k,v in ipairs(tblFields) do
       iup.SetAttribute(v.flddefault, "VALUE", tblDefaults[v.label])
    end
  end
  if tblTemplate[7] ~= nil and tblTemplate[7] ~= "" then   
  end
end  

-- CREATE SOURCE

function replace(strTxt,strOld,strNew,intNum)
   -- http://www.fhug.org.uk/wiki/doku.php?id=plugins:code_snippets:plain_text_substitution 
	local strMagic = "([%^%$%(%)%%%.%[%]%*%+%-%?])"		-- UTF-8 replacement for "(%W)"
   strOld = tostring(strOld or ""):gsub(strMagic,"%%%1")	-- Hide magic pattern symbols
	return tostring(strTxt or ""):gsub(strOld,function() return strNew end,tonumber(intNum))	-- Hide % capture symbols
end -- function replace


function AddSource()
   local function SetField(str)
     if str ~= nil and str ~= "" then
       for k,v in pairs(tblInputs) do 
         local newvalue = v    
           str = replace(str,"{"..k.."}", newvalue)
       end
     else str = ""
     end
     return str 
   end   
   -- gather inputs
   tblInputs = {}
   for k,v in ipairs(tblFields) do
     strInput = v.flddefault.value
     if strInput ~= nil then
        tblInputs[v.label] = strInput
     else strInput = "" 
     end
   end
   -- replace template fields
   for k,v in ipairs(tblTemplate) do
      strWriteValue = SetField(v)
      TemplateParts[k].writevalue = strWriteValue
   end
   -- write the new source
   local ptrSource = fhCreateItem("SOUR")             -- create a source record and ret ptr to it                    -- TODO get and use correct repository
   for k,v in ipairs({"TITL","ABBR","_TYPE","AUTH","REFN","PUBL","REPO","TEXT","NOTE2"}) do
      if v ~= "REPO" and TemplateParts[k].writevalue ~= nil and TemplateParts[k].writevalue ~= "" then
         local ptrWork = fhCreateItem(v, ptrSource)   -- create a TITL field within this record, and ret ptr to it
         fhSetValueAsText(ptrWork, TemplateParts[k].writevalue)                 -- set value of the title using passed in parameter
      elseif v == "REPO" and TemplateParts[k].writevalue ~= nil and TemplateParts[k].writevalue ~= "" then
         local ptrWork = fhCreateItem(v, ptrSource)
         local ptr = fhNewItemPtr()
         ptr:MoveToRecordById('REPO',tonumber(RepositoryNumber.value))
         if ptr:IsNotNull() then
            fhSetValueAsLink(ptrWork, ptr)
         else
            iup.Message("Warning","Repository "..RepositoryNumber.value.." not found.")
         end         
      end
   end
    a = {}
    a[1] = ptrSource:Clone()
    fhOutputResultSetColumn("Source", "item", a, 1, 200, "align_left") 
    fhOutputResultSetTitles("Source added from template")
end

--------------------------
-- ADJUST DIALOG
--------------------------
 
function ChooseRepository()
   tblRepo = fhPromptUserForRecordSel('REPO',1)
   if #tblRepo == 0 then
        iup.Message("Repository Selection",'None selected')
   else
    	 return fhGetRecordId(tblRepo[1]), fhGetDisplayText(tblRepo[1])
   end
end

function ClearTemplateFields()
   for k,v in ipairs(TemplateParts) do
      iup.SetAttribute(v, "VALUE", "")
   end
   iup.SetAttribute(txtRepository, "TITLE", "")
   iup.SetAttribute(RepositoryName, "TITLE", "")
   iup.SetAttribute(SourceDisplay, "VISIBLE", "NO")
   EnableButtons({btnSave,btnDelete,btnRename,btnCopy},"NO")
end

function MakeFieldSettings()
   -- creates the iup.gridbox ready to load with default values                           
   local bInsert = false
   if FieldSettings then iup.Detach(FieldSettings) iup.Destroy(FieldSettings) bInsert = true end
   FieldSettings = iup.gridbox { -- first line. The other lines are appended after file import.
                        orientation = "HORIZONTAL",
                        margin = "10x5",
                        numdiv = "2",
                        gaplin = "5",
                        gapcol = "5"} 
   if bInsert then iup.Insert(settingbox, NULL, FieldSettings) iup.Map(FieldSettings) iup.Refresh(tab1) end
end

function AddFieldSettings()
   normFieldPrompts = iup.normalizer{}
   -- adds default values to the gridbox
   for k,v in ipairs(tblFields) do
      if tblFields[k].include then
         if tblFields[k].default == nil then tblFields[k].default = "" end
         tblFields[k].fldlabel = iup.label {title = tblFields[k].label, border = "YES", NORMALIZERGROUP = normFieldPrompts, size = "x20", wordwrap = "YES"}
         tblFields[k].flddefault = iup.text{value = tblFields[k].default, 
                                           killfocus_cb = function(self) 
                                                         tblFields[k].default = self.value 
                                                         end,
                                          margin = "5x5", alignment = "ATOP", expand = "YES",
                                          multiline = "YES", scrollbar = "VERTICAL", autohide = "YES", visiblelines = "2", size = "x20", wordwrap = "YES"}
         iup.Append (FieldSettings, tblFields[k].fldlabel)    iup.Map(tblFields[k].fldlabel)
         iup.Append (FieldSettings, tblFields[k].flddefault)  iup.Map(tblFields[k].flddefault)
      end
   end
   normFieldPrompts.normalize = "HORIZONTAL" iup.Destroy(normFieldPrompts)
   iup.Refresh(FieldSettings)  -- repository label  
   local strRepo = ""
   local iRepository = ""
   if tblTemplate[7] ~= nil and tblTemplate[7] ~= "" then
     iRepository = tonumber(tblTemplate[7])
     local ptr = fhNewItemPtr()
     ptr:MoveToRecordById('REPO',iRepository)
     if ptr:IsNotNull() then
         strRepo = fhGetDisplayText(ptr)
     end
   end
   RepositoryName.title = strRepo
   RepositoryNumber.value = iRepository
   iup.SetAttribute(RepositoryDisplay, "VISIBLE", "YES")
   EnableButtons({btnAddSource,btnSetDefault},"YES")                                
end  

function EnableButtons(tblButtons,strSetting)
    -- strSetting can be "YES" or "NO"
    for k,v in ipairs(tblButtons) do
    iup.SetAttribute(v, "ACTIVE", strSetting)
    end
end   


--------------------------
-- DIALOG
--------------------------

function MainDialog()

  normShortLabel = iup.normalizer{}
  normShortButton = iup.normalizer{}
  normButtons = iup.normalizer{}
  
  txtTitle = iup.text{expand = "HORIZONTAL", multiline = "YES", scrollbar = "VERTICAL", visiblelines = "4", wordwrap = "YES"}
  txtShortTitle = iup.text{expand = "HORIZONTAL", wordwrap = "YES"}
  txtType = iup.text{expand = "HORIZONTAL", wordwrap = "YES"}
  txtAuthor = iup.text{expand = "HORIZONTAL", wordwrap = "YES"}
  txtCustomID = iup.text{expand = "HORIZONTAL", wordwrap = "YES"}
  txtPubInfo = iup.text{expand = "HORIZONTAL", wordwrap = "YES"}
  txtRepository = iup.label{expand = "HORIZONTAL", border = "YES"}
  txtiRepository = iup.text{visible = "YES", size = "1x1"}  
  txtText = iup.text{expand = "HORIZONTAL", multiline = "YES", scrollbar = "VERTICAL", visiblelines = "4", wordwrap = "YES"}
  txtNote = iup.text{expand = "HORIZONTAL", multiline = "YES", scrollbar = "VERTICAL", visiblelines = "4", wordwrap = "YES"}
  
  TemplateParts = {txtTitle,txtShortTitle,txtType,txtAuthor,txtCustomID,txtPubInfo,txtiRepository,txtText,txtNote}
    
  btnRepository = iup.button{title = "Select...",
                              action = function(self)
                                         iRepository, strRepository = ChooseRepository()
                                         if strRepository then
                                            txtRepository.title = strRepository
                                            txtiRepository.value = iRepository
                                         end   
                                       end,
                              padding = "10x2", 
                              NORMALIZERGROUP = normShortButton}

  btnInputRepository = iup.button{title = "Select...",
                              action = function(self)
                                         iRepository, strRepository = ChooseRepository()
                                         if strRepository then
                                            txtInputRepository.title = strRepository
                                            txtiInputRepository.value = iRepository
                                         end   
                                       end,
                              padding = "10x2", 
                              NORMALIZERGROUP = normShortButton}
  
  SourceDisplay = iup.vbox{
                          iup.hbox{iup.label{title = "Title:", NORMALIZERGROUP = normShortLabel},txtTitle; margin = "0x0"},
                          iup.hbox{iup.label{title = "Short Title: ", NORMALIZERGROUP = normShortLabel},txtShortTitle; margin = "0x0"},
                          iup.hbox{iup.label{title = "Type:", NORMALIZERGROUP = normShortLabel},txtType; margin = "0x0"},
                          iup.hbox{iup.label{title = "Author:", NORMALIZERGROUP = normShortLabel},txtAuthor; margin = "0x0"},
                          iup.hbox{iup.label{title = "Custom Id:", NORMALIZERGROUP = normShortLabel},txtCustomID; margin = "0x0"},
                          iup.hbox{iup.label{title = "Publication Information:  "},txtPubInfo; margin = "0x0"},
                          iup.hbox{iup.label{title = "Repository: ", NORMALIZERGROUP = normShortLabel},iup.frame{txtRepository},txtiRepository,btnRepository; margin = "0x0"},
                          iup.vbox{iup.label{title = "Text From Source:"},txtText; margin = "0x0"},
                          iup.vbox{iup.label{title = "Note:"},txtNote; margin = "0x0"};           
                          margin = "10x10", gap = "5", visible = "NO"}                        
  
  btnDelete = iup.button {title = "Delete",
                                 action = function(self)
                                            local oldvalue = listChooseTemplate.value
                                            local filename = savelocation(tblTemplateList[tonumber(listChooseTemplate.value)])
                                            local a = iup.Alarm("Delete Template","Confirm deletion?\n"..filename, "OK","Cancel")
                                            if a == 1 then
                                               os.remove(filename)
                                               SetTemplateLists()
                                               ClearTemplateFields()
                                               listChooseTemplate.value = ""
                                               listUseTemplate.value = ""
                                               iup.Message("Template deleted","Template deleted")
                                             end
                                          end,
                              padding = "10x2",
                              NORMALIZERGROUP = normShortButton}
  
  btnCancel1 = iup.button {title = "Cancel",
                              action = function(self)
                                  strButton = nil
                                  return iup.CLOSE
                              end,
                              padding = "10x2",
                              NORMALIZERGROUP = normShortButton}
                              
  btnCancel2 = iup.button {title = "Cancel",
                              action = function(self)
                                  strButton = nil
                                  return iup.CLOSE
                              end,
                              padding = "10x2",
                              NORMALIZERGROUP = normShortButton}
                              
  btnSave = iup.button{title = "Save",
                      action = function(self)
                                     GetTemplateFromDialog()
                                     GetFieldsFromTemplate()
                                     local SaveTable = CreateSaveTable()
                                     local strTT = tblTemplateList[tonumber(listChooseTemplate.value)]
                                     table.save(SaveTable,savelocation(strTT)) 
                                 end,
                       padding = "10x2",
                       NORMALIZERGROUP = normShortButton} 
                       
   btnCopy = iup.button{title = "Copy",
                        action = function(self)
                                     local strOldTitle = tblTemplateList[tonumber(listChooseTemplate.value)]
                                     local strNewTitle = iup.GetText("Enter New Template Name for Copy", strOldTitle.." - Copy")
                                     if strNewTitle then
                                       strNewTitle = strNewTitle:gsub('[^%w -]','')
                                       local exists = false
                                       for k,v in ipairs(tblTemplateList) do
                                         if  v== strNewTitle then
                                           exists = true
                                         end
                                       end
                                       if exists == true then
                                         iup.Message("Copy fail","A template with that name already exists")                                      
                                       else
                                         GetTemplateFromDialog()
                                         GetFieldsFromTemplate()
                                         local SaveTable = CreateSaveTable()
                                         table.save(SaveTable,savelocation(strNewTitle))
                                         SetTemplateLists()
                                         ClearTemplateFields()
                                         listChooseTemplate.value = ""
                                         listUseTemplate.value = ""
                                         iup.Message("Copy success","Copy created")
                                      end
                                    end
                                 end,
                       padding = "10x2",
                       NORMALIZERGROUP = normShortButton}
   
   btnRename = iup.button{title = "Rename",
                                 action = function(self)
                                 local strOldTitle = savelocation(tblTemplateList[tonumber(listChooseTemplate.value)])
                                 local strNewTitle = iup.GetText("Enter New Template Name","")
                                     if strNewTitle then
                                       strNewTitle = strNewTitle:gsub('[^%w -]','')
                                       if strNewTitle ~= "" then
                                         local exists = false
                                         for k,v in ipairs(tblTemplateList) do
                                           if  v== strNewTitle then
                                             exists = true
                                           end
                                         end
                                         if exists == true then
                                           iup.Message("Rename fail","A template with that name already exists")                                      
                                         else
                                           local strMessage = "'"..tblTemplateList[tonumber(listChooseTemplate.value)].."'".."\n has been renamed \n".."'"..strNewTitle.."'"
                                           strNewTitle = savelocation(strNewTitle)
                                           os.rename(strOldTitle,strNewTitle)
                                           ClearTemplateFields()
                                           listChooseTemplate.value = ""
                                           listUseTemplate.value = ""
                                           SetTemplateLists()
                                           iup.Message("Rename success",strMessage)
                                           EnableButtons({btnSetDefault,btnAddSource,btnSave,btnDelete,btnRename,btnCopy},"NO")
                                         end
                                       end
                                    end
                                 end,
                       padding = "10x2",
                       NORMALIZERGROUP = normShortButton}                     
                                 
   btnCreateNew = iup.button{title = "New...",
                                 action = function(self)
                                     -- clear other tab
                                    listUseTemplate.value = ""
                                    if FieldSettings then iup.Detach(FieldSettings) iup.Destroy(FieldSettings) end
                                    -- clear this tab and continue
                                     ClearTemplateFields()
                                     local strTemplateTitle = iup.GetText("Enter New Template Name","")
                                     if strTemplateTitle then
                                       strTemplateTitle = strTemplateTitle:gsub('[^%w -()_]','')
                                       if strTemplateTitle ~= "" then
                                         local exists = false
                                         for k,v in ipairs(tblTemplateList) do
                                           if  v== strTemplateTitle then
                                             exists = true
                                           end
                                         end
                                         if exists == true then
                                           iup.Message("Cannot create new template","A template with that name already exists") 
                                         else
                                           newvalue = #tblTemplateList+1
                                           tblTemplateList[newvalue] = strTemplateTitle
                                           iup.SetAttribute (SourceDisplay, "VISIBLE", "YES")
                                           iup.SetAttribute (listChooseTemplate, "APPENDITEM", tblTemplateList[newvalue])
                                           iup.SetAttribute (listUseTemplate, "APPENDITEM", tblTemplateList[newvalue])
                                           iup.SetAttribute (listChooseTemplate, "VALUE", newvalue)
                                           EnableButtons({btnSave, btnDelete, btnRename, btnCopy},"YES")
                                           btnSave.action()
                                         end
                                       end
                                    end
                                 end,
                                 padding = "10x2",
                                 NORMALIZERGROUP = normShortButton}
                                 
   listChooseTemplate = iup.list{valuechanged_cb = function(self)
                                    -- clear other tab
                                    listUseTemplate.value = ""
                                    if FieldSettings then iup.Detach(FieldSettings) iup.Destroy(FieldSettings) end
                                    -- continue
                                    ClearTemplateFields()
                                    local filename = savelocation(tblTemplateList[tonumber(listChooseTemplate.value)]) 
                                    local tbl = table.load(filename)
                                    tblTemplate = tbl[1]
                                    if tbl[2] then tblDefaults = tbl[2] end
                                    LoadTemplateToDialog()
                                    iup.SetAttribute (SourceDisplay, "VISIBLE", "YES")
                                    EnableButtons({btnSave,btnDelete,btnRename,btnCopy},"YES")
                                 end,
                                 dropdown = "YES", editbox = "NO", expand = "YES", visible_items = "20"}   

   listUseTemplate = iup.list{valuechanged_cb = function(self)
                                       -- clear other tab                                       
                                       listChooseTemplate.value = ""
                                       ClearTemplateFields()
                                       EnableButtons({btnSave,btnDelete,btnRename,btnCopy},"NO")
                                       -- continue
                                       local filename = savelocation(tblTemplateList[tonumber(listUseTemplate.value)]) 
                                       tbl = table.load(filename)
                                       if tbl then
                                         tblTemplate = tbl[1]
                                         tblDefaults = tbl[2]
                                         tblFields = {}                   
                                         GetFieldsFromTemplate()
                                         MakeFieldSettings()
                                         AddFieldSettings()
                                         WriteDefaultsToDialog()
                                       end
                                     end,
                           dropdown = "YES", editbox = "NO", expand = "YES", visible_items = "20"}                     
                                                                 
   btnAddSource = iup.button {title = "Add Source",
                                 action = function(self)
                                             AddSource()
                                             return iup.CLOSE
                                          end,
                              padding = "10x2",
                              NORMALIZERGROUP = normButtons}                     
      
   btnSetDefault = iup.button {title = "Save As Default", 
                                  action = function(self)
                                             GetDefaultsFromDialog()
                                             SaveTable = CreateSaveTable()
                                             local strTT = tblTemplateList[tonumber(listUseTemplate.value)]
                                             table.save(SaveTable,savelocation(strTT))
                                             strButton = nil
                                             iup.Message("Defaults saved","Defaults saved")
                                          end,
                              padding = "10x2",
                              NORMALIZERGROUP = normButtons} 

   -- repository in field settings   
   RepositoryLabel =  iup.label{title = "Repository: ", border = "YES", size = "80x8"}
   -- repository selection
   RepositoryName =   iup.label{expand = "YES", border ="YES"}
   RepositoryNumber = iup.text{visible = "YES", size = "1x1"}
   RepositoryButton = iup.button{title = "Select...",
                              action = function(self)
                                         iRepository, strRepository = ChooseRepository()
                                         if strRepository then
                                            RepositoryName.title = strRepository
                                            RepositoryNumber.value = iRepository
                                         end   
                                       end,
                              padding = "10x2"}
   RepositoryDisplay = iup.hbox{RepositoryLabel,iup.frame{RepositoryName; expand = "YES"},RepositoryNumber,RepositoryButton; margin = "10x10", size = "x20", visible = "NO"}
    
   MakeFieldSettings()     
   settingbox = iup.vbox{FieldSettings; expand = "YES", margin = "0x0"}
   
   tab1 =   iup.vbox{
                     iup.hbox{iup.label{title = "Template: ",font = "Helvetica, Bold 10", NORMALIZERGROUP = normShortLabel},listUseTemplate; gap = "5", alignment = "ATOP"},
                     iup.frame{iup.scrollbox{settingbox;size = "100x210"}; margin = "5x5"},
                     RepositoryDisplay,
                     iup.hbox{btnSetDefault,iup.fill{}, btnAddSource, btnCancel1};
                     tabtitle = "Add source from template", margin = "5x5", expandchildren = "YES", gap = "5"}

   tab2 = iup.vbox{  iup.hbox{iup.label{title = "Template: ", font = "Helvetica, Bold 10", NORMALIZERGROUP = normShortLabel},
                           listChooseTemplate,
                           btnCreateNew; gap = "5", alignment = "ATOP"},
                     iup.hbox{iup.label{title = "Tip: ", font = "Helvetica, Bold 10"},
                            iup.label{title = "Place field prompts in curly brackets. eg: {Surname}, {Given Name}", font = "Helvetica, Normal 9"};
                            alignment = "ATOP",  margin = "5x0"},
                     iup.frame{SourceDisplay; margin = "5x5"},
                     iup.hbox{btnCopy,
                           btnRename,
                           btnDelete,
                           iup.fill{},
                           btnSave,
                           btnCancel2; 
                           margin = "0x0"};
                     tabtitle = "Create and edit templates", margin = "5x5",gap ="5"}

   dlg = iup.dialog{ iup.tabs{tab1,tab2};                        
                     margin = "10x10",
                     title = "Add Source from Template",
                     expand = "HORIZONTAL",
                     size = "THIRDx330"}

normShortLabel.normalize = "HORIZONTAL" iup.Destroy(normShortLabel)
normShortButton.normalize = "HORIZONTAL" iup.Destroy(normShortLabel)
normButtons.normalize = "HORIZONTAL" iup.Destroy(normButtons)

dlg:show() 

SetTemplateLists()

EnableButtons({btnSetDefault,btnAddSource,btnSave,btnDelete, btnRename, btnCopy},"NO")

iup.MainLoop()
dlg:destroy()  

end

--------------------------------------------------------------------------------
-- MAIN CODE
--------------------------------------------------------------------------------

pluginDir = fhGetPluginDataFileName("CURRENT_PROJECT",true)


MainDialog()

Source:Add-Source-From-Template.fh_lua