-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathImport From PAF.fh_lua
3476 lines (3153 loc) · 159 KB
/
Import From PAF.fh_lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--[[
@Title: Import From PAF
@Author: Mike Tate
@Version: 2.1
@LastUpdated: 23 Apr 2014
@Description: Move PAF Tagged Notes to associated Fact Data Ref, move _UID & _AKA UDF, and mend Date Phrases.
@V2.1: Cope with (Age) as in "Date Phrase Cleanup (PAF)" Plugin, and PAF Guidelines for event dates, bug fix delete Date Phrase, and revised ReportError() & Cancel option.
@V2.0: Mode options "Apart", "Join", "Merge" can be restored by moving both --M comment tags to next line.
@V2.0: Allow - & _ in PAF Tags, default to 'Join' mode with no option, add F1 help.
@V1.5: Include all GEDCOM Standard Facts in TblGrid, move Edit > Undo advice to Close button.
@V1.4: New error handling, better droplists for FactOpt & TextFld, main buttons move to top, Census Year lookup dates framework.
@V1.3: Added Custom GedFactTag() to ValidPAF(), and Item dictionary to FindPAF(), strYear now uses "" instead of nil.
@V1.2: Add main GUI dialogue with Note Tags and _UID and _AKA and Date Phrase frames plus Help & Advice pages.
@V1.1: First fully functional trial availavle via FHUG WiP.
@V1.0: Preliminary prototype.
]]
--[[
@Title: aa Library Functions Preamble
@Author: Mike Tate
@Version: 1.7
@LastUpdated: 13 Apr 2014
@Description: All the library module functions as preamble for Plugins.
]]
---[==[
-- Initial +fh+ functions below should eventually become library modules --
--[[
@Title: +fh+stringx_v2
@Author: Mike Tate
@LastUpdated: 28 Dec 2013
@Version: 2.4
@Description: Extended string functions to supplement LUA string library.
@V2.4: Tolerant of integer & nil parameters just link match & gsub.
@V1.0: Initial version.
]]
local function stringx_v2(...) -- if not ... then error("\n\nThis is a Library Module, and so it can not be executed on its own.") end
local fh = {} -- Local environment table
package.seeall(fh) -- Enable all globals
module(...,package.seeall) -- Create matching module name
setfenv(1,fh) -- All public names are added to local fh table
function ReportVersion()
local strMessage = "This is +fh+stringx_v2"
print(strMessage)
return strMessage
end
-- Split a string using "," or chosen separator --
function split(strTxt,strSep)
local tblFields = {}
local strPattern = string.format("([^%s]+)", strSep or ",")
strTxt = tostring(strTxt or "")
strTxt:gsub(strPattern, function(strField) tblFields[#tblFields+1] = strField end)
return tblFields
end -- function split
-- Split a string into numbers using " " or "," or "x" separators -- Any non-number remains as a string
function splitnumbers(strTxt)
local tblNum = {}
strTxt = tostring(strTxt or "")
strTxt:gsub("([^ ,x]+)", function(strNum) tblNum[#tblNum+1] = tonumber(strNum) or strNum end)
return tblNum
end -- function splitnumbers
-- Hide magic pattern symbols ^ $ ( ) % . [ ] * + - ?
function plain(strTxt)
-- Prefix every non-alphanumeric character (%W) with a % escape character,
-- where %% is the % escape, and %1 is the original character capture.
strTxt = tostring(strTxt or ""):gsub("(%W)","%%%1")
return strTxt
end -- function plain
-- matches is plain text version of string.match()
function matches(strTxt,strFind,intInit)
strFind = tostring(strFind or ""):gsub("(%W)","%%%1") -- Hide magic pattern symbols
return tostring(strTxt or ""):match(strFind,tonumber(intInit))
end -- function matches
-- replace is plain text version of string.gsub()
function replace(strTxt,strOld,strNew,intNum)
strOld = tostring(strOld or ""):gsub("(%W)","%%%1") -- Hide magic pattern symbols
return tostring(strTxt or ""):gsub(strOld,function() return strNew end,tonumber(intNum)) -- Hide % capture symbols
end -- function replace
-- convert is pattern without captures version of string.gsub()
function convert(strTxt,strOld,strNew,intNum)
return tostring(strTxt or ""):gsub(tostring(strOld or ""),function() return strNew end,tonumber(intNum)) -- Hide % capture symbols
end -- function convert
-- import overloads fh functions into string table
function import()
for strIndex, anyValue in pairs(fh) do
if type(anyValue) == 'function' and strIndex ~= "import" then
string[strIndex] = anyValue
end
end
end -- function import
return fh
end -- local function stringx_v2
--[[
@Module: fh.tablex_v1
@Author: Mike Tate
@Version: 1.1
@LastUpdated: 19 Oct 2013
@Description: A Table Load Save Module.
@V1.0: Initial version 0.94 is Lua 5.1 compatible.
]]
local function tablex_v1(...) -- if not ... then error("\n\nThis is a Library Module, and so it can not be executed on its own.") end
local fh = {} -- Local environment table
package.seeall(fh) -- Enable all globals
module(...,package.seeall) -- Create matching module name
setfenv(1,fh) -- All public names are added to local fh table
------------------------------------------------------ Start Table Load Save
-- require "_tableloadsave"
--[[
Save Table to File/Stringtable
Load Table from File/Stringtable
v 0.94
Lua 5.1 compatible
Userdata and indices of these are not saved
Functions are saved via string.dump, so make sure it has no upvalues
References are saved
----------------------------------------------------
table.save( table [, filename] )
Saves a table so it can be called via the table.load function again
table must a object of type 'table'
filename is optional, and may be a string representing a filename or true/1
table.save( table )
on success: returns a string representing the table (stringtable)
(uses a string as buffer, ideal for smaller tables)
table.save( table, true or 1 )
on success: returns a string representing the table (stringtable)
(uses io.tmpfile() as buffer, ideal for bigger tables)
table.save( table, "filename" )
on success: returns 1
(saves the table to file "filename")
on failure: returns as second argument an error msg
----------------------------------------------------
table.load( filename or stringtable )
Loads a table that has been saved via the table.save function
on success: returns a previously saved table
on failure: returns as second argument an error msg
----------------------------------------------------
chillcode, http://lua-users.org/wiki/SaveTableToFile
Licensed under the same terms as Lua itself.
]]--
-- declare local variables
--// exportstring( string )
--// returns a "Lua" portable version of the string
local function exportstring( s )
s = string.format( "%q",s )
-- to replace
s = string.gsub( s,"\\\n","\\n" )
s = string.gsub( s,"\r","\\r" )
s = string.gsub( s,string.char(26),"\"..string.char(26)..\"" )
return s
end
--// The Save Function
function save( tbl,filename )
local charS,charE = " ","\n"
local file,err
-- create a pseudo file that writes to a string and return the string
if not filename then
file = { write = function( self,newstr ) self.str = self.str..newstr end, str = "" }
charS,charE = "",""
-- write table to tmpfile
elseif filename == true or filename == 1 then
charS,charE,file = "","",io.tmpfile()
-- write table to file
-- use io.open here rather than io.output, since in windows when clicking on a file opened with io.output will create an error
else
file,err = io.open( filename, "w" )
if err then return _,err end
end
-- initiate variables for save procedure
local tables,lookup = { tbl },{ [tbl] = 1 }
file:write( "return {"..charE )
for idx,t in ipairs( tables ) do
if filename and filename ~= true and filename ~= 1 then
file:write( "-- Table: {"..idx.."}"..charE )
end
file:write( "{"..charE )
local thandled = {}
for i,v in ipairs( t ) do
thandled[i] = true
-- escape functions and userdata
if type( v ) ~= "userdata" then
-- only handle value
if type( v ) == "table" then
if not lookup[v] then
table.insert( tables, v )
lookup[v] = #tables
end
file:write( charS.."{"..lookup[v].."},"..charE )
elseif type( v ) == "function" then
file:write( charS.."loadstring("..exportstring(string.dump( v )).."),"..charE )
else
local value = ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
file:write( charS..value..","..charE )
end
end
end
for i,v in pairs( t ) do
-- escape functions and userdata
if (not thandled[i]) and type( v ) ~= "userdata" then
-- handle index
if type( i ) == "table" then
if not lookup[i] then
table.insert( tables,i )
lookup[i] = #tables
end
file:write( charS.."[{"..lookup[i].."}]=" )
else
local index = ( type( i ) == "string" and "["..exportstring( i ).."]" ) or string.format( "[%d]",i )
file:write( charS..index.."=" )
end
-- handle value
if type( v ) == "table" then
if not lookup[v] then
table.insert( tables,v )
lookup[v] = #tables
end
file:write( "{"..lookup[v].."},"..charE )
elseif type( v ) == "function" then
file:write( "loadstring("..exportstring(string.dump( v )).."),"..charE )
else
local value = ( type( v ) == "string" and exportstring( v ) ) or tostring( v )
file:write( value..","..charE )
end
end
end
file:write( "},"..charE )
end
file:write( "}" )
-- Return Values
-- return stringtable from string
if not filename then
-- set marker for stringtable
return file.str.."--|"
-- return stringttable from file
elseif filename == true or filename == 1 then
file:seek ( "set" )
-- no need to close file, it gets closed and removed automatically
-- set marker for stringtable
return file:read( "*a" ).."--|"
-- close file and return 1
else
file:close()
return 1
end
end
--// The Load Function
function load( sfile )
local tables,err
-- catch marker for stringtable
if string.sub( sfile,-3,-1 ) == "--|" then
tables,err = loadstring( sfile )
else
tables,err = loadfile( sfile )
end
if err then return _,err
end
tables = tables()
for idx = 1,#tables do
local tolinkv,tolinki = {},{}
for i,v in pairs( tables[idx] ) do
if type( v ) == "table" and tables[v[1]] then
table.insert( tolinkv,{ i,tables[v[1]] } )
end
if type( i ) == "table" and tables[i[1]] then
table.insert( tolinki,{ i,tables[i[1]] } )
end
end
-- link values, first due to possible changes of indices
for _,v in ipairs( tolinkv ) do
tables[idx][v[1]] = v[2]
end
-- link indices
for _,v in ipairs( tolinki ) do
tables[idx][v[2]],tables[idx][v[1]] = tables[idx][v[1]],nil
end
end
return tables[1]
end
------------------------------------------------------ End Table Load Save
-- import overloads fh functions into table
function import()
for strIndex, anyValue in pairs(fh) do
if type(anyValue) == 'function' and strIndex ~= "import" then
table[strIndex] = anyValue
end
end
end -- function import
return fh
end -- local function tablex_v1
--[[
@Title: +fh+encoder_v2
@Author: Mike Tate
@LastUpdated: 29 Oct 2013
@Version: 2.2
@Description: Text encoder module for HTML XHTML XML URI UTF8 ISO CP1252 character codings.
@V2.0: StrUTF8_Encode() replaced by StrUTF_CP1252() for entire UTF-8 range, plus new StrCP1252_ISO().
@V1.0: Initial version.
]]
local function encoder_v2(...) -- if not ... then error("\n\nThis is a Library Module, and so it can not be executed on its own.") end
local fh = {} -- Local environment table
package.seeall(fh) -- Enable all globals
module(...,package.seeall) -- Create matching module name
setfenv(1,fh) -- All public names are added to local fh table
function ReportVersion()
local strMessage = "This is +fh+encoder_v2"
print(strMessage)
return strMessage
end
local br_Tag = "<br />" -- Markup language break tag default
local br_Lua = "<br ?/?>" -- Lua pattern for break tag recognition
local tblCodePage = {} -- Code Page to XML/XHTML/HTML/URI/UTF8 encodings: http://en.wikipedia.org/wiki/Windows-1252 & 1250 & etc
-- Control characters "\000" to "\031" for URI & Markup "[%c]" encodings are disallowed except for "\t" to "\r"
tblCodePage["\000"] = "" -- NUL
tblCodePage["\001"] = "" -- SOH
tblCodePage["\002"] = "" -- STX
tblCodePage["\003"] = "" -- ETX
tblCodePage["\004"] = "" -- EOT
tblCodePage["\005"] = "" -- ENQ
tblCodePage["\006"] = "" -- ACK
tblCodePage["\a"] = "" -- BEL
tblCodePage["\b"] = "" -- BS
tblCodePage["\t"] = "+" -- HT space in Markup see setURIEncodings() and setMarkupEncodings() below
tblCodePage["\n"] = "%0A" -- LF br_Tag in Markup
tblCodePage["\v"] = "%0A" -- VT br_Tag in Markup
tblCodePage["\f"] = "%0A" -- FF br_Tag in Markup
tblCodePage["\r"] = "%0D" -- CR br_Tag in Markup
tblCodePage["\014"] = "" -- SO
tblCodePage["\015"] = "" -- SI
tblCodePage["\016"] = "" -- DLE
tblCodePage["\017"] = "" -- DC1
tblCodePage["\018"] = "" -- DC2
tblCodePage["\019"] = "" -- DC3
tblCodePage["\020"] = "" -- DC4
tblCodePage["\021"] = "" -- NAK
tblCodePage["\022"] = "" -- SYN
tblCodePage["\023"] = "" -- ETB
tblCodePage["\024"] = "" -- CAN
tblCodePage["\025"] = "" -- EM
tblCodePage["\026"] = "" -- SUB
tblCodePage["\027"] = "" -- ESC
tblCodePage["\028"] = "" -- FS
tblCodePage["\029"] = "" -- GS
tblCodePage["\030"] = "" -- RS
tblCodePage["\031"] = "" -- US
-- ASCII characters "\032" to "\127" for URI "[%s%p]" encodings: http://en.wikipedia.org/wiki/URL and http://en.wikipedia.org/wiki/Percent-encoding
tblCodePage[" "] = "+" -- or "%20" Space
tblCodePage["!"] = "%21" -- Reserved character
tblCodePage['"'] = "%22" -- """ in Markup see setURIEncodings() and setMarkupEncodings() below
tblCodePage["#"] = "%23" -- Reserved character
tblCodePage["$"] = "%24" -- Reserved character
tblCodePage["%"] = "%25" -- Must be encoded
tblCodePage["&"] = "%26" -- Reserved character -- "&" in Markup see setURIEncodings() and setMarkupEncodings() below
tblCodePage["'"] = "%27" -- Reserved character -- "'" in Markup see setURIEncodings() and setMarkupEncodings() below
tblCodePage["("] = "%28" -- Reserved character
tblCodePage[")"] = "%29" -- Reserved character
tblCodePage["*"] = "%2A" -- Reserved character
tblCodePage["+"] = "%2B" -- Reserved character
tblCodePage[","] = "%2C" -- Reserved character
-- tblCodePage["-"] = "%2D" -- Unreserved character not encoded
-- tblCodePage["."] = "%2E" -- Unreserved character not encoded
tblCodePage["/"] = "%2F" -- Reserved character
-- Digits 0 to 9 -- Unreserved characters not encoded
tblCodePage[":"] = "%3A" -- Reserved character
tblCodePage[";"] = "%3B" -- Reserved character
tblCodePage["<"] = "%3C" -- "<" in Markup see setURIEncodings() and setMarkupEncodings() below
tblCodePage["="] = "%3D" -- Reserved character
tblCodePage[">"] = "%3E" -- ">" in Markup see setURIEncodings() and setMarkupEncodings() below
tblCodePage["?"] = "%3F" -- Reserved character
tblCodePage["@"] = "%40" -- Reserved character
-- Letters A to Z -- Unreserved characters not encoded
tblCodePage["["] = "%5B" -- Reserved character
tblCodePage["\\"]= "%5C"
tblCodePage["]"] = "%5D" -- Reserved character
tblCodePage["^"] = "%5E"
-- tblCodePage["_"] = "%5F" -- Unreserved character not encoded
tblCodePage["`"] = "%60"
-- Letters a to z -- Unreserved characters not encoded
tblCodePage["{"] = "%7B"
tblCodePage["|"] = "%7C"
tblCodePage["}"] = "%7D"
-- tblCodePage["~"] = "%7E" -- Unreserved character not encoded
tblCodePage["\127"] = "" -- DEL
-- Code Page 1252 Unicode characters "\128" to "\255" for UTF-8 scheme "[-ÿ]" encodings: http://en.wikipedia.org/wiki/UTF-8
tblCodePage[""] = string.char(0xE2,0x82,0xAC) -- "€"
tblCodePage["\129"] = "" -- Undefined
tblCodePage[""] = string.char(0xE2,0x80,0x9A)
tblCodePage[""] = string.char(0xC6,0x92)
tblCodePage[""] = string.char(0xE2,0x80,0x9E)
tblCodePage["
"] = string.char(0xE2,0x80,0xA6)
tblCodePage[""] = string.char(0xE2,0x80,0xA0)
tblCodePage[""] = string.char(0xE2,0x80,0xA1)
tblCodePage[""] = string.char(0xCB,0x86)
tblCodePage[""] = string.char(0xE2,0x80,0xB0)
tblCodePage[""] = string.char(0xC5,0xA0)
tblCodePage[""] = string.char(0xE2,0x80,0xB9)
tblCodePage[""] = string.char(0xC5,0x92)
tblCodePage["\141"] = "" -- Undefined
tblCodePage[""] = string.char(0xC5,0xBD)
tblCodePage["\143"] = "" -- Undefined
tblCodePage["\144"] = "" -- Undefined
tblCodePage[""] = string.char(0xE2,0x80,0x98)
tblCodePage[""] = string.char(0xE2,0x80,0x99)
tblCodePage[""] = string.char(0xE2,0x80,0x9C)
tblCodePage[""] = string.char(0xE2,0x80,0x9D)
tblCodePage[""] = string.char(0xE2,0x80,0xA2)
tblCodePage[""] = string.char(0xE2,0x80,0x93)
tblCodePage[""] = string.char(0xE2,0x80,0x94)
tblCodePage["\152"] = string.char(0xCB,0x9C) -- Small Tilde
tblCodePage[""] = string.char(0xE2,0x84,0xA2)
tblCodePage[""] = string.char(0xC5,0xA1)
tblCodePage[""] = string.char(0xE2,0x80,0xBA)
tblCodePage[""] = string.char(0xC5,0x93)
tblCodePage["\157"] = "" -- Undefined
tblCodePage[""] = string.char(0xC5,0xBE)
tblCodePage[""] = string.char(0xC5,0xB8)
tblCodePage["\160"] = string.char(0xC2,0xA0) -- " " No Break Space
tblCodePage["¡"] = string.char(0xC2,0xA1) -- "¡"
tblCodePage["¢"] = string.char(0xC2,0xA2) -- "¢"
tblCodePage["£"] = string.char(0xC2,0xA3) -- "£"
tblCodePage["¤"] = string.char(0xC2,0xA4) -- "¤"
tblCodePage["¥"] = string.char(0xC2,0xA5) -- "¥"
tblCodePage["¦"] = string.char(0xC2,0xA6)
tblCodePage["§"] = string.char(0xC2,0xA7)
tblCodePage["¨"] = string.char(0xC2,0xA8)
tblCodePage["©"] = string.char(0xC2,0xA9)
tblCodePage["ª"] = string.char(0xC2,0xAA)
tblCodePage["«"] = string.char(0xC2,0xAB)
tblCodePage["¬"] = string.char(0xC2,0xAC)
tblCodePage[""] = string.char(0xC2,0xAD) -- "­" Soft Hyphen
tblCodePage["®"] = string.char(0xC2,0xAE)
tblCodePage["¯"] = string.char(0xC2,0xAF)
tblCodePage["°"] = string.char(0xC2,0xB0)
tblCodePage["±"] = string.char(0xC2,0xB1)
tblCodePage["²"] = string.char(0xC2,0xB2)
tblCodePage["³"] = string.char(0xC2,0xB3)
tblCodePage["´"] = string.char(0xC2,0xB4)
tblCodePage["µ"] = string.char(0xC2,0xB5)
tblCodePage["¶"] = string.char(0xC2,0xB6)
tblCodePage["·"] = string.char(0xC2,0xB7)
tblCodePage["¸"] = string.char(0xC2,0xB8)
tblCodePage["¹"] = string.char(0xC2,0xB9)
tblCodePage["º"] = string.char(0xC2,0xBA)
tblCodePage["»"] = string.char(0xC2,0xBB)
tblCodePage["¼"] = string.char(0xC2,0xBC)
tblCodePage["½"] = string.char(0xC2,0xBD)
tblCodePage["¾"] = string.char(0xC2,0xBE)
tblCodePage["¿"] = string.char(0xC2,0xBF)
tblCodePage["À"] = string.char(0xC3,0x80)
tblCodePage["Á"] = string.char(0xC3,0x81)
tblCodePage["Â"] = string.char(0xC3,0x82)
tblCodePage["Ã"] = string.char(0xC3,0x83)
tblCodePage["Ä"] = string.char(0xC3,0x84)
tblCodePage["Å"] = string.char(0xC3,0x85)
tblCodePage["Æ"] = string.char(0xC3,0x86)
tblCodePage["Ç"] = string.char(0xC3,0x87)
tblCodePage["È"] = string.char(0xC3,0x88)
tblCodePage["É"] = string.char(0xC3,0x89)
tblCodePage["Ê"] = string.char(0xC3,0x8A)
tblCodePage["Ë"] = string.char(0xC3,0x8B)
tblCodePage["Ì"] = string.char(0xC3,0x8C)
tblCodePage["Í"] = string.char(0xC3,0x8D)
tblCodePage["Î"] = string.char(0xC3,0x8E)
tblCodePage["Ï"] = string.char(0xC3,0x8F)
tblCodePage["Ð"] = string.char(0xC3,0x90)
tblCodePage["Ñ"] = string.char(0xC3,0x91)
tblCodePage["Ò"] = string.char(0xC3,0x92)
tblCodePage["Ó"] = string.char(0xC3,0x93)
tblCodePage["Ô"] = string.char(0xC3,0x94)
tblCodePage["Õ"] = string.char(0xC3,0x95)
tblCodePage["Ö"] = string.char(0xC3,0x96)
tblCodePage["×"] = string.char(0xC3,0x97)
tblCodePage["Ø"] = string.char(0xC3,0x98)
tblCodePage["Ù"] = string.char(0xC3,0x99)
tblCodePage["Ú"] = string.char(0xC3,0x9A)
tblCodePage["Û"] = string.char(0xC3,0x9B)
tblCodePage["Ü"] = string.char(0xC3,0x9C)
tblCodePage["Ý"] = string.char(0xC3,0x9D)
tblCodePage["Þ"] = string.char(0xC3,0x9E)
tblCodePage["ß"] = string.char(0xC3,0x9F)
tblCodePage["à"] = string.char(0xC3,0xA0)
tblCodePage["á"] = string.char(0xC3,0xA1)
tblCodePage["â"] = string.char(0xC3,0xA2)
tblCodePage["ã"] = string.char(0xC3,0xA3)
tblCodePage["ä"] = string.char(0xC3,0xA4)
tblCodePage["å"] = string.char(0xC3,0xA5)
tblCodePage["æ"] = string.char(0xC3,0xA6)
tblCodePage["ç"] = string.char(0xC3,0xA7)
tblCodePage["è"] = string.char(0xC3,0xA8)
tblCodePage["é"] = string.char(0xC3,0xA9)
tblCodePage["ê"] = string.char(0xC3,0xAA)
tblCodePage["ë"] = string.char(0xC3,0xAB)
tblCodePage["ì"] = string.char(0xC3,0xAC)
tblCodePage["í"] = string.char(0xC3,0xAD)
tblCodePage["î"] = string.char(0xC3,0xAE)
tblCodePage["ï"] = string.char(0xC3,0xAF)
tblCodePage["ð"] = string.char(0xC3,0xB0)
tblCodePage["ñ"] = string.char(0xC3,0xB1)
tblCodePage["ò"] = string.char(0xC3,0xB2)
tblCodePage["ó"] = string.char(0xC3,0xB3)
tblCodePage["ô"] = string.char(0xC3,0xB4)
tblCodePage["õ"] = string.char(0xC3,0xB5)
tblCodePage["ö"] = string.char(0xC3,0xB6)
tblCodePage["÷"] = string.char(0xC3,0xB7)
tblCodePage["ø"] = string.char(0xC3,0xB8)
tblCodePage["ù"] = string.char(0xC3,0xB9)
tblCodePage["ú"] = string.char(0xC3,0xBA)
tblCodePage["û"] = string.char(0xC3,0xBB)
tblCodePage["ü"] = string.char(0xC3,0xBC)
tblCodePage["ý"] = string.char(0xC3,0xBD)
tblCodePage["þ"] = string.char(0xC3,0xBE)
tblCodePage["ÿ"] = string.char(0xC3,0xBF)
-- Code Page 1250 Unicode characters "\128" to "\255" for UTF-8 scheme "[-ÿ]" encodings: http://en.wikipedia.org/wiki/UTF-8
tblCodePage["1250"] = {}
tblCodePage["1250"]["\131"] = "" -- Undefined
tblCodePage["1250"]["\136"] = "" -- Undefined
tblCodePage["1250"][""] = string.char(0xC5,0x9A)
tblCodePage["1250"][""] = string.char(0xC5,0xA4)
tblCodePage["1250"][""] = string.char(0xC5,0xBD)
tblCodePage["1250"][""] = string.char(0xC5,0xB9)
tblCodePage["1250"]["\152"] = "" -- Undefined
tblCodePage["1250"][""] = string.char(0xC5,0x9B)
tblCodePage["1250"][""] = string.char(0xC5,0xA5)
tblCodePage["1250"][""] = string.char(0xC5,0xBE)
tblCodePage["1250"][""] = string.char(0xC5,0xBA)
tblCodePage["1250"]["¡"] = string.char(0xCB,0x87)
tblCodePage["1250"]["¢"] = string.char(0xCB,0x98)
tblCodePage["1250"]["£"] = string.char(0xC5,0x81)
tblCodePage["1250"]["¥"] = string.char(0xC4,0x84)
tblCodePage["1250"]["ª"] = string.char(0xC5,0x9E)
tblCodePage["1250"]["¯"] = string.char(0xC5,0xBB)
tblCodePage["1250"]["²"] = string.char(0xCB,0x9B)
tblCodePage["1250"]["³"] = string.char(0xC5,0x82)
tblCodePage["1250"]["¹"] = string.char(0xC4,0x85)
tblCodePage["1250"]["º"] = string.char(0xC5,0x9F)
tblCodePage["1250"]["¼"] = string.char(0xC5,0x7D)
tblCodePage["1250"]["½"] = string.char(0xCB,0x9D)
tblCodePage["1250"]["¾"] = string.char(0xC5,0x7E)
tblCodePage["1250"]["¿"] = string.char(0xC5,0xBC)
-- needs more 1250 codes hereon...
tblCodePage["1250"]["Æ"] = string.char(0xC4,0x86)
tblCodePage["1250"]["È"] = string.char(0xC4,0x8C)
tblCodePage["1250"]["æ"] = string.char(0xC4,0x87)
tblCodePage["1250"]["è"] = string.char(0xC4,0x8D)
-- Set XML/XHTML/HTML "[%c\"&'<>]" Markup encodings: http://en.wikipedia.org/wiki/XML and http://en.wikipedia.org/wiki/HTML
local function setMarkupEncodings()
tblCodePage["\t"] = " " -- HT "\t" to "\r" are treated as white space in Markup Languages by default
tblCodePage["\n"] = br_Tag -- LF
tblCodePage["\v"] = br_Tag -- VT line break tag "<br>" or "<br >" or "<br/>" or "<br />" is better
tblCodePage["\f"] = br_Tag -- FF
tblCodePage["\r"] = br_Tag -- CR
tblCodePage['"'] = """
tblCodePage["&"] = "&"
tblCodePage["'"] = "'"
tblCodePage["<"] = "<"
tblCodePage[">"] = ">"
end -- local function setMarkupEncodings
-- Set URI/URL/URN "[%s%p]" encodings: http://en.wikipedia.org/wiki/URL and http://en.wikipedia.org/wiki/Percent-encoding
local function setURIEncodings()
tblCodePage["\t"] = "+" -- HT space
tblCodePage["\n"] = "%0A" -- LF newline
tblCodePage["\v"] = "%0A" -- VT newline
tblCodePage["\f"] = "%0A" -- FF newline
tblCodePage["\r"] = "%0D" -- CR return
tblCodePage['"'] = "%22"
tblCodePage["&"] = "%26"
tblCodePage["'"] = "%27"
tblCodePage["<"] = "%3C"
tblCodePage[">"] = "%3E"
end -- local function setURIEncodings
-- Encode characters according to gsub pattern & lookup table --
local function strEncode(strText,strPattern,tblPattern)
strText = (strText or ""):gsub(strPattern,tblPattern)
return strText
end -- local function strEncode
-- Encode CP characters into UTF8 codes --
function StrCP_UTF(strText)
strText = strEncode(strText,"[\127-ÿ]",tblCodePage)
return strText
end -- function StrCP_UTF
function StrCP1252_UTF(strText)
return StrCP_UTF(strText)
end -- function StrCP1252_UTF
-- Encode CP characters into XML/XHTML/HTML/UTF8 codes --
function StrCP_XML(strText)
setMarkupEncodings()
strText = (strText or ""):gsub(br_Lua,"\n") -- Convert <br> & <br > & <br/> & <br /> to \n that becomes br_Tag
strText = strEncode(strText,"[%c\"&'<>\127-ÿ]",tblCodePage)
return strText
end -- function StrCP_XML
function StrCP1252_XML(strText)
return StrCP_XML(strText)
end -- function StrCP1252_XML
-- Encode Item Text characters into XML/HTML/UTF8 codes --
function StrGetItem_XML(ptrItem,strTags)
return StrCP_XML(fhGetItemText(ptrItem,strTags))
end -- function StrGetItem_XML
-- Encode CP characters into URI codes --
function StrCP_URI(strText)
setURIEncodings()
strText = (strText or ""):gsub(br_Lua,"\n") -- Convert <br> & <br > & <br/> & <br /> to \n that becomes %0A
strText = strEncode(strText,"[%c%s%p\127-ÿ]",tblCodePage)
return strText
end -- function StrCP_URI
function StrCP1252_URI(strText)
return StrCP_URI(strText)
end -- function StrCP1252_URI
-- Encode UTF-8 bytes into single CP character -- Legacy from V1.0
function StrUTF8_Encode(strText)
return StrUTF_CP(strText)
end -- function StrUTF8_Encode
-- Encode UTF-8 bytes into single CP character V2.0 upvalues --
local strByteRange = "["..string.char(0xC0).."-"..string.char(0xFF).."]"
local tblBytePoint = {0xC0,0xE0,0xF0,0xF8,0xFC} -- Byte codes for 2-byte, 3-byte, 4-byte, 5-byte, 6-byte UTF-8
local tblUTF8 = {}
for strByte = string.byte(""), string.byte("ÿ") do
local strChar = string.char(strByte) -- Use CodePage to UTF-8 table to populate UTF-8 to CodePage table
local strCode = tblCodePage[strChar]
tblUTF8[strCode] = strChar
end
-- Encode UTF-8 bytes into single CP character --
function StrUTF_CP(strText)
strText = strText or ""
if strText:match(strByteRange) then -- If text contains characters that need translating then
local intChar = 0 -- Input character index
local strChar = "" -- Current character
local strCode = "" -- UTF-8 multi-byte code
local tblLine = {} -- Translated output line
repeat
intChar = intChar + 1 -- Step through each character in text
strChar = strText:sub(intChar,intChar)
if strChar:match(strByteRange) then -- Convert UTF-8 bytes into CP character
strCode = strChar -- First UTF-8 byte code, whose top bits say how many bytes to append
for intByte, strByte in ipairs(tblBytePoint) do
if string.byte(strChar) >= strByte then
intChar = intChar + 1 -- Append next UTF-8 byte code character
strCode = strCode..strText:sub(intChar,intChar)
else
break
end
end
strChar = tblUTF8[strCode] or "¿" -- Translate UTF-8 code into CP character
end
table.insert(tblLine,strChar) -- Accumulate output char by char
until intChar >= #strText
strText = table.concat(tblLine)
end
return strText
end -- function StrUTF_CP
function StrUTF_CP1252(strText)
return StrUTF_CP(strText)
end -- function StrUTF_CP1252
-- Encode CP characters into ISO-8859-1 codes --
function StrCP_ISO(strText)
-- Set ISO-8859-1 "[\127-]" encodings: http://en.wikipedia.org/wiki/ISO/IEC_8859-1
local tblCodePage = { }
tblCodePage["\127"] = "" -- DEL
tblCodePage[""] = "EUR"
tblCodePage["\129"] = "" -- Undefined
tblCodePage[""] = "¸"
tblCodePage[""] = "f"
tblCodePage[""] = "¸¸"
tblCodePage["
"] = "..."
tblCodePage[""] = "+"
tblCodePage[""] = "±"
tblCodePage[""] = "^"
tblCodePage[""] = "%"
tblCodePage[""] = "S"
tblCodePage[""] = "<"
tblCodePage[""] = "OE"
tblCodePage["\141"] = "" -- Undefined
tblCodePage[""] = "Z"
tblCodePage["\143"] = "" -- Undefined
tblCodePage["\144"] = "" -- Undefined
tblCodePage[""] = "'"
tblCodePage[""] = "'"
tblCodePage[""] = '"'
tblCodePage[""] = '"'
tblCodePage[""] = "º"
tblCodePage[""] = "-"
tblCodePage[""] = "-"
tblCodePage["\152"] = "~" -- Small Tilde
tblCodePage[""] = "TM"
tblCodePage[""] = "s"
tblCodePage[""] = ">"
tblCodePage[""] = "oe"
tblCodePage["\157"] = "" -- Undefined
tblCodePage[""] = "z"
tblCodePage[""] = "Y"
strText = strEncode(strText,"[\127-]",tblCodePage)
return strText
end -- local function StrCP_ISO
function StrCP1252_ISO(strText)
return StrCP_ISO(strText)
end -- local function StrCP1252_ISO
-- Set markup language break tag --
function SetBreakTag(br_New)
if not (br_New or ""):match(br_Lua) then -- Ensure new break tag is "<br>" or "<br >" or "<br/>" or "<br />"
br_New = "<br />"
end
br_Tag = br_New
end -- function SetBreakTag
require "luacom"
local function getRegKey(strKey)
local luaShell = luacom.CreateObject "WScript.Shell"
local strValue
if pcall( function() strValue = luaShell:RegRead(strKey) end ) then
return strValue, false
else
return nil, true
end
end -- local function getRegKey
local strCodePage, isError = getRegKey("HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Nls\\CodePage\\ACP")
if isError then
error("\nCode Page ACP Registry Key Not Found.\n")
end
if strCodePage == "1252" then
-- do nothing as this is default
elseif tblCodePage[strCodePage] then
for strByte = string.byte(""), string.byte("ÿ") do
local strChar = string.char(strByte) -- Use CodePage to UTF-8 table to populate UTF-8 to CodePage table
tblCodePage[strChar] = tblCodePage[strCodePage][strChar] or tblCodePage[strChar]
end
else
error("\nCode Page "..strCodePage.." is not supported\n")
end
return fh
end -- local function encoder_v2
--[[
@Title: +fh+general_v1
@Author: Mike Tate
@LastUpdated: 19 Oct 2013
@Version: 1.1
@Description: A general functions module to supplement LUA functions.
@V1.0: Initial version.
]]
local function general_v1(...) -- if not ... then error("\n\nThis is a Library Module, and so it can not be executed on its own.") end
local fh = {} -- Local environment table
package.seeall(fh) -- Enable all globals
module(...,package.seeall) -- Create matching module name
setfenv(1,fh) -- All public names are added to local fh table
require "lfs" -- To access LUA filing system
-- Check if file exists --
function FlgFileExists(strFileName)
-- return pl.path.isfile(strFileName)
---[=[
if lfs.attributes(strFileName,"mode") == "file" then
return true
else
return false
end
--]=]
end -- function FlgFileExists
-- Check if folder exists --
function FlgFolderExists(strFolderName)
-- return pl.path.isdir(strFolderName)
---[=[
if lfs.attributes(strFolderName:gsub("\\$",""),"mode") == "directory" then
return true
else
return false
end
--]=]
end -- function FlgFolderExists
-- Check if folder writable --
function FlgFolderWrite(strFolderName)
if FlgFolderExists(strFolderName) then
local fileHandle, strError = io.open(strFolderName.."\\xyz.xyz","w")
if fileHandle ~= nil then
fileHandle:close()
os.remove(strFolderName.."\\xyz.xyz")
return true
end
end
return false
end -- function FlgFolderWrite
-- Open File and return Handle --
function OpenFile(strFileName,strMode)
local fileHandle, strError = io.open(strFileName,strMode)
if fileHandle == nil then
error("\n Unable to open file in \""..strMode.."\" mode. \n "..strFileName.." \n "..strError.." \n")
end
return fileHandle
end -- function OpenFile
-- Save string to file --
function SaveStringToFile(strString,strFileName)
local fileHandle = OpenFile(strFileName,"w")
fileHandle:write(strString)
assert(fileHandle:close())
end -- function SaveStringToFile
-- Load string from file --
function StrLoadFromFile(strFileName)
local fileHandle = OpenFile(strFileName,"r")
local strString = fileHandle:read("*all")
assert(fileHandle:close())
return strString
end -- function StrLoadFromFile
-- Return the Path, Filename, and extension as 3 values
function SplitFilename(strFilename)
return strFilename:match("(.-)([^\\]-([^\\%.]+))$")
end -- function SplitFilename
-- Return a Directory Tree entry & attributes on each iteration --
function DirTree(strDir)
assert(strDir and strDir ~= "", "directory parameter is missing or empty")
if strDir:sub(-1) == "/" then
strDir = strDir:sub(1,-2) -- Remove trailing "/"
end
local function doYieldTree(strDir)
--! for strEntry in pl.path.dir(strDir) do
for strEntry in lfs.dir(strDir) do
if strEntry ~= "." and strEntry ~= ".." then
strEntry = strDir.."\\"..strEntry
local tblAttr, strError = lfs.attributes(strEntry)
if not tblAttr then tblAttr = { mode="attrfail", error=strError } end
coroutine.yield(strEntry,tblAttr)
if tblAttr.mode == "directory" then
doYieldTree(strEntry)
end
end
end
end -- local function doYieldTree
return coroutine.wrap(function() doYieldTree(strDir) end)
end -- function DirTree
local function strErrorText(strError,strFileName,intRepeat)
return strError:gsub(strFileName:match("(.+\\).+"),"Del#"..tostring(intRepeat)..":")
end -- local function strErrorText
-- Delete file if it exists --
function DeleteFile(strFileName,errFunction)
if FlgFileExists(strFileName) then
local fileHandle, strError = os.remove(strFileName)
if fileHandle == nil then
local intRepeat = 1
repeat
if intRepeat > 1 and type(errFunction) == "function" then
errFunction(strErrorText(strError,strFileName,intRepeat))
end
fhSleep(300,100)
if FlgFileExists(strFileName) then
fileHandle, strError = os.remove(strFileName)
end
intRepeat = intRepeat + 1
until fileHandle ~= nil or intRepeat > 10
if intRepeat > 10 then error(strErrorText(strError,strFileName,intRepeat)) end
end
end
end -- function DeleteFile
-- Invoke FH Shell Execute API --
function DoExecute(strExecutable,...)
local errFunction = fhMessageBox
if type(arg[#arg]) == 'function' then
errFunction = arg[#arg]
table.remove(arg)
end
local isOK, intErrorCode, strErrorText = fhShellExecute(strExecutable,unpack(arg))
if not isOK then
errFunction(tostring(strErrorText).." ("..tostring(intErrorCode)..")")
end
return isOK
end -- function DoExecute
--[[
@function: BuildDataRef
@description: Get Full Data Reference for Pointer
@parameters: Item Pointer
@returns: Data Reference String, Record Id Integer, Record Type Tag String
@requires: None
]]
function BuildDataRef(ptrRef)
local strDataRef = "" -- Data Reference with instance indices e.g. INDI.RESI[2].ADDR
local intRecId = 0 -- Record Id for associated Record
local strRecTag = "" -- Record Tag of associated Record type i.e. INDI, FAM, NOTE, SOUR, etc
-- getDataRef() is called recursively per level of the Data Ref
-- ptrRef points to the upper Data Ref levels yet to be analysed
-- strRef compiles the lower Data Ref levels including instances
local function getDataRef(ptrRef,strRef)
local ptrTag = ptrRef:Clone()
local strTag = fhGetTag(ptrTag) -- Current level Tag
ptrTag:MoveToParentItem(ptrTag)
if ptrTag:IsNotNull() then -- Parent level exists
local intSib = 1
local ptrSib = ptrRef:Clone() -- Pointer to siblings with same Tag
ptrSib:MovePrev("SAME_TAG")
while ptrSib:IsNotNull() do -- Count previous siblings with same Tag
intSib = intSib + 1
ptrSib:MovePrev("SAME_TAG")
end
if intSib > 1 then strTag = strTag.."["..intSib.."]" end
getDataRef(ptrTag,"."..strTag..strRef) -- Now analyse the parent level
else
strDataRef = strTag..strRef -- Record level reached, so set return values
intRecId = fhGetRecordId(ptrRef)
strRecTag = strTag
if not fhIsValidDataRef(strDataRef) then print("BuildDataRef: "..strDataRef.." is Invalid") end
end
end -- local function getDataRef
if type(ptrRef) == "userdata" then getDataRef(ptrRef,"") end
return strDataRef, intRecId, strRecTag
end -- function BuildDataRef
--[[
@function: GetDataRefPtr
@description: Get Pointer for Full Data Reference
@parameters: Data Reference String, Record Id Integer, Record Type Tag String (optional)
@returns: Item Pointer which IsNull() if any parameters are invalid
@requires: None
]]
function GetDataRefPtr(strDataRef,intRecId,strRecTag)
strDataRef = strDataRef or ""
if not strRecTag then