Files
Geneweb/bin/gwu/gwuLib.ml
2024-03-05 22:01:20 +01:00

1753 lines
61 KiB
OCaml

(* Copyright (c) 1998-2007 INRIA *)
open Geneweb
open Def
open Gwdb
open Gwexport
let old_gw = ref false
let only_file = ref ""
let out_dir = ref ""
let raw_output = ref false
let sep_limit = ref 21
let separate_list = ref []
(* Returns true if `old_gw` is `true` and there exist an event associated to a
person that:
* is either a birth, baptism, death, burial or a cremation and is associated to
a note or a witness;
* is any other event.
Otherwise, returns false *)
let put_events_in_notes base p =
(* Si on est en mode old_gw, on mets tous les évènements *)
(* dans les notes. *)
if !old_gw then
let rec loop pevents =
match pevents with
| [] -> false
| evt :: events -> (
match evt.epers_name with
| Epers_Birth | Epers_Baptism | Epers_Death | Epers_Burial
| Epers_Cremation ->
if sou base evt.epers_note <> "" || evt.epers_witnesses <> [||]
then true
else loop events
| _ -> true)
in
loop (get_pevents p)
else false
let (ht_dup_occ : (Gwdb.iper, int) Hashtbl.t) = Hashtbl.create 20001
let (ht_orig_occ : (string, int list) Hashtbl.t) = Hashtbl.create 20001
let prepare_free_occ ?(select = fun _ -> true) base =
(* Parce qu'on est obligé ... *)
let sn = "?" in
let fn = "?" in
let key = Name.lower fn ^ " #@# " ^ Name.lower sn in
Hashtbl.add ht_orig_occ key [ 0 ];
Gwdb.Collection.iter
(fun ip ->
if select ip then
let p = poi base ip in
let sn = sou base (get_surname p) in
let fn = sou base (get_first_name p) in
if sn = "?" && fn = "?" then ()
else
let fn = Name.lower fn in
let sn = Name.lower sn in
if fn = "" || sn = "" then
let key = fn ^ " #@# " ^ sn in
let occ = get_occ p in
try
let l = Hashtbl.find ht_orig_occ key in
if List.mem occ l then Hashtbl.add ht_dup_occ ip occ
else Hashtbl.replace ht_orig_occ key (occ :: l)
with Not_found -> Hashtbl.add ht_orig_occ key [ occ ])
(Gwdb.ipers base);
Hashtbl.iter
(fun key l -> Hashtbl.replace ht_orig_occ key (List.sort compare l))
ht_orig_occ;
Hashtbl.iter
(fun ip _ ->
let p = poi base ip in
let sn = sou base (get_surname p) in
let fn = sou base (get_first_name p) in
let key = Name.lower fn ^ " #@# " ^ Name.lower sn in
try
let list_occ = Hashtbl.find ht_orig_occ key in
let rec loop list init new_list =
match list with
| x :: y :: l when y - x > 1 ->
(succ x, List.rev_append (y :: succ x :: x :: new_list) l)
| x :: l -> loop l (succ x) (x :: new_list)
| [] -> (init, [ init ])
in
let new_occ, new_list_occ = loop list_occ 0 [] in
Hashtbl.replace ht_dup_occ ip new_occ;
Hashtbl.replace ht_orig_occ key new_list_occ
with Not_found -> ())
ht_dup_occ
let get_new_occ p =
try Hashtbl.find ht_dup_occ (get_iper p) with Not_found -> get_occ p
type mfam = {
m_ifam : ifam;
m_fam : family;
m_fath : person;
m_moth : person;
m_chil : person array;
}
let soy y = if y = 0 then "-0" else string_of_int y
let oc opts = match opts.Gwexport.oc with _, oc, _ -> oc
let print_date_dmy opts d =
(match d.prec with
| About -> Printf.ksprintf (oc opts) "~"
| Maybe -> Printf.ksprintf (oc opts) "?"
| Before -> Printf.ksprintf (oc opts) "<"
| After -> Printf.ksprintf (oc opts) ">"
| Sure | OrYear _ | YearInt _ -> ());
if d.month = 0 then Printf.ksprintf (oc opts) "%s" (soy d.year)
else if d.day = 0 then Printf.ksprintf (oc opts) "%d/%s" d.month (soy d.year)
else Printf.ksprintf (oc opts) "%d/%d/%s" d.day d.month (soy d.year);
match d.prec with
| OrYear d2 ->
if not !old_gw then
if d2.month2 = 0 then Printf.ksprintf (oc opts) "|%s" (soy d2.year2)
else if d2.day2 = 0 then
Printf.ksprintf (oc opts) "|%d/%s" d2.month2 (soy d2.year2)
else
Printf.ksprintf (oc opts) "|%d/%d/%s" d2.day2 d2.month2 (soy d2.year2)
else Printf.ksprintf (oc opts) "|%s" (soy d2.year2)
| YearInt d2 ->
if not !old_gw then
if d2.month2 = 0 then Printf.ksprintf (oc opts) "..%s" (soy d2.year2)
else if d2.day2 = 0 then
Printf.ksprintf (oc opts) "..%d/%s" d2.month2 (soy d2.year2)
else
Printf.ksprintf (oc opts) "..%d/%d/%s" d2.day2 d2.month2
(soy d2.year2)
else Printf.ksprintf (oc opts) "..%s" (soy d2.year2)
| _ -> ()
let is_printable = function '\000' .. '\031' -> false | _ -> true
let starting_char no_num s =
match s.[0] with
(*'a'..'z' | 'A'..'Z' | 'à'..'ý' | 'À'..'Ý' *)
| 'a' .. 'z' | 'A' .. 'Z' | '\xE0' .. '\xFD' | '\xC0' .. '\xDD' -> true
| '0' .. '9' -> not no_num
| '?' -> if s = "?" then true else false
| _ -> false
let no_newlines s =
let conv_char i = match s.[i] with '\n' | '\r' -> ' ' | _ -> s.[i] in
String.init (String.length s) conv_char
let gen_correct_string no_num no_colon s =
let s = String.trim s in
let rec loop i len =
if i = String.length s then Buff.get len
else if len = 0 && not (starting_char no_num s) then
loop i (Buff.store len '_')
else
match s.[i] with
| ' ' | '\n' | '\t' ->
if i = String.length s - 1 then Buff.get len
else loop (i + 1) (Buff.store len '_')
| '_' | '\\' -> loop (i + 1) (Buff.store (Buff.store len '\\') s.[i])
| ':' when no_colon ->
let len = Buff.store len '\\' in
loop (i + 1) (Buff.store (Buff.store len '\\') s.[i])
| c ->
let c = if is_printable c then c else '_' in
loop (i + 1) (Buff.store len c)
in
loop 0 0
let s_correct_string s =
let s = gen_correct_string false false s in
if s = "" then "_" else s
let s_correct_string_nonum s =
let s = gen_correct_string true false s in
if s = "" then "_" else s
let correct_string base is = s_correct_string (sou base is)
let correct_string_no_colon base is =
gen_correct_string false true (sou base is)
let gen_print_date opts no_colon = function
| Dgreg (d, Dgregorian) -> print_date_dmy opts d
| Dgreg (d, Djulian) ->
print_date_dmy opts (Calendar.julian_of_gregorian d);
Printf.ksprintf (oc opts) "J"
| Dgreg (d, Dfrench) ->
print_date_dmy opts (Calendar.french_of_gregorian d);
Printf.ksprintf (oc opts) "F"
| Dgreg (d, Dhebrew) ->
print_date_dmy opts (Calendar.hebrew_of_gregorian d);
Printf.ksprintf (oc opts) "H"
| Dtext t ->
(* Dans le cas d'une date texte pour un titre, on échappe les ':' *)
let t = gen_correct_string false no_colon t in
Printf.ksprintf (oc opts) "0(%s)" t
let gen_print_date_option opts no_colon = function
| Some d -> gen_print_date opts no_colon d
| None -> ()
let print_date opts = gen_print_date opts false
let print_date_option opts = gen_print_date_option opts false
let print_title_date_option opts = gen_print_date_option opts true
let lines_list_of_string s =
let rec loop lines len i =
if i = String.length s then
List.rev (if len = 0 then lines else Buff.get len :: lines)
else if s.[i] = '\n' then
let line = Buff.get len in
loop (line :: lines) 0 (i + 1)
else loop lines (Buff.store len s.[i]) (i + 1)
in
loop [] 0 0
let has_infos_not_dates opts base p =
let has_picture_to_export =
sou base (get_image p) <> "" && not opts.no_picture
in
get_first_names_aliases p <> []
|| get_surnames_aliases p <> []
|| sou base (get_public_name p) <> ""
|| has_picture_to_export
|| get_qualifiers p <> []
|| get_aliases p <> []
|| get_titles p <> []
|| get_access p <> IfTitles
|| sou base (get_occupation p) <> ""
|| (opts.source <> None || sou base @@ get_psources p <> "")
|| sou base (get_birth_place p) <> ""
|| (opts.source = None && sou base (get_birth_src p) <> "")
|| sou base (get_baptism_place p) <> ""
|| (opts.source = None && sou base (get_baptism_src p) <> "")
|| sou base (get_death_place p) <> ""
|| (opts.source = None && sou base (get_death_src p) <> "")
|| sou base (get_burial_place p) <> ""
|| (opts.source = None && sou base (get_burial_src p) <> "")
let has_infos opts base p =
has_infos_not_dates opts base p
|| get_birth p <> Date.cdate_None
|| get_baptism p <> Date.cdate_None
|| get_death p <> NotDead
let print_if_not_equal_to opts x base lab is =
if sou base is <> x then
Printf.ksprintf (oc opts) " %s %s" lab (correct_string base is)
let print_src_if_not_equal_to opts x base lab is =
match opts.source with
| None -> if sou base is <> "" then print_if_not_equal_to opts x base lab is
| Some "" -> ()
| Some x -> Printf.ksprintf (oc opts) " %s %s" lab (s_correct_string x)
let print_if_no_empty opts = print_if_not_equal_to opts ""
let print_first_name_alias opts base is =
Printf.ksprintf (oc opts) " {%s}" (correct_string base is)
let print_surname_alias opts base is =
Printf.ksprintf (oc opts) " #salias %s" (correct_string base is)
let print_qualifier opts base is =
Printf.ksprintf (oc opts) " #nick %s" (correct_string base is)
let print_alias opts base is =
Printf.ksprintf (oc opts) " #alias %s" (correct_string base is)
let print_burial opts b =
match b with
| Buried cod -> (
Printf.ksprintf (oc opts) " #buri";
match Date.od_of_cdate cod with
| Some d ->
Printf.ksprintf (oc opts) " ";
print_date opts d;
()
| None -> ())
| Cremated cod -> (
Printf.ksprintf (oc opts) " #crem";
match Date.od_of_cdate cod with
| Some d ->
Printf.ksprintf (oc opts) " ";
print_date opts d;
()
| None -> ())
| UnknownBurial -> ()
let print_title opts base t =
let t_date_start = Date.od_of_cdate t.t_date_start in
let t_date_end = Date.od_of_cdate t.t_date_end in
Printf.ksprintf (oc opts) " [";
(match t.t_name with
| Tmain -> Printf.ksprintf (oc opts) "*"
| Tname s -> Printf.ksprintf (oc opts) "%s" (correct_string_no_colon base s)
| Tnone -> ());
Printf.ksprintf (oc opts) ":";
Printf.ksprintf (oc opts) "%s" (correct_string_no_colon base t.t_ident);
Printf.ksprintf (oc opts) ":";
Printf.ksprintf (oc opts) "%s" (correct_string_no_colon base t.t_place);
(if t.t_nth <> 0 then Printf.ksprintf (oc opts) ":"
else
match (t_date_start, t_date_end) with
| Some _, _ | _, Some _ -> Printf.ksprintf (oc opts) ":"
| _ -> ());
print_title_date_option opts t_date_start;
(if t.t_nth <> 0 then Printf.ksprintf (oc opts) ":"
else
match t_date_end with Some _ -> Printf.ksprintf (oc opts) ":" | None -> ());
print_title_date_option opts t_date_end;
if t.t_nth <> 0 then Printf.ksprintf (oc opts) ":%d" t.t_nth;
Printf.ksprintf (oc opts) "]"
let zero_birth_is_required opts base is_child p =
if get_baptism p <> Date.cdate_None then false
else
match get_death p with
| Death (_, _) | DeadYoung | DeadDontKnowWhen | OfCourseDead -> true
| DontKnowIfDead
when (not is_child)
&& (not (has_infos_not_dates opts base p))
&& p_first_name base p <> "?"
&& p_surname base p <> "?" ->
true
| _ -> false
let print_infos opts base is_child csrc cbp p =
List.iter (print_first_name_alias opts base) (get_first_names_aliases p);
List.iter (print_surname_alias opts base) (get_surnames_aliases p);
(match get_public_name p with
| s when sou base s <> "" ->
Printf.ksprintf (oc opts) " (%s)" (correct_string base s)
| _ -> ());
if not opts.no_picture then print_if_no_empty opts base "#image" (get_image p);
List.iter (print_qualifier opts base) (get_qualifiers p);
List.iter (print_alias opts base) (get_aliases p);
List.iter (print_title opts base) (get_titles p);
(match get_access p with
| IfTitles -> ()
| Public -> Printf.ksprintf (oc opts) " #apubl"
| Private -> Printf.ksprintf (oc opts) " #apriv");
print_if_no_empty opts base "#occu" (get_occupation p);
print_src_if_not_equal_to opts csrc base "#src" (get_psources p);
(match Date.od_of_cdate (get_birth p) with
| Some d ->
Printf.ksprintf (oc opts) " ";
print_date opts d
| _ when zero_birth_is_required opts base is_child p ->
Printf.ksprintf (oc opts) " 0"
| None -> ());
print_if_not_equal_to opts cbp base "#bp" (get_birth_place p);
if opts.source = None then print_if_no_empty opts base "#bs" (get_birth_src p);
(match Date.od_of_cdate (get_baptism p) with
| Some d ->
Printf.ksprintf (oc opts) " !";
print_date opts d
| None -> ());
print_if_no_empty opts base "#pp" (get_baptism_place p);
if opts.source = None then
print_if_no_empty opts base "#ps" (get_baptism_src p);
(match get_death p with
| Death (dr, d) ->
Printf.ksprintf (oc opts) " ";
(match dr with
| Killed -> Printf.ksprintf (oc opts) "k"
| Murdered -> Printf.ksprintf (oc opts) "m"
| Executed -> Printf.ksprintf (oc opts) "e"
| Disappeared -> Printf.ksprintf (oc opts) "s"
| _ -> ());
print_date opts (Date.date_of_cdate d)
| DeadYoung -> Printf.ksprintf (oc opts) " mj"
| DeadDontKnowWhen -> Printf.ksprintf (oc opts) " 0"
| DontKnowIfDead -> (
match
(Date.od_of_cdate (get_birth p), Date.od_of_cdate (get_baptism p))
with
| Some _, _ | _, Some _ -> Printf.ksprintf (oc opts) " ?"
| _ -> ())
| OfCourseDead -> Printf.ksprintf (oc opts) " od"
| NotDead -> ());
print_if_no_empty opts base "#dp" (get_death_place p);
if opts.source = None then print_if_no_empty opts base "#ds" (get_death_src p);
print_burial opts (get_burial p);
print_if_no_empty opts base "#rp" (get_burial_place p);
if opts.source = None then
print_if_no_empty opts base "#rs" (get_burial_src p)
type gen = {
mark : (iper, bool) Gwdb.Marker.t;
mark_rel : (iper, bool) Gwdb.Marker.t;
per_sel : iper -> bool;
fam_sel : ifam -> bool;
fam_done : (ifam, bool) Gwdb.Marker.t;
mutable notes_pl_p : person list;
mutable ext_files : (string * string list ref) list;
mutable notes_alias : (string * string) list;
mutable pevents_pl_p : person list;
}
let map_notes aliases f = try List.assoc f aliases with Not_found -> f
let add_linked_files gen from s some_linked_files =
let slen = String.length s in
let rec loop new_linked_files i =
if i = slen then new_linked_files
else if i < slen - 2 && s.[i] = '[' && s.[i + 1] = '[' && s.[i + 2] = '['
then
let j =
let rec loop j =
if j = slen then j
else if
j < slen - 2 && s.[j] = ']' && s.[j + 1] = ']' && s.[j + 2] = ']'
then j + 3
else loop (j + 1)
in
loop (i + 3)
in
if j > i + 6 then
let b = String.sub s (i + 3) (j - i - 6) in
let fname =
try
let k = String.index b '/' in
String.sub b 0 k
with Not_found -> b
in
let fname = map_notes gen.notes_alias fname in
let f = from () in
let new_linked_files =
try
let r = List.assoc fname gen.ext_files in
if List.mem f !r then () else r := f :: !r;
new_linked_files
with Not_found ->
let lf = (fname, ref [ f ]) in
gen.ext_files <- lf :: gen.ext_files;
lf :: new_linked_files
in
loop new_linked_files j
else loop new_linked_files (i + 1)
else loop new_linked_files (i + 1)
in
loop some_linked_files 0
let print_parent opts base gen p =
let has_printed_parents =
match get_parents p with Some ifam -> gen.fam_sel ifam | None -> false
in
let first_parent_definition =
if Gwdb.Marker.get gen.mark (get_iper p) then false
else (
Gwdb.Marker.set gen.mark (get_iper p) true;
true)
in
let pr = (not has_printed_parents) && first_parent_definition in
let has_infos = if pr then has_infos opts base p else false in
let first_name = sou base (get_first_name p) in
let surname = sou base (get_surname p) in
Printf.ksprintf (oc opts) "%s %s%s" (s_correct_string surname)
(s_correct_string first_name)
(if first_name = "?" && surname = "?" then ""
else if get_new_occ p = 0 then ""
else "." ^ string_of_int (get_new_occ p));
if pr then
if has_infos then print_infos opts base false "" "" p
else if first_name <> "?" && surname <> "?" then
Printf.ksprintf (oc opts) " 0"
let print_child opts base fam_surname csrc cbp p =
Printf.ksprintf (oc opts) "-";
(match get_sex p with
| Male -> Printf.ksprintf (oc opts) " h"
| Female -> Printf.ksprintf (oc opts) " f"
| _ -> ());
Printf.ksprintf (oc opts) " %s"
(s_correct_string (sou base (get_first_name p)));
if p_first_name base p = "?" && p_surname base p = "?" then ()
else if get_new_occ p = 0 then ()
else Printf.ksprintf (oc opts) ".%d" (get_new_occ p);
if not (eq_istr (get_surname p) fam_surname) then
Printf.ksprintf (oc opts) " %s"
(s_correct_string_nonum (sou base (get_surname p)));
print_infos opts base true csrc cbp p;
Printf.ksprintf (oc opts) "\n"
let bogus_person base p = p_first_name base p = "?" && p_surname base p = "?"
let common_children proj base children =
if Array.length children <= 1 then None
else
let list = List.map (fun p -> sou base (proj p)) (Array.to_list children) in
if List.mem "" list then None
else
let list = List.sort compare list in
let src_max, n_max, _, _ =
List.fold_left
(fun (src_max, n_max, prev_src, n) src ->
if src = prev_src then
let n = n + 1 in
if n > n_max then (src, n, src, n) else (src_max, n_max, src, n)
else (src_max, n_max, src, 1))
("", 0, "", 0) list
in
if n_max > 1 then Some src_max else None
let common_children_sources = common_children get_psources
let common_children_birth_place = common_children get_birth_place
let empty_family base m =
bogus_person base m.m_fath && bogus_person base m.m_moth
&& Array.for_all (bogus_person base) m.m_chil
let string_of_witness_kind :
Def.witness_kind -> ('a, unit, string, unit) format4 option = function
| Witness_GodParent -> Some "#godp"
| Witness -> None
| Witness_CivilOfficer -> Some "#offi"
| Witness_ReligiousOfficer -> Some "#reli"
| Witness_Informant -> Some "#info"
| Witness_Attending -> Some "#atte"
| Witness_Mentioned -> Some "#ment"
| Witness_Other -> Some "#othe"
let print_witness opts base gen p =
Printf.ksprintf (oc opts) "%s %s%s"
(correct_string base (get_surname p))
(correct_string base (get_first_name p))
(if get_new_occ p = 0 then "" else "." ^ string_of_int (get_new_occ p));
if
Array.length (get_family p) = 0
&& get_parents p = None
&& not (Gwdb.Marker.get gen.mark (get_iper p))
then (
Gwdb.Marker.set gen.mark (get_iper p) true;
if has_infos opts base p then print_infos opts base false "" "" p
else Printf.ksprintf (oc opts) " 0";
(match sou base (get_notes p) with
| "" ->
if put_events_in_notes base p then gen.notes_pl_p <- p :: gen.notes_pl_p
| _ -> gen.notes_pl_p <- p :: gen.notes_pl_p);
if get_pevents p <> [] then gen.pevents_pl_p <- p :: gen.pevents_pl_p)
let print_pevent opts base gen e =
(match e.epers_name with
| Epers_Birth -> Printf.ksprintf (oc opts) "#birt"
| Epers_Baptism -> Printf.ksprintf (oc opts) "#bapt"
| Epers_Death -> Printf.ksprintf (oc opts) "#deat"
| Epers_Burial -> Printf.ksprintf (oc opts) "#buri"
| Epers_Cremation -> Printf.ksprintf (oc opts) "#crem"
| Epers_Accomplishment -> Printf.ksprintf (oc opts) "#acco"
| Epers_Acquisition -> Printf.ksprintf (oc opts) "#acqu"
| Epers_Adhesion -> Printf.ksprintf (oc opts) "#adhe"
| Epers_BaptismLDS -> Printf.ksprintf (oc opts) "#bapl"
| Epers_BarMitzvah -> Printf.ksprintf (oc opts) "#barm"
| Epers_BatMitzvah -> Printf.ksprintf (oc opts) "#basm"
| Epers_Benediction -> Printf.ksprintf (oc opts) "#bles"
| Epers_ChangeName -> Printf.ksprintf (oc opts) "#chgn"
| Epers_Circumcision -> Printf.ksprintf (oc opts) "#circ"
| Epers_Confirmation -> Printf.ksprintf (oc opts) "#conf"
| Epers_ConfirmationLDS -> Printf.ksprintf (oc opts) "#conl"
| Epers_Decoration -> Printf.ksprintf (oc opts) "#awar"
| Epers_DemobilisationMilitaire -> Printf.ksprintf (oc opts) "#demm"
| Epers_Diploma -> Printf.ksprintf (oc opts) "#degr"
| Epers_Distinction -> Printf.ksprintf (oc opts) "#dist"
| Epers_Dotation -> Printf.ksprintf (oc opts) "#endl"
| Epers_DotationLDS -> Printf.ksprintf (oc opts) "#dotl"
| Epers_Education -> Printf.ksprintf (oc opts) "#educ"
| Epers_Election -> Printf.ksprintf (oc opts) "#elec"
| Epers_Emigration -> Printf.ksprintf (oc opts) "#emig"
| Epers_Excommunication -> Printf.ksprintf (oc opts) "#exco"
| Epers_FamilyLinkLDS -> Printf.ksprintf (oc opts) "#flkl"
| Epers_FirstCommunion -> Printf.ksprintf (oc opts) "#fcom"
| Epers_Funeral -> Printf.ksprintf (oc opts) "#fune"
| Epers_Graduate -> Printf.ksprintf (oc opts) "#grad"
| Epers_Hospitalisation -> Printf.ksprintf (oc opts) "#hosp"
| Epers_Illness -> Printf.ksprintf (oc opts) "#illn"
| Epers_Immigration -> Printf.ksprintf (oc opts) "#immi"
| Epers_ListePassenger -> Printf.ksprintf (oc opts) "#lpas"
| Epers_MilitaryDistinction -> Printf.ksprintf (oc opts) "#mdis"
| Epers_MilitaryPromotion -> Printf.ksprintf (oc opts) "#mpro"
| Epers_MilitaryService -> Printf.ksprintf (oc opts) "#mser"
| Epers_MobilisationMilitaire -> Printf.ksprintf (oc opts) "#mobm"
| Epers_Naturalisation -> Printf.ksprintf (oc opts) "#natu"
| Epers_Occupation -> Printf.ksprintf (oc opts) "#occu"
| Epers_Ordination -> Printf.ksprintf (oc opts) "#ordn"
| Epers_Property -> Printf.ksprintf (oc opts) "#prop"
| Epers_Recensement -> Printf.ksprintf (oc opts) "#cens"
| Epers_Residence -> Printf.ksprintf (oc opts) "#resi"
| Epers_Retired -> Printf.ksprintf (oc opts) "#reti"
| Epers_ScellentChildLDS -> Printf.ksprintf (oc opts) "#slgc"
| Epers_ScellentParentLDS -> Printf.ksprintf (oc opts) "#slgp"
| Epers_ScellentSpouseLDS -> Printf.ksprintf (oc opts) "#slgs"
| Epers_VenteBien -> Printf.ksprintf (oc opts) "#vteb"
| Epers_Will -> Printf.ksprintf (oc opts) "#will"
| Epers_Name s -> Printf.ksprintf (oc opts) "#%s" (correct_string base s));
Printf.ksprintf (oc opts) " ";
let epers_date = Date.od_of_cdate e.epers_date in
print_date_option opts epers_date;
print_if_no_empty opts base "#p" e.epers_place;
(* TODO *)
(*print_if_no_empty opts base "#c" e.epers_cause;*)
if opts.source = None then print_if_no_empty opts base "#s" e.epers_src;
Printf.ksprintf (oc opts) "\n";
Array.iter
(fun (ip, wk) ->
if gen.per_sel ip then (
let p = poi base ip in
Printf.ksprintf (oc opts) "wit";
(match get_sex p with
| Male -> Printf.ksprintf (oc opts) " m"
| Female -> Printf.ksprintf (oc opts) " f"
| _ -> ());
Printf.ksprintf (oc opts) ": ";
let sk = string_of_witness_kind wk in
(match sk with
| Some s -> Printf.ksprintf (oc opts) (s ^^ " ")
| None -> ());
print_witness opts base gen p;
Printf.ksprintf (oc opts) "\n"))
e.epers_witnesses;
let note = if opts.no_notes <> `nnn then sou base e.epers_note else "" in
if note <> "" then
List.iter
(fun line -> Printf.ksprintf (oc opts) "note %s\n" line)
(lines_list_of_string note)
let get_persons_with_pevents m list =
let fath = m.m_fath in
let moth = m.m_moth in
let list =
match (get_pevents fath, get_parents fath) with
| [], _ | _, Some _ -> list
| _ -> fath :: list
in
let list =
match (get_pevents moth, get_parents moth) with
| [], _ | _, Some _ -> list
| _ -> moth :: list
in
Array.fold_right
(fun p list -> if get_pevents p = [] then list else p :: list)
m.m_chil list
let print_pevents_for_person opts base gen p =
let pevents = get_pevents p in
let surn = s_correct_string (p_surname base p) in
let fnam = s_correct_string (p_first_name base p) in
if pevents <> [] && surn <> "?" && fnam <> "?" then (
Printf.ksprintf (oc opts) "\n";
Printf.ksprintf (oc opts) "pevt %s %s%s\n" surn fnam
(if get_new_occ p = 0 then "" else "." ^ string_of_int (get_new_occ p));
List.iter (print_pevent opts base gen) pevents;
Printf.ksprintf (oc opts) "end pevt\n")
let rec list_memf f x = function
| [] -> false
| a :: l -> f x a || list_memf f x l
let eq_key p1 p2 = get_iper p1 = get_iper p2
let eq_key_fst (p1, _) (p2, _) = get_iper p1 = get_iper p2
let print_pevents opts base gen ml =
let pl = List.fold_right get_persons_with_pevents ml gen.pevents_pl_p in
let pl =
List.fold_right
(fun p pl -> if list_memf eq_key p pl then pl else p :: pl)
pl []
in
List.iter
(fun p ->
if gen.per_sel (get_iper p) then print_pevents_for_person opts base gen p)
pl
let print_fevent opts base gen in_comment e =
let print_sep () =
if not in_comment then Printf.ksprintf (oc opts) "\n"
else Printf.ksprintf (oc opts) " "
in
(match e.efam_name with
| Efam_Marriage -> Printf.ksprintf (oc opts) "#marr"
| Efam_NoMarriage -> Printf.ksprintf (oc opts) "#nmar"
| Efam_NoMention -> Printf.ksprintf (oc opts) "#nmen"
| Efam_Engage -> Printf.ksprintf (oc opts) "#enga"
| Efam_Divorce -> Printf.ksprintf (oc opts) "#div"
| Efam_Separated -> Printf.ksprintf (oc opts) "#sep"
| Efam_Annulation -> Printf.ksprintf (oc opts) "#anul"
| Efam_MarriageBann -> Printf.ksprintf (oc opts) "#marb"
| Efam_MarriageContract -> Printf.ksprintf (oc opts) "#marc"
| Efam_MarriageLicense -> Printf.ksprintf (oc opts) "#marl"
| Efam_PACS -> Printf.ksprintf (oc opts) "#pacs"
| Efam_Residence -> Printf.ksprintf (oc opts) "#resi"
| Efam_Name n -> Printf.ksprintf (oc opts) "#%s" (correct_string base n));
Printf.ksprintf (oc opts) " ";
let efam_date = Date.od_of_cdate e.efam_date in
print_date_option opts efam_date;
print_if_no_empty opts base "#p" e.efam_place;
(*print_if_no_empty opts base "#c" e.efam_cause;*)
if opts.source = None then print_if_no_empty opts base "#s" e.efam_src;
print_sep ();
Array.iter
(fun (ip, wk) ->
if gen.per_sel ip then (
let p = poi base ip in
Printf.ksprintf (oc opts) "wit";
(match get_sex p with
| Male -> Printf.ksprintf (oc opts) " m"
| Female -> Printf.ksprintf (oc opts) " f"
| _ -> ());
Printf.ksprintf (oc opts) ": ";
let sk = string_of_witness_kind wk in
(match sk with
| Some s -> Printf.ksprintf (oc opts) (s ^^ " ")
| None -> ());
print_witness opts base gen p;
print_sep ()))
e.efam_witnesses;
let note = if opts.no_notes <> `nnn then sou base e.efam_note else "" in
if note <> "" then
List.iter
(fun line ->
Printf.ksprintf (oc opts) "note %s" line;
print_sep ())
(lines_list_of_string note)
let print_comment_for_family opts base gen fam =
let comm = if opts.no_notes <> `nnn then sou base (get_comment fam) else "" in
(* Si on est en mode old_gw, on mets tous les évènements dans les notes. *)
(* On supprime les 2 évènements principaux. *)
let fevents =
List.filter
(fun evt ->
match evt.efam_name with
| Efam_Divorce | Efam_Engage | Efam_Marriage | Efam_NoMarriage
| Efam_NoMention | Efam_Separated ->
false
| _ -> true)
(get_fevents fam)
in
let has_evt =
!old_gw && (fevents <> [] || sou base (get_marriage_note fam) <> "")
in
if comm <> "" || has_evt then (
Printf.ksprintf (oc opts) "comm";
if comm <> "" then Printf.ksprintf (oc opts) " %s" (no_newlines comm);
if !old_gw then (
if sou base (get_marriage_note fam) <> "" then
Printf.ksprintf (oc opts) " marriage: %s"
(no_newlines (sou base (get_marriage_note fam)));
List.iter
(fun e ->
Printf.ksprintf (oc opts) " ";
print_fevent opts base gen true e)
fevents);
Printf.ksprintf (oc opts) "\n")
let print_empty_family opts base p =
let string_quest = Gwdb.insert_string base "?" in
Printf.ksprintf (oc opts) "fam ? ?.0 + #noment ? ?.0\n";
Printf.ksprintf (oc opts) "beg\n";
print_child opts base string_quest "" "" p;
Printf.ksprintf (oc opts) "end\n"
let print_family opts base gen m =
let fam = m.m_fam in
Printf.ksprintf (oc opts) "fam ";
print_parent opts base gen m.m_fath;
Printf.ksprintf (oc opts) " +";
print_date_option opts (Date.od_of_cdate (get_marriage fam));
let print_sexes s =
let c x =
match get_sex x with Male -> 'm' | Female -> 'f' | Neuter -> '?'
in
Printf.ksprintf (oc opts) " %s %c%c" s (c m.m_fath) (c m.m_moth)
in
(match get_relation fam with
| Married -> ()
| NotMarried -> Printf.ksprintf (oc opts) " #nm"
| Engaged -> Printf.ksprintf (oc opts) " #eng"
| NoSexesCheckNotMarried -> print_sexes "#nsck"
| NoSexesCheckMarried -> print_sexes "#nsckm"
| NoMention -> print_sexes "#noment"
| MarriageBann -> print_sexes "#banns"
| MarriageContract -> print_sexes "#contract"
| MarriageLicense -> print_sexes "#license"
| Pacs -> print_sexes "#pacs"
| Residence -> print_sexes "#residence");
print_if_no_empty opts base "#mp" (get_marriage_place fam);
if opts.source = None then
print_if_no_empty opts base "#ms" (get_marriage_src fam);
(match get_divorce fam with
| NotDivorced -> ()
| Separated -> Printf.ksprintf (oc opts) " #sep"
| Divorced d ->
let d = Date.od_of_cdate d in
Printf.ksprintf (oc opts) " -";
print_date_option opts d);
Printf.ksprintf (oc opts) " ";
print_parent opts base gen m.m_moth;
Printf.ksprintf (oc opts) "\n";
Array.iter
(fun ip ->
if gen.per_sel ip then (
let p = poi base ip in
Printf.ksprintf (oc opts) "wit";
(match get_sex p with
| Male -> Printf.ksprintf (oc opts) " m"
| Female -> Printf.ksprintf (oc opts) " f"
| _ -> ());
Printf.ksprintf (oc opts) ": ";
print_witness opts base gen p;
Printf.ksprintf (oc opts) "\n"))
(get_witnesses fam);
(match opts.source with
| None ->
if sou base (get_fsources fam) <> "" then
Printf.ksprintf (oc opts) "src %s\n"
(correct_string base (get_fsources fam))
| Some "" -> ()
| Some x -> Printf.ksprintf (oc opts) "src %s\n" (s_correct_string x));
let csrc =
match common_children_sources base m.m_chil with
| Some s ->
Printf.ksprintf (oc opts) "csrc %s\n" (s_correct_string s);
s
| _ -> ""
in
let cbp =
match common_children_birth_place base m.m_chil with
| Some s ->
Printf.ksprintf (oc opts) "cbp %s\n" (s_correct_string s);
s
| _ -> ""
in
print_comment_for_family opts base gen fam;
if (not !old_gw) && get_fevents fam <> [] then (
Printf.ksprintf (oc opts) "fevt\n";
List.iter (print_fevent opts base gen false) (get_fevents fam);
Printf.ksprintf (oc opts) "end fevt\n");
(match Array.length m.m_chil with
| 0 -> ()
| _ ->
let fam_surname = get_surname m.m_fath in
Printf.ksprintf (oc opts) "beg\n";
Array.iter
(fun p ->
if gen.per_sel (get_iper p) then
print_child opts base fam_surname csrc cbp p)
m.m_chil;
Printf.ksprintf (oc opts) "end\n");
Gwdb.Marker.set gen.fam_done m.m_ifam true;
let f _ =
Printf.sprintf "family \"%s.%d %s\" & \"%s.%d %s\""
(p_first_name base m.m_fath)
(get_new_occ m.m_fath) (p_surname base m.m_fath)
(p_first_name base m.m_moth)
(get_new_occ m.m_moth) (p_surname base m.m_moth)
in
let s =
let sl =
let acc =
[ get_comment fam; get_marriage_note fam; get_marriage_src fam ]
in
if opts.source = None then get_fsources fam :: acc else acc
in
let sl =
if not !old_gw then
let rec loop l accu =
match l with
| [] -> accu
| evt :: l ->
let acc =
evt.efam_note
:: (if opts.source = None then evt.efam_src :: accu else accu)
in
loop l acc
in
loop (get_fevents fam) sl
else sl
in
String.concat " " (List.map (sou base) sl)
in
ignore (add_linked_files gen f s [] : _ list)
let get_persons_with_notes m list =
let list =
let fath = m.m_fath in
match get_parents fath with Some _ -> list | None -> fath :: list
in
let list =
let moth = m.m_moth in
match get_parents moth with Some _ -> list | None -> moth :: list
in
Array.fold_right List.cons m.m_chil list
let notes_aliases bdir =
let fname = Filename.concat bdir "notes.alias" in
match try Some (Secure.open_in fname) with Sys_error _ -> None with
| Some ic ->
let rec loop list =
match try Some (input_line ic) with End_of_file -> None with
| Some s ->
let list =
try
let i = String.index s ' ' in
( String.sub s 0 i,
String.sub s (i + 1) (String.length s - i - 1) )
:: list
with Not_found -> list
in
loop list
| None ->
close_in ic;
list
in
loop []
| None -> []
let print_notes_for_person opts base gen p =
let print_witness_in_notes witnesses =
Array.iter
(fun (ip, wk) ->
let p = poi base ip in
Printf.ksprintf (oc opts) "wit";
(match get_sex p with
| Male -> Printf.ksprintf (oc opts) " m"
| Female -> Printf.ksprintf (oc opts) " f"
| _ -> ());
Printf.ksprintf (oc opts) ": ";
let sk = string_of_witness_kind wk in
(match sk with
| Some s -> Printf.ksprintf (oc opts) (s ^^ " ")
| None -> ());
print_witness opts base gen p;
Printf.ksprintf (oc opts) "\n")
witnesses
in
let epers_name_to_string evt =
match evt.epers_name with
| Epers_Birth -> "birth"
| Epers_Baptism -> "baptism"
| Epers_Death -> "death"
| Epers_Burial -> "burial"
| Epers_Cremation -> "cremation"
| _ -> ""
in
let notes = if opts.no_notes <> `nnn then sou base (get_notes p) else "" in
let surn = s_correct_string (p_surname base p) in
let fnam = s_correct_string (p_first_name base p) in
(* Si on n'est en mode old_gw, on mets tous les évènements dans les notes. *)
if (notes <> "" || put_events_in_notes base p) && surn <> "?" && fnam <> "?"
then (
Printf.ksprintf (oc opts) "\n";
Printf.ksprintf (oc opts) "notes %s %s%s\n" surn fnam
(if get_new_occ p = 0 then "" else "." ^ string_of_int (get_new_occ p));
Printf.ksprintf (oc opts) "beg\n";
if notes <> "" then Printf.ksprintf (oc opts) "%s\n" notes;
(if put_events_in_notes base p then
let rec loop pevents =
match pevents with
| [] -> ()
| evt :: events -> (
match evt.epers_name with
| Epers_Birth | Epers_Baptism | Epers_Death | Epers_Burial
| Epers_Cremation ->
let name = epers_name_to_string evt in
let notes =
if opts.no_notes <> `nnn then sou base evt.epers_note else ""
in
if notes <> "" then
Printf.ksprintf (oc opts) "%s: %s\n" name notes;
print_witness_in_notes evt.epers_witnesses;
loop events
| _ ->
print_pevent opts base gen evt;
loop events)
in
loop (get_pevents p));
Printf.ksprintf (oc opts) "end notes\n");
let f _ =
Printf.sprintf "person \"%s.%d %s\"" (p_first_name base p) (get_new_occ p)
(p_surname base p)
in
let s =
let aux g = sou base (g p) in
let sl =
if opts.no_notes <> `nnn then
[
aux get_notes;
aux get_birth_note;
aux get_baptism_note;
aux get_death_note;
aux get_burial_note;
]
else []
in
let sl =
match opts.source with
| Some "" -> sl
| Some src -> src :: sl
| None ->
aux get_birth_src :: aux get_baptism_src :: aux get_death_src
:: aux get_burial_src :: aux get_psources :: sl
in
if (not !old_gw) && opts.source = None then
List.fold_left
(fun acc e ->
let acc =
if opts.no_notes <> `nnn then sou base e.epers_note :: acc else acc
in
let acc =
if opts.source = None then sou base e.epers_src :: acc else acc
in
acc)
sl (get_pevents p)
else sl
in
let s = String.concat " " s in
ignore (add_linked_files gen f s [] : _ list)
let print_notes opts base gen ml =
let pl = List.fold_right get_persons_with_notes ml gen.notes_pl_p in
let pl =
List.fold_right
(fun p pl -> if list_memf eq_key p pl then pl else p :: pl)
pl []
in
List.iter
(fun p ->
if gen.per_sel (get_iper p) then print_notes_for_person opts base gen p)
pl
let is_isolated p =
match get_parents p with
| Some _ -> false
| None -> Array.length (get_family p) = 0
let is_definition_for_parent p =
match get_parents p with Some _ -> false | None -> true
let get_isolated_related base m list =
let concat_isolated p_relation ip list =
let p = poi base ip in
if List.mem_assq p list then list
else if is_isolated p then
match get_rparents p with
| { r_fath = Some x } :: _ when x = get_iper p_relation ->
list @ [ (p, true) ]
| { r_fath = None; r_moth = Some x } :: _ when x = get_iper p_relation ->
list @ [ (p, true) ]
| _ -> list
else list
in
let list =
if is_definition_for_parent m.m_fath then
List.fold_right (concat_isolated m.m_fath) (get_related m.m_fath) list
else list
in
let list =
if is_definition_for_parent m.m_moth then
List.fold_right (concat_isolated m.m_moth) (get_related m.m_moth) list
else list
in
Array.fold_right
(fun p list -> List.fold_right (concat_isolated p) (get_related p) list)
m.m_chil list
let get_persons_with_relations base m list =
let fath = m.m_fath in
let moth = m.m_moth in
let list =
match (get_rparents fath, get_parents fath) with
| [], _ | _, Some _ -> list
| _ -> (fath, false) :: list
in
let list =
match (get_rparents moth, get_parents moth) with
| [], _ | _, Some _ -> list
| _ -> (moth, false) :: list
in
let list =
Array.fold_right
(fun ip list ->
let p = poi base ip in
match (get_rparents p, get_parents p) with
| [], _ | _, Some _ -> list
| { r_fath = Some x } :: _, _ when x <> get_iper m.m_fath -> list
| _ -> (p, false) :: list)
(get_witnesses m.m_fam) list
in
Array.fold_right
(fun p list ->
match get_rparents p with [] -> list | _ -> (p, false) :: list)
m.m_chil list
let print_relation_parent opts base mark defined_p p =
Printf.ksprintf (oc opts) "%s %s%s"
(correct_string base (get_surname p))
(correct_string base (get_first_name p))
(if get_new_occ p = 0 then "" else "." ^ string_of_int (get_new_occ p));
if
Array.length (get_family p) = 0
&& get_parents p = None
&& not (Gwdb.Marker.get mark (get_iper p))
then (
Gwdb.Marker.set mark (get_iper p) true;
if has_infos opts base p then print_infos opts base false "" "" p
else Printf.ksprintf (oc opts) " 0";
defined_p := p :: !defined_p)
let print_relation_for_person opts base gen def_p r =
let fath =
match r.r_fath with
| Some ip ->
if gen.per_sel ip then
let p = poi base ip in
if sou base (get_first_name p) = "?" || sou base (get_surname p) = "?"
then None
else Some p
else None
| None -> None
in
let moth =
match r.r_moth with
| Some ip ->
if gen.per_sel ip then
let p = poi base ip in
if sou base (get_first_name p) = "?" || sou base (get_surname p) = "?"
then None
else Some p
else None
| None -> None
in
let err_same_sex =
match (fath, moth) with
| Some fath, Some moth -> get_sex fath = get_sex moth
| _ -> false
in
let print_err_one_relation p =
Printf.ksprintf (oc opts) "- ";
(match r.r_type with
| Adoption -> Printf.ksprintf (oc opts) "adop"
| Recognition -> Printf.ksprintf (oc opts) "reco"
| CandidateParent -> Printf.ksprintf (oc opts) "cand"
| GodParent -> Printf.ksprintf (oc opts) "godp"
| FosterParent -> Printf.ksprintf (oc opts) "fost");
if get_sex p = Male then Printf.ksprintf (oc opts) " fath"
else Printf.ksprintf (oc opts) " moth";
Printf.ksprintf (oc opts) ": ";
print_relation_parent opts base gen.mark def_p p;
Printf.ksprintf (oc opts) "\n"
in
match (fath, moth) with
| None, None -> ()
| _ ->
if err_same_sex then
match (fath, moth) with
| Some fath, Some moth ->
print_err_one_relation fath;
print_err_one_relation moth
| _ -> ()
else (
Printf.ksprintf (oc opts) "- ";
(match r.r_type with
| Adoption -> Printf.ksprintf (oc opts) "adop"
| Recognition -> Printf.ksprintf (oc opts) "reco"
| CandidateParent -> Printf.ksprintf (oc opts) "cand"
| GodParent -> Printf.ksprintf (oc opts) "godp"
| FosterParent -> Printf.ksprintf (oc opts) "fost");
(match (fath, moth) with
| Some fath, None ->
if get_sex fath = Male then Printf.ksprintf (oc opts) " fath"
else Printf.ksprintf (oc opts) " moth"
| None, Some moth ->
if get_sex moth = Female then Printf.ksprintf (oc opts) " moth"
else Printf.ksprintf (oc opts) " fath"
| _ -> ());
Printf.ksprintf (oc opts) ": ";
(match (fath, moth) with
| Some fath, None -> print_relation_parent opts base gen.mark def_p fath
| None, Some moth -> print_relation_parent opts base gen.mark def_p moth
| Some fath, Some moth ->
if get_sex fath = Male && get_sex moth = Female then (
print_relation_parent opts base gen.mark def_p fath;
Printf.ksprintf (oc opts) " + ";
print_relation_parent opts base gen.mark def_p moth)
else (
print_relation_parent opts base gen.mark def_p moth;
Printf.ksprintf (oc opts) " + ";
print_relation_parent opts base gen.mark def_p fath)
| _ -> ());
Printf.ksprintf (oc opts) "\n")
let print_relations_for_person opts base gen def_p is_definition p =
let surn = correct_string base (get_surname p) in
let fnam = correct_string base (get_first_name p) in
let exist_relation =
List.exists
(fun r ->
match (r.r_fath, r.r_moth) with
| Some ip1, Some ip2 -> gen.per_sel ip1 && gen.per_sel ip2
| Some ip1, _ -> gen.per_sel ip1
| _, Some ip2 -> gen.per_sel ip2
| _ -> false)
(get_rparents p)
in
if
surn <> "?" && fnam <> "?" && exist_relation
&& not (Gwdb.Marker.get gen.mark_rel (get_iper p))
then (
Gwdb.Marker.set gen.mark_rel (get_iper p) true;
Printf.ksprintf (oc opts) "\n";
Printf.ksprintf (oc opts) "rel %s %s%s" surn fnam
(if get_new_occ p = 0 then "" else "." ^ string_of_int (get_new_occ p));
if is_definition then (
Gwdb.Marker.set gen.mark (get_iper p) true;
def_p := p :: !def_p;
if has_infos opts base p then print_infos opts base false "" "" p
else Printf.ksprintf (oc opts) " 0";
match get_sex p with
| Male -> Printf.ksprintf (oc opts) " #h"
| Female -> Printf.ksprintf (oc opts) " #f"
| Neuter -> ());
Printf.ksprintf (oc opts) "\n";
Printf.ksprintf (oc opts) "beg\n";
List.iter (print_relation_for_person opts base gen def_p) (get_rparents p);
Printf.ksprintf (oc opts) "end\n")
let print_relations opts base gen ml =
let pl = List.fold_right (get_persons_with_relations base) ml [] in
let pl = List.fold_right (get_isolated_related base) ml pl in
let pl =
List.fold_right
(fun p pl -> if list_memf eq_key_fst p pl then pl else p :: pl)
pl []
in
let rec loop = function
| [] -> ()
| (p, if_def) :: pl ->
let def_p = ref [] in
if get_rparents p <> [] && gen.per_sel (get_iper p) then (
print_relations_for_person opts base gen def_p if_def p;
List.iter (print_notes_for_person opts base gen) !def_p;
if not !old_gw then
List.iter (print_pevents_for_person opts base gen) !def_p);
loop (pl @ List.map (fun p -> (p, false)) !def_p)
in
loop pl
let print_isolated_relations opts base gen p =
let pl = [ (p, false) ] in
let pl =
List.fold_right
(fun p pl -> if list_memf eq_key_fst p pl then pl else p :: pl)
pl []
in
let rec loop = function
| [] -> ()
| (p, if_def) :: pl ->
let def_p = ref [] in
if get_rparents p <> [] && gen.per_sel (get_iper p) then (
print_relations_for_person opts base gen def_p if_def p;
List.iter (print_notes_for_person opts base gen) !def_p);
loop (pl @ List.map (fun p -> (p, false)) !def_p)
in
loop pl
let rec merge_families ifaml1f ifaml2f =
match (ifaml1f, ifaml2f) with
| ifam1 :: ifaml1, ifam2 :: ifaml2 ->
let m1 = List.mem ifam1 ifaml2 in
let m2 = List.mem ifam2 ifaml1 in
if m1 && m2 then merge_families ifaml1 ifaml2
else if m1 then ifam2 :: merge_families ifaml1f ifaml2
else if m2 then ifam1 :: merge_families ifaml1 ifaml2f
else if ifam2 < ifam1 then ifam2 :: ifam1 :: merge_families ifaml1 ifaml2
else if ifam1 < ifam2 then ifam1 :: ifam2 :: merge_families ifaml1 ifaml2
else ifam1 :: merge_families ifaml1 ifaml2
| ifaml1, [] -> ifaml1
| [], ifaml2 -> ifaml2
(* let connected_families base fam_sel ifam cpl =
* let rec loop ifaml scanned =
* function
* | ip :: ipl ->
* let scanned = ip :: scanned in
* let ipl, ifaml =
* Array.fold_right begin fun i (acci, accf) ->
* if fam_sel i && not @@ List.mem i accf
* then
* let accf = i :: accf in
* let cpl = foi base ifam in
* let fa = get_father cpl in
* let mo = get_mother cpl in
* let acci =
* if not @@ List.mem fa acci
* && not @@ List.mem fa scanned
* then fa :: acci
* else acci
* in
* let acci =
* if not @@ List.mem mo acci
* && not @@ List.mem mo scanned
* then mo :: acci
* else acci
* in
* (acci, accf)
* else (acci, accf)
* end (get_family @@ poi base ip) (ipl, ifaml)
* in
* loop ifaml scanned ipl
* | [] -> ifaml
* in
* loop [ ifam ] [] [ get_father cpl ; get_mother cpl ]
* |> List.sort_uniq compare *)
let rec filter f = function
| x :: l -> if f x then x :: filter f l else filter f l
| [] -> []
let connected_families base fam_sel ifam cpl =
let rec loop ifaml ipl_scanned = function
| ip :: ipl ->
if List.mem ip ipl_scanned then loop ifaml ipl_scanned ipl
else
let u = poi base ip in
let ifaml1 = Array.to_list (get_family u) in
let ifaml1 = filter fam_sel ifaml1 in
let ifaml = merge_families ifaml ifaml1 in
let ipl =
List.fold_right
(fun ifam ipl ->
let cpl = foi base ifam in
get_father cpl :: get_mother cpl :: ipl)
ifaml1 ipl
in
loop ifaml (ip :: ipl_scanned) ipl
| [] -> ifaml
in
loop [ ifam ] [] [ get_father cpl ]
let read_file_contents fname =
match try Some (open_in fname) with Sys_error _ -> None with
| Some ic -> (
let len = ref 0 in
try
let rec loop () =
len := Buff.store !len (input_char ic);
loop ()
in
loop ()
with End_of_file -> Buff.get !len)
| None -> ""
type separate = ToSeparate | NotScanned | BeingScanned | Scanned
let rec find_ancestors base surn p list =
match get_parents p with
| Some ifam ->
let cpl = foi base ifam in
let fath = poi base (get_father cpl) in
let moth = poi base (get_mother cpl) in
if
(not (eq_istr (get_surname fath) surn))
&& not (eq_istr (get_surname moth) surn)
then p :: list
else
let list =
if eq_istr (get_surname fath) surn then
find_ancestors base surn fath list
else list
in
if eq_istr (get_surname moth) surn then
find_ancestors base surn moth list
else list
| None -> p :: list
let mark_branch base mark surn p =
let rec loop top p =
for i = 0 to Array.length (get_family p) - 1 do
let ifam = (get_family p).(i) in
if Gwdb.Marker.get mark ifam = NotScanned then
let ifaml =
connected_families base (fun _ -> true) ifam (foi base ifam)
in
let children =
List.fold_left
(fun list ifam ->
let desc = foi base ifam in
Array.fold_left
(fun list ip -> poi base ip :: list)
list (get_children desc))
[] ifaml
in
if top || List.exists (fun p -> eq_istr (get_surname p) surn) children
then (
List.iter (fun ifam -> Gwdb.Marker.set mark ifam ToSeparate) ifaml;
List.iter (loop false) children)
done
in
loop true p
let mark_someone base mark s =
match Gutil.person_ht_find_all base s with
| [ ip ] ->
let p = poi base ip in
let plist = find_ancestors base (get_surname p) p [] in
List.iter (mark_branch base mark (get_surname p)) plist
| [] ->
Printf.eprintf "Error: \"%s\" is not found\n" s;
flush stderr;
exit 2
| _ ->
Printf.eprintf "Error: several answers for \"%s\"\n" s;
flush stderr;
exit 2
let scan_connex_component base test_action len ifam =
let rec loop len ifam =
let fam = foi base ifam in
let fath = poi base (get_father fam) in
let moth = poi base (get_mother fam) in
let len =
Array.fold_left
(fun len ifam1 ->
if ifam1 = ifam then len else test_action loop len ifam1)
len (get_family fath)
in
let len =
Array.fold_left
(fun len ifam1 ->
if ifam1 = ifam then len else test_action loop len ifam1)
len (get_family moth)
in
let len =
match get_parents fath with
| Some ifam -> test_action loop len ifam
| _ -> len
in
let len =
match get_parents moth with
| Some ifam -> test_action loop len ifam
| _ -> len
in
let children = get_children fam in
Array.fold_left
(fun len ip ->
Array.fold_left (test_action loop) len (get_family (poi base ip)))
len children
in
loop len ifam
let mark_one_connex_component base mark ifam =
let origin_file = sou base (get_origin_file (foi base ifam)) in
let test_action loop len ifam =
if
Gwdb.Marker.get mark ifam = NotScanned
&& sou base (get_origin_file (foi base ifam)) = origin_file
then (
Gwdb.Marker.set mark ifam BeingScanned;
loop (len + 1) ifam)
else len
in
let _ = test_action (fun _ _ -> 1) 0 ifam in
let len = 1 + scan_connex_component base test_action 0 ifam in
let set_mark x =
let test_action loop () ifam =
if Gwdb.Marker.get mark ifam = BeingScanned then (
Gwdb.Marker.set mark ifam x;
loop () ifam)
in
test_action (fun _ _ -> ()) () ifam;
scan_connex_component base test_action () ifam
in
if len <= !sep_limit && (!only_file = "" || !only_file = origin_file) then
set_mark ToSeparate
else (
Printf.eprintf "%s: group of size %d not included\n" origin_file len;
let cpl = foi base ifam in
Printf.eprintf " %s + %s\n"
(Gutil.designation base (poi base (get_father cpl)))
(Gutil.designation base (poi base (get_mother cpl)));
flush stderr;
set_mark Scanned)
let mark_connex_components base mark ifam =
let test_action _loop _len ifam =
if Gwdb.Marker.get mark ifam = NotScanned then
mark_one_connex_component base mark ifam
in
scan_connex_component base test_action () ifam
let add_small_connex_components base mark =
Gwdb.Collection.iter
(fun i ->
if Gwdb.Marker.get mark i = ToSeparate then
mark_connex_components base mark i)
(Gwdb.ifams base)
let separate base =
match List.rev !separate_list with
| [] -> fun _ -> false
| list ->
let ifams = Gwdb.ifams base in
let mark = Gwdb.ifam_marker (Gwdb.ifams base) NotScanned in
List.iter (mark_someone base mark) list;
add_small_connex_components base mark;
let len =
Gwdb.Collection.fold
(fun acc i ->
if Gwdb.Marker.get mark i = ToSeparate then acc + 1 else acc)
0 ifams
in
Printf.eprintf "*** extracted %d families\n" len;
flush stderr;
fun ifam -> Gwdb.Marker.get mark ifam = ToSeparate
let rs_printf opts s =
let rec loop bol i =
if i = String.length s then ()
else if s.[i] = '\n' then (
Printf.ksprintf (oc opts) "\n";
loop true (i + 1))
else (
if bol then Printf.ksprintf (oc opts) " ";
Printf.ksprintf (oc opts) "%c" s.[i];
loop false (i + 1))
in
loop true 0
let gwu opts isolated base in_dir out_dir src_oc_ht (per_sel, fam_sel) =
if out_dir <> "" && not (Sys.file_exists out_dir) then Mutil.mkdir_p out_dir;
let to_separate = separate base in
let out_oc_first = ref true in
let _ofile, oc, close = opts.oc in
let origin_file fname =
if fname = "" || out_dir = "" then (oc, out_oc_first, close)
else
let fname = Filename.basename fname in
try Hashtbl.find src_oc_ht fname
with Not_found ->
let oc = open_out (Filename.concat out_dir fname) in
let ((out, _, _) as x) =
(output_string oc, ref true, fun () -> close_out oc)
in
if not !raw_output then out "encoding: utf-8\n";
if !old_gw then out "\n" else out "gwplus\n\n";
Hashtbl.add src_oc_ht fname x;
x
in
let gen =
let mark = Gwdb.iper_marker (Gwdb.ipers base) false in
let mark_rel = Gwdb.iper_marker (Gwdb.ipers base) false in
let fam_done = Gwdb.ifam_marker (Gwdb.ifams base) false in
{
mark;
mark_rel;
per_sel;
fam_sel;
fam_done;
notes_pl_p = [];
ext_files = [];
notes_alias = notes_aliases in_dir;
pevents_pl_p = [];
}
in
let nb_fam = nb_of_families base in
if !Mutil.verbose then ProgrBar.start ();
Gwdb.Collection.iteri
(fun i ifam ->
if !Mutil.verbose then ProgrBar.run i nb_fam;
if not (Gwdb.Marker.get gen.fam_done ifam) then
let fam = foi base ifam in
let ifaml = connected_families base gen.fam_sel ifam fam in
let oc, first, _close =
if to_separate ifam then (oc, out_oc_first, close)
else origin_file (sou base (get_origin_file fam))
in
let f, _ooc, c = opts.oc in
let opts = { opts with oc = (f, oc, c) } in
let ml =
List.fold_right
(fun ifam ml ->
let fam = foi base ifam in
let m =
{
m_ifam = ifam;
m_fam = fam;
m_fath = poi base (get_father fam);
m_moth = poi base (get_mother fam);
m_chil = Array.map (fun ip -> poi base ip) (get_children fam);
}
in
if empty_family base m then (
Gwdb.Marker.set gen.fam_done m.m_ifam true;
ml)
else m :: ml)
ifaml []
in
if ml <> [] then (
gen.notes_pl_p <- [];
gen.pevents_pl_p <- [];
if not !first then Printf.ksprintf oc "\n";
first := false;
List.iter (print_family opts base gen) ml;
print_notes opts base gen ml;
print_relations opts base gen ml;
if not !old_gw then print_pevents opts base gen ml))
(Gwdb.ifams ~select:gen.fam_sel base);
(* Ajout des personnes isolée à l'export. On leur ajoute des *)
(* parents pour pouvoir utiliser les autres fonctions normales. *)
(* Export que si c'est toute la base. *)
if isolated && opts.asc = None && opts.desc = None && opts.ascdesc = None then
Gwdb.Collection.iter
(fun i ->
if
(not @@ Gwdb.Marker.get gen.mark i)
&& (not @@ Gwdb.Marker.get gen.mark_rel i)
&& per_sel i
then
let p = poi base i in
match get_parents p with
| Some _ -> ()
| None ->
if
bogus_person base p
&& not
(get_birth p <> Date.cdate_None
|| get_baptism p <> Date.cdate_None
|| get_first_names_aliases p <> []
|| get_surnames_aliases p <> []
|| sou base (get_public_name p) <> ""
|| get_qualifiers p <> []
|| get_aliases p <> []
|| get_titles p <> []
|| sou base (get_occupation p) <> ""
|| sou base (get_birth_place p) <> ""
|| sou base (get_birth_src p) <> ""
|| sou base (get_baptism_place p) <> ""
|| sou base (get_baptism_src p) <> ""
|| sou base (get_death_place p) <> ""
|| sou base (get_death_src p) <> ""
|| sou base (get_burial_place p) <> ""
|| sou base (get_burial_src p) <> ""
|| sou base (get_notes p) <> ""
|| sou base (get_psources p) <> ""
|| get_rparents p <> []
|| get_related p <> [])
then ()
else
let oc, _first, _ = origin_file (base_notes_origin_file base) in
let f, _ooc, c = opts.oc in
let opts = { opts with oc = (f, oc, c) } in
Printf.ksprintf oc "\n";
print_empty_family opts base p;
print_notes_for_person opts base gen p;
Gwdb.Marker.set gen.mark i true;
print_isolated_relations opts base gen p)
(Gwdb.ipers base);
if !Mutil.verbose then ProgrBar.finish ();
if opts.no_notes = `none then (
let s = base_notes_read base "" in
let oc, first, _ = origin_file (base_notes_origin_file base) in
let f, _ooc, c = opts.oc in
let opts = { opts with oc = (f, oc, c) } in
if s <> "" then (
if not !first then Printf.ksprintf oc "\n";
first := false;
Printf.ksprintf oc "notes-db\n";
rs_printf opts s;
Printf.ksprintf oc "\nend notes-db\n";
ignore (add_linked_files gen (fun _ -> "database notes") s [] : _ list));
(try
let files =
Sys.readdir (Filename.concat in_dir (base_wiznotes_dir base))
in
Array.sort compare files;
for i = 0 to Array.length files - 1 do
let file = files.(i) in
if Filename.check_suffix file ".txt" then
let wfile =
List.fold_left Filename.concat in_dir
[ base_wiznotes_dir base; file ]
in
let s = read_file_contents wfile in
ignore
(add_linked_files gen (fun _ -> "wizard \"" ^ file ^ "\"") s []
: _ list)
done
with Sys_error _ -> ());
let rec loop = function
| [] -> ()
| (f, _) :: files ->
let fn =
match NotesLinks.check_file_name f with
| Some (dl, f) -> List.fold_right Filename.concat dl f
| None -> "bad"
in
let s = base_notes_read base fn in
let files =
add_linked_files gen
(fun _ -> Printf.sprintf "extended page \"%s\"" f)
s files
in
loop files
in
loop gen.ext_files;
List.iter
(fun (f, r) ->
let fn =
match NotesLinks.check_file_name f with
| Some (dl, f) -> List.fold_right Filename.concat dl f
| None -> "bad"
in
let s = String.trim (base_notes_read base fn) in
if s <> "" then (
if not !first then Printf.ksprintf oc "\n";
first := false;
Printf.ksprintf oc "# extended page \"%s\" used by:\n" f;
List.iter
(fun f -> Printf.ksprintf oc "# - %s\n" f)
(List.sort compare !r);
Printf.ksprintf oc "page-ext %s\n" f;
rs_printf opts s;
Printf.ksprintf oc "\nend page-ext\n"))
(List.sort compare gen.ext_files);
let close () =
flush_all ();
close ();
Hashtbl.iter (fun _ (_, _, close) -> close ()) src_oc_ht
in
try
let files =
Sys.readdir (Filename.concat in_dir (base_wiznotes_dir base))
in
Array.sort compare files;
for i = 0 to Array.length files - 1 do
let file = files.(i) in
if Filename.check_suffix file ".txt" then (
let wizid = Filename.chop_suffix file ".txt" in
let wfile =
List.fold_left Filename.concat in_dir
[ base_wiznotes_dir base; file ]
in
let s = String.trim (read_file_contents wfile) in
Printf.ksprintf oc "\nwizard-note %s\n" wizid;
rs_printf opts s;
Printf.ksprintf oc "\nend wizard-note\n")
done;
close ()
with Sys_error _ -> close ())