Add GRO Index Entries.fh_lua

--[[
@Title: Add GRO Index Entries
@Type: Standard
@SubType: "Civil Registration Index"
@Author: Norman Martin
@Version: 1.3
@Keywords: 
@LastUpdated: 30 Jan 2025
@Licence: This plugin is copyright (c) 2023 Norman Martin and contributors, and is licensed under the MIT License
which is hereby incorporated by reference (see https://pluginstore.family-historian.co.uk/fh-plugin-licence)
@Description: Designed to work with the "Civil Registration Index" source template 
from the Essentials collection, this will add the GRO Index sources for Births, Marriages and Deaths for the current individual.
It will create a Birth or Death event if needed, and update the event date and place if requested.
The "Civil Registration Index" template from the Essential Collection needs to be added into the project first.
@changes:
1.3 (30 Jan 2025) Retain dialog size after saving an entry, so that dialog has the same size when loaded next time.
1.2 	(30 Jan 2025) Added Scroll bar for certificate details to cater for different screen resolutions.
		Auto resize dialog to fit display resolution (avoid need to resize form)
1.1 (19 Jan 2023) Added address field to be compatible with Add GRO Source plugin
]]


local help=[[
This plugin records Birth, Marriage and Death details from the General Registers Office Indexes using Civil Registration Index Template as a citation.
Before it can be used, the "Civil Registration Index" template from the Essentials collection must added. This can be done by selecting Tools>Source Template Definitions and then highlight the template(s) and add to project.
The first time you use this plug in, you will need to identify, or create, the appropriate source record.
To do this first, select the region and then press the "source" button of the bottom of the screen. This will list matching source records for the template, type and region. If there is only one matching source record it will select that. If there is more than one, you will be asked to choose which to use. If there are none, you will be asked to create one, when you can add extra fields such as the Repository for the source.
You can set up different source record for different regions (or change the selected source record for future use).
When you save an entry, the current region and template is remembered for future use, as is the assessment rating and Address (but not the place).
For the actual citation, you can overtype the name for the citation, but the name will NOT be changed. You must provide a Registration Date, Registration District and Reference.
The Registration District can be type in manually or selected from the list of places.
You can select to update the event date (Birth, Death or Marriage) with the registration date you have entered by ensuring that the Update Date checkbox is ticked. Similarly, you can update the event place by ensuring that the Update Date checkbox is ticked.
In the case of a Death entry, you can choose to update the birth date if can enter a birth date.
By pressing the "Save" button, the relevant facts and events are updated where requested, and the citation saved.
To allow for Birth, Marriage and Death to be recorded, the dialog is not closed, so press Exit to close the dialog.
]]

require("iuplua");
iup.SetGlobal("CUSTOMQUITMESSAGE","YES");
fh = require("fhUtils");

fhInitialise(7);  -- implies users will need version 7 as a minimum;

local dlgSize=""
local iniFile=""
local templateID=-1
local currPtr = fhNewItemPtr()
local curPerson=""
local curDates=""
local ptrTemplate=fhNewItemPtr()
local region=""		
local type="Birth"
local assessment=""
local address=""	
local source=-1
local haveCitation=false
local Places={}
local Families={}
-------------------------------------------------------
-- Define Dialog Fields
-------------------------------------------------------
local color = {error = '255 200 200',red = '255 0 0',green = '0 128 0'}

local lab_Source = iup.label{title=' ', expand='HORIZONTAL'}
local lab_Type = iup.label{title='Birth',  expand='HORIZONTAL'}
local lst_Type  = iup.list{name='Type',expand='HORIZONTAL', dropdown="YES"}
local lst_Region  = iup.list{name='Region',expand='HORIZONTAL', dropdown="YES"}
local lab_Repos = iup.label{title=' ', expand='HORIZONTAL'}
local info_Mess = iup.label{title='---------------Citation Details-------------------',fgcolor=color.blue, expand='HORIZONTAL'}
local txt_Name = iup.text{name='Name',expand='HORIZONTAL' }
local txt_Birthdate = iup.text{name='BirthDate',expand='HORIZONTAL',value='' }
local txt_Eventdate = iup.text{name='DeathDate',expand='HORIZONTAL' }
local txt_MaidenName = iup.text{name='MaidenName',expand='HORIZONTAL' }
local txt_Age = iup.text{name='Age',expand='HORIZONTAL' }
local lst_RegDistrict  = iup.list{name='RegDistrict',expand='HORIZONTAL',editbox='YES', dropdown="NO",visiblelines=3}
local lst_Spouse  = iup.list{name='Spouse',expand='HORIZONTAL', dropdown="NO"}
local txt_Address = iup.text{name='Address',expand='HORIZONTAL' }
local txt_Reference = iup.text{name='Reference',expand='HORIZONTAL' }
local lst_Assessment  = iup.list{name='Assessment',expand='HORIZONTAL', dropdown="YES"}
local txt_Notes = iup.text{name='Notes',expand='HORIZONTAL',multiline='YES',visiblelines=5}
local chk_Update=iup.toggle{title = "Update Date", value="OFF",expand='HORIZONTAL'}
local chk_Place=iup.toggle{title = "Update Place", value="OFF",expand='HORIZONTAL'}
local chk_Birth=iup.toggle{title = "****", value="OFF",expand='HORIZONTAL'}
local lab_message = iup.label{title=' ',fgcolor=color.red, expand='HORIZONTAL'}
local bt_Save = iup.button{name='save', title='Save'}
local btn_Cancel = iup.button{name='cancel', title='Exit'}
local btn_Source = iup.button{name='source', title='Source'}
local btn_Help = iup.button {name='help', title='Help'}




-------------------------------------------------------
-- function main 
-------------------------------------------------------
function main()

 	iniFile=fhGetContextInfo("CI_PROJECT_DATA_FOLDER").."\\Plugin Data\\"..fhGetContextInfo("CI_PLUGIN_NAME")..".dat"
	templateID=FindTemplate('Civil Registration Index')

	-- check that template exists
	if templateID~=-1 then
		--Try to get the Current Individual, Can't continue if not selected
		currPtr=fh.getCurrentIndividual ()
		if currPtr:IsNotNull() then
			curPerson=fhGetItemText(currPtr,'INDI.NAME')
			curDates=fhGetItemText(currPtr,'INDI.BIRT.DATE')..' - '..fhGetItemText(currPtr,'INDI.DEAT.DATE')
			dlgSize=fhGetIniFileValue(iniFile, "Defaults", "Dialog Size", "text",dlgSize)
			-- show dialog screen
			MainDialog()
		else
 			fhMessageBox("No person selected")
		end		
	else
 		fhMessageBox("Requires Civil Registration Index source template from the Essentials collection")
end

end


-- << insert additional functions here >>
----------------------------------------------------
-- Function: MainDialog - display dialog
--           This is the Main Dialog Screen
---------------------------------------------------
function MainDialog()
-------------------------------------------------------
-- Dialog field actions 
-------------------------------------------------------

function lst_Region:action(t,i,v)
    if v==1 then 
			-- item selected
			region=t
			source=fhGetIniFileValue(iniFile, region,type.. "Source", "text")
			assessment=fhGetIniFileValue(iniFile, region, type.."Assessment", "text",'') 
			address=fhGetIniFileValue(iniFile, region, type.."Address", "text",'') 
			lst_Assessment.valuestring=assessment	 
			txt_Address.value=	address
			lab_message.title = ''
			HasSource()
		end
end

function lst_Type:action(t,i,v)
    if v==1 then 
			-- item selected
			type=t
			SetUpScreen()
			source=fhGetIniFileValue(iniFile, region,type.. "Source", "text")
			assessment=fhGetIniFileValue(iniFile, region, type.."Assessment", "text",'') 
			address=fhGetIniFileValue(iniFile, region, type.."Address", "text",'') 
			lst_Assessment.valuestring=assessment	 
			txt_Address.value=	address
			lab_message.title = ''
			HasSource()
		end
end

function lst_Spouse:action(t,i,v)
    if v==1 then 
			-- item selected
			lab_message.title = ''
			DisplayCitation()
		end
end

function chk_Update:action(t,i,v)
		if t==1 then 
			chk_Update.value='ON'
		else
			chk_Update.value='OFF'
		end
end

function chk_Place:action(t,i,v)
		if t==1 then 
			chk_Place.value='ON'
		else
			chk_Place.value='OFF'
		end
end

function btn_Source:action() 
	SelectSource(templateID,region,type)
	DisplaySource()
	dlg:show()
end

-------------------------------------------------------
-- validate dialog and close screen if valid 
-------------------------------------------------------
function bt_Save:action() 
	-- validate
	lab_message.title = ''
	if haveCitation then
		lab_message.title = 'Citation exist - Please Press Exit button'
		return
	end
	if region =='' then
		lab_message.title = 'Please Select a Region'
		return
	end
	if source==-1 then	
		lab_message.title = 'Please Press Source button and select a source'
		return
	end
	if txt_Name.value=='' then
		lab_message.title = 'Must complete Name Recorded'
		return
	end

	if txt_Eventdate.value=='' then
		lab_message.title = 'Must complete Registration Date'
		return
	end

	if lst_RegDistrict.value=='' then
		lab_message.title = 'Must provide a Registration District'
		return
	end

	if txt_Reference.value=='' then
		lab_message.title = 'Must provide a GRO Reference'
		return
	end

	if type=='Death' and txt_Birthdate.value=='' and chk_Birth.value=='ON' then
		lab_message.title = 'Either provide Birth Date or Uncheck Update Birth Date'
		return
	end


	SaveEntry()

end

function btn_Cancel:action() 
	return iup.CLOSE 
end

function btn_Help:action()
	PluginHelp(help)
end

	dlg = iup.dialog{ 
            iup.vbox{ 
                     iup.hbox{iup.label{title='Templated Source',size='140'},lab_Source},
                     iup.hbox{iup.label{title='GRO Index Type',size='140'},lst_Type},
                     iup.hbox{iup.label{title='Region',size='140'},lst_Region},
                     iup.hbox{iup.label{title='Repository',size='140'},lab_Repos},
                     iup.hbox{iup.label{title='',size='140'},info_Mess},

							iup.scrollbox{ 
								iup.vbox{ 										

                     iup.hbox{iup.label{title='Name Recorded',size='140'},txt_Name},
                     iup.hbox{iup.label{title='Registration Date',size='140'},txt_Eventdate},
                     iup.hbox{iup.label{title='Registration District',size='140'}, lst_RegDistrict},
 										iup.hbox{iup.label{title='Address',size='140'},txt_Address},
 										iup.hbox{iup.label{title='GRO Index Reference',size='140'},txt_Reference},
 										iup.hbox{iup.label{title='Mothers Maiden Name (Birth Only)',size='140'},txt_MaidenName},
                     iup.hbox{iup.label{title='Recorded Date of Birth (Death Only)',size='140'},txt_Birthdate},
 										iup.hbox{iup.label{title='Recorded Age at Death (Death Only)',size='140'},txt_Age},
                     iup.hbox{iup.label{title='Spouse (Marriage Only)',size='140'}, lst_Spouse},
                     iup.hbox{iup.label{title='Assessment',size='140'}, lst_Assessment},
 										iup.hbox{iup.label{title='Notes',size='140'},txt_Notes},
        						},
      						},

 										iup.hbox{iup.label{title='',size='140'},chk_Update},
 										iup.hbox{iup.label{title='',size='140'},chk_Place},
 										iup.hbox{iup.label{title='',size='140'},chk_Birth},

                     iup.label{title='Status'},lab_message,
                     iup.hbox{bt_Save,btn_Cancel,btn_Source,btn_Help;padding='10',gap='5'}
                     ;padding='5',gap='5',nmargin='20x20'
                     },
             title='Add GRO Index Entry for '..curPerson..' '..curDates,padding='10',gap='5', size='500',
             close_cb=function() res='closed' return iup.CLOSE end}


						-- populate list with defaults
						PopulateList(lst_Region,GetRegions(templateID))
						PopulateList(lst_RegDistrict,fh.createPlaceList())
						ListType(lst_Type)
						lst_Type.valuestring='Birth'
						ListAssessments(lst_Assessment)

						-- populate name 
						txt_Name.value=curPerson
						SetUpScreen()

						-- read ini file and populate accordingly
						region=fhGetIniFileValue(iniFile, "Defaults", "Region", "text","") 			
						assessment=fhGetIniFileValue(iniFile, region, type.."Assessment", "text",'') 			
						lst_Assessment.valuestring=assessment
						address=fhGetIniFileValue(iniFile, region, type.."Address", "text",'') 	
						txt_Address.value=	address	
						source=fhGetIniFileValue(iniFile, region, type.."Source", "integer",-1) 
						if region =='' then
							lab_message.title = 'Please Select a Region'
						else
							lst_Region.valuestring=region
							-- check for source record
							HasSource()
							DisplaySource ()
						end

	dlg:show()      -- Show the dialog
		-- size the dialog screen appropriately
		if dlgSize ~= '' then 
			dlg.Size = dlgSize
			dlg:showxy(iup.CENTER, iup.CENTER)
			iup.Map(dlg)		
		else		
			dlg.size=ResizeDialog(dlg)
		end

	iup.MainLoop()  -- Process the dialog

	dlg:destroy()   -- Clean up the dialog, note all dialog controls are destroyed as well



end

-- << Dialog Helper Function >>
----------------------------------------------------
-- Function: SetUpScreen - 
--           sets up screen according to type
---------------------------------------------------
function SetUpScreen()
local ptr=fhNewItemPtr()
local array={}

	chk_Update.value='OFF'
	chk_Place.value='OFF'
	chk_Birth.value='OFF'

	txt_Eventdate.value='' 
	PopulateList(lst_RegDistrict,fh.createPlaceList())	txt_Reference.value='' 

	Families={}

	if type=='Birth' then
		txt_Age.value='****'						
		txt_Age.readonly='YES'
		txt_Birthdate.value='****'						
		txt_Birthdate.readonly='YES'
		txt_MaidenName.value=''						
		txt_MaidenName.readonly='NO'
		chk_Update.title='Update Birth Date with Registration Date'
		chk_Place.title='Update Birth Place with Registration District/Address'
		chk_Birth.title='****'
		PopulateList(lst_Spouse,array)
		-- check if date and place already recorded
		ptr=fhGetItemPtr(currPtr,'~.BIRT')
			if ptr:IsNotNull() then
				if fhGetItemText(ptr,'~.PLAC')=='' then
					chk_Place.value='ON'
				end
				if fhGetItemText(ptr,'~.DATE')=='' then
					chk_Update.value='ON'
				end
			else
				chk_Update.value='ON'
				chk_Place.value='ON'
			end
	elseif type=='Death' then
		txt_Age.value=''						
		txt_Age.readonly='NO'
		txt_Birthdate.value=''						
		txt_Birthdate.readonly='NO'
		txt_MaidenName.value='****'						
		txt_MaidenName.readonly='YES'
		chk_Update.title='Update Death Date with Registration Date'
		chk_Place.title='Update Death Place with Registration District/Address'
		chk_Birth.title='Update Birth Date'
		PopulateList(lst_Spouse,array)
		-- check if date and place already recorded
		ptr=fhGetItemPtr(currPtr,'~.DEAT')
			if ptr:IsNotNull() then
				if fhGetItemText(ptr,'~.PLAC')=='' then
					chk_Place.value='ON'
				end
				if fhGetItemText(ptr,'~.DATE')=='' then
					chk_Update.value='ON'
				end
			else
				chk_Update.value='ON'
				chk_Place.value='ON'
			end
		ptr=fhGetItemPtr(currPtr,'~.BIRT')
			if ptr:IsNotNull() then
				if fhGetItemText(ptr,'~.DATE')=='' then
					chk_Birth.value='ON'end
			end

	elseif type=='Marriage' then
		txt_Age.value='****'						
		txt_Age.readonly='YES'
		txt_Birthdate.value='****'						
		txt_Birthdate.readonly='YES'
		txt_MaidenName.value='****'						
		txt_MaidenName.readonly='YES'
		chk_Update.title='Update Marriage Date with Registration Date'
		chk_Place.title='Update Marriage Place with Registration District/Address'
		chk_Birth.title='****'
		ListMarriages()
	end

end

----------------------------------------------------
-- Function: SaveEntry - Saves  ini file settings
--           and creates citation
--           then updates events and saves citation
---------------------------------------------------
function SaveEntry()
local txt=""

local ptrLink =fhNewItemPtr();
local ptrParent=fhNewItemPtr();
local ptrTextFromSource=fhNewItemPtr();

	-- save ini file settings
	fhSetIniFileValue(iniFile, "Defaults", "Region", "text",region)
	fhSetIniFileValue(iniFile,  region, type.."Assessment", "text",lst_Assessment.valuestring)
	fhSetIniFileValue(iniFile,  region, type.."Address", "text",txt_Address.value)
	fhSetIniFileValue(iniFile, "Defaults", "Dialog Size", "text",dlg.Size)

	-- now clear current prepared citation
	ptrLink=ClearCitation()

	-- now save citation
		-- now create citation
		AddInfo(ptrLink, '~NM-NAME_RECORDED', txt_Name.value)
		AddInfo(ptrLink, '~DT-DATE', txt_Eventdate.value)
		AddInfo(ptrLink, '~TX-REGISTRATION_DISTRICT', lst_RegDistrict.value)
		AddInfo(ptrLink, '~TX-REFERENCE', txt_Reference.value)
		AddInfo(ptrLink, 'QUAY', lst_Assessment.valuestring)
		AddInfo(ptrLink, 'NOTE2', txt_Notes.value)

		local pCite=fh.loadPreparedCitation ()

		ptrParent = fhGetItemPtr(pCite.ptr, "~.SOUR.DATA")
		if ptrParent:IsNull() then
			ptrParent = fhGetItemPtr(pCite.ptr, "~.SOUR")
			ptrParent = fhCreateItem("DATA", ptrParent)
		end

		-- add text from source
		txt=region ..' Civil Index of '..type..'s\n'
		txt=txt..'Date: '..txt_Eventdate.value
		txt=txt..' Name: '..txt_Name.value
		txt=txt..' Registration District: '..lst_RegDistrict.value
		txt=txt..' Reference: '..txt_Reference.value
		-- add relevant text for type
		if type=='Birth' then
			txt=txt..' Mothers Maiden Name: '..txt_MaidenName.value
		end
		if type=='Marriage' then
			txt=txt..' Spouse Name: '..lst_Spouse.valuestring
		end
		if type=='Death' then
			txt=txt..' Age: '..txt_Age.value
			txt=txt..' Date of Birth: '..txt_Birthdate.value
		end

	ptrTextFromSource = fhGetItemPtr(ptrParent, "~.TEXT")
	if ptrTextFromSource:IsNull() then
		ptrTextFromSource = fhCreateItem("TEXT", ptrParent)
	end
	fhSetValueAsText(ptrTextFromSource, txt)

	if type=='Birth' then
		SaveBirthEntry()
	end

	if type=='Death' then
		SaveDeathEntry()
	end

	if type=='Marriage' then
		SaveMarriageEntry()
	end
	

end

----------------------------------------------------
-- Function: SaveBirthEntry - 
--           update birth date and place, if requested
--           then saves citation
---------------------------------------------------
function SaveBirthEntry()
local ptrBirth=fhNewItemPtr();
local ptrInfo=fhNewItemPtr();

	-- update current values
	ptrBirth=fhGetItemPtr(currPtr,'INDI.BIRT')
	if ptrBirth:IsNull() then
		ptrBirth=fhCreateItem('BIRT', currPtr)
	end
	if chk_Update.value=='ON' then 
		ptrInfo=fhGetItemPtr(ptrBirth,'~.DATE')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('DATE', ptrBirth)
		end
		fhSetValueAsText(ptrInfo, txt_Eventdate.value)
	end
	if chk_Place.value=='ON' then 
		ptrInfo=fhGetItemPtr(ptrBirth,'~.PLAC')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('PLAC', ptrBirth)
		end
		fhSetValueAsText(ptrInfo, lst_RegDistrict.value)
		ptrInfo=fhGetItemPtr(ptrBirth,'~.ADDR')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('ADDR', ptrBirth)
		end
		fhSetValueAsText(ptrInfo, txt_Address.value)
	end

		local pCite=fh.loadPreparedCitation ()

	-- append citation to birth
		if ptrBirth and ptrBirth:IsNotNull() then
			pCite:appendCitation(ptrBirth)
		end

	lab_message.title = 'Birth Entry Saved'
end

----------------------------------------------------
-- Function: SaveDeathEntry - 
--           update Death date and place, if requested
--           then saves citation
---------------------------------------------------
function SaveDeathEntry()
local ptrBirth=fhNewItemPtr();
local ptrDeath=fhNewItemPtr();
local ptrInfo=fhNewItemPtr();

	-- Update Birth Date if requested
	if chk_Birth.value=='ON' then 
		ptrBirth=fhGetItemPtr(currPtr,'INDI.BIRT')
		if ptrBirth:IsNull() then
			ptrBirth=fhCreateItem('BIRT',currPtr) 
		end
		ptrInfo=fhGetItemPtr(ptrBirth,'~.DATE')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('DATE', ptrBirth)
		end
		fhSetValueAsText(ptrInfo, txt_Birthdate.value)
	end

	-- Update Death Date if requested
	ptrDeath=fhGetItemPtr(currPtr,'INDI.DEAT')
	if ptrDeath:IsNull() then
		ptrDeath=fhCreateItem('DEAT',currPtr) 
	end
	if chk_Update.value=='ON' then 
		ptrInfo=fhGetItemPtr(ptrDeath,'~.DATE')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('DATE', ptrDeath)
		end
		fhSetValueAsText(ptrInfo, txt_Eventdate.value)
	end

	-- update age
	if txt_Age.value ~='' then
		ptrInfo=fhGetItemPtr(ptrDeath,'~.AGE')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('AGE', ptrDeath)
		end
		fhSetValueAsText(ptrInfo, txt_Age.value)
	end

	-- Update Death Place if requested
	if chk_Place.value=='ON' then 
		ptrInfo=fhGetItemPtr(ptrDeath,'~.PLAC')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('PLAC', ptrDeath)
		end
		fhSetValueAsText(ptrInfo, lst_RegDistrict.value)
		ptrInfo=fhGetItemPtr(ptrDeath,'~.ADDR')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('ADDR', ptrDeath)
		end
		fhSetValueAsText(ptrInfo, txt_Address.value)
	end

	local pCite=fh.loadPreparedCitation ()

	-- append citation to Death
		if ptrDeath and ptrDeath:IsNotNull() then
			pCite:appendCitation(ptrDeath)
		end
	-- append citation to Birth
		if chk_Birth.value=='ON' and ptrBirth and ptrBirth:IsNotNull() then
			pCite:appendCitation(ptrBirth)
		end
		lab_message.title = 'Death Entry Saved'

end

----------------------------------------------------
-- Function: SaveMarriageEntry - 
--           update Marriage date and place, if requested
--           then saves citation
---------------------------------------------------
function SaveMarriageEntry()
local ptrFamily=fhNewItemPtr();
local ptrMarriage=fhNewItemPtr();
local ptrInfo=fhNewItemPtr();

	ptrFamily=GetRecordByID('FAM',Families[tonumber(lst_Spouse.value)])
	-- update current values
	ptrMarriage=fhGetItemPtr(ptrFamily,'~.MARR')
	if ptrMarriage:IsNull() then
		ptrMarriage=fhCreateItem('MARR', ptrFamily)
	end
	if chk_Update.value=='ON' then 
		ptrInfo=fhGetItemPtr(ptrMarriage,'~.DATE')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('DATE', ptrMarriage)
		end
		fhSetValueAsText(ptrInfo, txt_Eventdate.value)
	end
	if chk_Place.value=='ON' then 
		ptrInfo=fhGetItemPtr(ptrMarriage,'~.PLAC')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('PLAC', ptrMarriage)
		end
		fhSetValueAsText(ptrInfo, lst_RegDistrict.value)
		ptrInfo=fhGetItemPtr(ptrMarriage,'~.ADDR')
		if ptrInfo:IsNull() then
			ptrInfo= fhCreateItem('ADDR', ptrMarriage)
		end
		fhSetValueAsText(ptrInfo, txt_Address.value)
	end

		local pCite=fh.loadPreparedCitation ()


	-- append citation to Marriage
		if ptrMarriage and ptrMarriage:IsNotNull() then
			pCite:appendCitation(ptrMarriage)
		end

		lab_message.title = 'Marriage Entry Saved'

end


----------------------------------------------------
-- Function: ListMarriages - 
--           sets up screen according to type
---------------------------------------------------
function ListMarriages()
local array={}
local ptrMarriage = fhNewItemPtr() 
local ptrTemp = fhNewItemPtr()
local cnt=0
local SpouseName=""
local Select={}


	ptrMarriage:MoveTo(currPtr, "~.FAMS")    -- point to the first record
	while ptrMarriage:IsNotNull() do
		-- probably only one
		ptrTemp = fhGetValueAsLink(ptrMarriage)
		cnt=cnt+1
		if fhGetRecordId(fhGetValueAsLink(fhGetItemPtr(ptrTemp,'FAM.HUSB')))==fhGetRecordId(currPtr) then
			SpouseName=fhGetItemText(fhGetValueAsLink(fhGetItemPtr(ptrTemp,'FAM.WIFE')),'~.NAME')
		else
			SpouseName=fhGetItemText(fhGetValueAsLink(fhGetItemPtr(ptrTemp,'FAM.HUSB')),'~.NAME')
		end
		table.insert(array,SpouseName)
		table.insert(Families,fhGetRecordId(ptrTemp))
   	ptrMarriage:MoveNext("SAME_TAG")
	end
	PopulateList(lst_Spouse,array)
	if cnt>0 then
		lst_Spouse.value="1"
	end
end

----------------------------------------------------
-- Function: HasSource - checks if source record selected
--           stored in in file after save
---------------------------------------------------
function HasSource()
	lab_Source.title=''
	lab_Repos.title=''
	source=fhGetIniFileValue(iniFile, region, type.."Source", "integer",-1) 
	if source==-1 then	
		lab_message.title = 'Please Press Source button and select a source'
	else
		lab_message.title = ''
		DisplaySource()
	end
end

----------------------------------------------------
-- Function: DisplaySource - displays the selected source record metadata
---------------------------------------------------
function DisplaySource()
local ptrSource=fhNewItemPtr()
local ptrRepos=fhNewItemPtr()

	if source~=-1 then
		ptrSource=GetRecordByID('SOUR',source)
		if ptrSource:IsNotNull() then
			lab_Source.title=fhGetItemText(ptrSource,'~.TITL')..' -- Record ID '..source
			ptrRepos=fhGetItemPtr(ptrSource,'~.~RP-REPOSITORY')
			lab_Repos.title=fhGetItemText(fhGetValueAsLink(ptrRepos),'~.NAME')
			lab_message.title = ''
			DisplayCitation()
		end
	end

end

----------------------------------------------------
-- Function: DisplayCitation - displays existing citation
--      not expected unless amending
---------------------------------------------------
function DisplayCitation()
local ptrSource=fhNewItemPtr()
local ptrQual=fhNewItemPtr()
local qual=""
	
	haveCitation=false

	if type=='Birth' then
		qual='BIRT'
		ptrSource:MoveTo(currPtr,'~.'..qual..'.SOUR')
	elseif type=='Death' then
		qual='DEAT'
		ptrSource:MoveTo(currPtr,'~.'..qual..'.SOUR')
	elseif type=='Marriage' then
		ptrSource=GetRecordByID('FAM',Families[tonumber(lst_Spouse.value)])
		-- check if date and place already recorded
		if fhGetItemText(ptrSource,'~.PLAC')=='' then
			chk_Place.value='ON'
		end
		if fhGetItemText(ptrSource,'~.DATE')=='' then
			chk_Update.value='ON'
		end
		ptrSource:MoveTo(ptrSource,'~.MARR.SOUR')
	end

		while not ptrSource:IsNull() do
			if fhGetRecordId(fhGetValueAsLink(ptrSource))==source then
				-- have citation display values
				lab_message.title = 'Citation exist - Please Change Type or Press Exit button'
				haveCitation=true
			end
			ptrSource:MoveNext()
		end
end

----------------------------------------------------
-- Function: ClearCitation - Clear prepared citation
--      ready to add new fields
---------------------------------------------------
function ClearCitation(sourceID)
local ptr=fhNewItemPtr()
local Cite=fhNewItemPtr()
local ptrFld= fhNewItemPtr()
local ptrSrce= fhNewItemPtr()
	-- find correct source
	ptrSrce=GetRecordByID('SOUR',source)
	ptr:MoveToFirstRecord('HEAD') -- Move to header record
	Cite:MoveTo(ptr, "~._PCIT.SOUR")
	if Cite:IsNotNull() then
		-- clear current citation fields

		-- delete citation fields
		while (true)
		do
			ptrFld:MoveTo(Cite, "SOUR._FIELD")
			if ptrFld:IsNotNull() then
				fhDeleteItem(ptrFld)
			else
				break
			end
		end
	else
		-- may not have a citation
	end
	fhSetValueAsLink(Cite, ptrSrce)		
	return Cite
end


---------------------------------------------------
--function SelectSource(Template ID, Region,Type)
-- Dialog to select templated source (Only show relevant sources
-------------------------------------------------------
function SelectSource(tID,Region,Type)
local cnt=0
local buttons = { "OK", "Cancel" }
local array={}
local ptrSource = fhNewItemPtr() 
local ptrTemp = fhNewItemPtr()
local strTitle=""
local strTest=Region..' '..Type..' Registration Index'
local select=""

	ptrSource:MoveToFirstRecord("SOUR")    -- point to the first record
	while not ptrSource:IsNull() do
		strTitle=fhGetItemText(ptrSource,'~.TITL')
		if strTitle== strTest then
			-- check for correct template ID
			ptrTemp=fhGetItemPtr(ptrSource,'~._SRCT')
			if ptrTemp:IsNotNull() then
				if fhGetRecordId(fhGetValueAsLink(ptrTemp))==tID then
					cnt=cnt+1
					source=fhGetRecordId(ptrSource)
					table.insert(array,strTitle ..' >>'..fhGetRecordId(ptrSource))
				end
			end
		end
   	ptrSource:MoveNext()
	end

	if cnt>1 then 
		-- set up fields for dialog form. Reordering fields and changing labels will only affect the appearance 
		-- on the dialog form and the text written to the text from source in the Source Record
		fields = {}
		table.insert(fields,{tag = "Source",label = "Valid Sources",	type = "LIST"	,values = array,prompts =array})

		local r = fh.getParam("Please Select a source record from list below", "", fields, buttons,s,dlg)
		if r.ok then
			select=string.gsub(r.results["Source"],strTest,'')
			select=string.gsub(select,' >>','')
			source=tonumber(select)
			fhSetIniFileValue(iniFile, region, type.."Source", "integer",source)
			fhSetIniFileValue(iniFile, "Defaults", "Region", "text",region)
		else
			source= -1
		end
	elseif cnt==1 then
		fhSetIniFileValue(iniFile, region, type.."Source", "integer",source)
		fhSetIniFileValue(iniFile, "Defaults", "Region", "text",region)
	else	
		-- identify current repositories, allowing selection
		local repos=GetRepositories()
		-- set up fields for dialog form.
		fields = {}
		table.insert(fields,{tag = "Title",label = "Title",	type = "STRING"	,value = strTest,	protect = true,})
		table.insert(fields,{tag = "Template",label = "Template",	type = "STRING"	,value = 'Civil Registration Index',	protect = true,})
		table.insert(fields,{tag = "Type",label = "Type",	type = "STRING"	,value = type,	protect = true,})
		table.insert(fields,{tag = "Region",label = "Region",	type = "STRING"	,value = region,	protect = true,})
		table.insert(fields,{tag = "Repository",label = "Repository",	type = "LIST"	,value = Repository,values = repos,prompts =repos})
		table.insert(fields,{tag = "Collection",label = "Collection",	type = "STRING"	,value = ''})
		table.insert(fields,{tag = "URL",label = "URL",	type = "STRING"	,value=''})
		table.insert(fields,{tag = "Create",label = "Create Source",	type = "BOOLEAN"	,value=false})

		local r = fh.getParam("Create Source Record", "Tick Create Source and \nadd any optional details in fields below and Press OK", fields, buttons,s,dlg)
		if r.ok then
			if r.results["Create"] then
					-- Create Source
				local ptrRepos=fhNewItemPtr()
				local ptrLink=fhNewItemPtr()

				-- create source with title and type
				ptrSource= fhCreateItem("SOUR")
				ptrLink = fhCreateItem("_SRCT", ptrSource) 
				fhSetValueAsLink(ptrLink, ptrTemplate)
				AddInfo(ptrSource,"TITL",strTest)
				AddInfo(ptrSource, '~EN-TYPE', type)
				AddInfo(ptrSource, '~EN-REGION', region)
				if r.results["Repository"]~=nil then
					-- link to repository
		
					ptrRepos:MoveToFirstRecord("REPO")    -- point to the first record
					while not ptrRepos:IsNull() do
 			  			-- find the correct Repository and link it to the source
 		 	 			if r.results["Repository"] ==fhGetItemText(ptrRepos,'REPO.NAME') then
							ptrLink = fhCreateItem('~RP-REPOSITORY', ptrSource) 
							fhSetValueAsLink(ptrLink, ptrRepos)
						end 
	   				ptrRepos:MoveNext()
					end
				end
				if r.results["Collection"]~=nil then
					AddInfo(ptrSource, '~TX-COLLECTION', r.results["Collection"])
				end
				if r.results["URL"]~=nil then
					AddInfo(ptrSource, '~UL-URL', r.results["URL"])
				end
				source=fhGetRecordId(ptrSource)
				fhSetIniFileValue(iniFile, region, type.."Source", "integer",source)
				fhSetIniFileValue(iniFile, "Defaults", "Region", "text",region)
			end
		end
	end
end


---------------------------------------------------
--Resize Dialog
-------------------------------------------------------
function ResizeDialog(dlg)
local resize=false  -- do I need to resize
local dlgSize=dlg.naturalsize 					-- size of dialog in pixels
local dlgArea=dlg.size									-- size of dialog in size units
local screenPixels=Split(iup.GetGlobal("SCREENSIZE"),'x') 	-- width and height of screen in pixels
local dialogPixels=Split(dlgSize,'x')			-- width and height of screen in size units
local dialogSize=Split(dlgArea,'x')		 	-- width and height of dialog in pixels
local width=tonumber(dialogSize[1])			-- new width of dialog in size units - default no change
local height=tonumber(dialogSize[2])		-- new height of dialog in size units - default no change

	-- get smaller of width and height
	if tonumber(dialogPixels[1])>tonumber(screenPixels[1]) then
		-- recalculate width in size units
		width=(tonumber(screenPixels[1]) * tonumber(dialogSize[1]) / tonumber(dialogPixels[1]))
		width=math.floor(width)
		resize=true
	end

	if tonumber(dialogPixels[2])>tonumber(screenPixels[2]) then
		-- recalculate height in size units
		height=(tonumber(screenPixels[2]) * tonumber(dialogSize[2]) / tonumber(dialogPixels[2]))
		height=math.floor(height)
		resize=true
	end


	if resize then
 		-- resize (i.e. shrink) dialog, centered on the screen
		dlg.size=tostring(width).."x"..tostring(height)
		dlg:showxy(iup.CENTER, iup.CENTER)
		iup.Map(dlg)
	end
end

---------------------------------------------------
--function FindTemplate(template name)
-------------------------------------------------------
function FindTemplate(tName)
local ptr=fhNewItemPtr();


	ptr:MoveToFirstRecord('_SRCT')
	while ptr:IsNotNull() do
		if fhGetItemText(ptr,'~.NAME')==tName then
			ptrTemplate=ptr
			return fhGetRecordId(ptr)
		end
		ptr:MoveNext()
	end
	return -1
end

---------------------------------------
-- Function: GetRegions - returns table of regions for CRI
---------------------------------------
function GetRegions(ID)

local array={}
local ptrTemplate = fhNewItemPtr()  -- declare pointer
local ptrFDef=fhNewItemPtr()
local strRegions=""

	ptrTemplate:MoveToFirstRecord("_SRCT")    -- point to the first record
	while not ptrTemplate:IsNull() do
  	 	if fhGetRecordId(ptrTemplate)==ID then
			-- loop through regions
			ptrFDef=	fhGetItemPtr(ptrTemplate,'~.FDEF')
			while not ptrFDef:IsNull() do
				if fhGetItemText(ptrFDef,'~.NAME')=='Region' then
					-- found field definiton
					strRegions =fhGetItemText(ptrFDef,'~.PROM')
					return Split(strRegions,'|')
				end
				ptrFDef:MoveNext('SAME_TAG')
			end
		end
   	ptrTemplate:MoveNext()
	end

	return array
end

---------------------------------------
-- Function: GetRepositories - returns table of repositories
---------------------------------------
function GetRepositories()

local array={}
local ptrRepos = fhNewItemPtr()  -- declare pointer
local strRepos=""

	ptrRepos:MoveToFirstRecord("REPO")    -- point to the first record
	while not ptrRepos:IsNull() do
   	-- For each Repository Add the Name to the list
  	 	strRepos =fhGetItemText(ptrRepos,'REPO.NAME')
		table.insert(array,strRepos )
   	ptrRepos:MoveNext()
	end

	return array
end

---------------------------------------
-- Function: ListType - returns table of GRO Index types
---------------------------------------
function ListType(l)
local array ={}
	
	table.insert(array,'Birth')
	table.insert(array,'Marriage')
	table.insert(array,'Death')
	PopulateList(l,array)

end

---------------------------------------
-- Function: ListAssessment - returns table of regions for CRI
---------------------------------------
function ListAssessments(l)
local array ={}
	
	table.insert(array,'Unreliable')
	table.insert(array,'Questionable')
	table.insert(array,'Secondary information')
	table.insert(array,'Primary information')
	table.insert(array,'')
	PopulateList(l,array)

end
-------------------------------------------------------
-- PopulateList populates a dialog list with table values
-------------------------------------------------------

function PopulateList(l, tblVals)
   local is_indexed = (rawget( tblVals, 1 ) ~= nil)
   l.REMOVEITEM = "ALL"
   if not is_indexed then
      local i=1
      for k, _ in pairs(tblVals) do
         l[tostring(i)]=k
         i=i+1
       end
   else
       for i, v in ipairs(tblVals) do
          l[tostring(i)]=v
       end	
   end
end

---------------------------------------
-- Function: AddInfo - add info to fact, updating if fact exists
---------------------------------------
function AddInfo(ptr, Type, Value)
	
	if Type and Value then
		local infoPtr=fhGetItemPtr(ptr,'~.'..Type)
		if infoPtr:IsNull() then
			infoPtr= fhCreateItem(Type, ptr)
		end
		fhSetValueAsText(infoPtr, Value)
	end
end

---------------------------------------
-- Function: GetRecordByID - find record by ID
---------------------------------------
function GetRecordByID(DataRef,ID)
local ptr=fhNewItemPtr()

	ptr:MoveToFirstRecord(DataRef)    -- point to the first record
	while not ptr:IsNull() do
		if fhGetRecordId(ptr)==ID then
			return ptr
		end
		ptr:MoveNext()
	end
	return ptr
end


---------------------------------------
-- Function: Split - splits a string by delimter
--										and returns a table of strings
---------------------------------------
function Split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, trim(match));
    end
    return result;
end

---------------------------------------
-- Function: trim - removes leading and trailing spaces
---------------------------------------
function trim(s)
  return (string.gsub(s, "^%s*(.-)%s*$", "%1"))
end

---------------------------------------
-- Function: PluginHelp - displays help
---------------------------------------
function PluginHelp()
  	fhMessageBox(help, "MB_OK", "", dlg.HWND)

end

main();

Source:Add-GRO-Index-Entries-2.fh_lua