GRO Source Reference.fh_lua--[[
@Title: GRO Source Reference
@Type: Standard
@Author: Chris Read
@Contributors: Mike Tate, Jane Taubman
@Version: 1.5
@Keywords: GRO
@LastUpdated: 04/04/2024
@Licence: This plugin is copyright (c) Chris Read 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: Add a GRO Index Source Citation to an Event and optionally create the event and or set the fields.
This version is derived from 'Add GRO Index Source Citation' V1.0 by Mike Tate which in turn was derived from 'Add GRO Source' V1.3 by Jane Taubman.
The primary difference is the dynamic behaviour of the UI and awarness of the changes in the GRO index information over time. Also, the addition of
user definable formats for the GRO Index citation. As of v1.2 this includes the ability to specify a date range the format applies to, so they are
auto-filtered in the selection list for convenience.
@V1.0 It's my first foray in to LUA and FH Plugin development, and I have much to learn. I will say, IUP is drastically short on good examples beyond
the booming obvious, but hey-ho, and onward we go. 40 years of software development should count for something.
This implementation adds:
- Enable/disable of parameter fields relevant to the selected BMD type and the citation reference type selected.
- Selectable citation reference string formats for each register type. These use a named field style i.e. {YEAR} internally
for the built-in formats.
Future enhancements:
- Allow user creation of citation formats using the internal named field implementation, once I figure out how best to save/restore
them and implement a creation dialog.
@V1.1 This implementation adds:
- Handling for Age at Death starting 1866, and changing to Date of Birth from Q2 1969
- Changed auto-text {BIRTH} to {DOB} and separated {AGE} & {DOB} to only contain a value when applicable
- Removed extraneous 'c' in Oct in {MONTH} field
@V1.2 This implementation adds:
- Specification of a date period for formats so that the list of formats will be filtered to those applicable to the GRO Index Date and quarter/month.
I found that in practical use, as I had defined several formats for the different GRO Index information (particularly Deaths), I was constantly having
to locate and select different ones. In theory you only need one or maybe two per period; one for single line version (for 'Where in') and one
for multi-line (Text from Source/Event Note); that is, if you like to put the extra info (Mothers Maiden name, Death Age/DoB) on the next line.
In general a given user will probably only use one option for where the citation gets put, so only needs one format the way they like it. This means
the format selection essentially become automatic.
- Added the selected register type to the saved settings, and bumped the data version to V2. For previous V1 settings, it will default to births when loaded.
@V1.3 This implementation adds:
- Tidy ups and corrections as suggested by Visual Studio Code LUA Extension, and selected formatting using the StyLua Extension
- Separated {VOL}/{REG} and {PAG}/{ENT} to only contain a value when applicable as previoulsuy done for the {AGE} & {DOB} fields.
@V1.4 This implementation adds:
- Removal of the pre-defined BIRTH format Q3 1837 to Q3 1911 with no mothers maiden name, as although the official date of the information being included
is Q3 1911, the GRO has been retrospectivly adding the information where it is able to determine it. Date range for subsequent format has been updated to
cover from Q3 1837.
- Corrected unintentional error in the removal of formats due to missunderstanding of LUA tables which resulted in a subsequent plugin crash.
- Removed unecessary error information when the plugin aborts due to missing information or other issue when attempting to apply a citation. This makes
it looks less like an uncontrolled crash.
@V1.5 This implementation adds:
- Input field for selected persons name as recorded in the GRO Index. This may be different from their actual name due to miss-transcription and use of initials
rather than full given names. The name will be available for formats definitions as {RNAME}.
- Input field for selected persons spouse as recorded in the GRO Index for marriages. This may be different from their actual name due to miss-transcription. The
name will be available for format definitions as {RSPOUSE}.
- Resolved problem restoring the previously saved register type.
- Corrected error in formatted citation generation for the actual citation.
]]
Version = "1.5"
require("iuplua")
require("iupluacontrols")
if fhGetAppVersion() > 5 then
fhSetStringEncoding("UTF-8")
iup.SetGlobal("UTF8MODE","YES")
iup.SetGlobal("UTF8MODE_FILE","NO")
iup.SetGlobal("CUSTOMQUITMESSAGE","YES") -- Needed for IUP 3.28
end
-- Define the named fields for Citation format strings
namedFields = { "RNAME",
"YEAR",
"QTR",
"MONTH",
"DIST",
"DISTNO",
"VOL",
"REG",
"PAGE",
"ENT",
"RSPOUSE",
"MAID",
"AGE",
"DOB"}
--[[
Definitions of the pre-canned citation formats for each register type BIRTH, MARRIAGE, DEATH
Each register entry is itself a table of formats, where each entry comprises
a PERIOD of FROM, TO during which the format should be applicable.
a DISPLAY string to display that could be a name or an example of the format
a FORMAT string using the named fields that will be used to create the GRO string.
]]
--[[
Rules for GRO Registers
Q3 1837 • Civil Registration in England and Wales begins
1866 • GRO indexes include age at death
Q3 1911 • GRO Birth Indexes include Mothers Maiden Name, but GRO has been adding this to earlier index entries.
Q1 1912 • GRO Marriage Indexes include Spouses Surname
Q2 1969 • GRO Death Indexes show date of Birth instead of age at Death
Q2 1974 • GRO Volume Numbers re-organised (e.g. 9c became 32).
Q1 1993 • Grouping of Districts into Volumes ceased for Births & Deaths, District/Register/Entry Numbers started
Q1 1994 • Grouping of Districts into Volumes ceased for Marriages, District/Register/Entry Numbers started
]]
citationFormats = { BIRTH = { {PERIOD = {FROM = "Q3 1837", TO = "Q4 1992"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page|Mother:",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}\nMother: {MAID}"},
{PERIOD = {FROM = "Q1 1993"},
DISPLAY = "GRO: Qn yyyy, District(No.), Reg, Entry|Mother:",
FORMAT = "GRO: {QTR} {YEAR} {MONTH}, {DIST}({DISTNO}), {REG}, {ENT}\nMother: {MAID}"}
},
MARRIAGE = { {PERIOD = {FROM = "Q3 1837", TO = "Q4 1993"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}"},
{PERIOD = {FROM = "Q1 1994"},
DISPLAY = "GRO: Qn yyyy, District(No.), Reg, Entry",
FORMAT = "GRO: {QTR} {YEAR} {MONTH}, {DIST}({DISTNO}), {REG}, {ENT}"}
},
DEATH = { {PERIOD = {FROM = "Q3 1837", TO = "1865"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}"},
{PERIOD = {FROM = "1866", TO = "Q1 1969"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page|Age: nnn",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}\nAge: {AGE}"},
{PERIOD = {FROM = "Q2 1969", TO="1992"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page|DoB: dd mmm yyyy",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}\nDoB: {DOB}"},
{PERIOD = {FROM = "1993"},
DISPLAY = "GRO: Qn yyyy, District(No.), Reg, Entry|DoB: dd mmm yyyy",
FORMAT = "GRO: {QTR} {YEAR} {MONTH}, {DIST}({DISTNO}), {REG}, {ENT}\nDoB: {DOB}"}
}
}
function main()
local dlgResult
local deathInfo = "AGE"
local volregInfo = "VOLUME"
local arrShortPeriod = {"Q1";"Q2";"Q3";"Q4";"Jan";"Feb";"Mar";"Apr";"May";"Jun";"Jul";"Aug";"Sep";"Oct";"Nov";"Dec";}
local formatMap = {} -- Used to map the selection list entries to the formats after filtering for the drop-down list
-- Create the active objects we need
-- Buttons for completion and opening customisation dialog
btnOk = iup.button({
name = "OK",
title = "Apply",
size = "40x20",
tip = "Apply the GRO Source Citation according to your inputs and option settings",
action = function(self)
dlgResult = self.name
return iup.CLOSE
end,
})
btnCancel = iup.button({
name = "CANCEL",
title = "Close",
size = "40x20",
tip = "Exit without making any changes to the project",
action = function(self)
dlgResult = self.name
return iup.CLOSE
end,
})
btnCustomise = iup.button({
name = "EDIT",
title = "Customise...",
size = "x10",
action = function()
showCustomiseDialog()
end,
tip = "Manage and customise the available GRO formats",
})
-- Toggles that we need for selection of the register
radBirth = iup.toggle({
name = "BIRTH",
title = "Birth",
value = "OFF",
tip = "Select Birth Registrations",
action = function(self)
selectRegister(self)
return iup.DEFAULT
end,
})
radMarriage = iup.toggle({
name = "MARRIAGE",
title = "Marriage",
value = "OFF",
tip = "Select Marriage Registrations",
action = function(self)
selectRegister(self)
return iup.DEFAULT
end,
})
radDeath = iup.toggle({
name = "DEATH",
title = "Death",
value = "OFF",
tip = "Select Death Registrations",
action = function(self)
selectRegister(self)
return iup.DEFAULT
end,
})
radBMD = iup.radio({ iup.hbox({ radBirth, radMarriage, radDeath }) })
-- List to select the GRO Quarter or Month as applicable
listQuarter = iup.list({
"Q1 Jan-Feb-Mar",
"Q2 Apr-May-Jun",
"Q3 Jul-Aug-Sep",
"Q4 Oct-Nov-Dec",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
value = 1,
dropdown = "YES",
visible_items = 5,
tip = "Select registration quarter or month",
})
-- List to select the option for what to do with the GRO date information if anything
listIndexInDate = iup.list({
"No Event Date",
"Year Only Event Date",
"Inexact Event Date",
value = 1,
dropdown = "YES",
size = "100",
tip = "When should the event date be updated",
})
-- List to select the option for how the citation should be recorded
listCitRef = iup.list({
"Where within",
"Text From Source",
"Event Note Only",
value = 1,
dropdown = "YES",
size = "100",
tip = "Where should the citation reference be put",
})
-- Dynamic list of the GRO citation formats that can be selected
listRefFormat = iup.list({
value = 0,
size = "200",
dropdown = "YES",
action = function()
updateCitation()
end,
tip = "Select citation reference format",
})
-- List to select the option for how the citation date should be recorded
listCitDate = iup.list({
"No Date",
"Today's Date",
"GRO Index Reg Date",
value = 1,
dropdown = "YES",
size = "100",
tip = "What date should be used for the citation",
})
-- List to select the option for what assesment to give the citation
listCitAss = iup.list({
"None",
"Unreliable",
"Questionable",
"Secondary Evidence",
"Primary Evidence",
value = 1,
dropdown = "YES",
size = "100",
tip = "Select the assessement to give the citation",
})
-- Table of values used to set the assesement when option is to apply one
local tblAssess = { "Unreliable", "Questionable", "Secondary Evidence", "Primary Evidence", "" }
-- Checkbox to select to add the citation to individual/parents names
chkAddToName = iup.toggle({ value = "OFF", tip = "Should the citation be added to the individual/parents name" })
-- Text input fields
textRecordedName = iup.text{size="200", value="", tip = "Name as recorded in GRO Index", active = "YES"}
textRecordedSpouse = iup.text{size="200", value="", tip = "Spouse name as recorded in GRO Index", active = "NO"}
textDistrict = iup.text{size="200", value="", tip = "Name of the registration district"}
textDistrictNo = iup.text({ size = "100", value = "", tip = "Registration district number after 1992." })
textRefVolReg = iup.text({ size = "100", value = "", tip = "Volume pre-1993, Register after 1992." })
textYear = iup.text({ SPIN = "YES", SPINMIN = 1837, SPINMAX = 2005, value = "1837" })
textRefPagEnt = iup.text({ size = "100", value = "", tip = "Page number pre-1993, Entry number after 1992." })
textMother = iup.text({ active = "YES", value = "", size = "200", tip = "Maiden name of mother for birth registrations" })
textCitation = iup.text({
active = "YES",
multiline = "YES",
size = "200x30",
tip = "What the citation will look like based on your selections",
})
textDeath = iup.text({ size = "100", active = "NO", value = "", tip = "Age at Death or Birth date:" })
textBirthId = iup.text({ tip = "Family Historian source record ID for GRO Birth Index source" })
textMarriageId = iup.text({ tip = "Family Historian source record ID for GRO Marriage Index source" })
textDeathId = iup.text({ tip = "Family Historian source record ID for GRO Death Index source" })
-- Named labels where we want to be able to change active state of
lblRecordedSpouse = iup.label{ title = "Spouse as Recorded:", active = "NO" }
lblDistrict = iup.label{ title = "Registration District:" }
lblDistrictNo = iup.label{ title = "Registration District Number:", active = "NO" }
lblRefVolReg = iup.label{ title = "Volume or Register number:" }
lblRefPagEnt = iup.label{ title = "Volume Page or Register Entry:" }
lblMother = iup.label{ title = "Mothers Maiden name:", active = "YES" }
lblDeath = iup.label{ title = "Age at Death or Birth date:", active = "NO" }
lblBirthSrcId = iup.label{ title = "Birth Source Record ID:" }
lblMarriageSrcId = iup.label{ title = "Marriage Source Record ID:" }
lblDeathSrcId = iup.label{ title = "Death Source Record ID:" }
lblCitDate = iup.label{ title = "Set Citation Entry Date:" }
lblCitAss = iup.label{ title = "Set Citation Assessment:" }
lblAddToName = iup.label{ title = "Add Citation to Name:" }
-- Create display grid
grid = iup.gridbox{ iup.label{title = "GRO Index Type:"}, radBMD,
iup.label{ title = "Name as Recorded:" }, textRecordedName,
iup.label{title = "Registration Year:"}, textYear,
iup.label{title = "Registration Quarter or Month:"}, listQuarter,
lblDistrict, textDistrict,
lblDistrictNo, textDistrictNo,
lblRefVolReg, textRefVolReg,
lblRefPagEnt, textRefPagEnt,
lblRecordedSpouse, textRecordedSpouse,
lblMother, textMother,
lblDeath, textDeath,
iup.label{title = "Put GRO Index date in event Date when:", size="150"}, listIndexInDate,
iup.label{title = "Select Citation Reference Field:"}, listCitRef,
iup.hbox{iup.label{title = "GRO Reference Format:"}, btnCustomise; alignment="ACENTER"}, listRefFormat,
iup.label{title = "GRO Reference Preview:"}, textCitation,
iup.label{separator = "HORIZONTAL"}, iup.label{separator = "HORIZONTAL"},
lblBirthSrcId, textBirthId,
lblMarriageSrcId, textMarriageId,
lblDeathSrcId, textDeathId,
lblCitDate, listCitDate,
lblCitAss, listCitAss,
lblAddToName, chkAddToName;
orientation = "HORIZONTAL", numdiv = 2, sizecol=-1, sizelin=-1, padding="2x5", fontstyle=""}
-- Set Parameter Default Values
local intPYear = 1900 -- Registration Year
local intPQuarter = 1 -- Registration Quarter or Month
local intPIndexInDate = 1 -- Overwrite Event Date Criteria
local intPCitRef = 1 -- Select Citation Field for Ref
local intPBirthId = nil -- Source Record Id Birth
local intPMarriageId = nil -- Source Record Id Marriage
local intPDeathId = nil -- Source Record Id Death
local intPCitDate = 1 -- Select Citation Entry Date
local intPCitAss = 1 -- Select Citation Assessment
local strPAddToName = "" -- Add Citation to Name?
local tblCitationFormats = citationFormats -- Assume the pre-defined if nothing saved (first run)
function textYear:valuechanged_cb()
-- Check it is a valid year
if ValidYear(textYear.value) then
-- Enable/Disable fields for year and register
setForYear(radBMD.value.name, tonumber(textYear.value))
-- Update citation
updateCitation()
else
iup.Message("Registration Year", "Year value not recognised as a year, please correct before continuing.")
end
end
function textYear:spin_cb(pos)
-- NOTE: pos is the value it will be after the spin, not current value
-- Check it is a valid year
if ValidYear(pos) then
-- Enable/Disable fields for year and register
setForYear(radBMD.value.name, tonumber(pos))
-- Update citation
updateCitation()
else
iup.Message("Registration Year", "Year value not recognised as a year, please correct before continuing.")
end
end
function listQuarter:action(t, i, v)
if v == 1 then
-- Enable/Disable fields for year and register
setForYear(radBMD.value.name, tonumber(textYear.value))
-- Update citation
updateCitation()
end
return iup.DEFAULT
end
--[[
Rules for GRO Registers
Q3 1837 • Civil Registration in England and Wales begins
1852 • GRO References change from Roman Numerals (XVI) to Arabic numbers and letters (6d)
1866 • GRO indexes include age at death
Q3 1911 • GRO Birth Indexes include Mothers Maiden Name, but GRO has been adding this to earlier index entries.
Q1 1912 • GRO Marriage Indexes include Spouses Surname
Q2 1969 • GRO Death Indexes show date of Birth instead of age at Death
Q2 1974 • GRO Volume Numbers re-organised (e.g. 9c became 32).
Q1 1993 • Grouping of Districts into Volumes ceased for Births & Deaths, District/Register/Entry Numbers started
Q1 1994 • Grouping of Districts into Volumes ceased for Marriages, District/Register/Entry Numbers started
]]
function setForYear(reg, year)
theQuarter, _ = getQuarterAndMonth()
if (year < 1837) or (year == 1837 and (theQuarter == "Q1" or theQuarter == "Q2")) then
-- No GRO Indexes prior to Q3 1837, all GRO input fields disabled
lblDistrict.active = "NO"
textDistrict.active = "NO"
lblDistrictNo.active = "NO"
textDistrictNo.active = "NO"
lblRefVolReg.active = "NO"
textRefVolReg.active = "NO"
lblRefPagEnt.active = "NO"
textRefPagEnt.active = "NO"
elseif
((reg == "BIRTH" or reg == "DEATH") and (year >= 1837 and year <= 1992))
or (reg == "MARRIAGE" and (year >= 1837 and year <= 1993))
then
-- No District number, Volume and Page
volregInfo = "VOLUME"
lblDistrict.active = "YES"
textDistrict.active = "YES"
lblDistrictNo.active = "NO"
textDistrictNo.active = "NO"
lblRefVolReg.title = "Volume Number:"
lblRefVolReg.active = "YES"
textRefVolReg.active = "YES"
lblRefPagEnt.title = "Page Number:"
lblRefPagEnt.active = "YES"
textRefPagEnt.active = "YES"
else
-- District number, Register and Entry
volregInfo = "REGISTER"
lblDistrict.active = "YES"
textDistrict.active = "YES"
lblDistrictNo.active = "YES"
textDistrictNo.active = "YES"
lblRefVolReg.title = "Register Number:"
lblRefVolReg.active = "YES"
textRefVolReg.active = "YES"
lblRefPagEnt.title = "Register Entry:"
lblRefPagEnt.active = "YES"
textRefPagEnt.active = "YES"
end
setForBMDType(reg, year, theQuarter)
end -- setForYear
-- Essentially called as the common BMD toggle action
function selectRegister(self)
if self.value == "ON" then
setForYear(radBMD.value.name, tonumber(textYear.value))
-- Load the relevant formats for the selected register type
loadFormats(radBMD.value.name)
updateCitation()
end
end -- selectRegister
-- Set the availability of the Mother's maiden name and Death Age based on register type selection
function setForBMDType(reg, year, qtr)
if (year < 1837) or (year == 1837 and (theQuarter == "Q1" or theQuarter == "Q2")) then
-- No GRO Indexes prior to Q3 1837, all GRO input fields disabled
textRecordedSpouse.active = "NO"
textMother.active = "NO"
textDeath.active = "NO"
lblRecordedSpouse.active = "NO"
lblMother.active = "NO"
lblDeath.active = "NO"
else
-- Set the Death age/DoB label as appropriate to the year etc.
if ((year >= 1866) and (year <= 1968)) or ((year == 1969) and (qtr == "Q1")) then
deathInfo = "AGE"
lblDeath.title = "Age at Death:"
else
deathInfo = "DOB"
lblDeath.title = "Date of Birth:"
end
-- Enable/Disable GRO fields relevant to the register type
if reg == "BIRTH" then
textRecordedSpouse.active = "NO"
textMother.active = "YES"
textDeath.active = "NO"
lblRecordedSpouse.active = "NO"
lblMother.active = "YES"
lblDeath.active = "NO"
elseif reg == "MARRIAGE" then
textRecordedSpouse.active = "YES"
textMother.active = "NO"
textDeath.active = "NO"
lblRecordedSpouse.active = "YES"
lblMother.active = "NO"
lblDeath.active = "NO"
elseif reg == "DEATH" then
textRecordedSpouse.active = "NO"
textMother.active = "NO"
textDeath.active = "YES"
lblRecordedSpouse.active = "NO"
lblMother.active = "NO"
-- No age recorded prior to 1866
if year < 1866 then
lblDeath.active = "NO"
textDeath.active = "NO"
else
lblDeath.active = "YES"
textDeath.active = "YES"
end
else
-- Should never get here unless we did a bad coding LOL
iup.Message(
"function setForBMDType()",
'Called with invalid register type: "'
.. reg
.. '".\nPlease debug and correct the coding error.\n\nPlugin aborted!'
)
return iup.CLOSE
end
end
-- Load the relevant formats for the selected register type
loadFormats(reg)
end --setForBMDType
-- Populate the format selection list for the specified register
function loadFormats(reg)
-- Convert the GRO Index year to a date object (should be valid already)
local groDate = fhNewDate()
local added = 0
local quarter
local month
quarter, month = getQuarterAndMonth()
if string.len(month) > 3 then
-- It's a quarter date selection
groDate:SetValueAsText(quarter .. " " .. textYear.value)
else
-- It's a specific month selection
groDate:SetValueAsText(month .. " " .. textYear.value)
end
-- Clear the list
listRefFormat[1] = nil
formatMap[1] = nil
for f = 1, #tblCitationFormats[reg] do
local fromDate = nil
local toDate = nil
if tblCitationFormats[reg][f].PERIOD then
-- PERIOD is present get limits if present
if tblCitationFormats[reg][f].PERIOD.FROM then
fromDate = fhNewDate()
res = fromDate:SetValueAsText(tblCitationFormats[reg][f].PERIOD.FROM)
end
if tblCitationFormats[reg][f].PERIOD.TO then
toDate = fhNewDate()
res = toDate:SetValueAsText(tblCitationFormats[reg][f].PERIOD.TO)
end
end
-- Add the format if within the period specified
if InPeriod(groDate, fromDate, toDate) then
added = added + 1
formatMap[added] = f
listRefFormat[added] = tblCitationFormats[reg][f]["DISPLAY"]
end
end
if tonumber(listRefFormat.count) > 0 then
listRefFormat.value = 1
end
end -- loadFormats
-- Enable/Disable the citation fields depending on citation type selection
function listCitRef:action(t, i, v)
if v == 1 then
setForCitRefField(i)
end
return iup.DEFAULT
end
-- Enable/Disable the fields that only apply to a source citation
function setForCitRefField(i)
if i == 3 then
-- Event Note only so disable all fields
textBirthId.active = "NO"
textMarriageId.active = "NO"
textDeathId.active = "NO"
listCitDate.active = "NO"
listCitAss.active = "NO"
chkAddToName.active = "NO"
lblBirthSrcId.active = "NO"
lblBirthSrcId.active = "NO"
lblMarriageSrcId.active = "NO"
lblDeathSrcId.active = "NO"
lblCitDate.active = "NO"
lblCitAss.active = "NO"
lblAddToName.active = "NO"
else
-- Other selections enable all fields
textBirthId.active = "YES"
textMarriageId.active = "YES"
textDeathId.active = "YES"
listCitDate.active = "YES"
listCitAss.active = "YES"
chkAddToName.active = "YES"
lblBirthSrcId.active = "YES"
lblBirthSrcId.active = "YES"
lblMarriageSrcId.active = "YES"
lblDeathSrcId.active = "YES"
lblCitDate.active = "YES"
lblCitAss.active = "YES"
lblAddToName.active = "YES"
end
end -- setForCitRefField
function textDistrict:valuechanged_cb()
-- Update citation
updateCitation()
end
function textRecordedName:valuechanged_cb()
-- Update citation
updateCitation()
end
function textDistrictNo:valuechanged_cb()
-- Update citation
updateCitation()
end
function textRefVolReg:valuechanged_cb()
-- Update citation
updateCitation()
end
function textRefPagEnt:valuechanged_cb()
-- Update citation
updateCitation()
end
function textRecordedSpouse:valuechanged_cb()
-- Update citation
updateCitation()
end
function textMother:valuechanged_cb()
-- Update citation
updateCitation()
end
function textDeath:valuechanged_cb()
-- Update citation
updateCitation()
end
function chkAddToName:action()
if chkAddToName.value == "ON" then
chkAddToName.title = "On"
else
chkAddToName.title = "Off"
end
end
function updateCitation()
-- Declare the shared values for separation purposes
local deathAge = ""
local deathDoB = ""
local volName = ""
local regName = ""
local pageNo = ""
local entNo = ""
-- Split the Volume/Register and Page/Entry
if volregInfo == "VOLUME" then
volName = textRefVolReg.value
pageNo = textRefPagEnt.value
else
regName = textRefVolReg.value
entNo = textRefPagEnt.value
end
-- Split the Age/Dob for death
if deathInfo == "AGE" then
deathAge = textDeath.value
else
deathDoB = textDeath.value
end
-- Convert the Quarter or Month selection to a Quarter and a Month
theQuarter, theMonth = getQuarterAndMonth()
if tonumber(listRefFormat.value) > 0 then
-- Create the Citation string from the input parameters and selected format
textCitation.value = formatCitation(tblCitationFormats[radBMD.value.name][formatMap[tonumber(listRefFormat.value)]]["FORMAT"],
{ RNAME = textRecordedName.value,
YEAR = textYear.value,
QTR = theQuarter,
MONTH = theMonth,
DIST = textDistrict.value,
DISTNO = textDistrictNo.value,
VOL = volName,
REG = regName,
PAGE = pageNo,
ENT = entNo,
RSPOUSE = textRecordedSpouse.value,
MAID = textMother.value,
AGE = deathAge,
DOB = deathDoB})
else
textCitation.value = ""
end
end
-- vvvvvvvvvvvvvvvvvvvvv Customise GRO Format Dialog vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
--[[
This function displays and handles the format customisation.
]]
function showCustomiseDialog()
formatHelp =
[[
The format can make use of most standard ASCII characters. Special auto-text fields
may also be used to substitute in values you have entered in the main dialog.
These are as follows:
{RNAME}, the name of the individual as recorded
{YEAR}, the year of registration
{QTR}, the quarter of registration
{MONTH}, the month of registration where applicable
{DIST}, the registration district name
{DISTNO}, the registration district number where applicable
{VOL}, the volume number as applicable
{REG}, the register number as applicable
{PAGE}, the page number as applicable
{ENT}, the entry number as applicable
{RSPOUSE}, the name of the spouse as recorded
{MAID}, the mother's maiden name for births
{AGE}, Age at Death
{DOB}}, Date of Birth (for deaths)
]]
local textDisplay = iup.text({ size = "250", value = "", tip = "Display name for the format" })
local textFormat = iup.text({ multiline = "YES", size = "300x30", value = "", tip = formatHelp })
local textFrom = iup.text({ size = "50", value = "", tip = "Date from which the format is applicable" })
local textTo = iup.text({ size = "50", value = "", tip = "Date to which the format is applicable" })
-- for some reaason this has to go before the use in listExisting action
function updateFields()
-- Copy selected format information to edit fields
if listExisting.value ~= 0 then
local format = tblCitationFormats[radBMD.value.name][tonumber(listExisting.value)]
if format.PERIOD ~= nil then
if format.PERIOD.FROM ~= nil then
textFrom.value = format.PERIOD.FROM
else
textFrom.value = ""
end
if format.PERIOD.TO ~= nil then
textTo.value = format.PERIOD.TO
else
textTo.value = ""
end
end
textDisplay.value = format["DISPLAY"]
textFormat.value = format["FORMAT"]
end
end -- updateFields
function doAdd()
if ValidDate(textFrom.value) then
if ValidDate(textTo.value) then
-- Simply take whatever is in the fields and add to the format table
-- Create the PERIOD table
local tblPeriod = {}
if textFrom.value ~= "" then
tblPeriod.FROM = textFrom.value
end
if textTo.value ~= "" then
tblPeriod.TO = textTo.value
end
-- Does not care if it is a duplicate as that is not an issue
table.insert(
tblCitationFormats[radBMD.value.name],
{ PERIOD = tblPeriod, DISPLAY = textDisplay.value, FORMAT = textFormat.value }
)
loadExisting()
else
iup.Message("Add Format", "The To date is invalid.\nFormat not added.")
end
else
iup.Message("Add Format", "The From date is invalid.\nFormat not added.")
end
end -- doAdd
function doRemove()
-- Remove the format table entry for the selected one, by corresponding index position
table.remove(tblCitationFormats[radBMD.value.name], tonumber(listExisting.value))
loadExisting()
end -- doRemove
function doUpdate()
if ValidDate(textFrom.value) then
if ValidDate(textTo.value) then
-- Create the PERIOD table
local tblPeriod = {}
if textFrom.value ~= "" then
tblPeriod.FROM = textFrom.value
end
if textTo.value ~= "" then
tblPeriod.TO = textTo.value
end
-- replace the selected entry data with the edit fields content.
tblCitationFormats[radBMD.value.name][tonumber(listExisting.value)] =
{ PERIOD = tblPeriod, DISPLAY = textDisplay.value, FORMAT = textFormat.value }
loadExisting()
else
iup.Message("Add Format", "The To date is invalid.\nFormat not updated.")
end
else
iup.Message("Add Format", "The From date is invalid.\nFormat not updated.")
end
end -- doUpdate
-- Populate the format selection list
function loadExisting()
listExisting[1] = nil
for f = 1, #tblCitationFormats[radBMD.value.name] do
listExisting[f] = tblCitationFormats[radBMD.value.name][f]["DISPLAY"]
end
listExisting.value = 1
updateFields()
end -- loadExisting
listExisting = iup.list({
value = 0,
dropdown = "YES",
tip = "Select existing format",
size = "250",
action = function()
updateFields()
end,
})
local btnAdd = iup.button({
name = "ADD",
title = "Add",
size = "40x",
action = function()
doAdd()
return iup.DEFAULT
end,
tip = "Add a new GRO format",
})
local btnUpdate = iup.button({
name = "UPDATE",
title = "Update",
size = "40x",
action = function()
doUpdate()
return iup.DEAFULT
end,
tip = "Update the selected GRO format",
})
local btnRemove = iup.button({
name = "REMOVE",
title = "Remove",
size = "40x",
action = function()
doRemove()
return iup.DEFAULT
end,
tip = "Remove the selected GRO format",
})
local btnSave = iup.button({
name = "SAVE",
title = "Save",
size = "40x",
action = function()
SaveSettings()
return iup.DEFAULT
end,
tip = "Save plugin settings with GRO formats",
})
local btnClose = iup.button({
name = "CLOSE",
title = "Close",
size = "40x20",
action = function()
return iup.CLOSE
end,
})
local content = iup.vbox{
iup.frame {iup.vbox{
iup.vbox {iup.hbox{iup.fill{},iup.label{title = "Select an Existing GRO Format:"}, iup.fill{}},iup.hbox{iup.fill{}, listExisting, iup.fill{}}},
iup.hbox {iup.label{separator = "HORIZONTAL", size="300"}, margin ="0x5"},
iup.vbox {iup.hbox{iup.fill{}, iup.label{title = "Period for which the Format is Applicable:"}, iup.fill{}},iup.hbox{iup.fill{}, iup.label{title="From:"}, textFrom, iup.label{title="To:"}, textTo, iup.fill{}}},
iup.vbox {iup.hbox{iup.fill{}, iup.label{title = "Friendly Name to Show for Selection:"}, iup.fill{}},iup.hbox{iup.fill{}, textDisplay, iup.fill{}}},
iup.vbox {iup.hbox{iup.fill{}, iup.label{title = "Define the Format using Text and Field Names:"}, iup.fill{}},iup.hbox{iup.fill{}, textFormat, iup.fill{}}},
iup.hbox {iup.fill{}, btnAdd, btnUpdate, btnRemove, btnSave, iup.fill{}; margin="5x10", normalizesize="YES", gap="20", alignment="ACENTER"},
padding="2x5"}
},
iup.hbox {iup.fill{}, btnClose, iup.fill{}};
}
local dlgCustomise = iup.dialog{iup.frame{content}, title="Customise GRO Formats for "..radBMD.value.name; resize="NO", minbox="NO", maxbox="NO"}
-- Initialise the edit fields with default selection
loadExisting()
dlgCustomise:popup(IUP_CENTERPARENT, IUP_CENTERPARENT)
loadFormats(radBMD.value.name)
end -- showCustomiseDialog
-- ^^^^^^^^^^^^^^^^^^^^^ Customise GRO Format Dialog ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- =========================== Start doing things ==============================
local strParamFile = fhGetPluginDataFileName()
function LoadSettings()
local strChunk = fhLoadTextFile(strParamFile)
if strChunk then
local doChunk = load(strChunk)
-- Get the saved data version by reading first value ignoring the rest
local strDataVer = doChunk()
if strDataVer == "V1" then
-- Original V1 saved data
strDataVer, intPYear, intPQuarter, intPIndexInDate, intPCitRef, intPBirthId, intPMarriageId, intPDeathId, intPCitDate, intPCitAss, strPAddToName, tblCitationFormats =
doChunk()
-- Add missing register type defaulted to births
strPRegister = "BIRTH"
elseif strDataVer == "V2" then
-- Updated to include register type in V2 data
strDataVer, strPRegister, intPYear, intPQuarter, intPIndexInDate, intPCitRef, intPBirthId, intPMarriageId, intPDeathId, intPCitDate, intPCitAss, strPAddToName, tblCitationFormats =
doChunk()
end
end
-- Poulate the dialog fields from restored values
-- It seems that radBMD.value has to be updated with the desired toggle rather than setting the
-- toggle value to "ON". This seems to set the toggle to "ON" as desired, so it does not need to
-- be explicitly set.
if strPRegister == "BIRTH" then
radBMD.value = radBirth
elseif strPRegister == "MARRIAGE" then
radBMD.value = radMarriage
else
radBMD.value = radDeath
end
textYear.value = intPYear
listQuarter.value = intPQuarter
listIndexInDate.value = intPIndexInDate
listCitRef.value = intPCitRef
textBirthId.value = intPBirthId
textMarriageId.value = intPMarriageId
textDeathId.value = intPDeathId
listCitDate.value = intPCitDate
listCitAss.value = intPCitAss
chkAddToName.value = strPAddToName
if strPAddToName == "ON" then
chkAddToName.title = "On"
else
chkAddToName.title = "Off"
end
end -- function LoadSettings
function SaveSettings()
-- Get the settings parameters to save for next time
strRegister = string.format('%q', radBMD.value.name)
intPYear = tonumber(textYear.value)
intPQuarter = tonumber(listQuarter.value)
intPIndexInDate = tonumber(listIndexInDate.value)
intPCitRef = tonumber(listCitRef.value)
intPBirthId = textBirthId.value
intPMarriageId = textMarriageId.value
intPDeathId = textDeathId.value
intPCitDate = tonumber(listCitDate.value)
intPCitAss = tonumber(listCitAss.value)
strPAddToName = chkAddToName.value
strFormats = FormatsAsString(tblCitationFormats)
strDataVer = string.format('%q', "V2") -- V2 includes the register type selection
-- Save Sticky Parameters
if fhGetContextInfo("CI_APP_MODE") == "Project Mode" then
local strParams = "return "..strDataVer..","..strRegister..","..intPYear..","..intPQuarter..","..intPIndexInDate..","..intPCitRef..","..intPBirthId..","..intPMarriageId..","..intPDeathId..","..intPCitDate..","..intPCitAss..","..string.format('%q', strPAddToName)..","..strFormats.."\n"
fhSaveTextFile(strParamFile, strParams, "UTF-8")
end
end -- function SaveSettings
-- Get Parameters from Previous Sticky Data
LoadSettings()
setForYear(radBMD.value.name, tonumber(textYear.value))
-- Select BMD Source Records if not restored from Sticky Data
if intPBirthId == nil then
local strAns = "Retry"
while strAns == "Retry" do
strAns = ""
fhMessageBox(
"\n Please select just one generic GRO Index source record. \n ALTERNATIVELY \n Select 3 source records for Birth, Marriage, and Death, \n ensuring they are in that order in the righthand pane. \n",
"MB_OK",
"MB_ICONINFORMATION"
)
-- Get Source Records to use.
local ptrList = fhPromptUserForRecordSel("SOUR", 3)
if #ptrList == 0 then
strAns = fhMessageBox(
"\n No source records have been selected ...\n\n Click 'Abort' to cancel the plugin\n Click 'Retry' to select the sources again\n Click 'Ignore' to continue without sources \n",
"MB_ABORTRETRYIGNORE",
"MB_ICONQUESTION"
)
if strAns == "Abort" then
return
end
intPBirthId = 0
intPMarriageId = 0
intPDeathId = 0
elseif #ptrList == 1 then
intPBirthId = fhGetRecordId(ptrList[1])
intPMarriageId = fhGetRecordId(ptrList[1])
intPDeathId = fhGetRecordId(ptrList[1])
elseif #ptrList == 2 then
strAns = fhMessageBox(
"\n Only two source records were selected ...\n\n Click 'Retry' to select the sources again \n Click 'Cancel' to cancel the plugin \n",
"MB_RETRYCANCEL",
"MB_ICONQUESTION"
)
if strAns == "Cancel" then
return
end
else --#ptrList == 3 then
intPBirthId = fhGetRecordId(ptrList[1])
intPMarriageId = fhGetRecordId(ptrList[2])
intPDeathId = fhGetRecordId(ptrList[3])
end
end
end
-- Get Current Individual Record if Available
local ptrList = fhGetCurrentRecordSel("INDI")
if #ptrList == 1 then
strName = "Current Record: "..fhGetItemText(ptrList[1],"~.NAME"):gsub("%%","%%%%").." ("..fhCallBuiltInFunction("LifeDates",ptrList[1])..")"
else
strName = "No record selected"
end
-- Poulate the dialog fields from restored values
textYear.value = intPYear
listQuarter.value = intPQuarter
listIndexInDate.value = intPIndexInDate
listCitRef.value = intPCitRef
textBirthId.value = intPBirthId
textMarriageId.value = intPMarriageId
textDeathId.value = intPDeathId
listCitDate.value = intPCitDate
listCitAss.value = intPCitAss
chkAddToName.value = strPAddToName
-- Set active fields based on default or restored values
updateCitation()
setForCitRefField(tonumber(listCitRef.value))
-- Construct and Display the parameters dialog to the user
frmParams = iup.frame({ grid, title = strName, fontstyle = "Bold" })
boxbuttons = iup.hbox({ iup.fill({}), btnOk, btnCancel, iup.fill({}), gap = "10" })
dlg = iup.dialog({
iup.vbox({ frmParams, boxbuttons }),
title = "GRO Source Reference V" .. Version,
size = "370x355",
childoffset = "5x5",
resize = "NO",
maxbox = "NO",
})
dlg:showxy(iup.CENTER, iup.CENTER)
if (iup.MainLoopLevel()==0) then
iup.MainLoop()
end
-- How did the dialog exit
if dlgResult == "OK" then
-- Save Sticky Parameters
SaveSettings()
-- Now do the actual citation stuff copied and modified from Mike's plug-in
-- Select Source Record
if radBMD.value.name == "BIRTH" then
intSource = intPBirthId
end
if radBMD.value.name == "MARRIAGE" then
intSource = intPMarriageId
end
if radBMD.value.name == "DEATH" then
intSource = intPDeathId
end
local ptrSource = fhNewItemPtr()
ptrSource:MoveToRecordById("SOUR", intSource)
if ptrSource:IsNull() then
doError("Source Record Id " .. intSource .. " Not Found")
end
-- Obtain Desired Record
if radBMD.value.name == "MARRIAGE" then
ptrList = fhGetCurrentRecordSel("FAM")
if #ptrList == 0 then
ptrList = fhGetCurrentRecordSel("INDI")
if #ptrList == 1 then
ptrList = getSpouseFamilies(ptrList[1])
end
end
if #ptrList ~= 1 then
ptrList = fhPromptUserForRecordSel("FAM", 1)
end
else
ptrList = fhGetCurrentRecordSel("INDI")
if #ptrList ~= 1 then
ptrList = fhPromptUserForRecordSel("INDI", 1)
end
end
if #ptrList == 0 then
doError("No Principal Record Selected")
end
-- Check Registration Year
if intPYear < 1837 then
doError("Registration Year before 1837")
end
local ptrEvent = fhNewItemPtr()
local ptrField = fhNewItemPtr()
local evtType = string.sub(radBMD.value.name, 1, 4)
ptrEvent:MoveTo(ptrList[1], "~." .. evtType)
if ptrEvent:IsNull() then
-- Create Event, using first four letters of register type
ptrEvent = fhCreateItem(evtType, ptrList[1])
end
-- Set Event Date based on selection
ptrField:MoveTo(ptrEvent, "~.DATE")
if ptrField:IsNull() then
ptrField = fhCreateItem("DATE", ptrEvent)
end
local dtDate = fhGetValueAsDate(ptrField)
local dpOne = dtDate:GetDatePt1()
local dpTwo = dtDate:GetDatePt2()
local Month = dpOne:GetMonth()
local DayNo = dpOne:GetDay()
if
intPIndexInDate == 1 and dpOne:IsNull() and dpTwo:IsNull() -- No Date
or intPIndexInDate == 2 and dpOne:GetMonth() == 0 and dpTwo:GetMonth() == 0 -- Year Only Date
or intPIndexInDate == 3 and dpOne:GetDay() == 0 and dpTwo:GetDay() == 0 -- Inexact Date
then
dtDate:SetValueAsText(arrShortPeriod[intPQuarter] .. " " .. intPYear)
fhSetValueAsDate(ptrField, dtDate)
end
-- Set Event Place & Address
strPdist = promptPlace(textDistrict.value)
ptrField:MoveTo(ptrEvent, "~.PLAC")
if ptrField:IsNull() then
ptrField = fhCreateItem("PLAC", ptrEvent)
end
if fhGetValueAsText(ptrField) == "" then
fhSetValueAsText(ptrField, strPdist)
-- If Place was added, add "Registration District" as the Address field
ptrField:MoveTo(ptrEvent, "~.ADDR")
if ptrField:IsNull() then
ptrField = fhCreateItem("ADDR", ptrEvent)
end
if fhGetValueAsText(ptrField) == "" then
fhSetValueAsText(ptrField, "Registration District")
end
end
-- For Death Add age if entered.
if deathInfo == "AGE" and radBMD.value.name == "DEATH" and textDeath.value:len() > 0 then
-- Check it looks like a viable age
if tonumber(textDeath.value) < 130 then
ptrField:MoveTo(ptrEvent, "~.AGE")
if ptrField:IsNull() then
ptrField = fhCreateItem("AGE", ptrEvent)
fhSetValueAsText(ptrField, textDeath.value)
end
end
end
-- Declare the shared values for separation purposes
local deathAge = ""
local deathDoB = ""
local volName = ""
local regName = ""
local pageNo = ""
local entNo = ""
-- Split the Volume/Register and Page/Entry
if volregInfo == "VOLUME" then
volName = textRefVolReg.value
pageNo = textRefPagEnt.value
else
regName = textRefVolReg.value
entNo = textRefPagEnt.value
end
-- Split the Age/Dob for death
if deathInfo == "AGE" then
deathAge = textDeath.value
else
deathDoB = textDeath.value
end
-- Convert the Quarter or Month selection to a Quarter and a Month
theQuarter, theMonth = getQuarterAndMonth()
-- Create the Citation string from the input parameters and selected format
strCitation = formatCitation(tblCitationFormats[radBMD.value.name][formatMap[tonumber(listRefFormat.value)]]["FORMAT"],
{ RNAME = textRecordedName.value,
YEAR = textYear.value,
QTR = theQuarter,
MONTH = theMonth,
DIST = textDistrict.value,
DISTNO = textDistrictNo.value,
VOL = volName,
REG = regName,
PAGE = pageNo,
ENT = entNo,
RSPOUSE = textRecordedSpouse.value,
MAID = textMother.value,
AGE = deathAge,
DOB = deathDoB})
-- Add Source Citation
local eDate = nil
if intPCitDate ~= 1 then
-- Record Entry Date
eDate = fhNewDate()
if intPCitDate == 2 then
eDate:SetSimpleDate(fhCallBuiltInFunction("today"))
else
if tonumber(listQuarter.value) > 4 then
eDate:SetValueAsText(theMonth .. " " .. textYear.value)
else
eDate:SetValueAsText(theQuarter .. " " .. textYear.value)
end
end
end
-- Add Citation to Event
local strAssessment = nil
if intPCitAss > 1 then
strAssessment = tblAssess[intPCitAss - 1]
end
addSource(ptrEvent, ptrSource, strCitation, intPCitRef, eDate, strAssessment)
-- Add Citation to Name(s)
local tblTags = {
BIRTH = { "~.NAME[1]" },
MARRIAGE = { "~.HUSB[1]>NAME[1]", "~.WIFE[1]>NAME[1]", "~.HUSB[2]>NAME[1]", "~.WIFE[2]>NAME[1]" },
DEATH = { "~.NAME[1]" },
}
if strPAddToName == "ON" then
for _, strTag in ipairs(tblTags[radBMD.value.name]) do
ptrField:MoveTo(ptrList[1], strTag)
if ptrField:IsNotNull() then
addSource(ptrField, ptrSource, strCitation, intPCitRef, eDate, tblAssess[intPCitAss - 1])
end
end
end
-- Check Data
ptrField:MoveTo(ptrEvent, "~.DATE")
local strResult = fhCallBuiltInFunction("GetDataWarning", ptrField, 1)
if strResult ~= "" then
local strButton =
fhMessageBox(strResult .. "\nDo you wish to undo the entry?", "MB_YESNO", "MB_ICONEXCLAMATION")
if strButton == "Yes" then
doError("Date Validation Failed")
end
end
end -- Successful exit of dialog
end -- function main
function addSource(ptrFact, ptrSource, strCit, intWhere, eDate, strAssess)
if intWhere == 3 then
-- Event Note Only
local ptrNote = fhNewItemPtr()
ptrNote:MoveTo(ptrFact, "~.NOTE2")
if ptrNote:IsNull() then
ptrNote = fhCreateItem("NOTE2", ptrFact) -- FACT.NOTE2
end
local strNote = fhGetValueAsText(ptrNote)
if strNote ~= "" then
-- Put it at the start of existing note
strNote = strCit .. "\n" .. strNote
else
strNote = strCit
end
fhSetValueAsText(ptrNote, strNote)
else -- Not the Event Note, so need to Add Citation
local ptrCite = fhCreateItem("SOUR", ptrFact) -- FACT.SOUR
fhSetValueAsLink(ptrCite, ptrSource)
local ptrData = fhNewItemPtr()
local ptrAge = fhNewItemPtr()
if eDate or intWhere == 2 then
-- Text From Source
ptrData = fhCreateItem("DATA", ptrCite) -- FACT.SOUR.DATA
end
if eDate then
local ptrDate = fhCreateItem("DATE", ptrData) -- FACT.SOUR.DATA.DATE
fhSetValueAsDate(ptrDate, eDate)
end
if strAssess then
ptrQuay = fhCreateItem("QUAY", ptrCite) -- FACT.SOUR.QUAY
fhSetValueAsText(ptrQuay, strAssess)
end
if intWhere == 1 then
-- Where within Source
ptrAge = fhCreateItem("PAGE", ptrCite) -- FACT.SOUR.PAGE
else
ptrAge = fhCreateItem("TEXT", ptrData) -- FACT.SOUR.DATA.TEXT
end
fhSetValueAsText(ptrAge, strCit)
end
end -- function addSource
function getSpouseFamilies(ptrIndi)
local arrFams = {}
local ptrFams = fhNewItemPtr()
ptrFams:MoveTo(ptrIndi, "~.FAMS")
while ptrFams:IsNotNull() do
table.insert(arrFams, fhGetValueAsLink(ptrFams))
ptrFams:MoveNext("SAME_TAG")
end
return arrFams
end -- function getSpouseFamilies
function addParam(arrParams, strText, strType, strTip)
table.insert(arrParams, strText .. strType .. "{" .. (strTip or "") .. "}")
end -- function addParam
function promptPlace(strDistrict)
local arrPlaces = placeList(strDistrict) -- List of Place names matching Registration District entered
local arrPrompt = {}
addParam(arrPrompt, "Please select a Place from the list or ", "%t")
addParam(arrPrompt, "use the entry box to enter a Place name ", "%t")
addParam(arrPrompt, " Enter the District Place name: ", "%s")
addParam(
arrPrompt,
" Select from District Place list: ",
"%l|Use Place Above|" .. table.concat(arrPlaces, "|") .. "|"
)
local strPrompt = table.concat(arrPrompt, "\n") .. "\n"
local isOK, strPlace, intPlace = iup.GetParam("Select District Place Name", param_action, strPrompt, strDistrict, 0)
-- Check for Cancel
if not isOK then
return strDistrict
end
if intPlace > 0 then
strPlace = arrPlaces[intPlace]
end
return strPlace
end -- function promptPlace
function placeList(strFind)
strFind = strFind:lower()
local arrPlac = {}
local ptrPlac = fhNewItemPtr()
ptrPlac:MoveToFirstRecord("_PLAC")
while ptrPlac:IsNotNull() do
local strPlac = fhGetDisplayText(ptrPlac)
if strPlac:lower():find(strFind) then
table.insert(arrPlac, strPlac)
end
ptrPlac:MoveNext()
end
table.sort(arrPlac)
return arrPlac
end -- function placeList
--[[
function formatCitation
This function takes a GRO format string and table of named values, then substitutes the
fields in the format with the corresponding named value. This implementation is better than
the initial version that relied on value position correspondance, which is not a guarantee
in LUA (although in practice worked).
]]
function formatCitation(strFormat, values)
-- Starting with the format string, substitute fields by iterating their names and corresponding values
local strOutput = strFormat
-- iterate the named fields
for key, value in pairs(namedFields) do
-- Need to check for missed input fields due to programming error rather than user error, treat as empty string
local subst = values[value]
if subst == nil then
subst = ""
end
-- Do a substitution for each named field with the corresponding named input value
strOutput = string.gsub(strOutput, "{" .. value .. "}", subst)
end
return strOutput
end
--[[ function getQuarterAndMonth()
This function returns the quarter and month based on the Quarter selection
]]
function getQuarterAndMonth()
if listQuarter.value == "1" then
return "Q1", "Jan-Feb-Mar"
elseif listQuarter.value == "2" then
return "Q2", "Apr-May-Jun"
elseif listQuarter.value == "3" then
return "Q3", "Jul-Aug-Sep"
elseif listQuarter.value == "4" then
return "Q4", "Oct-Nov-Dec"
elseif listQuarter.value == "5" then
return "Q1", "Jan"
elseif listQuarter.value == "6" then
return "Q1", "Feb"
elseif listQuarter.value == "7" then
return "Q1", "Mar"
elseif listQuarter.value == "8" then
return "Q2", "Apr"
elseif listQuarter.value == "9" then
return "Q2", "May"
elseif listQuarter.value == "10" then
return "Q2", "Jun"
elseif listQuarter.value == "11" then
return "Q3", "Jul"
elseif listQuarter.value == "12" then
return "Q3", "Aug"
elseif listQuarter.value == "13" then
return "Q3", "Sep"
elseif listQuarter.value == "14" then
return "Q4", "Oct"
elseif listQuarter.value == "15" then
return "Q4", "Nov"
elseif listQuarter.value == "16" then
return "Q4", "Dec"
else
return "", ""
end
end -- getQuarterAndMonth
--[[
fuction TableToString
A function to convert format definition table to a safe string for output
]]
function FormatsAsString(formatTable)
strTable = "{"
-- iterate the outermost table BIRTH/MARRIAGE/DEATH
for keyBMD, valBMD in pairs(formatTable) do
strTable = strTable .. keyBMD .. " = {"
-- Iterate the arbitrary list of formats defined for each BMD option
for defn = 1, #valBMD do
-- Iterate the DISPLAY/FUNCTION/PERIOD for each format
strTable = strTable .. "{"
for keyFmt, valFmt in pairs(valBMD[defn]) do
if keyFmt == "PERIOD" then
strTable = strTable .. keyFmt .. " = {"
for periodKey, periodVal in pairs(valBMD[defn].PERIOD) do
strTable = strTable .. periodKey .. " = " .. string.format("%q", periodVal) .. ", "
end
strTable = strTable .. "}, "
else
-- Ensure the string for Display/Format is correctly escaped and quoted
strTable = strTable .. keyFmt .. " = " .. string.format("%q", valFmt) .. ", "
end
end
strTable = strTable .. "}, "
end
strTable = strTable .. "}, "
end
strTable = strTable .. "}"
return strTable
end -- TableToString
-- Function to validate that the input represents a Year
function ValidYear(year)
local aDate = fhNewDate()
return aDate:SetValueAsText(year)
end -- ValidYear
function ValidDate(date)
local aDate = fhNewDate()
return aDate:SetValueAsText(date)
end -- ValidateDate
function InPeriod(date, from, to)
local cmpLower = -1 -- Assume before lower bound
local cmpUpper = 1 -- Assume after upper bound
-- Compare date to lower bound
if from ~= nil then
cmpLower = date:Compare(from)
else
-- Treat as equal to lower
cmpLower = 0
end
-- Compare date to upper bound
if to ~= nil then
cmpUpper = date:Compare(to)
else
-- Treat as equal to upper
cmpUpper = 0
end
return ((cmpLower == 0) or (cmpLower == 1)) and ((cmpUpper == 0) or (cmpUpper == -1))
end -- inPeriod
function doError(strMessage)
error("\n\n" .. strMessage .. " - Plugin Aborted.\n\n", 0)
end -- function doError
fhInitialise(7,0,0,"save_recommended")
main()
--[[
@Title: GRO Source Reference
@Type: Standard
@Author: Chris Read
@Contributors: Mike Tate, Jane Taubman
@Version: 1.5
@Keywords: GRO
@LastUpdated: 04/04/2024
@Licence: This plugin is copyright (c) Chris Read 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: Add a GRO Index Source Citation to an Event and optionally create the event and or set the fields.
This version is derived from 'Add GRO Index Source Citation' V1.0 by Mike Tate which in turn was derived from 'Add GRO Source' V1.3 by Jane Taubman.
The primary difference is the dynamic behaviour of the UI and awarness of the changes in the GRO index information over time. Also, the addition of
user definable formats for the GRO Index citation. As of v1.2 this includes the ability to specify a date range the format applies to, so they are
auto-filtered in the selection list for convenience.
@V1.0 It's my first foray in to LUA and FH Plugin development, and I have much to learn. I will say, IUP is drastically short on good examples beyond
the booming obvious, but hey-ho, and onward we go. 40 years of software development should count for something.
This implementation adds:
- Enable/disable of parameter fields relevant to the selected BMD type and the citation reference type selected.
- Selectable citation reference string formats for each register type. These use a named field style i.e. {YEAR} internally
for the built-in formats.
Future enhancements:
- Allow user creation of citation formats using the internal named field implementation, once I figure out how best to save/restore
them and implement a creation dialog.
@V1.1 This implementation adds:
- Handling for Age at Death starting 1866, and changing to Date of Birth from Q2 1969
- Changed auto-text {BIRTH} to {DOB} and separated {AGE} & {DOB} to only contain a value when applicable
- Removed extraneous 'c' in Oct in {MONTH} field
@V1.2 This implementation adds:
- Specification of a date period for formats so that the list of formats will be filtered to those applicable to the GRO Index Date and quarter/month.
I found that in practical use, as I had defined several formats for the different GRO Index information (particularly Deaths), I was constantly having
to locate and select different ones. In theory you only need one or maybe two per period; one for single line version (for 'Where in') and one
for multi-line (Text from Source/Event Note); that is, if you like to put the extra info (Mothers Maiden name, Death Age/DoB) on the next line.
In general a given user will probably only use one option for where the citation gets put, so only needs one format the way they like it. This means
the format selection essentially become automatic.
- Added the selected register type to the saved settings, and bumped the data version to V2. For previous V1 settings, it will default to births when loaded.
@V1.3 This implementation adds:
- Tidy ups and corrections as suggested by Visual Studio Code LUA Extension, and selected formatting using the StyLua Extension
- Separated {VOL}/{REG} and {PAG}/{ENT} to only contain a value when applicable as previoulsuy done for the {AGE} & {DOB} fields.
@V1.4 This implementation adds:
- Removal of the pre-defined BIRTH format Q3 1837 to Q3 1911 with no mothers maiden name, as although the official date of the information being included
is Q3 1911, the GRO has been retrospectivly adding the information where it is able to determine it. Date range for subsequent format has been updated to
cover from Q3 1837.
- Corrected unintentional error in the removal of formats due to missunderstanding of LUA tables which resulted in a subsequent plugin crash.
- Removed unecessary error information when the plugin aborts due to missing information or other issue when attempting to apply a citation. This makes
it looks less like an uncontrolled crash.
@V1.5 This implementation adds:
- Input field for selected persons name as recorded in the GRO Index. This may be different from their actual name due to miss-transcription and use of initials
rather than full given names. The name will be available for formats definitions as {RNAME}.
- Input field for selected persons spouse as recorded in the GRO Index for marriages. This may be different from their actual name due to miss-transcription. The
name will be available for format definitions as {RSPOUSE}.
- Resolved problem restoring the previously saved register type.
- Corrected error in formatted citation generation for the actual citation.
]]
Version = "1.5"
require("iuplua")
require("iupluacontrols")
if fhGetAppVersion() > 5 then
fhSetStringEncoding("UTF-8")
iup.SetGlobal("UTF8MODE","YES")
iup.SetGlobal("UTF8MODE_FILE","NO")
iup.SetGlobal("CUSTOMQUITMESSAGE","YES") -- Needed for IUP 3.28
end
-- Define the named fields for Citation format strings
namedFields = { "RNAME",
"YEAR",
"QTR",
"MONTH",
"DIST",
"DISTNO",
"VOL",
"REG",
"PAGE",
"ENT",
"RSPOUSE",
"MAID",
"AGE",
"DOB"}
--[[
Definitions of the pre-canned citation formats for each register type BIRTH, MARRIAGE, DEATH
Each register entry is itself a table of formats, where each entry comprises
a PERIOD of FROM, TO during which the format should be applicable.
a DISPLAY string to display that could be a name or an example of the format
a FORMAT string using the named fields that will be used to create the GRO string.
]]
--[[
Rules for GRO Registers
Q3 1837 • Civil Registration in England and Wales begins
1866 • GRO indexes include age at death
Q3 1911 • GRO Birth Indexes include Mothers Maiden Name, but GRO has been adding this to earlier index entries.
Q1 1912 • GRO Marriage Indexes include Spouses Surname
Q2 1969 • GRO Death Indexes show date of Birth instead of age at Death
Q2 1974 • GRO Volume Numbers re-organised (e.g. 9c became 32).
Q1 1993 • Grouping of Districts into Volumes ceased for Births & Deaths, District/Register/Entry Numbers started
Q1 1994 • Grouping of Districts into Volumes ceased for Marriages, District/Register/Entry Numbers started
]]
citationFormats = { BIRTH = { {PERIOD = {FROM = "Q3 1837", TO = "Q4 1992"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page|Mother:",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}\nMother: {MAID}"},
{PERIOD = {FROM = "Q1 1993"},
DISPLAY = "GRO: Qn yyyy, District(No.), Reg, Entry|Mother:",
FORMAT = "GRO: {QTR} {YEAR} {MONTH}, {DIST}({DISTNO}), {REG}, {ENT}\nMother: {MAID}"}
},
MARRIAGE = { {PERIOD = {FROM = "Q3 1837", TO = "Q4 1993"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}"},
{PERIOD = {FROM = "Q1 1994"},
DISPLAY = "GRO: Qn yyyy, District(No.), Reg, Entry",
FORMAT = "GRO: {QTR} {YEAR} {MONTH}, {DIST}({DISTNO}), {REG}, {ENT}"}
},
DEATH = { {PERIOD = {FROM = "Q3 1837", TO = "1865"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}"},
{PERIOD = {FROM = "1866", TO = "Q1 1969"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page|Age: nnn",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}\nAge: {AGE}"},
{PERIOD = {FROM = "Q2 1969", TO="1992"},
DISPLAY = "GRO: Qn yyyy, District, Vol, Page|DoB: dd mmm yyyy",
FORMAT = "GRO: {QTR} {YEAR}, {DIST}, {VOL}, {PAGE}\nDoB: {DOB}"},
{PERIOD = {FROM = "1993"},
DISPLAY = "GRO: Qn yyyy, District(No.), Reg, Entry|DoB: dd mmm yyyy",
FORMAT = "GRO: {QTR} {YEAR} {MONTH}, {DIST}({DISTNO}), {REG}, {ENT}\nDoB: {DOB}"}
}
}
function main()
local dlgResult
local deathInfo = "AGE"
local volregInfo = "VOLUME"
local arrShortPeriod = {"Q1";"Q2";"Q3";"Q4";"Jan";"Feb";"Mar";"Apr";"May";"Jun";"Jul";"Aug";"Sep";"Oct";"Nov";"Dec";}
local formatMap = {} -- Used to map the selection list entries to the formats after filtering for the drop-down list
-- Create the active objects we need
-- Buttons for completion and opening customisation dialog
btnOk = iup.button({
name = "OK",
title = "Apply",
size = "40x20",
tip = "Apply the GRO Source Citation according to your inputs and option settings",
action = function(self)
dlgResult = self.name
return iup.CLOSE
end,
})
btnCancel = iup.button({
name = "CANCEL",
title = "Close",
size = "40x20",
tip = "Exit without making any changes to the project",
action = function(self)
dlgResult = self.name
return iup.CLOSE
end,
})
btnCustomise = iup.button({
name = "EDIT",
title = "Customise...",
size = "x10",
action = function()
showCustomiseDialog()
end,
tip = "Manage and customise the available GRO formats",
})
-- Toggles that we need for selection of the register
radBirth = iup.toggle({
name = "BIRTH",
title = "Birth",
value = "OFF",
tip = "Select Birth Registrations",
action = function(self)
selectRegister(self)
return iup.DEFAULT
end,
})
radMarriage = iup.toggle({
name = "MARRIAGE",
title = "Marriage",
value = "OFF",
tip = "Select Marriage Registrations",
action = function(self)
selectRegister(self)
return iup.DEFAULT
end,
})
radDeath = iup.toggle({
name = "DEATH",
title = "Death",
value = "OFF",
tip = "Select Death Registrations",
action = function(self)
selectRegister(self)
return iup.DEFAULT
end,
})
radBMD = iup.radio({ iup.hbox({ radBirth, radMarriage, radDeath }) })
-- List to select the GRO Quarter or Month as applicable
listQuarter = iup.list({
"Q1 Jan-Feb-Mar",
"Q2 Apr-May-Jun",
"Q3 Jul-Aug-Sep",
"Q4 Oct-Nov-Dec",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
value = 1,
dropdown = "YES",
visible_items = 5,
tip = "Select registration quarter or month",
})
-- List to select the option for what to do with the GRO date information if anything
listIndexInDate = iup.list({
"No Event Date",
"Year Only Event Date",
"Inexact Event Date",
value = 1,
dropdown = "YES",
size = "100",
tip = "When should the event date be updated",
})
-- List to select the option for how the citation should be recorded
listCitRef = iup.list({
"Where within",
"Text From Source",
"Event Note Only",
value = 1,
dropdown = "YES",
size = "100",
tip = "Where should the citation reference be put",
})
-- Dynamic list of the GRO citation formats that can be selected
listRefFormat = iup.list({
value = 0,
size = "200",
dropdown = "YES",
action = function()
updateCitation()
end,
tip = "Select citation reference format",
})
-- List to select the option for how the citation date should be recorded
listCitDate = iup.list({
"No Date",
"Today's Date",
"GRO Index Reg Date",
value = 1,
dropdown = "YES",
size = "100",
tip = "What date should be used for the citation",
})
-- List to select the option for what assesment to give the citation
listCitAss = iup.list({
"None",
"Unreliable",
"Questionable",
"Secondary Evidence",
"Primary Evidence",
value = 1,
dropdown = "YES",
size = "100",
tip = "Select the assessement to give the citation",
})
-- Table of values used to set the assesement when option is to apply one
local tblAssess = { "Unreliable", "Questionable", "Secondary Evidence", "Primary Evidence", "" }
-- Checkbox to select to add the citation to individual/parents names
chkAddToName = iup.toggle({ value = "OFF", tip = "Should the citation be added to the individual/parents name" })
-- Text input fields
textRecordedName = iup.text{size="200", value="", tip = "Name as recorded in GRO Index", active = "YES"}
textRecordedSpouse = iup.text{size="200", value="", tip = "Spouse name as recorded in GRO Index", active = "NO"}
textDistrict = iup.text{size="200", value="", tip = "Name of the registration district"}
textDistrictNo = iup.text({ size = "100", value = "", tip = "Registration district number after 1992." })
textRefVolReg = iup.text({ size = "100", value = "", tip = "Volume pre-1993, Register after 1992." })
textYear = iup.text({ SPIN = "YES", SPINMIN = 1837, SPINMAX = 2005, value = "1837" })
textRefPagEnt = iup.text({ size = "100", value = "", tip = "Page number pre-1993, Entry number after 1992." })
textMother = iup.text({ active = "YES", value = "", size = "200", tip = "Maiden name of mother for birth registrations" })
textCitation = iup.text({
active = "YES",
multiline = "YES",
size = "200x30",
tip = "What the citation will look like based on your selections",
})
textDeath = iup.text({ size = "100", active = "NO", value = "", tip = "Age at Death or Birth date:" })
textBirthId = iup.text({ tip = "Family Historian source record ID for GRO Birth Index source" })
textMarriageId = iup.text({ tip = "Family Historian source record ID for GRO Marriage Index source" })
textDeathId = iup.text({ tip = "Family Historian source record ID for GRO Death Index source" })
-- Named labels where we want to be able to change active state of
lblRecordedSpouse = iup.label{ title = "Spouse as Recorded:", active = "NO" }
lblDistrict = iup.label{ title = "Registration District:" }
lblDistrictNo = iup.label{ title = "Registration District Number:", active = "NO" }
lblRefVolReg = iup.label{ title = "Volume or Register number:" }
lblRefPagEnt = iup.label{ title = "Volume Page or Register Entry:" }
lblMother = iup.label{ title = "Mothers Maiden name:", active = "YES" }
lblDeath = iup.label{ title = "Age at Death or Birth date:", active = "NO" }
lblBirthSrcId = iup.label{ title = "Birth Source Record ID:" }
lblMarriageSrcId = iup.label{ title = "Marriage Source Record ID:" }
lblDeathSrcId = iup.label{ title = "Death Source Record ID:" }
lblCitDate = iup.label{ title = "Set Citation Entry Date:" }
lblCitAss = iup.label{ title = "Set Citation Assessment:" }
lblAddToName = iup.label{ title = "Add Citation to Name:" }
-- Create display grid
grid = iup.gridbox{ iup.label{title = "GRO Index Type:"}, radBMD,
iup.label{ title = "Name as Recorded:" }, textRecordedName,
iup.label{title = "Registration Year:"}, textYear,
iup.label{title = "Registration Quarter or Month:"}, listQuarter,
lblDistrict, textDistrict,
lblDistrictNo, textDistrictNo,
lblRefVolReg, textRefVolReg,
lblRefPagEnt, textRefPagEnt,
lblRecordedSpouse, textRecordedSpouse,
lblMother, textMother,
lblDeath, textDeath,
iup.label{title = "Put GRO Index date in event Date when:", size="150"}, listIndexInDate,
iup.label{title = "Select Citation Reference Field:"}, listCitRef,
iup.hbox{iup.label{title = "GRO Reference Format:"}, btnCustomise; alignment="ACENTER"}, listRefFormat,
iup.label{title = "GRO Reference Preview:"}, textCitation,
iup.label{separator = "HORIZONTAL"}, iup.label{separator = "HORIZONTAL"},
lblBirthSrcId, textBirthId,
lblMarriageSrcId, textMarriageId,
lblDeathSrcId, textDeathId,
lblCitDate, listCitDate,
lblCitAss, listCitAss,
lblAddToName, chkAddToName;
orientation = "HORIZONTAL", numdiv = 2, sizecol=-1, sizelin=-1, padding="2x5", fontstyle=""}
-- Set Parameter Default Values
local intPYear = 1900 -- Registration Year
local intPQuarter = 1 -- Registration Quarter or Month
local intPIndexInDate = 1 -- Overwrite Event Date Criteria
local intPCitRef = 1 -- Select Citation Field for Ref
local intPBirthId = nil -- Source Record Id Birth
local intPMarriageId = nil -- Source Record Id Marriage
local intPDeathId = nil -- Source Record Id Death
local intPCitDate = 1 -- Select Citation Entry Date
local intPCitAss = 1 -- Select Citation Assessment
local strPAddToName = "" -- Add Citation to Name?
local tblCitationFormats = citationFormats -- Assume the pre-defined if nothing saved (first run)
function textYear:valuechanged_cb()
-- Check it is a valid year
if ValidYear(textYear.value) then
-- Enable/Disable fields for year and register
setForYear(radBMD.value.name, tonumber(textYear.value))
-- Update citation
updateCitation()
else
iup.Message("Registration Year", "Year value not recognised as a year, please correct before continuing.")
end
end
function textYear:spin_cb(pos)
-- NOTE: pos is the value it will be after the spin, not current value
-- Check it is a valid year
if ValidYear(pos) then
-- Enable/Disable fields for year and register
setForYear(radBMD.value.name, tonumber(pos))
-- Update citation
updateCitation()
else
iup.Message("Registration Year", "Year value not recognised as a year, please correct before continuing.")
end
end
function listQuarter:action(t, i, v)
if v == 1 then
-- Enable/Disable fields for year and register
setForYear(radBMD.value.name, tonumber(textYear.value))
-- Update citation
updateCitation()
end
return iup.DEFAULT
end
--[[
Rules for GRO Registers
Q3 1837 • Civil Registration in England and Wales begins
1852 • GRO References change from Roman Numerals (XVI) to Arabic numbers and letters (6d)
1866 • GRO indexes include age at death
Q3 1911 • GRO Birth Indexes include Mothers Maiden Name, but GRO has been adding this to earlier index entries.
Q1 1912 • GRO Marriage Indexes include Spouses Surname
Q2 1969 • GRO Death Indexes show date of Birth instead of age at Death
Q2 1974 • GRO Volume Numbers re-organised (e.g. 9c became 32).
Q1 1993 • Grouping of Districts into Volumes ceased for Births & Deaths, District/Register/Entry Numbers started
Q1 1994 • Grouping of Districts into Volumes ceased for Marriages, District/Register/Entry Numbers started
]]
function setForYear(reg, year)
theQuarter, _ = getQuarterAndMonth()
if (year < 1837) or (year == 1837 and (theQuarter == "Q1" or theQuarter == "Q2")) then
-- No GRO Indexes prior to Q3 1837, all GRO input fields disabled
lblDistrict.active = "NO"
textDistrict.active = "NO"
lblDistrictNo.active = "NO"
textDistrictNo.active = "NO"
lblRefVolReg.active = "NO"
textRefVolReg.active = "NO"
lblRefPagEnt.active = "NO"
textRefPagEnt.active = "NO"
elseif
((reg == "BIRTH" or reg == "DEATH") and (year >= 1837 and year <= 1992))
or (reg == "MARRIAGE" and (year >= 1837 and year <= 1993))
then
-- No District number, Volume and Page
volregInfo = "VOLUME"
lblDistrict.active = "YES"
textDistrict.active = "YES"
lblDistrictNo.active = "NO"
textDistrictNo.active = "NO"
lblRefVolReg.title = "Volume Number:"
lblRefVolReg.active = "YES"
textRefVolReg.active = "YES"
lblRefPagEnt.title = "Page Number:"
lblRefPagEnt.active = "YES"
textRefPagEnt.active = "YES"
else
-- District number, Register and Entry
volregInfo = "REGISTER"
lblDistrict.active = "YES"
textDistrict.active = "YES"
lblDistrictNo.active = "YES"
textDistrictNo.active = "YES"
lblRefVolReg.title = "Register Number:"
lblRefVolReg.active = "YES"
textRefVolReg.active = "YES"
lblRefPagEnt.title = "Register Entry:"
lblRefPagEnt.active = "YES"
textRefPagEnt.active = "YES"
end
setForBMDType(reg, year, theQuarter)
end -- setForYear
-- Essentially called as the common BMD toggle action
function selectRegister(self)
if self.value == "ON" then
setForYear(radBMD.value.name, tonumber(textYear.value))
-- Load the relevant formats for the selected register type
loadFormats(radBMD.value.name)
updateCitation()
end
end -- selectRegister
-- Set the availability of the Mother's maiden name and Death Age based on register type selection
function setForBMDType(reg, year, qtr)
if (year < 1837) or (year == 1837 and (theQuarter == "Q1" or theQuarter == "Q2")) then
-- No GRO Indexes prior to Q3 1837, all GRO input fields disabled
textRecordedSpouse.active = "NO"
textMother.active = "NO"
textDeath.active = "NO"
lblRecordedSpouse.active = "NO"
lblMother.active = "NO"
lblDeath.active = "NO"
else
-- Set the Death age/DoB label as appropriate to the year etc.
if ((year >= 1866) and (year <= 1968)) or ((year == 1969) and (qtr == "Q1")) then
deathInfo = "AGE"
lblDeath.title = "Age at Death:"
else
deathInfo = "DOB"
lblDeath.title = "Date of Birth:"
end
-- Enable/Disable GRO fields relevant to the register type
if reg == "BIRTH" then
textRecordedSpouse.active = "NO"
textMother.active = "YES"
textDeath.active = "NO"
lblRecordedSpouse.active = "NO"
lblMother.active = "YES"
lblDeath.active = "NO"
elseif reg == "MARRIAGE" then
textRecordedSpouse.active = "YES"
textMother.active = "NO"
textDeath.active = "NO"
lblRecordedSpouse.active = "YES"
lblMother.active = "NO"
lblDeath.active = "NO"
elseif reg == "DEATH" then
textRecordedSpouse.active = "NO"
textMother.active = "NO"
textDeath.active = "YES"
lblRecordedSpouse.active = "NO"
lblMother.active = "NO"
-- No age recorded prior to 1866
if year < 1866 then
lblDeath.active = "NO"
textDeath.active = "NO"
else
lblDeath.active = "YES"
textDeath.active = "YES"
end
else
-- Should never get here unless we did a bad coding LOL
iup.Message(
"function setForBMDType()",
'Called with invalid register type: "'
.. reg
.. '".\nPlease debug and correct the coding error.\n\nPlugin aborted!'
)
return iup.CLOSE
end
end
-- Load the relevant formats for the selected register type
loadFormats(reg)
end --setForBMDType
-- Populate the format selection list for the specified register
function loadFormats(reg)
-- Convert the GRO Index year to a date object (should be valid already)
local groDate = fhNewDate()
local added = 0
local quarter
local month
quarter, month = getQuarterAndMonth()
if string.len(month) > 3 then
-- It's a quarter date selection
groDate:SetValueAsText(quarter .. " " .. textYear.value)
else
-- It's a specific month selection
groDate:SetValueAsText(month .. " " .. textYear.value)
end
-- Clear the list
listRefFormat[1] = nil
formatMap[1] = nil
for f = 1, #tblCitationFormats[reg] do
local fromDate = nil
local toDate = nil
if tblCitationFormats[reg][f].PERIOD then
-- PERIOD is present get limits if present
if tblCitationFormats[reg][f].PERIOD.FROM then
fromDate = fhNewDate()
res = fromDate:SetValueAsText(tblCitationFormats[reg][f].PERIOD.FROM)
end
if tblCitationFormats[reg][f].PERIOD.TO then
toDate = fhNewDate()
res = toDate:SetValueAsText(tblCitationFormats[reg][f].PERIOD.TO)
end
end
-- Add the format if within the period specified
if InPeriod(groDate, fromDate, toDate) then
added = added + 1
formatMap[added] = f
listRefFormat[added] = tblCitationFormats[reg][f]["DISPLAY"]
end
end
if tonumber(listRefFormat.count) > 0 then
listRefFormat.value = 1
end
end -- loadFormats
-- Enable/Disable the citation fields depending on citation type selection
function listCitRef:action(t, i, v)
if v == 1 then
setForCitRefField(i)
end
return iup.DEFAULT
end
-- Enable/Disable the fields that only apply to a source citation
function setForCitRefField(i)
if i == 3 then
-- Event Note only so disable all fields
textBirthId.active = "NO"
textMarriageId.active = "NO"
textDeathId.active = "NO"
listCitDate.active = "NO"
listCitAss.active = "NO"
chkAddToName.active = "NO"
lblBirthSrcId.active = "NO"
lblBirthSrcId.active = "NO"
lblMarriageSrcId.active = "NO"
lblDeathSrcId.active = "NO"
lblCitDate.active = "NO"
lblCitAss.active = "NO"
lblAddToName.active = "NO"
else
-- Other selections enable all fields
textBirthId.active = "YES"
textMarriageId.active = "YES"
textDeathId.active = "YES"
listCitDate.active = "YES"
listCitAss.active = "YES"
chkAddToName.active = "YES"
lblBirthSrcId.active = "YES"
lblBirthSrcId.active = "YES"
lblMarriageSrcId.active = "YES"
lblDeathSrcId.active = "YES"
lblCitDate.active = "YES"
lblCitAss.active = "YES"
lblAddToName.active = "YES"
end
end -- setForCitRefField
function textDistrict:valuechanged_cb()
-- Update citation
updateCitation()
end
function textRecordedName:valuechanged_cb()
-- Update citation
updateCitation()
end
function textDistrictNo:valuechanged_cb()
-- Update citation
updateCitation()
end
function textRefVolReg:valuechanged_cb()
-- Update citation
updateCitation()
end
function textRefPagEnt:valuechanged_cb()
-- Update citation
updateCitation()
end
function textRecordedSpouse:valuechanged_cb()
-- Update citation
updateCitation()
end
function textMother:valuechanged_cb()
-- Update citation
updateCitation()
end
function textDeath:valuechanged_cb()
-- Update citation
updateCitation()
end
function chkAddToName:action()
if chkAddToName.value == "ON" then
chkAddToName.title = "On"
else
chkAddToName.title = "Off"
end
end
function updateCitation()
-- Declare the shared values for separation purposes
local deathAge = ""
local deathDoB = ""
local volName = ""
local regName = ""
local pageNo = ""
local entNo = ""
-- Split the Volume/Register and Page/Entry
if volregInfo == "VOLUME" then
volName = textRefVolReg.value
pageNo = textRefPagEnt.value
else
regName = textRefVolReg.value
entNo = textRefPagEnt.value
end
-- Split the Age/Dob for death
if deathInfo == "AGE" then
deathAge = textDeath.value
else
deathDoB = textDeath.value
end
-- Convert the Quarter or Month selection to a Quarter and a Month
theQuarter, theMonth = getQuarterAndMonth()
if tonumber(listRefFormat.value) > 0 then
-- Create the Citation string from the input parameters and selected format
textCitation.value = formatCitation(tblCitationFormats[radBMD.value.name][formatMap[tonumber(listRefFormat.value)]]["FORMAT"],
{ RNAME = textRecordedName.value,
YEAR = textYear.value,
QTR = theQuarter,
MONTH = theMonth,
DIST = textDistrict.value,
DISTNO = textDistrictNo.value,
VOL = volName,
REG = regName,
PAGE = pageNo,
ENT = entNo,
RSPOUSE = textRecordedSpouse.value,
MAID = textMother.value,
AGE = deathAge,
DOB = deathDoB})
else
textCitation.value = ""
end
end
-- vvvvvvvvvvvvvvvvvvvvv Customise GRO Format Dialog vvvvvvvvvvvvvvvvvvvvvvvvvvvvv
--[[
This function displays and handles the format customisation.
]]
function showCustomiseDialog()
formatHelp =
[[
The format can make use of most standard ASCII characters. Special auto-text fields
may also be used to substitute in values you have entered in the main dialog.
These are as follows:
{RNAME}, the name of the individual as recorded
{YEAR}, the year of registration
{QTR}, the quarter of registration
{MONTH}, the month of registration where applicable
{DIST}, the registration district name
{DISTNO}, the registration district number where applicable
{VOL}, the volume number as applicable
{REG}, the register number as applicable
{PAGE}, the page number as applicable
{ENT}, the entry number as applicable
{RSPOUSE}, the name of the spouse as recorded
{MAID}, the mother's maiden name for births
{AGE}, Age at Death
{DOB}}, Date of Birth (for deaths)
]]
local textDisplay = iup.text({ size = "250", value = "", tip = "Display name for the format" })
local textFormat = iup.text({ multiline = "YES", size = "300x30", value = "", tip = formatHelp })
local textFrom = iup.text({ size = "50", value = "", tip = "Date from which the format is applicable" })
local textTo = iup.text({ size = "50", value = "", tip = "Date to which the format is applicable" })
-- for some reaason this has to go before the use in listExisting action
function updateFields()
-- Copy selected format information to edit fields
if listExisting.value ~= 0 then
local format = tblCitationFormats[radBMD.value.name][tonumber(listExisting.value)]
if format.PERIOD ~= nil then
if format.PERIOD.FROM ~= nil then
textFrom.value = format.PERIOD.FROM
else
textFrom.value = ""
end
if format.PERIOD.TO ~= nil then
textTo.value = format.PERIOD.TO
else
textTo.value = ""
end
end
textDisplay.value = format["DISPLAY"]
textFormat.value = format["FORMAT"]
end
end -- updateFields
function doAdd()
if ValidDate(textFrom.value) then
if ValidDate(textTo.value) then
-- Simply take whatever is in the fields and add to the format table
-- Create the PERIOD table
local tblPeriod = {}
if textFrom.value ~= "" then
tblPeriod.FROM = textFrom.value
end
if textTo.value ~= "" then
tblPeriod.TO = textTo.value
end
-- Does not care if it is a duplicate as that is not an issue
table.insert(
tblCitationFormats[radBMD.value.name],
{ PERIOD = tblPeriod, DISPLAY = textDisplay.value, FORMAT = textFormat.value }
)
loadExisting()
else
iup.Message("Add Format", "The To date is invalid.\nFormat not added.")
end
else
iup.Message("Add Format", "The From date is invalid.\nFormat not added.")
end
end -- doAdd
function doRemove()
-- Remove the format table entry for the selected one, by corresponding index position
table.remove(tblCitationFormats[radBMD.value.name], tonumber(listExisting.value))
loadExisting()
end -- doRemove
function doUpdate()
if ValidDate(textFrom.value) then
if ValidDate(textTo.value) then
-- Create the PERIOD table
local tblPeriod = {}
if textFrom.value ~= "" then
tblPeriod.FROM = textFrom.value
end
if textTo.value ~= "" then
tblPeriod.TO = textTo.value
end
-- replace the selected entry data with the edit fields content.
tblCitationFormats[radBMD.value.name][tonumber(listExisting.value)] =
{ PERIOD = tblPeriod, DISPLAY = textDisplay.value, FORMAT = textFormat.value }
loadExisting()
else
iup.Message("Add Format", "The To date is invalid.\nFormat not updated.")
end
else
iup.Message("Add Format", "The From date is invalid.\nFormat not updated.")
end
end -- doUpdate
-- Populate the format selection list
function loadExisting()
listExisting[1] = nil
for f = 1, #tblCitationFormats[radBMD.value.name] do
listExisting[f] = tblCitationFormats[radBMD.value.name][f]["DISPLAY"]
end
listExisting.value = 1
updateFields()
end -- loadExisting
listExisting = iup.list({
value = 0,
dropdown = "YES",
tip = "Select existing format",
size = "250",
action = function()
updateFields()
end,
})
local btnAdd = iup.button({
name = "ADD",
title = "Add",
size = "40x",
action = function()
doAdd()
return iup.DEFAULT
end,
tip = "Add a new GRO format",
})
local btnUpdate = iup.button({
name = "UPDATE",
title = "Update",
size = "40x",
action = function()
doUpdate()
return iup.DEAFULT
end,
tip = "Update the selected GRO format",
})
local btnRemove = iup.button({
name = "REMOVE",
title = "Remove",
size = "40x",
action = function()
doRemove()
return iup.DEFAULT
end,
tip = "Remove the selected GRO format",
})
local btnSave = iup.button({
name = "SAVE",
title = "Save",
size = "40x",
action = function()
SaveSettings()
return iup.DEFAULT
end,
tip = "Save plugin settings with GRO formats",
})
local btnClose = iup.button({
name = "CLOSE",
title = "Close",
size = "40x20",
action = function()
return iup.CLOSE
end,
})
local content = iup.vbox{
iup.frame {iup.vbox{
iup.vbox {iup.hbox{iup.fill{},iup.label{title = "Select an Existing GRO Format:"}, iup.fill{}},iup.hbox{iup.fill{}, listExisting, iup.fill{}}},
iup.hbox {iup.label{separator = "HORIZONTAL", size="300"}, margin ="0x5"},
iup.vbox {iup.hbox{iup.fill{}, iup.label{title = "Period for which the Format is Applicable:"}, iup.fill{}},iup.hbox{iup.fill{}, iup.label{title="From:"}, textFrom, iup.label{title="To:"}, textTo, iup.fill{}}},
iup.vbox {iup.hbox{iup.fill{}, iup.label{title = "Friendly Name to Show for Selection:"}, iup.fill{}},iup.hbox{iup.fill{}, textDisplay, iup.fill{}}},
iup.vbox {iup.hbox{iup.fill{}, iup.label{title = "Define the Format using Text and Field Names:"}, iup.fill{}},iup.hbox{iup.fill{}, textFormat, iup.fill{}}},
iup.hbox {iup.fill{}, btnAdd, btnUpdate, btnRemove, btnSave, iup.fill{}; margin="5x10", normalizesize="YES", gap="20", alignment="ACENTER"},
padding="2x5"}
},
iup.hbox {iup.fill{}, btnClose, iup.fill{}};
}
local dlgCustomise = iup.dialog{iup.frame{content}, title="Customise GRO Formats for "..radBMD.value.name; resize="NO", minbox="NO", maxbox="NO"}
-- Initialise the edit fields with default selection
loadExisting()
dlgCustomise:popup(IUP_CENTERPARENT, IUP_CENTERPARENT)
loadFormats(radBMD.value.name)
end -- showCustomiseDialog
-- ^^^^^^^^^^^^^^^^^^^^^ Customise GRO Format Dialog ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- =========================== Start doing things ==============================
local strParamFile = fhGetPluginDataFileName()
function LoadSettings()
local strChunk = fhLoadTextFile(strParamFile)
if strChunk then
local doChunk = load(strChunk)
-- Get the saved data version by reading first value ignoring the rest
local strDataVer = doChunk()
if strDataVer == "V1" then
-- Original V1 saved data
strDataVer, intPYear, intPQuarter, intPIndexInDate, intPCitRef, intPBirthId, intPMarriageId, intPDeathId, intPCitDate, intPCitAss, strPAddToName, tblCitationFormats =
doChunk()
-- Add missing register type defaulted to births
strPRegister = "BIRTH"
elseif strDataVer == "V2" then
-- Updated to include register type in V2 data
strDataVer, strPRegister, intPYear, intPQuarter, intPIndexInDate, intPCitRef, intPBirthId, intPMarriageId, intPDeathId, intPCitDate, intPCitAss, strPAddToName, tblCitationFormats =
doChunk()
end
end
-- Poulate the dialog fields from restored values
-- It seems that radBMD.value has to be updated with the desired toggle rather than setting the
-- toggle value to "ON". This seems to set the toggle to "ON" as desired, so it does not need to
-- be explicitly set.
if strPRegister == "BIRTH" then
radBMD.value = radBirth
elseif strPRegister == "MARRIAGE" then
radBMD.value = radMarriage
else
radBMD.value = radDeath
end
textYear.value = intPYear
listQuarter.value = intPQuarter
listIndexInDate.value = intPIndexInDate
listCitRef.value = intPCitRef
textBirthId.value = intPBirthId
textMarriageId.value = intPMarriageId
textDeathId.value = intPDeathId
listCitDate.value = intPCitDate
listCitAss.value = intPCitAss
chkAddToName.value = strPAddToName
if strPAddToName == "ON" then
chkAddToName.title = "On"
else
chkAddToName.title = "Off"
end
end -- function LoadSettings
function SaveSettings()
-- Get the settings parameters to save for next time
strRegister = string.format('%q', radBMD.value.name)
intPYear = tonumber(textYear.value)
intPQuarter = tonumber(listQuarter.value)
intPIndexInDate = tonumber(listIndexInDate.value)
intPCitRef = tonumber(listCitRef.value)
intPBirthId = textBirthId.value
intPMarriageId = textMarriageId.value
intPDeathId = textDeathId.value
intPCitDate = tonumber(listCitDate.value)
intPCitAss = tonumber(listCitAss.value)
strPAddToName = chkAddToName.value
strFormats = FormatsAsString(tblCitationFormats)
strDataVer = string.format('%q', "V2") -- V2 includes the register type selection
-- Save Sticky Parameters
if fhGetContextInfo("CI_APP_MODE") == "Project Mode" then
local strParams = "return "..strDataVer..","..strRegister..","..intPYear..","..intPQuarter..","..intPIndexInDate..","..intPCitRef..","..intPBirthId..","..intPMarriageId..","..intPDeathId..","..intPCitDate..","..intPCitAss..","..string.format('%q', strPAddToName)..","..strFormats.."\n"
fhSaveTextFile(strParamFile, strParams, "UTF-8")
end
end -- function SaveSettings
-- Get Parameters from Previous Sticky Data
LoadSettings()
setForYear(radBMD.value.name, tonumber(textYear.value))
-- Select BMD Source Records if not restored from Sticky Data
if intPBirthId == nil then
local strAns = "Retry"
while strAns == "Retry" do
strAns = ""
fhMessageBox(
"\n Please select just one generic GRO Index source record. \n ALTERNATIVELY \n Select 3 source records for Birth, Marriage, and Death, \n ensuring they are in that order in the righthand pane. \n",
"MB_OK",
"MB_ICONINFORMATION"
)
-- Get Source Records to use.
local ptrList = fhPromptUserForRecordSel("SOUR", 3)
if #ptrList == 0 then
strAns = fhMessageBox(
"\n No source records have been selected ...\n\n Click 'Abort' to cancel the plugin\n Click 'Retry' to select the sources again\n Click 'Ignore' to continue without sources \n",
"MB_ABORTRETRYIGNORE",
"MB_ICONQUESTION"
)
if strAns == "Abort" then
return
end
intPBirthId = 0
intPMarriageId = 0
intPDeathId = 0
elseif #ptrList == 1 then
intPBirthId = fhGetRecordId(ptrList[1])
intPMarriageId = fhGetRecordId(ptrList[1])
intPDeathId = fhGetRecordId(ptrList[1])
elseif #ptrList == 2 then
strAns = fhMessageBox(
"\n Only two source records were selected ...\n\n Click 'Retry' to select the sources again \n Click 'Cancel' to cancel the plugin \n",
"MB_RETRYCANCEL",
"MB_ICONQUESTION"
)
if strAns == "Cancel" then
return
end
else --#ptrList == 3 then
intPBirthId = fhGetRecordId(ptrList[1])
intPMarriageId = fhGetRecordId(ptrList[2])
intPDeathId = fhGetRecordId(ptrList[3])
end
end
end
-- Get Current Individual Record if Available
local ptrList = fhGetCurrentRecordSel("INDI")
if #ptrList == 1 then
strName = "Current Record: "..fhGetItemText(ptrList[1],"~.NAME"):gsub("%%","%%%%").." ("..fhCallBuiltInFunction("LifeDates",ptrList[1])..")"
else
strName = "No record selected"
end
-- Poulate the dialog fields from restored values
textYear.value = intPYear
listQuarter.value = intPQuarter
listIndexInDate.value = intPIndexInDate
listCitRef.value = intPCitRef
textBirthId.value = intPBirthId
textMarriageId.value = intPMarriageId
textDeathId.value = intPDeathId
listCitDate.value = intPCitDate
listCitAss.value = intPCitAss
chkAddToName.value = strPAddToName
-- Set active fields based on default or restored values
updateCitation()
setForCitRefField(tonumber(listCitRef.value))
-- Construct and Display the parameters dialog to the user
frmParams = iup.frame({ grid, title = strName, fontstyle = "Bold" })
boxbuttons = iup.hbox({ iup.fill({}), btnOk, btnCancel, iup.fill({}), gap = "10" })
dlg = iup.dialog({
iup.vbox({ frmParams, boxbuttons }),
title = "GRO Source Reference V" .. Version,
size = "370x355",
childoffset = "5x5",
resize = "NO",
maxbox = "NO",
})
dlg:showxy(iup.CENTER, iup.CENTER)
if (iup.MainLoopLevel()==0) then
iup.MainLoop()
end
-- How did the dialog exit
if dlgResult == "OK" then
-- Save Sticky Parameters
SaveSettings()
-- Now do the actual citation stuff copied and modified from Mike's plug-in
-- Select Source Record
if radBMD.value.name == "BIRTH" then
intSource = intPBirthId
end
if radBMD.value.name == "MARRIAGE" then
intSource = intPMarriageId
end
if radBMD.value.name == "DEATH" then
intSource = intPDeathId
end
local ptrSource = fhNewItemPtr()
ptrSource:MoveToRecordById("SOUR", intSource)
if ptrSource:IsNull() then
doError("Source Record Id " .. intSource .. " Not Found")
end
-- Obtain Desired Record
if radBMD.value.name == "MARRIAGE" then
ptrList = fhGetCurrentRecordSel("FAM")
if #ptrList == 0 then
ptrList = fhGetCurrentRecordSel("INDI")
if #ptrList == 1 then
ptrList = getSpouseFamilies(ptrList[1])
end
end
if #ptrList ~= 1 then
ptrList = fhPromptUserForRecordSel("FAM", 1)
end
else
ptrList = fhGetCurrentRecordSel("INDI")
if #ptrList ~= 1 then
ptrList = fhPromptUserForRecordSel("INDI", 1)
end
end
if #ptrList == 0 then
doError("No Principal Record Selected")
end
-- Check Registration Year
if intPYear < 1837 then
doError("Registration Year before 1837")
end
local ptrEvent = fhNewItemPtr()
local ptrField = fhNewItemPtr()
local evtType = string.sub(radBMD.value.name, 1, 4)
ptrEvent:MoveTo(ptrList[1], "~." .. evtType)
if ptrEvent:IsNull() then
-- Create Event, using first four letters of register type
ptrEvent = fhCreateItem(evtType, ptrList[1])
end
-- Set Event Date based on selection
ptrField:MoveTo(ptrEvent, "~.DATE")
if ptrField:IsNull() then
ptrField = fhCreateItem("DATE", ptrEvent)
end
local dtDate = fhGetValueAsDate(ptrField)
local dpOne = dtDate:GetDatePt1()
local dpTwo = dtDate:GetDatePt2()
local Month = dpOne:GetMonth()
local DayNo = dpOne:GetDay()
if
intPIndexInDate == 1 and dpOne:IsNull() and dpTwo:IsNull() -- No Date
or intPIndexInDate == 2 and dpOne:GetMonth() == 0 and dpTwo:GetMonth() == 0 -- Year Only Date
or intPIndexInDate == 3 and dpOne:GetDay() == 0 and dpTwo:GetDay() == 0 -- Inexact Date
then
dtDate:SetValueAsText(arrShortPeriod[intPQuarter] .. " " .. intPYear)
fhSetValueAsDate(ptrField, dtDate)
end
-- Set Event Place & Address
strPdist = promptPlace(textDistrict.value)
ptrField:MoveTo(ptrEvent, "~.PLAC")
if ptrField:IsNull() then
ptrField = fhCreateItem("PLAC", ptrEvent)
end
if fhGetValueAsText(ptrField) == "" then
fhSetValueAsText(ptrField, strPdist)
-- If Place was added, add "Registration District" as the Address field
ptrField:MoveTo(ptrEvent, "~.ADDR")
if ptrField:IsNull() then
ptrField = fhCreateItem("ADDR", ptrEvent)
end
if fhGetValueAsText(ptrField) == "" then
fhSetValueAsText(ptrField, "Registration District")
end
end
-- For Death Add age if entered.
if deathInfo == "AGE" and radBMD.value.name == "DEATH" and textDeath.value:len() > 0 then
-- Check it looks like a viable age
if tonumber(textDeath.value) < 130 then
ptrField:MoveTo(ptrEvent, "~.AGE")
if ptrField:IsNull() then
ptrField = fhCreateItem("AGE", ptrEvent)
fhSetValueAsText(ptrField, textDeath.value)
end
end
end
-- Declare the shared values for separation purposes
local deathAge = ""
local deathDoB = ""
local volName = ""
local regName = ""
local pageNo = ""
local entNo = ""
-- Split the Volume/Register and Page/Entry
if volregInfo == "VOLUME" then
volName = textRefVolReg.value
pageNo = textRefPagEnt.value
else
regName = textRefVolReg.value
entNo = textRefPagEnt.value
end
-- Split the Age/Dob for death
if deathInfo == "AGE" then
deathAge = textDeath.value
else
deathDoB = textDeath.value
end
-- Convert the Quarter or Month selection to a Quarter and a Month
theQuarter, theMonth = getQuarterAndMonth()
-- Create the Citation string from the input parameters and selected format
strCitation = formatCitation(tblCitationFormats[radBMD.value.name][formatMap[tonumber(listRefFormat.value)]]["FORMAT"],
{ RNAME = textRecordedName.value,
YEAR = textYear.value,
QTR = theQuarter,
MONTH = theMonth,
DIST = textDistrict.value,
DISTNO = textDistrictNo.value,
VOL = volName,
REG = regName,
PAGE = pageNo,
ENT = entNo,
RSPOUSE = textRecordedSpouse.value,
MAID = textMother.value,
AGE = deathAge,
DOB = deathDoB})
-- Add Source Citation
local eDate = nil
if intPCitDate ~= 1 then
-- Record Entry Date
eDate = fhNewDate()
if intPCitDate == 2 then
eDate:SetSimpleDate(fhCallBuiltInFunction("today"))
else
if tonumber(listQuarter.value) > 4 then
eDate:SetValueAsText(theMonth .. " " .. textYear.value)
else
eDate:SetValueAsText(theQuarter .. " " .. textYear.value)
end
end
end
-- Add Citation to Event
local strAssessment = nil
if intPCitAss > 1 then
strAssessment = tblAssess[intPCitAss - 1]
end
addSource(ptrEvent, ptrSource, strCitation, intPCitRef, eDate, strAssessment)
-- Add Citation to Name(s)
local tblTags = {
BIRTH = { "~.NAME[1]" },
MARRIAGE = { "~.HUSB[1]>NAME[1]", "~.WIFE[1]>NAME[1]", "~.HUSB[2]>NAME[1]", "~.WIFE[2]>NAME[1]" },
DEATH = { "~.NAME[1]" },
}
if strPAddToName == "ON" then
for _, strTag in ipairs(tblTags[radBMD.value.name]) do
ptrField:MoveTo(ptrList[1], strTag)
if ptrField:IsNotNull() then
addSource(ptrField, ptrSource, strCitation, intPCitRef, eDate, tblAssess[intPCitAss - 1])
end
end
end
-- Check Data
ptrField:MoveTo(ptrEvent, "~.DATE")
local strResult = fhCallBuiltInFunction("GetDataWarning", ptrField, 1)
if strResult ~= "" then
local strButton =
fhMessageBox(strResult .. "\nDo you wish to undo the entry?", "MB_YESNO", "MB_ICONEXCLAMATION")
if strButton == "Yes" then
doError("Date Validation Failed")
end
end
end -- Successful exit of dialog
end -- function main
function addSource(ptrFact, ptrSource, strCit, intWhere, eDate, strAssess)
if intWhere == 3 then
-- Event Note Only
local ptrNote = fhNewItemPtr()
ptrNote:MoveTo(ptrFact, "~.NOTE2")
if ptrNote:IsNull() then
ptrNote = fhCreateItem("NOTE2", ptrFact) -- FACT.NOTE2
end
local strNote = fhGetValueAsText(ptrNote)
if strNote ~= "" then
-- Put it at the start of existing note
strNote = strCit .. "\n" .. strNote
else
strNote = strCit
end
fhSetValueAsText(ptrNote, strNote)
else -- Not the Event Note, so need to Add Citation
local ptrCite = fhCreateItem("SOUR", ptrFact) -- FACT.SOUR
fhSetValueAsLink(ptrCite, ptrSource)
local ptrData = fhNewItemPtr()
local ptrAge = fhNewItemPtr()
if eDate or intWhere == 2 then
-- Text From Source
ptrData = fhCreateItem("DATA", ptrCite) -- FACT.SOUR.DATA
end
if eDate then
local ptrDate = fhCreateItem("DATE", ptrData) -- FACT.SOUR.DATA.DATE
fhSetValueAsDate(ptrDate, eDate)
end
if strAssess then
ptrQuay = fhCreateItem("QUAY", ptrCite) -- FACT.SOUR.QUAY
fhSetValueAsText(ptrQuay, strAssess)
end
if intWhere == 1 then
-- Where within Source
ptrAge = fhCreateItem("PAGE", ptrCite) -- FACT.SOUR.PAGE
else
ptrAge = fhCreateItem("TEXT", ptrData) -- FACT.SOUR.DATA.TEXT
end
fhSetValueAsText(ptrAge, strCit)
end
end -- function addSource
function getSpouseFamilies(ptrIndi)
local arrFams = {}
local ptrFams = fhNewItemPtr()
ptrFams:MoveTo(ptrIndi, "~.FAMS")
while ptrFams:IsNotNull() do
table.insert(arrFams, fhGetValueAsLink(ptrFams))
ptrFams:MoveNext("SAME_TAG")
end
return arrFams
end -- function getSpouseFamilies
function addParam(arrParams, strText, strType, strTip)
table.insert(arrParams, strText .. strType .. "{" .. (strTip or "") .. "}")
end -- function addParam
function promptPlace(strDistrict)
local arrPlaces = placeList(strDistrict) -- List of Place names matching Registration District entered
local arrPrompt = {}
addParam(arrPrompt, "Please select a Place from the list or ", "%t")
addParam(arrPrompt, "use the entry box to enter a Place name ", "%t")
addParam(arrPrompt, " Enter the District Place name: ", "%s")
addParam(
arrPrompt,
" Select from District Place list: ",
"%l|Use Place Above|" .. table.concat(arrPlaces, "|") .. "|"
)
local strPrompt = table.concat(arrPrompt, "\n") .. "\n"
local isOK, strPlace, intPlace = iup.GetParam("Select District Place Name", param_action, strPrompt, strDistrict, 0)
-- Check for Cancel
if not isOK then
return strDistrict
end
if intPlace > 0 then
strPlace = arrPlaces[intPlace]
end
return strPlace
end -- function promptPlace
function placeList(strFind)
strFind = strFind:lower()
local arrPlac = {}
local ptrPlac = fhNewItemPtr()
ptrPlac:MoveToFirstRecord("_PLAC")
while ptrPlac:IsNotNull() do
local strPlac = fhGetDisplayText(ptrPlac)
if strPlac:lower():find(strFind) then
table.insert(arrPlac, strPlac)
end
ptrPlac:MoveNext()
end
table.sort(arrPlac)
return arrPlac
end -- function placeList
--[[
function formatCitation
This function takes a GRO format string and table of named values, then substitutes the
fields in the format with the corresponding named value. This implementation is better than
the initial version that relied on value position correspondance, which is not a guarantee
in LUA (although in practice worked).
]]
function formatCitation(strFormat, values)
-- Starting with the format string, substitute fields by iterating their names and corresponding values
local strOutput = strFormat
-- iterate the named fields
for key, value in pairs(namedFields) do
-- Need to check for missed input fields due to programming error rather than user error, treat as empty string
local subst = values[value]
if subst == nil then
subst = ""
end
-- Do a substitution for each named field with the corresponding named input value
strOutput = string.gsub(strOutput, "{" .. value .. "}", subst)
end
return strOutput
end
--[[ function getQuarterAndMonth()
This function returns the quarter and month based on the Quarter selection
]]
function getQuarterAndMonth()
if listQuarter.value == "1" then
return "Q1", "Jan-Feb-Mar"
elseif listQuarter.value == "2" then
return "Q2", "Apr-May-Jun"
elseif listQuarter.value == "3" then
return "Q3", "Jul-Aug-Sep"
elseif listQuarter.value == "4" then
return "Q4", "Oct-Nov-Dec"
elseif listQuarter.value == "5" then
return "Q1", "Jan"
elseif listQuarter.value == "6" then
return "Q1", "Feb"
elseif listQuarter.value == "7" then
return "Q1", "Mar"
elseif listQuarter.value == "8" then
return "Q2", "Apr"
elseif listQuarter.value == "9" then
return "Q2", "May"
elseif listQuarter.value == "10" then
return "Q2", "Jun"
elseif listQuarter.value == "11" then
return "Q3", "Jul"
elseif listQuarter.value == "12" then
return "Q3", "Aug"
elseif listQuarter.value == "13" then
return "Q3", "Sep"
elseif listQuarter.value == "14" then
return "Q4", "Oct"
elseif listQuarter.value == "15" then
return "Q4", "Nov"
elseif listQuarter.value == "16" then
return "Q4", "Dec"
else
return "", ""
end
end -- getQuarterAndMonth
--[[
fuction TableToString
A function to convert format definition table to a safe string for output
]]
function FormatsAsString(formatTable)
strTable = "{"
-- iterate the outermost table BIRTH/MARRIAGE/DEATH
for keyBMD, valBMD in pairs(formatTable) do
strTable = strTable .. keyBMD .. " = {"
-- Iterate the arbitrary list of formats defined for each BMD option
for defn = 1, #valBMD do
-- Iterate the DISPLAY/FUNCTION/PERIOD for each format
strTable = strTable .. "{"
for keyFmt, valFmt in pairs(valBMD[defn]) do
if keyFmt == "PERIOD" then
strTable = strTable .. keyFmt .. " = {"
for periodKey, periodVal in pairs(valBMD[defn].PERIOD) do
strTable = strTable .. periodKey .. " = " .. string.format("%q", periodVal) .. ", "
end
strTable = strTable .. "}, "
else
-- Ensure the string for Display/Format is correctly escaped and quoted
strTable = strTable .. keyFmt .. " = " .. string.format("%q", valFmt) .. ", "
end
end
strTable = strTable .. "}, "
end
strTable = strTable .. "}, "
end
strTable = strTable .. "}"
return strTable
end -- TableToString
-- Function to validate that the input represents a Year
function ValidYear(year)
local aDate = fhNewDate()
return aDate:SetValueAsText(year)
end -- ValidYear
function ValidDate(date)
local aDate = fhNewDate()
return aDate:SetValueAsText(date)
end -- ValidateDate
function InPeriod(date, from, to)
local cmpLower = -1 -- Assume before lower bound
local cmpUpper = 1 -- Assume after upper bound
-- Compare date to lower bound
if from ~= nil then
cmpLower = date:Compare(from)
else
-- Treat as equal to lower
cmpLower = 0
end
-- Compare date to upper bound
if to ~= nil then
cmpUpper = date:Compare(to)
else
-- Treat as equal to upper
cmpUpper = 0
end
return ((cmpLower == 0) or (cmpLower == 1)) and ((cmpUpper == 0) or (cmpUpper == -1))
end -- inPeriod
function doError(strMessage)
error("\n\n" .. strMessage .. " - Plugin Aborted.\n\n", 0)
end -- function doError
fhInitialise(7,0,0,"save_recommended")
main()
Source:GRO-Source-Reference-2.fh_lua