1(* camlp5r ./pa_html.cmo *) 2(* $Id: perso.ml,v 5.82 2007-09-12 09:58:44 ddr Exp $ *) 3(* Copyright (c) 1998-2007 INRIA *) 4 5open Config; 6open Def; 7open Gutil; 8open Gwdb; 9open Mutil; 10open TemplAst; 11open Util; 12 13value max_im_wid = 240; 14value max_im_hei = 240; 15value round_2_dec x = floor (x *. 100.0 +. 0.5) /. 100.0; 16 17value has_children base u = 18 List.exists 19 (fun ifam -> 20 let des = foi base ifam in 21 Array.length (get_children des) > 0) 22 (Array.to_list (get_family u)) 23; 24 25value string_of_marriage_text conf base fam = 26 let marriage = Adef.od_of_codate (get_marriage fam) in 27 let marriage_place = sou base (get_marriage_place fam) in 28 let s = 29 match marriage with 30 [ Some d -> " " ^ Date.string_of_ondate conf d 31 | _ -> "" ] 32 in 33 match marriage_place with 34 [ "" -> s 35 | _ -> s ^ ", " ^ string_with_macros conf [] marriage_place ^ "," ] 36; 37 38value string_of_title conf base and_txt p (nth, name, title, places, dates) = 39 let href = 40 "m=TT;sm=S;t=" ^ code_varenv (sou base title) ^ ";p=" ^ 41 code_varenv (sou base (List.hd places)) 42 in 43 let (tit, est) = (sou base title, sou base (List.hd places)) in 44 let s = tit ^ " " ^ est in 45 let b = Buffer.create 50 in 46 do { 47 Buffer.add_string b (geneweb_link conf href s); 48 let rec loop places = 49 do { 50 match places with 51 [ [] -> () 52 | [_] -> Printf.bprintf b "\n%s " and_txt 53 | _ -> Buffer.add_string b ",\n" ]; 54 match places with 55 [ [place :: places] -> 56 let href = 57 "m=TT;sm=S;t=" ^ code_varenv (sou base title) ^ ";p=" ^ 58 code_varenv (sou base place) 59 in 60 let est = sou base place in 61 do { 62 Buffer.add_string b (geneweb_link conf href est); 63 loop places 64 } 65 | _ -> () ] 66 } 67 in 68 loop (List.tl places); 69 let paren = 70 match (nth, dates, name) with 71 [ (n, _, _) when n > 0 -> True 72 | (_, _, Tname _) -> True 73 | (_, [(Some _, _) :: _], _) -> authorized_age conf base p 74 | _ -> False ] 75 in 76 if paren then Buffer.add_string b "\n(" else (); 77 let first = 78 if nth > 0 then do { 79 Buffer.add_string b 80 (if nth >= 100 then string_of_int nth 81 else transl_nth conf "nth" nth); 82 False 83 } 84 else True 85 in 86 let first = 87 match name with 88 [ Tname n -> 89 do { 90 if not first then Buffer.add_string b " ," else (); 91 Buffer.add_string b (sou base n); 92 False 93 } 94 | _ -> first ] 95 in 96 if authorized_age conf base p && dates <> [(None, None)] then 97 let _ = 98 List.fold_left 99 (fun first (date_start, date_end) -> 100 do { 101 if not first then Buffer.add_string b ",\n" else (); 102 match date_start with 103 [ Some d -> Buffer.add_string b (Date.string_of_date conf d) 104 | None -> () ]; 105 match date_end with 106 [ Some (Dgreg d _) -> 107 if d.month <> 0 then Buffer.add_string b " - " 108 else Buffer.add_string b "-" 109 | _ -> () ]; 110 match date_end with 111 [ Some d -> Buffer.add_string b (Date.string_of_date conf d) 112 | None -> () ]; 113 False 114 }) 115 first dates 116 in 117 () 118 else (); 119 if paren then Buffer.add_string b ")" else (); 120 Buffer.contents b 121 } 122; 123 124value name_equiv n1 n2 = 125 Futil.eq_title_names eq_istr n1 n2 || n1 = Tmain && n2 = Tnone || 126 n1 = Tnone && n2 = Tmain 127; 128 129value nobility_titles_list conf base p = 130 let titles = 131 List.fold_right 132 (fun t l -> 133 let t_date_start = Adef.od_of_codate t.t_date_start in 134 let t_date_end = Adef.od_of_codate t.t_date_end in 135 match l with 136 [ [(nth, name, title, place, dates) :: rl] 137 when 138 not conf.is_rtl && nth = t.t_nth && name_equiv name t.t_name && 139 eq_istr title t.t_ident && eq_istr place t.t_place -> 140 [(nth, name, title, place, 141 [(t_date_start, t_date_end) :: dates]) :: 142 rl] 143 | _ -> 144 [(t.t_nth, t.t_name, t.t_ident, t.t_place, 145 [(t_date_start, t_date_end)]) :: 146 l] ]) 147 (Util.nobtit conf base p) [] 148 in 149 List.fold_right 150 (fun (t_nth, t_name, t_ident, t_place, t_dates) l -> 151 match l with 152 [ [(nth, name, title, places, dates) :: rl] 153 when 154 not conf.is_rtl && nth = t_nth && name_equiv name t_name && 155 eq_istr title t_ident && dates = t_dates -> 156 [(nth, name, title, [t_place :: places], dates) :: rl] 157 | _ -> [(t_nth, t_name, t_ident, [t_place], t_dates) :: l] ]) 158 titles [] 159; 160 161(* obsolete; should be removed one day *) 162 163value string_of_titles conf base cap and_txt p = 164 let titles = nobility_titles_list conf base p in 165 List.fold_left 166 (fun s t -> 167 s ^ (if s = "" then "" else ",") ^ "\n" ^ 168 string_of_title conf base and_txt p t) 169 "" titles 170; 171 172value string_of_num sep num = 173 let len = ref 0 in 174 do { 175 Num.print (fun x -> len.val := Buff.mstore len.val x) sep num; 176 Buff.get len.val 177 } 178; 179 180value print_base_loop conf base p = 181 do { 182 Wserver.wprint 183 (fcapitale 184 (ftransl conf "loop in database: %s is his/her own ancestor")) 185 (Util.update_family_loop conf base p (designation base p)); 186 Wserver.wprint ".\n"; 187 Hutil.trailer conf; 188 exit 2 189 } 190; 191 192(* This is the old version, the new one has few optimisations *) 193(* Version matching the Sosa number of the "ancestor" pages *) 194(* 195value find_sosa_aux conf base a p = 196 let tstab = 197 try Util.create_topological_sort conf base with 198 [ Consang.TopologicalSortError p -> print_base_loop conf base p ] 199 in 200 let mark = Array.make (nb_of_persons base) False in 201 let rec gene_find = 202 fun 203 [ [] -> Left [] 204 | [(z, ip) :: zil] -> 205 if ip = get_key_index a then Right z 206 else if mark.(Adef.int_of_iper ip) then gene_find zil 207 else do { 208 mark.(Adef.int_of_iper ip) := True; 209 if tstab.(Adef.int_of_iper (get_key_index a)) <= 210 tstab.(Adef.int_of_iper ip) then 211 gene_find zil 212 else 213 let asc = pget conf base ip in 214 match get_parents asc with 215 [ Some ifam -> 216 let cpl = foi base ifam in 217 let z = Num.twice z in 218 match gene_find zil with 219 [ Left zil -> 220 Left 221 [(z, get_father cpl); (Num.inc z 1, (get_mother cpl)) :: 222 zil] 223 | Right z -> Right z ] 224 | None -> gene_find zil ] 225 } ] 226 in 227 let rec find zil = 228 match gene_find zil with 229 [ Left [] -> None 230 | Left zil -> find zil 231 | Right z -> Some (z, p) ] 232 in 233 find [(Num.one, get_key_index p)] 234; 235(* Male version 236value find_sosa_aux conf base a p = 237 let mark = Array.make base.data.persons.len False in 238 let rec find z ip = 239 if ip = a.key_index then Some z 240 else if mark.(Adef.int_of_iper ip) then None 241 else do { 242 mark.(Adef.int_of_iper ip) := True; 243 let asc = aget conf base ip in 244 match asc.parents with 245 [ Some ifam -> 246 let cpl = coi base ifam in 247 let z = Num.twice z in 248 match find z (father cpl) with 249 [ Some z -> Some z 250 | None -> find (Num.inc z 1) (mother cpl) ] 251 | None -> None ] 252 } 253 in 254 find Num.one (get_key_index p) 255; 256*) 257 258value find_sosa conf base a sosa_ref_l = 259 match Lazy.force sosa_ref_l with 260 [ Some p -> 261 if get_key_index a = get_key_index p then Some (Num.one, p) 262 else 263 let u = pget conf base (get_key_index a) in 264 if has_children base u then find_sosa_aux conf base a p else None 265 | None -> None ] 266; 267*) 268 269(* Optimisation de find_sosa_aux : *) 270(* - ajout d'un cache pour conserver les descendants du sosa que l'on calcul *) 271(* - on sauvegarde la dernière génération où l'on a arrêté le calcul pour *) 272(* ne pas reprendre le calcul depuis la racine *) 273 274(* Type pour ne pas créer à chaque fois un tableau tstab et mark *) 275type sosa_t = 276 { tstab : array int; 277 mark : array bool; 278 last_zil : mutable list (Def.iper * Num.t); 279 sosa_ht : Hashtbl.t Def.iper (option (Num.t * Gwdb.person)) 280 } 281; 282 283value init_sosa_t conf base sosa_ref = 284 let tstab = 285 try Util.create_topological_sort conf base with 286 [ Consang.TopologicalSortError p -> 287 (* Avec la nouvelle implementation du calcul de sosa, si à *) 288 (* l'init il y a une boucle, alors on a pas encore interprété *) 289 (* le template, donc on n'a pas de header. *) 290 (* Il faut trouver aussi un algo de suppression de boucle parce *) 291 (* que si la boucle n'est pas à une génération d'écart, alors on *) 292 (* boucle sur l'interprétation du template. *) 293 do { 294 let title _ = Wserver.wprint "%s" (capitale (transl conf "error")) in 295 Hutil.rheader conf title; 296 print_base_loop conf base p 297 } ] 298 in 299 let mark = Array.make (nb_of_persons base) False in 300 let last_zil = [(get_key_index sosa_ref, Num.one)] in 301 let sosa_ht = Hashtbl.create 5003 in 302 let () = 303 Hashtbl.add sosa_ht (get_key_index sosa_ref) (Some (Num.one, sosa_ref)) 304 in 305 let t_sosa = 306 { tstab = tstab; 307 mark = mark; 308 last_zil = last_zil; 309 sosa_ht = sosa_ht 310 } 311 in 312 t_sosa 313; 314 315value find_sosa_aux conf base a p t_sosa = 316 let cache = ref [] in 317 let has_ignore = ref False in 318 let ht_add ht k v new_sosa = 319 match try Hashtbl.find ht k with [ Not_found -> v ] with 320 [ Some (z, _) -> 321 if not (Num.gt new_sosa z) then Hashtbl.replace ht k v 322 else () 323 | _ -> () ] 324 in 325 let rec gene_find = 326 fun 327 [ [] -> Left [] 328 | [(ip, z) :: zil] -> 329 let _ = cache.val := [(ip, z) :: cache.val] in 330 if ip = get_key_index a then Right z 331 else if t_sosa.mark.(Adef.int_of_iper ip) then gene_find zil 332 else do { 333 t_sosa.mark.(Adef.int_of_iper ip) := True; 334 if t_sosa.tstab.(Adef.int_of_iper (get_key_index a)) <= 335 t_sosa.tstab.(Adef.int_of_iper ip) then 336 let _ = has_ignore.val := True in 337 gene_find zil 338 else 339 let asc = pget conf base ip in 340 match get_parents asc with 341 [ Some ifam -> 342 let cpl = foi base ifam in 343 let z = Num.twice z in 344 match gene_find zil with 345 [ Left zil -> 346 Left 347 [(get_father cpl, z); (get_mother cpl, Num.inc z 1) :: 348 zil] 349 | Right z -> Right z ] 350 | None -> gene_find zil ] 351 } ] 352 in 353 let rec find zil = 354 match 355 (* Dans le cas ou le fichier tstab n'est plus à jour, on supprime *) 356 (* le fichier pour qu'il se régénère la prochaine fois. *) 357 try gene_find zil with 358 [ Invalid_argument "index out of bounds" -> 359 do { 360 Update.delete_topological_sort conf base; 361 Left [] 362 } ] 363 with 364 [ Left [] -> 365 let _ = 366 List.iter 367 (fun (ip, _) -> Array.set t_sosa.mark (Adef.int_of_iper ip) False) 368 cache.val 369 in 370 None 371 | Left zil -> 372 let _ = 373 if has_ignore.val then () 374 else do { 375 List.iter 376 (fun (ip, z) -> ht_add t_sosa.sosa_ht ip (Some (z, p)) z) 377 zil; 378 t_sosa.last_zil := zil } 379 in 380 find zil 381 | Right z -> 382 let _ = 383 List.iter 384 (fun (ip, _) -> Array.set t_sosa.mark (Adef.int_of_iper ip) False) 385 cache.val 386 in 387 Some (z, p) ] 388 in 389 find t_sosa.last_zil 390; 391 392value find_sosa conf base a sosa_ref_l t_sosa = 393 match Lazy.force sosa_ref_l with 394 [ Some p -> 395 if get_key_index a = get_key_index p then Some (Num.one, p) 396 else 397 let u = pget conf base (get_key_index a) in 398 if has_children base u then 399 try Hashtbl.find t_sosa.sosa_ht (get_key_index a) with 400 [ Not_found -> find_sosa_aux conf base a p t_sosa ] 401 else None 402 | None -> None ] 403; 404 405 406(* [Type]: (Def.iper, Num.t) Hashtbl.t *) 407value sosa_ht = Hashtbl.create 5003; 408 409 410(* ************************************************************************ *) 411(* [Fonc] build_sosa_ht : config -> base -> unit *) 412(** [Description] : Construit à partir du sosa de référence de la base, la 413 liste de tous ces ancêtres directs et la stocke dans une hashtbl. La 414 clé de la table est l'iper de la personne et on lui associe son numéro 415 de sosa. Les sosa multiples ne sont représentés qu'une seule fois par 416 leur plus petit numéro sosa. 417 [Args] : 418 - conf : configuration de la base 419 - base : base de donnée 420 [Retour] : 421 - unit 422 [Rem] : Exporté en clair hors de ce module. *) 423(* ************************************************************************ *) 424value build_sosa_ht conf base = 425 let () = load_ascends_array base in 426 let () = load_couples_array base in 427 match Util.find_sosa_ref conf base with 428 [ Some sosa_ref -> 429 let nb_persons = nb_of_persons base in 430 let mark = Array.make nb_persons False in 431 (* Tableau qui va socker au fur et à mesure les ancêtres du sosa_ref. *) 432 (* Attention, on créé un tableau de la longueur de la base + 1 car on *) 433 (* commence à l'indice 1 ! *) 434 let sosa_accu = 435 Array.make (nb_persons + 1) (Num.zero, Adef.iper_of_int 0) 436 in 437 let () = Array.set sosa_accu 1 (Num.one, get_key_index sosa_ref) in 438 let rec loop i len = 439 if i > nb_persons then () 440 else 441 let (sosa_num, ip) = Array.get sosa_accu i in 442 (* Si la personne courante n'a pas de numéro de sosa, alors il n'y *) 443 (* a plus d'ancêtres car ils ont été ajoutés par ordre croissant. *) 444 if Num.eq sosa_num Num.zero then () 445 else do { 446 Hashtbl.add sosa_ht ip sosa_num; 447 let asc = pget conf base ip in 448 (* Ajoute les nouveaux ascendants au tableau des ancêtres. *) 449 match get_parents asc with 450 [ Some ifam -> 451 let cpl = foi base ifam in 452 let z = Num.twice sosa_num in 453 let len = 454 if not mark.(Adef.int_of_iper (get_father cpl)) then do { 455 Array.set sosa_accu (len + 1) (z, get_father cpl) ; 456 mark.(Adef.int_of_iper (get_father cpl)) := True ; 457 len + 1 } 458 else len 459 in 460 let len = 461 if not mark.(Adef.int_of_iper (get_mother cpl)) then do { 462 Array.set sosa_accu (len + 1) (Num.inc z 1, get_mother cpl); 463 mark.(Adef.int_of_iper (get_mother cpl)) := True ; 464 len + 1 } 465 else len 466 in 467 loop (i + 1) len 468 | None -> loop (i + 1) len ] 469 } 470 in 471 loop 1 1 472 | None -> () ] 473; 474 475 476(* ******************************************************************** *) 477(* [Fonc] get_sosa_person : config -> base -> person -> Num.t *) 478(** [Description] : Recherche si la personne passée en argument a un 479 numéro de sosa. 480 [Args] : 481 - conf : configuration de la base 482 - base : base de donnée 483 - p : personne dont on cherche si elle a un numéro sosa 484 [Retour] : 485 - Num.t : retourne Num.zero si la personne n'a pas de numéro de 486 sosa, ou retourne son numéro de sosa sinon 487 [Rem] : Exporté en clair hors de ce module. *) 488(* ******************************************************************** *) 489value get_sosa_person conf base p = 490 try Hashtbl.find sosa_ht (get_key_index p) with 491 [ Not_found -> Num.zero ] 492; 493 494 495(* ******************************************************************** *) 496(* [Fonc] get_single_sosa : config -> base -> person -> Num.t *) 497(** [Description] : Recherche si la personne passée en argument a un 498 numéro de sosa. 499 [Args] : 500 - conf : configuration de la base 501 - base : base de donnée 502 - p : personne dont on cherche si elle a un numéro sosa 503 [Retour] : 504 - Num.t : retourne Num.zero si la personne n'a pas de numéro de 505 sosa, ou retourne son numéro de sosa sinon 506 [Rem] : Exporté en clair hors de ce module. *) 507(* ******************************************************************** *) 508value get_single_sosa conf base p = 509 let sosa_ref = Util.find_sosa_ref conf base in 510 match sosa_ref with 511 [ Some p_sosa -> 512 let sosa_ref_l = 513 let sosa_ref () = sosa_ref in 514 Lazy.from_fun sosa_ref 515 in 516 let t_sosa = init_sosa_t conf base p_sosa in 517 match find_sosa conf base p sosa_ref_l t_sosa with 518 [ Some (z, p) -> z 519 | None -> Num.zero ] 520 | None -> Num.zero ] 521; 522 523 524(* ************************************************************************ *) 525(* [Fonc] print_sosa : config -> base -> person -> bool -> unit *) 526(** [Description] : Affiche le picto sosa ainsi que le lien de calcul de 527 relation entre la personne et le sosa 1 (si l'option cancel_link 528 n'est pas activée). 529 [Args] : 530 - conf : configuration de la base 531 - base : base de donnée 532 - p : la personne que l'on veut afficher 533 - link : ce booléen permet d'afficher ou non le lien sur le picto 534 sosa. Il n'est pas nécessaire de mettre le lien si on a 535 déjà affiché cette personne. 536 [Retour] : 537 - unit 538 [Rem] : Exporté en clair hors de ce module. *) 539(* ************************************************************************ *) 540value print_sosa conf base p link = 541 let sosa_num = get_sosa_person conf base p in 542 if Num.gt sosa_num Num.zero then 543 match Util.find_sosa_ref conf base with 544 [ Some ref -> 545 do { 546 if conf.cancel_links || not link then () 547 else 548 let sosa_link = 549 let i1 = string_of_int (Adef.int_of_iper (get_key_index p)) in 550 let i2 = string_of_int (Adef.int_of_iper (get_key_index ref)) in 551 let b2 = Num.to_string sosa_num in 552 "m=RL;i1=" ^ i1 ^ ";i2=" ^ i2 ^ ";b1=1;b2=" ^ b2 553 in 554 Wserver.wprint "<a href=\"%s%s\" style=\"text-decoration:none\">" 555 (commd conf) sosa_link; 556 let title = 557 if (is_hide_names conf ref) && not (fast_auth_age conf ref) then "" 558 else 559 let direct_ancestor = 560 Name.strip_c (p_first_name base ref) '"' ^ " " 561 ^ Name.strip_c (p_surname base ref) '"' 562 in 563 Printf.sprintf 564 (fcapitale 565 (ftransl conf "direct ancestor of %s")) direct_ancestor ^ 566 Printf.sprintf ", Sosa: %s" 567 (string_of_num (transl conf "(thousand separator)") sosa_num) 568 in 569 Wserver.wprint "<img src=\"%s/sosa.png\" alt=\"sosa\" title=\"%s\"/>" 570 (image_prefix conf) title; 571 if conf.cancel_links || not link then () 572 else Wserver.wprint "</a> "; 573 } 574 | None -> () ] 575 else () 576; 577 578 579value max_ancestor_level conf base ip max_lev = 580 let x = ref 0 in 581 let mark = Array.make (nb_of_persons base) False in 582 let rec loop level ip = 583 if mark.(Adef.int_of_iper ip) then () 584 else do { 585 mark.(Adef.int_of_iper ip) := True; 586 x.val := max x.val level; 587 if x.val = max_lev then () 588 else 589 match get_parents (pget conf base ip) with 590 [ Some ifam -> 591 let cpl = foi base ifam in 592 do { 593 loop (succ level) (get_father cpl); 594 loop (succ level) (get_mother cpl) 595 } 596 | _ -> () ] 597 } 598 in 599 do { loop 0 ip; x.val } 600; 601 602value default_max_cousin_lev = 5; 603 604value max_cousin_level conf base p = 605 let max_lev = 606 try int_of_string (List.assoc "max_cousins_level" conf.base_env) with 607 [ Not_found | Failure _ -> default_max_cousin_lev ] 608 in 609 max_ancestor_level conf base (get_key_index p) max_lev + 1 610; 611 612value limit_anc_by_tree conf = 613 match p_getint conf.base_env "max_anc_tree" with 614 [ Some x -> max 1 x 615 | None -> 7 ] 616; 617 618value limit_desc conf = 619 match p_getint conf.base_env "max_desc_level" with 620 [ Some x -> max 1 x 621 | None -> 12 ] 622; 623 624value infinite = 10000; 625 626value make_desc_level_table conf base max_level p = do { 627 let line = 628 match p_getenv conf.env "t" with 629 [ Some "M" -> Male 630 | Some "F" -> Female 631 | Some _ | None -> Neuter ] 632 in 633 (* the table 'levt' may be not necessary, since I added 'flevt'; kept 634 because '%max_desc_level;' is still used... *) 635 let levt = Array.make (nb_of_persons base) infinite in 636 let flevt = Array.make (nb_of_families base) infinite in 637 let get = pget conf base in 638 let ini_ip = get_key_index p in 639 let rec fill lev = 640 fun 641 [ [] -> () 642 | ipl -> 643 let new_ipl = 644 List.fold_left 645 (fun ipl ip -> 646 if levt.(Adef.int_of_iper ip) <= lev then ipl 647 else if lev <= max_level then do { 648 levt.(Adef.int_of_iper ip) := lev; 649 let down = 650 if ip = ini_ip then True 651 else 652 match line with 653 [ Male -> get_sex (pget conf base ip) <> Female 654 | Female -> get_sex (pget conf base ip) <> Male 655 | Neuter -> True ] 656 in 657 if down then 658 Array.fold_left 659 (fun ipl ifam -> do { 660 if flevt.(Adef.int_of_ifam ifam) <= lev then () 661 else flevt.(Adef.int_of_ifam ifam) := lev; 662 let ipa = get_children (foi base ifam) in 663 Array.fold_left (fun ipl ip -> [ip :: ipl]) ipl ipa 664 }) 665 ipl (get_family (get ip)) 666 else ipl 667 } 668 else ipl) 669 [] ipl 670 in 671 fill (succ lev) new_ipl ] 672 in 673 fill 0 [ini_ip]; 674 (levt, flevt) 675}; 676 677value desc_level_max conf base desc_level_table_l = 678 let (levt, _) = Lazy.force desc_level_table_l in 679 let x = ref 0 in 680 do { 681 for i = 0 to Array.length levt - 1 do { 682 let lev = levt.(i) in 683 if lev != infinite && x.val < lev then x.val := lev else () 684 }; 685 x.val 686 } 687; 688 689value max_descendant_level conf base desc_level_table_l = 690(* 691 min (limit_desc conf) 692*) 693 (desc_level_max conf base desc_level_table_l) 694; 695 696(* ancestors by list *) 697 698type generation_person = 699 [ GP_person of Num.t and iper and option ifam 700 | GP_same of Num.t and Num.t and iper 701 | GP_interv of option (Num.t * Num.t * option (Num.t * Num.t)) 702 | GP_missing of Num.t and iper ] 703; 704 705value next_generation conf base mark gpl = 706 let gpl = 707 List.fold_right 708 (fun gp gpl -> 709 match gp with 710 [ GP_person n ip _ -> 711 let n_fath = Num.twice n in 712 let n_moth = Num.inc n_fath 1 in 713 let a = pget conf base ip in 714 match get_parents a with 715 [ Some ifam -> 716 let cpl = foi base ifam in 717 [GP_person n_fath (get_father cpl) (Some ifam); 718 GP_person n_moth (get_mother cpl) (Some ifam) :: gpl] 719 | None -> [GP_missing n ip :: gpl] ] 720 | GP_interv None -> [gp :: gpl] 721 | GP_interv (Some (n1, n2, x)) -> 722 let x = 723 match x with 724 [ Some (m1, m2) -> Some (Num.twice m1, Num.twice m2) 725 | None -> None ] 726 in 727 let gp = GP_interv (Some (Num.twice n1, Num.twice n2, x)) in 728 [gp :: gpl] 729 | _ -> gpl ]) 730 gpl [] 731 in 732 let gpl = 733 List.fold_left 734 (fun gpl gp -> 735 match gp with 736 [ GP_person n ip _ -> 737 let i = Adef.int_of_iper ip in 738 let m = mark.(i) in 739 if Num.eq m Num.zero then do { mark.(i) := n; [gp :: gpl] } 740 else [GP_same n m ip :: gpl] 741 | _ -> [gp :: gpl] ]) 742 [] gpl 743 in 744 List.rev gpl 745; 746 747value next_generation2 conf base mark gpl = 748 let gpl = 749 List.map 750 (fun gp -> 751 match gp with 752 [ GP_same n m ip -> 753 GP_interv (Some (n, Num.inc n 1, Some (m, Num.inc m 1))) 754 | _ -> gp ]) 755 gpl 756 in 757 let gpl = next_generation conf base mark gpl in 758 List.fold_right 759 (fun gp gpl -> 760 match (gp, gpl) with 761 [ (GP_interv (Some (n1, n2, x)), 762 [GP_interv (Some (n3, n4, y)) :: gpl1]) -> 763 if Num.eq n2 n3 then 764 let z = 765 match (x, y) with 766 [ (Some (m1, m2), Some (m3, m4)) -> 767 if Num.eq m2 m3 then Some (m1, m4) else None 768 | _ -> None ] 769 in 770 [GP_interv (Some (n1, n4, z)) :: gpl1] 771 else [GP_interv None :: gpl1] 772 | (GP_interv _, [GP_interv _ :: gpl]) -> 773 [GP_interv None :: gpl] 774 | (GP_missing _ _, gpl) -> gpl 775 | _ -> [gp :: gpl] ]) 776 gpl [] 777; 778 779value sosa_is_present all_gp n1 = 780 loop all_gp where rec loop = 781 fun 782 [ [GP_person n _ _ :: gpl] 783 | [GP_same n _ _ :: gpl] -> if Num.eq n n1 then True else loop gpl 784 | [gp :: gpl] -> loop gpl 785 | [] -> False ] 786; 787 788value get_link all_gp ip = 789 loop all_gp where rec loop = 790 fun 791 [ [(GP_person n ip0 _ as gp) :: gpl] -> 792 if ip = ip0 then Some gp else loop gpl 793 | [gp :: gpl] -> loop gpl 794 | [] -> None ] 795; 796 797value parent_sosa conf base ip all_gp n parent = 798 if sosa_is_present all_gp n then Num.to_string n 799 else 800 match get_parents (pget conf base ip) with 801 [ Some ifam -> 802 match get_link all_gp (parent (foi base ifam)) with 803 [ Some (GP_person n _ _) -> Num.to_string n 804 | _ -> "" ] 805 | None -> "" ] 806; 807 808value will_print = 809 fun 810 [ GP_person _ _ _ -> True 811 | GP_same _ _ _ -> True 812 | _ -> False ] 813; 814 815value get_all_generations conf base p = 816 let max_level = 817 match p_getint conf.env "v" with 818 [ Some v -> v (* + 1 *) 819 | None -> 0 ] 820 in 821 let mark = Array.make (nb_of_persons base) Num.zero in 822 let rec get_generations level gpll gpl = 823 let gpll = [gpl :: gpll] in 824 if level < max_level then 825 let next_gpl = next_generation conf base mark gpl in 826 if List.exists will_print next_gpl then 827 get_generations (level + 1) gpll next_gpl 828 else gpll 829 else gpll 830 in 831 let gpll = 832 get_generations 1 [] [GP_person Num.one (get_key_index p) None] 833 in 834 let gpll = List.rev gpll in 835 List.flatten gpll 836; 837 838(* Ancestors by tree: 839 840 8 ? ? ? ? ? ? ? 841 4 5 ? 7 842 2 3 843 1 844 8451) Build list of levels (t1 = True for parents flag, size 1) 846 => [ [8At1 E E] [4Lt1 5Rt1 7At1] [2Lt1 3Rt1] [1Ct1] ] 847 8482) Enrich list of levels (parents flag, sizing) 849 => [ [8At1 E E] [4Lt1 5Rf1 7Af1] [2Lt3 3Rt1] [1Ct5] ] 850 8513) Display it 852 For each cell: 853 Top vertical bar if parents flag (not on top line) 854 Person 855 Person tree link (vertical bar) ) not on bottom line 856 Horizontal line ) 857 858*) 859 860type pos = [ Left | Right | Center | Alone ]; 861type cell = 862 [ Cell of person and option ifam and pos and bool and int 863 | Empty ] 864; 865 866value rec enrich lst1 lst2 = 867 match (lst1, lst2) with 868 [ (_, []) -> [] 869 | ([], lst) -> lst 870 | ([Cell _ _ Right _ s1 :: l1], [Cell p f d u s2 :: l2]) -> 871 [Cell p f d u (s1 + s2 + 1) :: enrich l1 l2] 872 | ([Cell _ _ Left _ s :: l1], [Cell p f d u _ :: l2]) -> 873 enrich l1 [Cell p f d u s :: l2] 874 | ([Cell _ _ _ _ s :: l1], [Cell p f d u _ :: l2]) -> 875 [Cell p f d u s :: enrich l1 l2] 876 | ([Empty :: l1], [Cell p f d _ s :: l2]) -> 877 [Cell p f d False s :: enrich l1 l2] 878 | ([_ :: l1], [Empty :: l2]) -> [Empty :: enrich l1 l2] ] 879; 880 881value is_empty = List.for_all (\= Empty); 882 883value rec enrich_tree lst = 884 match lst with 885 [ [] -> [] 886 | [head :: tail] -> 887 if is_empty head then enrich_tree tail 888 else 889 match tail with 890 [ [] -> [head] 891 | [thead :: ttail] -> 892 [head :: enrich_tree [enrich head thead :: ttail]] ] ] 893; 894 895(* tree_generation_list 896 conf: configuration parameters 897 base: base name 898 gv: number of generations 899 p: person *) 900value tree_generation_list conf base gv p = 901 let next_gen pol = 902 List.fold_right 903 (fun po list -> 904 match po with 905 [ Empty -> [Empty :: list] 906 | Cell p _ _ _ _ -> 907 match get_parents p with 908 [ Some ifam -> 909 let cpl = foi base ifam in 910 let fath = 911 let p = pget conf base (get_father cpl) in 912 if know base p then Some p else None 913 in 914 let moth = 915 let p = pget conf base (get_mother cpl) in 916 if know base p then Some p else None 917 in 918 let fo = Some ifam in 919 match (fath, moth) with 920 [ (Some f, Some m) -> 921 [Cell f fo Left True 1; Cell m fo Right True 1 :: list] 922 | (Some f, None) -> [Cell f fo Alone True 1 :: list] 923 | (None, Some m) -> [Cell m fo Alone True 1 :: list] 924 | (None, None) -> [Empty :: list] ] 925 | _ -> [Empty :: list] ] ]) 926 pol [] 927 in 928 let gen = 929 loop (gv - 1) [Cell p None Center True 1] [] where rec loop i gen list = 930 if i = 0 then [gen :: list] 931 else loop (i - 1) (next_gen gen) [gen :: list] 932 in 933 enrich_tree gen 934; 935 936(* Ancestors surnames list *) 937 938value get_date_place conf base auth_for_all_anc p = 939 if auth_for_all_anc || authorized_age conf base p then 940 let d1 = 941 match Adef.od_of_codate (get_birth p) with 942 [ None -> Adef.od_of_codate (get_baptism p) 943 | x -> x ] 944 in 945 let d1 = 946 if d1 <> None then d1 947 else 948 List.fold_left 949 (fun d ifam -> 950 if d <> None then d 951 else Adef.od_of_codate (get_marriage (foi base ifam))) 952 d1 (Array.to_list (get_family p)) 953 in 954 let d2 = 955 match get_death p with 956 [ Death _ cd -> Some (Adef.date_of_cdate cd) 957 | _ -> 958 match get_burial p with 959 [ Buried cod -> Adef.od_of_codate cod 960 | Cremated cod -> Adef.od_of_codate cod 961 | _ -> None ] ] 962 in 963 let auth_for_all_anc = 964 if auth_for_all_anc then True 965 else 966 match d2 with 967 [ Some (Dgreg d _) -> 968 let a = CheckItem.time_elapsed d conf.today in 969 Util.strictly_after_private_years conf a 970 | _ -> False ] 971 in 972 let pl = 973 let pl = "" in 974 let pl = if pl <> "" then pl else sou base (get_birth_place p) in 975 let pl = if pl <> "" then pl else sou base (get_baptism_place p) in 976 let pl = if pl <> "" then pl else sou base (get_death_place p) in 977 let pl = if pl <> "" then pl else sou base (get_burial_place p) in 978 let pl = 979 if pl <> "" then pl 980 else 981 List.fold_left 982 (fun pl ifam -> 983 if pl <> "" then pl 984 else sou base (get_marriage_place (foi base ifam))) 985 pl (Array.to_list (get_family p)) 986 in 987 pl 988 in 989 ((d1, d2, pl), auth_for_all_anc) 990 else ((None, None, ""), False) 991; 992 993(* duplications proposed for merging *) 994 995type dup = [ DupFam of ifam and ifam | DupInd of iper and iper | NoDup ]; 996type excl_dup = (list (Adef.iper * Adef.iper) * list (Adef.ifam * Adef.ifam)); 997 998value gen_excluded_possible_duplications conf s i_of_int = 999 match p_getenv conf.env s with 1000 [ Some s -> 1001 loop [] 0 where rec loop ipl i = 1002 if i >= String.length s then ipl 1003 else 1004 let j = 1005 try String.index_from s i ',' with 1006 [ Not_found -> String.length s ] 1007 in 1008 if j = String.length s then ipl 1009 else 1010 let k = 1011 try String.index_from s (j + 1) ',' with 1012 [ Not_found -> String.length s ] 1013 in 1014 let s1 = String.sub s i (j - i) in 1015 let s2 = String.sub s (j + 1) (k - j - 1) in 1016 let ipl = 1017 match 1018 try Some (int_of_string s1, int_of_string s2) with 1019 [ Failure _ -> None ] 1020 with 1021 [ Some (i1, i2) -> [(i_of_int i1, i_of_int i2) :: ipl] 1022 | None -> ipl ] 1023 in 1024 loop ipl (k + 1) 1025 | None -> [] ] 1026; 1027 1028value excluded_possible_duplications conf = 1029 (gen_excluded_possible_duplications conf "iexcl" Adef.iper_of_int, 1030 gen_excluded_possible_duplications conf "fexcl" Adef.ifam_of_int) 1031; 1032 1033value first_possible_duplication base ip (iexcl, fexcl) = 1034 let ifaml = Array.to_list (get_family (poi base ip)) in 1035 let cand_spouse = 1036 loop_spouse ifaml where rec loop_spouse = 1037 fun 1038 [ [ifam1 :: ifaml1] -> 1039 let isp1 = Gutil.spouse ip (foi base ifam1) in 1040 let sp1 = poi base isp1 in 1041 let fn1 = get_first_name sp1 in 1042 let sn1 = get_surname sp1 in 1043 loop_same ifaml1 where rec loop_same = 1044 fun 1045 [ [ifam2 :: ifaml2] -> 1046 let isp2 = Gutil.spouse ip (foi base ifam2) in 1047 if isp2 = isp1 then 1048 if not (List.mem (ifam1, ifam2) fexcl) then 1049 DupFam ifam1 ifam2 1050 else loop_same ifaml2 1051 else 1052 let sp2 = poi base isp2 in 1053 if List.mem (isp1, isp2) iexcl then loop_same ifaml2 1054 else if eq_istr (get_first_name sp2) fn1 && 1055 eq_istr (get_surname sp2) sn1 1056 then 1057 DupInd isp1 isp2 1058 else loop_same ifaml2 1059 | [] -> loop_spouse ifaml1 ] 1060 | [] -> NoDup ] 1061 in 1062 if cand_spouse <> NoDup then cand_spouse 1063 else 1064 let ipl = 1065 loop ifaml where rec loop = 1066 fun 1067 [ [ifam :: ifaml] -> 1068 let ipl = Array.to_list (get_children (foi base ifam)) in 1069 ipl @ loop ifaml 1070 | [] -> [] ] 1071 in 1072 loop_chil ipl where rec loop_chil = 1073 fun 1074 [ [ip1 :: ipl1] -> 1075 let p1 = poi base ip1 in 1076 let fn1 = get_first_name p1 in 1077 loop_same ipl1 where rec loop_same = 1078 fun 1079 [ [ip2 :: ipl2] -> 1080 let p2 = poi base ip2 in 1081 if List.mem (ip1, ip2) iexcl then loop_same ipl2 1082 else if eq_istr (get_first_name p2) fn1 then 1083 DupInd ip1 ip2 1084 else loop_same ipl2 1085 | [] -> loop_chil ipl1 ] 1086 | [] -> NoDup ] 1087; 1088 1089value has_possible_duplications conf base p = 1090 let ip = get_key_index p in 1091 let excl = excluded_possible_duplications conf in 1092 first_possible_duplication base ip excl <> NoDup 1093; 1094 1095value merge_date_place conf base surn ((d1, d2, pl), auth) p = 1096 let ((pd1, pd2, ppl), auth) = get_date_place conf base auth p in 1097 let nd1 = 1098 if pd1 <> None then pd1 1099 else if eq_istr (get_surname p) surn then if pd2 <> None then pd2 else d1 1100 else None 1101 in 1102 let nd2 = 1103 if eq_istr (get_surname p) surn then 1104 if d2 <> None then d2 1105 else if d1 <> None then d1 1106 else if pd1 <> None then pd2 1107 else pd1 1108 else if pd2 <> None then pd2 1109 else if pd1 <> None then pd1 1110 else d1 1111 in 1112 let pl = 1113 if ppl <> "" then ppl else if eq_istr (get_surname p) surn then pl 1114 else "" 1115 in 1116 ((nd1, nd2, pl), auth) 1117; 1118 1119value build_surnames_list conf base v p = 1120 let ht = Hashtbl.create 701 in 1121 let mark = Array.make (nb_of_persons base) 5 in 1122 let auth = conf.wizard || conf.friend in 1123 let add_surname sosa p surn dp = 1124 let r = 1125 try Hashtbl.find ht surn with 1126 [ Not_found -> 1127 let r = ref ((fst dp, p), []) in 1128 do { Hashtbl.add ht surn r; r } ] 1129 in 1130 r.val := (fst r.val, [sosa :: snd r.val]) 1131 in 1132 let rec loop lev sosa p surn dp = 1133 if mark.(Adef.int_of_iper (get_key_index p)) = 0 then () 1134 else if lev = v then 1135 if (is_hide_names conf p) && not (fast_auth_age conf p) then () 1136 else add_surname sosa p surn dp 1137 else do { 1138 mark.(Adef.int_of_iper (get_key_index p)) := 1139 mark.(Adef.int_of_iper (get_key_index p)) - 1; 1140 match get_parents p with 1141 [ Some ifam -> 1142 let cpl = foi base ifam in 1143 let fath = pget conf base (get_father cpl) in 1144 let moth = pget conf base (get_mother cpl) in 1145 do { 1146 if not (eq_istr surn (get_surname fath)) && 1147 not (eq_istr surn (get_surname moth)) 1148 then 1149 add_surname sosa p surn dp 1150 else (); 1151 let sosa = Num.twice sosa in 1152 if not (is_hidden fath) then 1153 let dp1 = merge_date_place conf base surn dp fath in 1154 loop (lev + 1) sosa fath (get_surname fath) dp1 1155 else (); 1156 let sosa = Num.inc sosa 1 in 1157 if not (is_hidden moth) then 1158 let dp2 = merge_date_place conf base surn dp moth in 1159 loop (lev + 1) sosa moth (get_surname moth) dp2 1160 else (); 1161 } 1162 | None -> add_surname sosa p surn dp ] 1163 } 1164 in 1165 do { 1166 loop 1 Num.one p (get_surname p) (get_date_place conf base auth p); 1167 let list = ref [] in 1168 Hashtbl.iter 1169 (fun i dp -> 1170 let surn = sou base i in 1171 if surn <> "?" then list.val := [(surn, dp.val) :: list.val] else ()) 1172 ht; 1173 List.sort 1174 (fun (s1, _) (s2, _) -> 1175 match 1176 Gutil.alphabetic_order (surname_end base s1) (surname_end base s2) 1177 with 1178 [ 0 -> 1179 Gutil.alphabetic_order (surname_begin base s1) 1180 (surname_begin base s2) 1181 | x -> x ]) 1182 list.val 1183 } 1184; 1185 1186 1187(* ************************************************************************* *) 1188(* [Fonc] build_list_eclair : 1189 config -> base -> int -> person -> 1190 list 1191 (string * string * option date * option date * person * list iper) *) 1192(** [Description] : Construit la liste éclair des ascendants de p jusqu'à la 1193 génération v. 1194 [Args] : 1195 - conf : configuration de la base 1196 - base : base de donnée 1197 - v : le nombre de génération 1198 - p : person 1199 [Retour] : (surname * place * date begin * date end * person * list iper) 1200 [Rem] : Exporté en clair hors de ce module. *) 1201(* ************************************************************************* *) 1202value build_list_eclair conf base v p = 1203 let ht = Hashtbl.create 701 in 1204 let mark = Array.make (nb_of_persons base) False in 1205 (* Fonction d'ajout dans la Hashtbl. A la clé (surname, place) on associe *) 1206 (* la personne (pour l'interprétation dans le template), la possible date *) 1207 (* de début, la possible date de fin, la liste des personnes/évènements. *) 1208 (* Astuce: le nombre d'élément de la liste correspond au nombre *) 1209 (* d'évènements et le nombre d'iper unique correspond au nombre d'individu. *) 1210 let add_surname p surn pl d = 1211 if not (is_empty_string pl) then 1212 (* On utilise la string du lieu, parce qu'en gwc2, les adresses des *) 1213 (* lieux sont différentes selon l'évènement. *) 1214 (* On fait un string_of_place à cause des éventuels crochets, pour *) 1215 (* avoir l'unicité du lieu et le trie alphabétique. *) 1216 let pl = Util.string_of_place conf (sou base pl) in 1217 let r = 1218 try Hashtbl.find ht (surn, pl) with 1219 [ Not_found -> 1220 let r = ref (p, None, None, []) in 1221 do { Hashtbl.add ht (surn, pl) r; r } ] 1222 in 1223 (* Met la jour le binding : dates et liste des iper. *) 1224 r.val := 1225 (fun p (pp, db, de, l) -> 1226 let db = 1227 match db with 1228 [ Some dd -> 1229 match d with 1230 [ Some d -> 1231 if Date.compare_date d dd < 0 then Some d 1232 else db 1233 | None -> db ] 1234 | None -> d ] 1235 in 1236 let de = 1237 match de with 1238 [ Some dd -> 1239 match d with 1240 [ Some d -> 1241 if Date.compare_date d dd > 0 then Some d 1242 else de 1243 | None -> de ] 1244 | None -> d ] 1245 in 1246 (pp, db, de, [(get_key_index p) :: l])) 1247 p r.val 1248 else () 1249 in 1250 (* Fonction d'ajout de tous les évènements d'une personne (birth, bapt...). *) 1251 let add_person p surn = 1252 if mark.(Adef.int_of_iper (get_key_index p)) then () 1253 else do { 1254 mark.(Adef.int_of_iper (get_key_index p)) := True; 1255 add_surname p surn (get_birth_place p) (Adef.od_of_codate (get_birth p)); 1256 add_surname p surn (get_baptism_place p) 1257 (Adef.od_of_codate (get_baptism p)); 1258 let death = 1259 match get_death p with 1260 [ Death _ cd -> Some (Adef.date_of_cdate cd) 1261 | _ -> None ] 1262 in 1263 add_surname p surn (get_death_place p) death; 1264 let burial = 1265 match get_burial p with 1266 [ Buried cod | Cremated cod -> Adef.od_of_codate cod 1267 | _ -> None ] 1268 in 1269 add_surname p surn (get_burial_place p) burial; 1270 List.iter 1271 (fun ifam -> 1272 let fam = foi base ifam in 1273 add_surname p surn (get_marriage_place fam) 1274 (Adef.od_of_codate (get_marriage fam))) 1275 (Array.to_list (get_family p)) 1276 } 1277 in 1278 (* Parcours les ascendants de p et les ajoute dans la Hashtbl. *) 1279 let rec loop lev p surn = 1280 if lev = v then 1281 if (is_hide_names conf p) && not (fast_auth_age conf p) then () 1282 else add_person p surn 1283 else do { 1284 add_person p surn; 1285 match get_parents p with 1286 [ Some ifam -> 1287 let cpl = foi base ifam in 1288 let fath = pget conf base (get_father cpl) in 1289 let moth = pget conf base (get_mother cpl) in 1290 do { 1291 if not (is_hidden fath) then loop (lev + 1) fath (get_surname fath) 1292 else (); 1293 if not (is_hidden moth) then loop (lev + 1) moth (get_surname moth) 1294 else (); 1295 } 1296 | None -> () ] 1297 } 1298 in 1299 do { 1300 (* Construction de la Hashtbl. *) 1301 loop 1 p (get_surname p); 1302 (* On parcours la Hashtbl, et on élimine les noms vide (=?) *) 1303 let list = ref [] in 1304 Hashtbl.iter 1305 (fun (istr, place) ht_val -> 1306 let surn = sou base istr in 1307 if surn <> "?" then 1308 let (p, db, de, pl) = (fun x -> x) ht_val.val in 1309 list.val := [(surn, place, db, de, p, pl) :: list.val] 1310 else ()) 1311 ht; 1312 (* On trie la liste par nom, puis lieu. *) 1313 List.sort 1314 (fun (s1, pl1, _, _, _, _) (s2, pl2, _, _, _, _) -> 1315 match 1316 Gutil.alphabetic_order (surname_end base s1) (surname_end base s2) 1317 with 1318 [ 0 -> 1319 match Gutil.alphabetic_order (surname_begin base s1) 1320 (surname_begin base s2) 1321 with 1322 [ 0 -> Gutil.alphabetic_order pl1 pl2 1323 | x -> x ] 1324 | x -> x ]) 1325 list.val 1326 } 1327; 1328 1329value linked_page_text conf base p s key str (pg, (_, il)) = 1330 match pg with 1331 [ NotesLinks.PgMisc pg -> 1332 let list = List.map snd (List.filter (fun (k, _) -> k = key) il) in 1333 List.fold_right 1334 (fun text str -> 1335 try 1336 let (nenv, _) = Notes.read_notes base pg in 1337 let v = 1338 let v = List.assoc s nenv in 1339 if v = "" then raise Not_found 1340 else Util.nth_field v (Util.index_of_sex (get_sex p)) 1341 in 1342 match text.NotesLinks.lnTxt with 1343 [ Some "" -> str 1344 | _ -> 1345 let str1 = 1346 let v = 1347 let text = text.NotesLinks.lnTxt in 1348 match text with 1349 [ Some text -> 1350 loop 0 0 where rec loop i len = 1351 if i = String.length text then Buff.get len 1352 else if text.[i] = '*' then 1353 loop (i + 1) (Buff.mstore len v) 1354 else loop (i + 1) (Buff.store len text.[i]) 1355 | None -> v ] 1356 in 1357 let (a, b, c) = 1358 try 1359 let i = String.index v '{' in 1360 let j = String.index v '}' in 1361 let a = String.sub v 0 i in 1362 let b = String.sub v (i + 1) (j - i - 1) in 1363 let c = 1364 String.sub v (j + 1) (String.length v - j - 1) 1365 in 1366 (a, b, c) 1367 with 1368 [ Not_found -> ("", v, "") ] 1369 in 1370 Printf.sprintf 1371 "%s<a href=\"%sm=NOTES;f=%s#p_%d\">%s</a>%s" a 1372 (commd conf) pg text.NotesLinks.lnPos b c 1373 in 1374 if str = "" then str1 else str ^ ", " ^ str1 ] 1375 with 1376 [ Not_found -> str ]) 1377 list str 1378 | _ -> str ] 1379; 1380 1381value links_to_ind conf base db key = 1382 let list = 1383 List.fold_left 1384 (fun pgl (pg, (_, il)) -> 1385 let record_it = 1386 match pg with 1387 [ NotesLinks.PgInd ip -> authorized_age conf base (pget conf base ip) 1388 | NotesLinks.PgFam ifam -> 1389 let fam = foi base ifam in 1390 if is_deleted_family fam then False 1391 else authorized_age conf base (pget conf base (get_father fam)) 1392 | NotesLinks.PgNotes | NotesLinks.PgMisc _ 1393 | NotesLinks.PgWizard _ -> True ] 1394 in 1395 if record_it then 1396 List.fold_left 1397 (fun pgl (k, _) -> if k = key then [pg :: pgl] else pgl) 1398 pgl il 1399 else pgl) 1400 [] db 1401 in 1402 list_uniq (List.sort compare list) 1403; 1404 1405(* Interpretation of template file *) 1406 1407value rec compare_ls sl1 sl2 = 1408 match (sl1, sl2) with 1409 [ ([s1 :: sl1], [s2 :: sl2]) -> 1410 (* Je ne sais pas s'il y a des effets de bords, mais on *) 1411 (* essaie de convertir s1 s2 en int pour éviter que "10" *) 1412 (* soit plus petit que "2". J'espère qu'on ne casse pas *) 1413 (* les performances à cause du try..with. *) 1414 let c = 1415 try Pervasives.compare (int_of_string s1) (int_of_string s2) 1416 with [ Failure "int_of_string" -> Gutil.alphabetic_order s1 s2 ] 1417 in 1418 if c = 0 then compare_ls sl1 sl2 else c 1419 | ([_ :: _], []) -> 1 1420 | ([], [_ :: _]) -> -1 1421 | ([], []) -> 0 ] 1422; 1423 1424module SortedList = 1425 Set.Make (struct type t = list string; value compare = compare_ls; end) 1426; 1427 1428module IperSet = 1429 Set.Make 1430 (struct 1431 type t = iper; 1432 value compare i1 i2 = 1433 Pervasives.compare (Adef.int_of_iper i1) (Adef.int_of_iper i2); 1434 end) 1435; 1436 1437 1438(* 1439 Type pour représenté soit : 1440 - la liste des branches patronymique 1441 (surname * date begin * date end * place * person * list sosa * loc) 1442 - la liste éclair 1443 (surname * place * date begin * date end * person * list iper * loc) 1444*) 1445type ancestor_surname_info = 1446 [ Branch of 1447 (string * option date * option date * string * person * list Num.t * loc) 1448 | Eclair of 1449 (string * string * option date * option date * person * list iper * loc) ] 1450; 1451 1452type env 'a = 1453 [ Vallgp of list generation_person 1454 | Vanc of generation_person 1455 | Vanc_surn of ancestor_surname_info 1456 | Vcell of cell 1457 | Vcelll of list cell 1458 | Vcnt of ref int 1459 | Vdesclevtab of Lazy.t (array int * array int) 1460 | Vdmark of ref (array bool) 1461 | Vslist of ref SortedList.t 1462 | Vslistlm of list (list string) 1463 | Vind of person 1464 | Vfam of ifam and family and (iper * iper * iper) and bool 1465 | Vrel of relation and option person 1466 | Vbool of bool 1467 | Vint of int 1468 | Vgpl of list generation_person 1469 | Vnldb of NotesLinks.notes_links_db 1470 | Vstring of string 1471 | Vsosa_ref of Lazy.t (option person) 1472 | Vsosa of ref (list (iper * option (Num.t * person))) 1473 | Vt_sosa of sosa_t 1474 | Vtitle of person and title_item 1475 | Vlazyp of ref (option string) 1476 | Vlazy of Lazy.t (env 'a) 1477 | Vother of 'a 1478 | Vnone ] 1479and title_item = 1480 (int * gen_title_name istr * istr * list istr * 1481 list (option date * option date)) 1482; 1483 1484value get_env v env = 1485 try 1486 match List.assoc v env with 1487 [ Vlazy l -> Lazy.force l 1488 | x -> x ] 1489 with 1490 [ Not_found -> Vnone ] 1491; 1492value get_vother = fun [ Vother x -> Some x | _ -> None ]; 1493value set_vother x = Vother x; 1494 1495value not_impl func x = 1496 let desc = 1497 if Obj.is_block (Obj.repr x) then 1498 "tag = " ^ string_of_int (Obj.\tag (Obj.repr x)) 1499 else "int_val = " ^ string_of_int (Obj.magic x) 1500 in 1501 ">Perso." ^ func ^ ": not impl " ^ desc ^ "<p>\n" 1502; 1503 1504value extract_var sini s = 1505 let len = String.length sini in 1506 if String.length s > len && String.sub s 0 (String.length sini) = sini then 1507 String.sub s len (String.length s - len) 1508 else "" 1509; 1510 1511value template_file = ref "perso.txt"; 1512 1513value warning_use_has_parents_before_parent (bp, ep) var r = 1514 IFDEF UNIX THEN do { 1515 Printf.eprintf "*** <W> %s" template_file.val; 1516 Printf.eprintf ", chars %d-%d" bp ep; 1517 Printf.eprintf "\ 1518: since v5.00, must test \"has_parents\" before using \"%s\"\n" 1519 var; 1520 flush stderr; 1521 r 1522 } 1523 ELSE r END 1524; 1525 1526value obsolete_list = ref []; 1527 1528value obsolete (bp, ep) version var new_var r = 1529 if List.mem var obsolete_list.val then r 1530 else IFDEF UNIX THEN do { 1531 Printf.eprintf "*** <W> %s, chars %d-%d:" template_file.val bp ep; 1532 Printf.eprintf " \"%s\" obsolete since v%s%s\n" var version 1533 (if new_var = "" then "" else "; rather use \"" ^ new_var ^ "\""); 1534 flush stderr; 1535 obsolete_list.val := [var :: obsolete_list.val]; 1536 r 1537 } 1538 ELSE r END 1539; 1540 1541 1542value bool_val x = VVbool x; 1543value str_val x = VVstring x; 1544 1545value gen_string_of_img_sz max_wid max_hei conf base env (p, p_auth) = 1546 if p_auth then 1547 let v = image_and_size conf base p (limited_image_size max_wid max_hei) in 1548 match v with 1549 [ Some (_, _, Some (width, height)) -> 1550 Format.sprintf " width=\"%d\" height=\"%d\"" width height 1551 | Some (_, _, None) -> Format.sprintf " height=\"%d\"" max_hei 1552 | None -> "" ] 1553 else "" 1554; 1555value string_of_image_size = gen_string_of_img_sz max_im_wid max_im_wid; 1556value string_of_image_medium_size = gen_string_of_img_sz 160 120; 1557value string_of_image_small_size = gen_string_of_img_sz 100 75; 1558 1559value get_sosa conf base env r p = 1560 try List.assoc (get_key_index p) r.val with 1561 [ Not_found -> do { 1562 let s = 1563 match get_env "sosa_ref" env with 1564 [ Vsosa_ref v -> 1565 match get_env "t_sosa" env with 1566 [ Vt_sosa t_sosa -> find_sosa conf base p v t_sosa 1567 | _ -> None ] 1568 | _ -> None ] 1569 in 1570 r.val := [(get_key_index p, s) :: r.val]; 1571 s 1572 } ] 1573; 1574 1575value make_ep conf base ip = 1576 let p = pget conf base ip in 1577 let p_auth = authorized_age conf base p in (p, p_auth) 1578; 1579 1580value make_efam conf base ip ifam = 1581 let fam = foi base ifam in 1582 let ifath = get_father fam in 1583 let imoth = get_mother fam in 1584 let ispouse = if ip = ifath then imoth else ifath in 1585 let cpl = (ifath, imoth, ispouse) in 1586 let m_auth = 1587 authorized_age conf base (pget conf base ifath) && 1588 authorized_age conf base (pget conf base imoth) 1589 in 1590 (fam, cpl, m_auth) 1591; 1592 1593value rec eval_var conf base env ep loc sl = 1594 try eval_simple_var conf base env ep sl with 1595 [ Not_found -> eval_compound_var conf base env ep loc sl ] 1596and eval_simple_var conf base env ep = 1597 fun 1598 [ [s] -> 1599 try bool_val (eval_simple_bool_var conf base env ep s) with 1600 [ Not_found -> str_val (eval_simple_str_var conf base env ep s) ] 1601 | _ -> raise Not_found ] 1602and eval_simple_bool_var conf base env (_, p_auth) = 1603 fun 1604 [ "are_divorced" -> 1605 match get_env "fam" env with 1606 [ Vfam _ fam _ _ -> 1607 match get_divorce fam with 1608 [ Divorced _ -> True 1609 | _ -> False ] 1610 | _ -> raise Not_found ] 1611 | "are_engaged" -> 1612 match get_env "fam" env with 1613 [ Vfam _ fam _ _ -> get_relation fam = Engaged 1614 | _ -> raise Not_found ] 1615 | "are_married" -> 1616 match get_env "fam" env with 1617 [ Vfam _ fam _ _ -> 1618 get_relation fam = Married || get_relation fam = NoSexesCheckMarried 1619 | _ -> raise Not_found ] 1620 | "are_not_married" -> 1621 match get_env "fam" env with 1622 [ Vfam _ fam _ _ -> 1623 get_relation fam = NotMarried || 1624 get_relation fam = NoSexesCheckNotMarried 1625 | _ -> raise Not_found ] 1626 | "are_separated" -> 1627 match get_env "fam" env with 1628 [ Vfam _ fam _ _ -> 1629 match get_divorce fam with 1630 [ Separated -> True 1631 | _ -> False ] 1632 | _ -> raise Not_found ] 1633 | "browsing_with_sosa_ref" -> 1634 match get_env "sosa_ref" env with 1635 [ Vsosa_ref v -> Lazy.force v <> None 1636 | _ -> raise Not_found ] 1637 | "has_comment" -> 1638 match get_env "fam" env with 1639 [ Vfam _ fam _ m_auth -> 1640 m_auth && not conf.no_note && sou base (get_comment fam) <> "" 1641 | _ -> raise Not_found ] 1642 | "has_relation_her" -> 1643 match get_env "rel" env with 1644 [ Vrel {r_moth = Some _} None -> True 1645 | _ -> False ] 1646 | "has_relation_him" -> 1647 match get_env "rel" env with 1648 [ Vrel {r_fath = Some _} None -> True 1649 | _ -> False ] 1650 | "has_witnesses" -> 1651 match get_env "fam" env with 1652 [ Vfam _ fam _ m_auth -> 1653 m_auth && Array.length (get_witnesses fam) > 0 1654 | _ -> raise Not_found ] 1655 | "is_first" -> 1656 match get_env "first" env with 1657 [ Vbool x -> x 1658 | _ -> raise Not_found ] 1659 | "is_last" -> 1660 match get_env "last" env with 1661 [ Vbool x -> x 1662 | _ -> raise Not_found ] 1663 | "is_no_mention" -> 1664 match get_env "fam" env with 1665 [ Vfam _ fam _ _ -> get_relation fam = NoMention 1666 | _ -> raise Not_found ] 1667 | "is_no_sexes_check" -> 1668 match get_env "fam" env with 1669 [ Vfam _ fam _ _ -> 1670 get_relation fam = NoSexesCheckNotMarried || 1671 get_relation fam = NoSexesCheckMarried 1672 | _ -> raise Not_found ] 1673 | "is_self" -> get_env "pos" env = Vstring "self" 1674 | "is_sibling_after" -> get_env "pos" env = Vstring "next" 1675 | "is_sibling_before" -> get_env "pos" env = Vstring "prev" 1676 | "lazy_printed" -> 1677 match get_env "lazy_print" env with 1678 [ Vlazyp r -> r.val = None 1679 | _ -> raise Not_found ] 1680 | s -> 1681 let v = extract_var "file_exists_" s in 1682 if v <> "" then 1683 let v = code_varenv v in 1684 let s = Srcfile.source_file_name conf v in 1685 Sys.file_exists s 1686 else raise Not_found ] 1687and eval_simple_str_var conf base env (_, p_auth) = 1688 fun 1689 [ "alias" -> 1690 match get_env "alias" env with 1691 [ Vstring s -> s 1692 | _ -> raise Not_found ] 1693 | "child_cnt" -> string_of_int_env "child_cnt" env 1694 | "comment" -> 1695 match get_env "fam" env with 1696 [ Vfam _ fam _ m_auth -> 1697 if m_auth && not conf.no_note then 1698 let s = sou base (get_comment fam) in 1699 let s = string_with_macros conf [] s in 1700 let lines = Wiki.html_of_tlsw conf s in 1701 let wi = 1702 {Wiki.wi_mode = "NOTES"; 1703 Wiki.wi_cancel_links = conf.cancel_links; 1704 Wiki.wi_file_path = Notes.file_path conf base; 1705 Wiki.wi_person_exists = person_exists conf base; 1706 Wiki.wi_always_show_link = conf.wizard || conf.friend} 1707 in 1708 let s = Wiki.syntax_links conf wi (String.concat "\n" lines) in 1709 if conf.pure_xhtml then Util.check_xhtml s else s 1710 else "" 1711 | _ -> raise Not_found ] 1712 | "count" -> 1713 match get_env "count" env with 1714 [ Vcnt c -> string_of_int c.val 1715 | _ -> "" ] 1716 | "divorce_date" -> 1717 match get_env "fam" env with 1718 [ Vfam _ fam (_, _, isp) m_auth -> 1719 match get_divorce fam with 1720 [ Divorced d -> 1721 let d = Adef.od_of_codate d in 1722 match d with 1723 [ Some d when m_auth -> 1724 match p_getenv conf.base_env "long_date" with 1725 [ Some "yes" -> " <em>" ^ (Date.string_of_ondate conf d) 1726 ^ (Date.get_wday conf d) ^ "</em>" 1727 | _ -> " <em>" ^ Date.string_of_ondate conf d ^ "</em>" ] 1728 | _ -> "" ] 1729 | _ -> raise Not_found ] 1730 | _ -> raise Not_found ] 1731 | "slash_divorce_date" -> 1732 match get_env "fam" env with 1733 [ Vfam _ fam (_, _, isp) m_auth -> 1734 match get_divorce fam with 1735 [ Divorced d -> 1736 let d = Adef.od_of_codate d in 1737 match d with 1738 [ Some d when m_auth -> Date.string_slash_of_date conf d 1739 | _ -> "" ] 1740 | _ -> raise Not_found ] 1741 | _ -> raise Not_found ] 1742 | "empty_sorted_list" -> 1743 match get_env "list" env with 1744 [ Vslist l -> do { l.val := SortedList.empty; "" } 1745 | _ -> raise Not_found ] 1746 | "family_cnt" -> string_of_int_env "family_cnt" env 1747 | "first_name_alias" -> 1748 match get_env "first_name_alias" env with 1749 [ Vstring s -> s 1750 | _ -> "" ] 1751 | "incr_count" -> 1752 match get_env "count" env with 1753 [ Vcnt c -> do { incr c; "" } 1754 | _ -> "" ] 1755 | "lazy_force" -> 1756 match get_env "lazy_print" env with 1757 [ Vlazyp r -> 1758 match r.val with 1759 [ Some s -> do { r.val := None; s } 1760 | None -> "" ] 1761 | _ -> raise Not_found ] 1762 | "level" -> 1763 match get_env "level" env with 1764 [ Vint i -> string_of_int i 1765 | _ -> "" ] 1766 | "marriage_place" -> 1767 match get_env "fam" env with 1768 [ Vfam _ fam _ m_auth -> 1769 if m_auth then 1770 Util.string_of_place conf (sou base (get_marriage_place fam)) 1771 else "" 1772 | _ -> raise Not_found ] 1773 | "max_anc_level" -> 1774 match get_env "max_anc_level" env with 1775 [ Vint i -> string_of_int i 1776 | _ -> "" ] 1777 | "max_cous_level" -> 1778 match get_env "max_cous_level" env with 1779 [ Vint i -> string_of_int i 1780 | _ -> "" ] 1781 | "max_desc_level" -> 1782 match get_env "max_desc_level" env with 1783 [ Vint i -> string_of_int i 1784 | _ -> "" ] 1785 | "nobility_title" -> 1786 match get_env "nobility_title" env with 1787 [ Vtitle p t -> 1788 if p_auth then 1789 string_of_title conf base (transl_nth conf "and" 0) p t 1790 else "" 1791 | _ -> raise Not_found ] 1792 | "number_of_subitems" -> 1793 match get_env "item" env with 1794 [ Vslistlm [[s :: _] :: sll] -> 1795 let n = 1796 loop 1 sll where rec loop n = 1797 fun 1798 [ [[s1 :: _] :: sll] -> if s = s1 then loop (n + 1) sll else n 1799 | _ -> n ] 1800 in 1801 string_of_int n 1802 | _ -> raise Not_found ] 1803 | "on_marriage_date" -> 1804 match get_env "fam" env with 1805 [ Vfam _ fam _ m_auth -> 1806 match (m_auth, Adef.od_of_codate (get_marriage fam)) with 1807 [ (True, Some s) -> 1808 match p_getenv conf.base_env "long_date" with 1809 [ Some "yes" -> (Date.string_of_ondate conf s) ^ (Date.get_wday conf s) 1810 | _ -> Date.string_of_ondate conf s ] 1811 | _ -> "" ] 1812 | _ -> raise Not_found ] 1813 | "slash_marriage_date" -> 1814 match get_env "fam" env with 1815 [ Vfam _ fam _ m_auth -> 1816 match (m_auth, Adef.od_of_codate (get_marriage fam)) with 1817 [ (True, Some s) -> Date.string_slash_of_date conf s 1818 | _ -> "" ] 1819 | _ -> raise Not_found ] 1820 | "origin_file" -> 1821 if conf.wizard then 1822 match get_env "fam" env with 1823 [ Vfam _ fam _ _ -> sou base (get_origin_file fam) 1824 | _ -> "" ] 1825 else raise Not_found 1826 | "qualifier" -> 1827 match get_env "qualifier" env with 1828 [ Vstring nn -> nn 1829 | _ -> raise Not_found ] 1830 | "related_type" -> 1831 match get_env "rel" env with 1832 [ Vrel r (Some c) -> 1833 rchild_type_text conf r.r_type (index_of_sex (get_sex c)) 1834 | _ -> raise Not_found ] 1835 | "relation_type" -> 1836 match get_env "rel" env with 1837 [ Vrel r None -> 1838 match (r.r_fath, r.r_moth) with 1839 [ (Some ip, None) -> relation_type_text conf r.r_type 0 1840 | (None, Some ip) -> relation_type_text conf r.r_type 1 1841 | (Some ip1, Some ip2) -> relation_type_text conf r.r_type 2 1842 | _ -> raise Not_found ] 1843 | _ -> raise Not_found ] 1844 | "reset_count" -> 1845 match get_env "count" env with 1846 [ Vcnt c -> do { c.val := 0; "" } 1847 | _ -> "" ] 1848 | "reset_desc_level" -> 1849 let flevt_save = 1850 match get_env "desc_level_table_save" env with 1851 [ Vdesclevtab levt -> 1852 let (_, flevt) = Lazy.force levt in 1853 flevt 1854 | _ -> raise Not_found ] 1855 in 1856 match get_env "desc_level_table" env with 1857 [ Vdesclevtab levt -> do { 1858 let (_, flevt) = Lazy.force levt in 1859 for i = 0 to Array.length flevt - 1 do { 1860 flevt.(i) := flevt_save.(i); 1861 }; 1862 "" 1863 } 1864 | _ -> raise Not_found ] 1865 | "source_type" -> 1866 match get_env "src_typ" env with 1867 [ Vstring s -> s 1868 | _ -> raise Not_found ] 1869 | "surname_alias" -> 1870 match get_env "surname_alias" env with 1871 [ Vstring s -> s 1872 | _ -> raise Not_found ] 1873 | s -> 1874 loop 1875 [("evar_", 1876 fun v -> 1877 match p_getenv (conf.env @ conf.henv) v with 1878 [ Some vv -> quote_escaped vv 1879 | None -> "" ]); 1880 (* warning: "cvar_" deprecated since 5.00; use "bvar." *) 1881 ("cvar_", 1882 fun v -> try List.assoc v conf.base_env with [ Not_found -> "" ])] 1883 where rec loop = 1884 fun 1885 [ [(pfx, f) :: pfx_list] -> 1886 let v = extract_var pfx s in 1887 if v <> "" then f v 1888 else loop pfx_list 1889 | [] -> raise Not_found ] ] 1890and eval_compound_var conf base env ((a, _) as ep) loc = 1891 fun 1892 [ ["ancestor" :: sl] -> 1893 match get_env "ancestor" env with 1894 [ Vanc gp -> eval_ancestor_field_var conf base env gp loc sl 1895 | Vanc_surn info -> eval_anc_by_surnl_field_var conf base env ep info sl 1896 | _ -> raise Not_found ] 1897 | ["base"; "name"] -> VVstring conf.bname 1898 | ["base"; "nb_persons"] -> 1899 VVstring 1900 (string_of_num (Util.transl conf "(thousand separator)") 1901 (Num.of_int (nb_of_persons base))) 1902 | ["cell" :: sl] -> 1903 match get_env "cell" env with 1904 [ Vcell cell -> eval_cell_field_var conf base env ep cell loc sl 1905 | _ -> raise Not_found ] 1906 | ["child" :: sl] -> 1907 match get_env "child" env with 1908 [ Vind p -> 1909 let auth = authorized_age conf base p in 1910 let ep = (p, auth) in 1911 eval_person_field_var conf base env ep loc sl 1912 | _ -> raise Not_found ] 1913 | ["enclosing" :: sl] -> 1914 let rec loop = 1915 fun 1916 [ [("#loop", _) :: env] -> 1917 eval_person_field_var conf base env ep loc sl 1918 | [_ :: env] -> loop env 1919 | [] -> raise Not_found ] 1920 in 1921 loop env 1922 | ["family" :: sl] -> 1923 match get_env "fam" env with 1924 [ Vfam i f c m -> 1925 eval_family_field_var conf base env (i, f, c, m) loc sl 1926 | _ -> raise Not_found ] 1927 | ["father" :: sl] -> 1928 match get_parents a with 1929 [ Some ifam -> 1930 let cpl = foi base ifam in 1931 let ep = make_ep conf base (get_father cpl) in 1932 eval_person_field_var conf base env ep loc sl 1933 | None -> 1934 warning_use_has_parents_before_parent loc "father" (str_val "") ] 1935 | ["item" :: sl] -> 1936 match get_env "item" env with 1937 [ Vslistlm ell -> eval_item_field_var env ell sl 1938 | _ -> raise Not_found ] 1939 | ["mother" :: sl] -> 1940 match get_parents a with 1941 [ Some ifam -> 1942 let cpl = foi base ifam in 1943 let ep = make_ep conf base (get_mother cpl) in 1944 eval_person_field_var conf base env ep loc sl 1945 | None -> 1946 warning_use_has_parents_before_parent loc "mother" (str_val "") ] 1947 | ["next_item" :: sl] -> 1948 match get_env "item" env with 1949 [ Vslistlm [_ :: ell] -> eval_item_field_var env ell sl 1950 | _ -> raise Not_found ] 1951 | ["number_of_ancestors" :: sl] -> 1952 match get_env "n" env with 1953 [ Vint n -> VVstring (eval_num conf (Num.of_int (n - 1)) sl) 1954 | _ -> raise Not_found ] 1955 | ["number_of_descendants" :: sl] -> 1956 match get_env "level" env with 1957 [ Vint i -> 1958 match get_env "desc_level_table" env with 1959 [ Vdesclevtab t -> 1960 let cnt = 1961 Array.fold_left (fun cnt v -> if v <= i then cnt + 1 else cnt) 1962 0 (fst (Lazy.force t)) 1963 in 1964 VVstring (eval_num conf (Num.of_int (cnt - 1)) sl) 1965 | _ -> raise Not_found ] 1966 | _ -> raise Not_found ] 1967 | ["parent" :: sl] -> 1968 match get_env "parent" env with 1969 [ Vind p -> 1970 let ep = (p, authorized_age conf base p) in 1971 eval_person_field_var conf base env ep loc sl 1972 | _ -> raise Not_found ] 1973 | ["prev_item" :: sl] -> 1974 match get_env "prev_item" env with 1975 [ Vslistlm ell -> eval_item_field_var env ell sl 1976 | _ -> raise Not_found ] 1977 | ["prev_family" :: sl] -> 1978 match get_env "prev_fam" env with 1979 [ Vfam i f c m -> 1980 eval_family_field_var conf base env (i, f, c, m) loc sl 1981 | _ -> raise Not_found ] 1982 | ["pvar"; v :: sl] -> 1983 match find_person_in_env conf base v with 1984 [ Some p -> 1985 let ep = make_ep conf base (get_key_index p) in 1986 eval_person_field_var conf base env ep loc sl 1987 | None -> raise Not_found ] 1988 | ["related" :: sl] -> 1989 match get_env "rel" env with 1990 [ Vrel {r_type = rt} (Some p) -> 1991 eval_relation_field_var conf base env 1992 (index_of_sex (get_sex p), rt, get_key_index p, False) loc sl 1993 | _ -> raise Not_found ] 1994 | ["relation_her" :: sl] -> 1995 match get_env "rel" env with 1996 [ Vrel {r_moth = Some ip; r_type = rt} None -> 1997 eval_relation_field_var conf base env (1, rt, ip, True) loc sl 1998 | _ -> raise Not_found ] 1999 | ["relation_him" :: sl] -> 2000 match get_env "rel" env with 2001 [ Vrel {r_fath = Some ip; r_type = rt} None -> 2002 eval_relation_field_var conf base env (0, rt, ip, True) loc sl 2003 | _ -> raise Not_found ] 2004 | ["self" :: sl] -> eval_person_field_var conf base env ep loc sl 2005 | ["sosa_ref" :: sl] -> 2006 match get_env "sosa_ref" env with 2007 [ Vsosa_ref v -> 2008 match Lazy.force v with 2009 [ Some p -> 2010 let ep = make_ep conf base (get_key_index p) in 2011 eval_person_field_var conf base env ep loc sl 2012 | None -> raise Not_found ] 2013 | _ -> raise Not_found ] 2014 | ["spouse" :: sl] -> 2015 match get_env "fam" env with 2016 [ Vfam _ _ (_, _, ip) _ -> 2017 let ep = make_ep conf base ip in 2018 eval_person_field_var conf base env ep loc sl 2019 | _ -> raise Not_found ] 2020 | ["witness" :: sl] -> 2021 match get_env "witness" env with 2022 [ Vind p -> 2023 let ep = (p, authorized_age conf base p) in 2024 eval_person_field_var conf base env ep loc sl 2025 | _ -> raise Not_found ] 2026 | ["witness_relation" :: sl] -> 2027 match get_env "fam" env with 2028 [ Vfam i f c m -> 2029 eval_witness_relation_var conf base env (i, f, c, m) loc sl 2030 | _ -> raise Not_found ] 2031 | sl -> eval_person_field_var conf base env ep loc sl ] 2032and eval_item_field_var env ell = 2033 fun 2034 [ [s] -> 2035 try 2036 match ell with 2037 [ [el :: _] -> 2038 let v = int_of_string s in 2039 let r = try List.nth el (v - 1) with [ Failure _ -> "" ] in 2040 VVstring r 2041 | [] -> VVstring "" ] 2042 with 2043 [ Failure _ -> raise Not_found ] 2044 | _ -> raise Not_found ] 2045and eval_relation_field_var conf base env (i, rt, ip, is_relation) loc = 2046 fun 2047 [ ["type"] -> 2048 if is_relation then VVstring (relation_type_text conf rt i) 2049 else VVstring (rchild_type_text conf rt i) 2050 | sl -> 2051 let ep = make_ep conf base ip in 2052 eval_person_field_var conf base env ep loc sl ] 2053and eval_cell_field_var conf base env ep cell loc = 2054 fun 2055 [ ["colspan"] -> 2056 match cell with 2057 [ Empty -> VVstring "1" 2058 | Cell _ _ _ _ s -> VVstring (string_of_int s) ] 2059 | ["family" :: sl] -> 2060 match cell with 2061 [ Cell p (Some ifam) _ _ _ -> 2062 let (f, c, a) = make_efam conf base (get_key_index p) ifam in 2063 eval_family_field_var conf base env (ifam, f, c, a) loc sl 2064 | _ -> VVstring "" ] 2065 | ["is_center"] -> 2066 match cell with 2067 [ Cell _ _ Center _ _ -> VVbool True 2068 | _ -> VVbool False ] 2069 | ["is_empty"] -> 2070 match cell with 2071 [ Empty -> VVbool True 2072 | _ -> VVbool False ] 2073 | ["is_left"] -> 2074 match cell with 2075 [ Cell _ _ Left _ _ -> VVbool True 2076 | _ -> VVbool False ] 2077 | ["is_right"] -> 2078 match cell with 2079 [ Cell _ _ Right _ _ -> VVbool True 2080 | _ -> VVbool False ] 2081 | ["is_top"] -> 2082 match cell with 2083 [ Cell _ _ _ False _ -> VVbool True 2084 | _ -> VVbool False ] 2085 | ["person" :: sl] -> 2086 match cell with 2087 [ Cell p _ _ _ _ -> 2088 let ep = make_ep conf base (get_key_index p) in 2089 eval_person_field_var conf base env ep loc sl 2090 | _ -> raise Not_found ] 2091 | _ -> raise Not_found ] 2092and eval_ancestor_field_var conf base env gp loc = 2093 fun 2094 [ ["family" :: sl] -> 2095 match gp with 2096 [ GP_person _ ip (Some ifam) -> 2097 let f = foi base ifam in 2098 let ifath = get_father f in 2099 let imoth = get_mother f in 2100 let ispouse = if ip = ifath then imoth else ifath in 2101 let c = (ifath, imoth, ispouse) in 2102 let m_auth = 2103 authorized_age conf base (pget conf base ifath) && 2104 authorized_age conf base (pget conf base imoth) 2105 in 2106 eval_family_field_var conf base env (ifam, f, c, m_auth) loc sl 2107 | _ -> raise Not_found ] 2108 | ["father" :: sl] -> 2109 match gp with 2110 [ GP_person _ ip _ -> 2111 match (get_parents (pget conf base ip), get_env "all_gp" env) with 2112 [ (Some ifam, Vallgp all_gp) -> 2113 let cpl = foi base ifam in 2114 match get_link all_gp (get_father cpl) with 2115 [ Some gp -> eval_ancestor_field_var conf base env gp loc sl 2116 | None -> 2117 let ep = make_ep conf base (get_father cpl) in 2118 eval_person_field_var conf base env ep loc sl ] 2119 | (_, _) -> raise Not_found ] 2120 | GP_same _ _ ip -> 2121 match get_parents (pget conf base ip) with 2122 [ Some ifam -> 2123 let cpl = foi base ifam in 2124 let ep = make_ep conf base (get_father cpl) in 2125 eval_person_field_var conf base env ep loc sl 2126 | _ -> raise Not_found ] 2127 | _ -> raise Not_found ] 2128 | ["father_sosa"] -> 2129 match (gp, get_env "all_gp" env) with 2130 [ (GP_person n ip _ | GP_same n _ ip, Vallgp all_gp) -> 2131 let n = Num.twice n in 2132 VVstring (parent_sosa conf base ip all_gp n get_father) 2133 | _ -> VVstring "" ] 2134 | ["interval"] -> 2135 match gp with 2136 [ GP_interv (Some (n1, n2, Some (n3, n4))) -> 2137 let n2 = Num.sub n2 Num.one in 2138 let n4 = Num.sub n4 Num.one in 2139 let sep = transl conf "(thousand separator)" in 2140 let r = 2141 Num.to_string_sep sep n1 ^ "-" ^ Num.to_string_sep sep n2 ^ " = " ^ 2142 Num.to_string_sep sep n3 ^ "-" ^ Num.to_string_sep sep n4 2143 in 2144 VVstring r 2145 | GP_interv (Some (n1, n2, None)) -> 2146 let n2 = Num.sub n2 Num.one in 2147 let sep = transl conf "(thousand separator)" in 2148 let r = 2149 Num.to_string_sep sep n1 ^ "-" ^ Num.to_string_sep sep n2 ^ 2150 " = ..." 2151 in 2152 VVstring r 2153 | GP_interv None -> VVstring "..." 2154 | _ -> VVstring "" ] 2155 | ["mother_sosa"] -> 2156 match (gp, get_env "all_gp" env) with 2157 [ (GP_person n ip _ | GP_same n _ ip, Vallgp all_gp) -> 2158 let n = Num.inc (Num.twice n) 1 in 2159 VVstring (parent_sosa conf base ip all_gp n get_mother) 2160 | _ -> VVstring "" ] 2161 | ["same" :: sl] -> 2162 match gp with 2163 [ GP_same _ n _ -> VVstring (eval_num conf n sl) 2164 | _ -> VVstring "" ] 2165 | ["anc_sosa" :: sl] -> 2166 match gp with 2167 [ GP_person n _ _ | GP_same n _ _ -> VVstring (eval_num conf n sl) 2168 | _ -> VVstring "" ] 2169 | ["spouse" :: sl] -> 2170 match gp with 2171 [ GP_person _ ip (Some ifam) -> 2172 let ip = Gutil.spouse ip (foi base ifam) in 2173 let ep = make_ep conf base ip in 2174 eval_person_field_var conf base env ep loc sl 2175 | _ -> raise Not_found ] 2176 | sl -> 2177 match gp with 2178 [ GP_person _ ip _ | GP_same _ _ ip -> 2179 let ep = make_ep conf base ip in 2180 eval_person_field_var conf base env ep loc sl 2181 | _ -> raise Not_found ] ] 2182and eval_anc_by_surnl_field_var conf base env ep info = 2183 match info with 2184 [ Branch (s, db, de, place, p, sosa_list, loc) -> 2185 fun 2186 [ ["date_begin" :: sl] -> 2187 match db with 2188 [ Some d -> eval_date_field_var conf d sl 2189 | None -> VVstring "" ] 2190 | ["date_end" :: sl] -> 2191 match de with 2192 [ Some d -> eval_date_field_var conf d sl 2193 | None -> VVstring "" ] 2194 | ["nb_times"] -> VVstring (string_of_int (List.length sosa_list)) 2195 | ["place"] -> VVstring (Util.string_of_place conf place) 2196 | ["sosa_access"] -> 2197 let (str, _) = 2198 List.fold_right 2199 (fun sosa (str, n) -> 2200 let str = 2201 str ^ ";s" ^ string_of_int n ^ "=" ^ Num.to_string sosa 2202 in 2203 (str, n + 1)) 2204 sosa_list ("", 1) 2205 in 2206 let (p, _) = ep in 2207 VVstring (acces_n conf base "1" p ^ str) 2208 | sl -> 2209 let ep = make_ep conf base (get_key_index p) in 2210 eval_person_field_var conf base env ep loc sl ] 2211 | Eclair (s, place, db, de, p, persl, loc) -> 2212 fun 2213 [ ["date_begin" :: sl] -> 2214 match db with 2215 [ Some d -> eval_date_field_var conf d sl 2216 | None -> VVstring "" ] 2217 | ["date_end" :: sl] -> 2218 match de with 2219 [ Some d -> eval_date_field_var conf d sl 2220 | None -> VVstring "" ] 2221 | ["nb_events"] -> VVstring (string_of_int (List.length persl)) 2222 | ["nb_ind"] -> 2223 let list = 2224 IperSet.elements 2225 (List.fold_right IperSet.add persl IperSet.empty) 2226 in 2227 VVstring (string_of_int (List.length list)) 2228 | ["place"] -> VVstring place 2229 | sl -> 2230 let ep = make_ep conf base (get_key_index p) in 2231 eval_person_field_var conf base env ep loc sl ] ] 2232and eval_num conf n = 2233 fun 2234 [ ["hexa"] -> "0x" ^ Num.to_string_sep_base "" 16 n 2235 | ["octal"] -> "0o" ^ Num.to_string_sep_base "" 8 n 2236 | ["v"] -> Num.to_string n 2237 | [] -> Num.to_string_sep (transl conf "(thousand separator)") n 2238 | _ -> raise Not_found ] 2239and eval_person_field_var conf base env ((p, p_auth) as ep) loc = 2240 fun 2241 [ ["baptism_date" :: sl] -> 2242 match Adef.od_of_codate (get_baptism p) with 2243 [ Some d when p_auth -> eval_date_field_var conf d sl 2244 | _ -> VVstring "" ] 2245 | ["birth_date" :: sl] -> 2246 match Adef.od_of_codate (get_birth p) with 2247 [ Some d when p_auth -> eval_date_field_var conf d sl 2248 | _ -> VVstring "" ] 2249 | ["burial_date" :: sl] -> 2250 match get_burial p with 2251 [ Buried cod when p_auth -> 2252 match Adef.od_of_codate cod with 2253 [ Some d -> eval_date_field_var conf d sl 2254 | None -> VVstring "" ] 2255 | _ -> VVstring "" ] 2256 | ["cremated_date" :: sl] -> 2257 match get_burial p with 2258 [ Cremated cod when p_auth -> 2259 match Adef.od_of_codate cod with 2260 [ Some d -> eval_date_field_var conf d sl 2261 | None -> VVstring "" ] 2262 | _ -> VVstring "" ] 2263 | ["death_date" :: sl] -> 2264 match get_death p with 2265 [ Death _ cd when p_auth -> 2266 eval_date_field_var conf (Adef.date_of_cdate cd) sl 2267 | _ -> VVstring "" ] 2268 | ["father" :: sl] -> 2269 match get_parents p with 2270 [ Some ifam -> 2271 let cpl = foi base ifam in 2272 let ep = make_ep conf base (get_father cpl) in 2273 eval_person_field_var conf base env ep loc sl 2274 | None -> 2275 warning_use_has_parents_before_parent loc "father" (str_val "") ] 2276 | ["has_linked_page"; s] -> 2277 match get_env "nldb" env with 2278 [ Vnldb db -> 2279 let key = 2280 let fn = Name.lower (sou base (get_first_name p)) in 2281 let sn = Name.lower (sou base (get_surname p)) in 2282 (fn, sn, get_occ p) 2283 in 2284 let r = 2285 List.exists 2286 (fun (pg, (_, il)) -> 2287 match pg with 2288 [ NotesLinks.PgMisc pg -> 2289 if List.mem_assoc key il then 2290 let (nenv, _) = Notes.read_notes base pg in 2291 List.mem_assoc s nenv 2292 else False 2293 | _ -> False ]) 2294 db 2295 in 2296 VVbool r 2297 | _ -> raise Not_found ] 2298 | ["has_linked_pages"] -> 2299 match get_env "nldb" env with 2300 [ Vnldb db -> 2301 let r = 2302 if p_auth then 2303 let key = 2304 let fn = Name.lower (sou base (get_first_name p)) in 2305 let sn = Name.lower (sou base (get_surname p)) in 2306 (fn, sn, get_occ p) 2307 in 2308 links_to_ind conf base db key <> [] 2309 else False 2310 in 2311 VVbool r 2312 | _ -> raise Not_found ] 2313 | ["has_sosa"] -> 2314 match get_env "sosa" env with 2315 [ Vsosa r -> VVbool (get_sosa conf base env r p <> None) 2316 | _ -> VVbool False ] 2317 | ["linked_page"; s] -> 2318 match get_env "nldb" env with 2319 [ Vnldb db -> 2320 let key = 2321 let fn = Name.lower (sou base (get_first_name p)) in 2322 let sn = Name.lower (sou base (get_surname p)) in 2323 (fn, sn, get_occ p) 2324 in 2325 let s = List.fold_left (linked_page_text conf base p s key) "" db in 2326 VVstring s 2327 | _ -> raise Not_found ] 2328 | ["marriage_date" :: sl] -> 2329 match get_env "fam" env with 2330 [ Vfam _ fam _ True -> 2331 match Adef.od_of_codate (get_marriage fam) with 2332 [ Some d -> eval_date_field_var conf d sl 2333 | None -> VVstring "" ] 2334 | _ -> raise Not_found ] 2335 | ["mother" :: sl] -> 2336 match get_parents p with 2337 [ Some ifam -> 2338 let cpl = foi base ifam in 2339 let ep = make_ep conf base (get_mother cpl) in 2340 eval_person_field_var conf base env ep loc sl 2341 | None -> 2342 warning_use_has_parents_before_parent loc "mother" (str_val "") ] 2343 | ["nobility_title" :: sl] -> 2344 match Util.main_title conf base p with 2345 [ Some t when p_auth -> 2346 let id = sou base t.t_ident in 2347 let pl = sou base t.t_place in 2348 eval_nobility_title_field_var (id, pl) sl 2349 | _ -> VVstring "" ] 2350 | ["self" :: sl] -> 2351 eval_person_field_var conf base env ep loc sl 2352 | ["sosa" :: sl] -> 2353 match get_env "sosa" env with 2354 [ Vsosa x -> 2355 match get_sosa conf base env x p with 2356 [ Some (n, p) -> VVstring (eval_num conf n sl) 2357 | None -> VVstring "" ] 2358 | _ -> raise Not_found ] 2359 | ["spouse" :: sl] -> 2360 match get_env "fam" env with 2361 [ Vfam ifam fam _ _ -> 2362 let cpl = foi base ifam in 2363 let ip = Gutil.spouse (get_key_index p) cpl in 2364 let ep = make_ep conf base ip in 2365 eval_person_field_var conf base env ep loc sl 2366 | _ -> raise Not_found ] 2367 | ["var"] -> VVother (eval_person_field_var conf base env ep loc) 2368 | [s] -> 2369 try bool_val (eval_bool_person_field conf base env ep s) with 2370 [ Not_found -> 2371 try str_val (eval_str_person_field conf base env ep s) with 2372 [ Not_found -> obsolete_eval conf base env ep loc s ] ] 2373 | [] -> str_val (simple_person_text conf base p p_auth) 2374 | _ -> raise Not_found ] 2375and eval_date_field_var conf d = 2376 fun 2377 [ ["prec"] -> 2378 match d with 2379 [ Dgreg dmy _ -> VVstring (quote_escaped (Date.prec_text conf dmy)) 2380 | _ -> VVstring "" ] 2381 | ["day"] -> 2382 match d with 2383 [ Dgreg dmy _ -> VVstring (Date.day_text dmy) 2384 | _ -> VVstring "" ] 2385 | ["month"] -> 2386 match d with 2387 [ Dgreg dmy _ -> VVstring (Date.month_text dmy) 2388 | _ -> VVstring "" ] 2389 | ["year"] -> 2390 match d with 2391 [ Dgreg dmy _ -> VVstring (Date.year_text dmy) 2392 | _ -> VVstring "" ] 2393 | _ -> raise Not_found ] 2394and eval_nobility_title_field_var (id, pl) = 2395 fun 2396 [ ["ident_key"] -> VVstring (code_varenv id) 2397 | ["place_key"] -> VVstring (code_varenv pl) 2398 | [] -> VVstring (if pl = "" then id else id ^ " " ^ pl) 2399 | _ -> raise Not_found ] 2400and eval_bool_person_field conf base env (p, p_auth) = 2401 fun 2402 [ "access_by_key" -> 2403 Util.accessible_by_key conf base p (p_first_name base p) 2404 (p_surname base p) 2405 | "birthday" -> 2406 match (p_auth, Adef.od_of_codate (get_birth p)) with 2407 [ (True, Some (Dgreg d _)) -> 2408 if d.prec = Sure && get_death p = NotDead then 2409 d.day = conf.today.day && d.month = conf.today.month && 2410 d.year < conf.today.year || 2411 not (CheckItem.leap_year conf.today.year) && 2412 d.day = 29 && d.month = 2 && 2413 conf.today.day = 1 && conf.today.month = 3 2414 else False 2415 | _ -> False ] 2416 | "wedding_birthday" -> 2417 match get_env "fam" env with 2418 [ Vfam _ fam _ m_auth -> 2419 match (get_relation fam, get_divorce fam) with 2420 [ (Married | NoSexesCheckMarried, NotDivorced) -> 2421 match (m_auth, Adef.od_of_codate (get_marriage fam)) with 2422 [ (True, Some (Dgreg d _)) -> 2423 let father = pget conf base (get_father fam) in 2424 let mother = pget conf base (get_mother fam) in 2425 if d.prec = Sure && authorized_age conf base father 2426 && get_death father = NotDead 2427 && authorized_age conf base mother 2428 && get_death mother = NotDead then 2429 (d.day = conf.today.day && d.month = conf.today.month && 2430 d.year < conf.today.year) || 2431 (not (CheckItem.leap_year conf.today.year) && 2432 d.day = 29 && d.month = 2 && 2433 conf.today.day = 1 && conf.today.month = 3) 2434 else False 2435 | _ -> False ] 2436 | _ -> False ] 2437 | _ -> False ] 2438 | "computable_age" -> 2439 if p_auth then 2440 match (Adef.od_of_codate (get_birth p), get_death p) with 2441 [ (Some (Dgreg d _), NotDead) -> 2442 not (d.day = 0 && d.month = 0 && d.prec <> Sure) 2443 | _ -> False ] 2444 else False 2445 | "computable_death_age" -> 2446 if p_auth then 2447 match Date.get_birth_death_date p with 2448 [ (Some (Dgreg ({prec = Sure | About | Maybe} as d1) _), 2449 Some (Dgreg ({prec = Sure | About | Maybe} as d2) _), approx) 2450 when d1 <> d2 -> 2451 let a = CheckItem.time_elapsed d1 d2 in 2452 a.year > 0 || 2453 a.year = 0 && (a.month > 0 || a.month = 0 && a.day > 0) 2454 | _ -> False ] 2455 else False 2456 | "computable_marriage_age" -> 2457 match get_env "fam" env with 2458 [ Vfam _ fam _ m_auth -> 2459 if m_auth then 2460 match (Adef.od_of_codate (get_birth p), 2461 Adef.od_of_codate (get_marriage fam)) 2462 with 2463 [ (Some (Dgreg ({prec = Sure | About | Maybe} as d1) _), 2464 Some (Dgreg ({prec = Sure | About | Maybe} as d2) _)) -> 2465 let a = CheckItem.time_elapsed d1 d2 in 2466 (a.year > 0 || 2467 a.year = 0 && (a.month > 0 || a.month = 0 && a.day > 0)) 2468 | _ -> False ] 2469 else False 2470 | _ -> raise Not_found ] 2471 | "has_aliases" -> 2472 if not p_auth && (is_hide_names conf p) then False 2473 else get_aliases p <> [] 2474 | "has_baptism_date" -> p_auth && get_baptism p <> Adef.codate_None 2475 | "has_baptism_place" -> p_auth && sou base (get_baptism_place p) <> "" 2476 | "has_birth_date" -> p_auth && get_birth p <> Adef.codate_None 2477 | "has_birth_place" -> p_auth && sou base (get_birth_place p) <> "" 2478 | "has_burial_date" -> 2479 if p_auth then 2480 match get_burial p with 2481 [ Buried cod -> Adef.od_of_codate cod <> None 2482 | _ -> False ] 2483 else False 2484 | "has_burial_place" -> p_auth && sou base (get_burial_place p) <> "" 2485 | "has_children" -> 2486 match get_env "fam" env with 2487 [ Vfam _ fam _ _ -> Array.length (get_children fam) > 0 2488 | _ -> 2489 List.exists 2490 (fun ifam -> 2491 let des = foi base ifam in Array.length (get_children des) > 0) 2492 (Array.to_list (get_family p)) ] 2493 | "has_consanguinity" -> 2494 p_auth && get_consang p != Adef.fix (-1) && 2495 get_consang p >= Adef.fix_of_float 0.0001 2496 | "has_cremation_date" -> 2497 if p_auth then 2498 match get_burial p with 2499 [ Cremated cod -> Adef.od_of_codate cod <> None 2500 | _ -> False ] 2501 else False 2502 | "has_cremation_place" -> p_auth && sou base (get_burial_place p) <> "" 2503 | "has_death_date" -> 2504 match get_death p with 2505 [ Death _ _ -> p_auth 2506 | _ -> False ] 2507 | "has_death_place" -> p_auth && sou base (get_death_place p) <> "" 2508 | "has_families" -> Array.length (get_family p) > 0 2509 | "has_first_names_aliases" -> 2510 if not p_auth && (is_hide_names conf p) then False 2511 else get_first_names_aliases p <> [] 2512 | "has_history" -> 2513 let fn = sou base (get_first_name p) in 2514 let sn = sou base (get_surname p) in 2515 let occ = get_occ p in 2516 let person_file = History_diff.history_file fn sn occ in 2517 p_auth && (Sys.file_exists (History_diff.history_path conf person_file)) 2518 | "has_image" -> Util.has_image conf base p 2519 | "has_nephews_or_nieces" -> has_nephews_or_nieces conf base p 2520 | "has_nobility_titles" -> p_auth && nobtit conf base p <> [] 2521 | "has_notes" -> p_auth && not conf.no_note && sou base (get_notes p) <> "" 2522 | "has_occupation" -> p_auth && sou base (get_occupation p) <> "" 2523 | "has_parents" -> get_parents p <> None 2524 | "has_possible_duplications" -> has_possible_duplications conf base p 2525 | "has_public_name" -> 2526 if not p_auth && (is_hide_names conf p) then False 2527 else sou base (get_public_name p) <> "" 2528 | "has_qualifiers" -> 2529 if not p_auth && (is_hide_names conf p) then False 2530 else get_qualifiers p <> [] 2531 | "has_relations" -> 2532 if p_auth && conf.use_restrict then 2533 let related = 2534 List.fold_left 2535 (fun l ip -> 2536 let rp = pget conf base ip in 2537 if is_hidden rp then l else [ip :: l]) 2538 [] (get_related p) 2539 in 2540 get_rparents p <> [] || related <> [] 2541 else p_auth && (get_rparents p <> [] || get_related p <> []) 2542 | "has_siblings" -> 2543 match get_parents p with 2544 [ Some ifam -> Array.length (get_children (foi base ifam)) > 1 2545 | None -> False ] 2546 | "has_sources" -> 2547 p_auth && 2548 (sou base (get_psources p) <> "" || 2549 sou base (get_birth_src p) <> "" || 2550 sou base (get_baptism_src p) <> "" || 2551 sou base (get_death_src p) <> "" || 2552 sou base (get_burial_src p) <> "" || 2553 List.exists 2554 (fun ifam -> 2555 let fam = foi base ifam in 2556 let isp = Gutil.spouse (get_key_index p) fam in 2557 let sp = poi base isp in 2558 (* On sait que p_auth vaut vrai. *) 2559 let m_auth = authorized_age conf base sp in 2560 m_auth && 2561 (sou base (get_marriage_src fam) <> "" || 2562 sou base (get_fsources fam) <> "")) 2563 (Array.to_list (get_family p))) 2564 | "has_surnames_aliases" -> 2565 if not p_auth && (is_hide_names conf p) then False 2566 else get_surnames_aliases p <> [] 2567 | "is_buried" -> 2568 match get_burial p with 2569 [ Buried _ -> p_auth 2570 | _ -> False ] 2571 | "is_cremated" -> 2572 match get_burial p with 2573 [ Cremated _ -> p_auth 2574 | _ -> False ] 2575 | "is_dead" -> 2576 match get_death p with 2577 [ Death _ _ | DeadYoung | DeadDontKnowWhen -> p_auth 2578 | _ -> False ] 2579 | "is_descendant" -> 2580 match get_env "desc_mark" env with 2581 [ Vdmark r -> r.val.(Adef.int_of_iper (get_key_index p)) 2582 | _ -> raise Not_found ] 2583 | "is_female" -> get_sex p = Female 2584 | "is_invisible" -> 2585 let conf = {(conf) with wizard = False; friend = False} in 2586 not (authorized_age conf base p) 2587 | "is_male" -> get_sex p = Male 2588 | "is_private" -> get_access p = Private 2589 | "is_public" -> get_access p = Public 2590 | "is_restricted" -> is_hidden p 2591 | _ -> raise Not_found ] 2592and eval_str_person_field conf base env ((p, p_auth) as ep) = 2593 fun 2594 [ "access" -> acces conf base p 2595 | "age" -> 2596 match (p_auth, Adef.od_of_codate (get_birth p), get_death p) with 2597 [ (True, Some (Dgreg d _), NotDead) -> 2598 let a = CheckItem.time_elapsed d conf.today in 2599 Date.string_of_age conf a 2600 | _ -> "" ] 2601 | "alias" -> 2602 match get_aliases p with 2603 [ [nn :: _] -> 2604 if not p_auth && (is_hide_names conf p) then "" 2605 else sou base nn 2606 | _ -> "" ] 2607 | "auto_image_file_name" -> 2608 match auto_image_file conf base p with 2609 [ Some s when p_auth -> s 2610 | _ -> "" ] 2611 | "birth_place" -> 2612 if p_auth then Util.string_of_place conf (sou base (get_birth_place p)) 2613 else "" 2614 | "baptism_place" -> 2615 if p_auth then Util.string_of_place conf (sou base (get_baptism_place p)) 2616 else "" 2617 | "burial_place" -> 2618 if p_auth then Util.string_of_place conf (sou base(get_burial_place p)) 2619 else "" 2620 | "child_name" -> 2621 let force_surname = 2622 match get_parents p with 2623 [ None -> False 2624 | Some ifam -> 2625 p_surname base (pget conf base (get_father (foi base ifam))) <> 2626 p_surname base p ] 2627 in 2628 if not p_auth && (is_hide_names conf p) then "x x" 2629 else if force_surname then person_text conf base p 2630 else person_text_no_surn_no_acc_chk conf base p 2631 | "consanguinity" -> 2632 if p_auth then 2633 string_of_decimal_num conf 2634 (round_2_dec (Adef.float_of_fix (get_consang p) *. 100.0)) ^ "%" 2635 else "" 2636 | "cremation_place" -> 2637 if p_auth then Util.string_of_place conf (sou base (get_burial_place p)) 2638 else "" 2639 | "dates" -> 2640 if p_auth then Date.short_dates_text conf base p else "" 2641 | "death_age" -> 2642 if p_auth then 2643 match Date.get_birth_death_date p with 2644 [ (Some (Dgreg ({prec = Sure | About | Maybe} as d1) _), 2645 Some (Dgreg ({prec = Sure | About | Maybe} as d2) _), approx) 2646 when d1 <> d2 -> 2647 let a = CheckItem.time_elapsed d1 d2 in 2648 let s = 2649 if not approx && d1.prec = Sure && d2.prec = Sure then "" 2650 else transl_decline conf "possibly (date)" "" ^ " " 2651 in 2652 s ^ Date.string_of_age conf a 2653 | _ -> "" ] 2654 else "" 2655 | "death_place" -> 2656 if p_auth then Util.string_of_place conf (sou base (get_death_place p)) 2657 else "" 2658 | "died" -> string_of_died conf base env p p_auth 2659 | "fam_access" -> 2660 (* deprecated since 5.00: rather use "i=%family.index;;ip=%index;" *) 2661 match get_env "fam" env with 2662 [ Vfam ifam _ _ _ -> 2663 Printf.sprintf "i=%d;ip=%d" (Adef.int_of_ifam ifam) 2664 (Adef.int_of_iper (get_key_index p)) 2665 | _ -> raise Not_found ] 2666 | "father_age_at_birth" -> string_of_parent_age conf base ep get_father 2667 | "first_name" -> 2668 if not p_auth && (is_hide_names conf p) then "x" else p_first_name base p 2669 | "first_name_key" -> 2670 if (is_hide_names conf p) && not p_auth then "" 2671 else code_varenv (Name.lower (p_first_name base p)) 2672 | "first_name_key_val" -> 2673 if (is_hide_names conf p) && not p_auth then "" 2674 else Name.lower (p_first_name base p) 2675 | "first_name_key_strip" -> 2676 if (is_hide_names conf p) && not p_auth then "" 2677 else Name.strip_c (p_first_name base p) '"' 2678 | "history_file" -> 2679 if not p_auth then "" 2680 else 2681 let fn = sou base (get_first_name p) in 2682 let sn = sou base (get_surname p) in 2683 let occ = get_occ p in 2684 History_diff.history_file fn sn occ 2685 | "image" -> if not p_auth then "" else sou base (get_image p) 2686 | "image_html_url" -> string_of_image_url conf base env ep True 2687 | "image_size" -> string_of_image_size conf base env ep 2688 | "image_medium_size" -> string_of_image_medium_size conf base env ep 2689 | "image_small_size" -> string_of_image_small_size conf base env ep 2690 | "image_url" -> string_of_image_url conf base env ep False 2691 | "ind_access" -> 2692 (* deprecated since 5.00: rather use "i=%index;" *) 2693 "i=" ^ string_of_int (Adef.int_of_iper (get_key_index p)) 2694 | "index" -> string_of_int (Adef.int_of_iper (get_key_index p)) 2695 | "mark_descendants" -> 2696 match get_env "desc_mark" env with 2697 [ Vdmark r -> 2698 let tab = Array.make (nb_of_persons base) False in 2699 let rec mark_descendants len p = 2700 let i = Adef.int_of_iper (get_key_index p) in 2701 if tab.(i) then () 2702 else do { 2703 tab.(i) := True; 2704 let u = p in 2705 for i = 0 to Array.length (get_family u) - 1 do { 2706 let des = foi base (get_family u).(i) in 2707 for i = 0 to Array.length (get_children des) - 1 do { 2708 mark_descendants (len + 1) 2709 (pget conf base (get_children des).(i)) 2710 } 2711 } 2712 } 2713 in 2714 do { 2715 mark_descendants 0 p; 2716 r.val := tab; 2717 ""; 2718 } 2719 | _ -> raise Not_found ] 2720 | "marriage_age" -> 2721 match get_env "fam" env with 2722 [ Vfam _ fam _ m_auth -> 2723 if m_auth then 2724 match (Adef.od_of_codate (get_birth p), 2725 Adef.od_of_codate (get_marriage fam)) 2726 with 2727 [ (Some (Dgreg ({prec = Sure | About | Maybe} as d1) _), 2728 Some (Dgreg ({prec = Sure | About | Maybe} as d2) _)) -> 2729 let a = CheckItem.time_elapsed d1 d2 in 2730 Date.string_of_age conf a 2731 | _ -> "" ] 2732 else "" 2733 | _ -> raise Not_found ] 2734 | "mother_age_at_birth" -> string_of_parent_age conf base ep get_mother 2735 | "misc_names" -> 2736 if p_auth then 2737 let list = Gwdb.person_misc_names base p (Util.nobtit conf base) in 2738 let list = 2739 let first_name = p_first_name base p in 2740 let surname = p_surname base p in 2741 if first_name <> "?" && surname <> "?" then 2742 [Name.lower (first_name ^ " " ^ surname) :: list] 2743 else list 2744 in 2745 if list <> [] then 2746 "<ul>\n" ^ 2747 List.fold_left (fun s n -> s ^ "<li>" ^ n ^ "</li>\n") "" list ^ 2748 "</ul>\n" 2749 else "" 2750 else "" 2751 | "nb_children" -> 2752 match get_env "fam" env with 2753 [ Vfam _ fam _ _ -> string_of_int (Array.length (get_children fam)) 2754 | _ -> 2755 let n = 2756 List.fold_left 2757 (fun n ifam -> 2758 n + Array.length (get_children (foi base ifam))) 2759 0 (Array.to_list (get_family p)) 2760 in 2761 string_of_int n ] 2762 | "nb_families" -> string_of_int (Array.length (get_family p)) 2763 | "notes" -> 2764 if p_auth && not conf.no_note then 2765 let env = [('i', fun () -> Util.default_image_name base p)] in 2766 let s = sou base (get_notes p) in 2767 let s = string_with_macros conf env s in 2768 let lines = Wiki.html_of_tlsw conf s in 2769 let wi = 2770 {Wiki.wi_mode = "NOTES"; Wiki.wi_cancel_links = conf.cancel_links; 2771 Wiki.wi_file_path = Notes.file_path conf base; 2772 Wiki.wi_person_exists = person_exists conf base; 2773 Wiki.wi_always_show_link = conf.wizard || conf.friend} 2774 in 2775 let s = Wiki.syntax_links conf wi (String.concat "\n" lines) in 2776 if conf.pure_xhtml then Util.check_xhtml s else s 2777 else "" 2778 | "occ" -> 2779 if (is_hide_names conf p) && not p_auth then "" 2780 else string_of_int (get_occ p) 2781 | "occupation" -> 2782 if p_auth then 2783 let s = sou base (get_occupation p) in 2784 let s = 2785 let wi = 2786 {Wiki.wi_mode = "NOTES"; Wiki.wi_cancel_links = conf.cancel_links; 2787 Wiki.wi_file_path = Notes.file_path conf base; 2788 Wiki.wi_person_exists = person_exists conf base; 2789 Wiki.wi_always_show_link = conf.wizard || conf.friend} 2790 in 2791 Wiki.syntax_links conf wi s 2792 in 2793 string_with_macros conf [] s 2794 else "" 2795 | "on_baptism_date" -> 2796 match (p_auth, Adef.od_of_codate (get_baptism p)) with 2797 [ (True, Some d) -> 2798 match p_getenv conf.base_env "long_date" with 2799 [ Some "yes" -> (Date.string_of_ondate conf d) ^ (Date.get_wday conf d) 2800 | _ -> Date.string_of_ondate conf d ] 2801 | _ -> "" ] 2802 | "slash_baptism_date" -> 2803 match (p_auth, Adef.od_of_codate (get_baptism p)) with 2804 [ (True, Some d) -> Date.string_slash_of_date conf d 2805 | _ -> "" ] 2806 | "on_birth_date" -> 2807 match (p_auth, Adef.od_of_codate (get_birth p)) with 2808 [ (True, Some d) -> 2809 match p_getenv conf.base_env "long_date" with 2810 [ Some "yes" -> (Date.string_of_ondate conf d) ^ (Date.get_wday conf d) 2811 | _ -> Date.string_of_ondate conf d ] 2812 | _ -> "" ] 2813 | "slash_birth_date" -> 2814 match (p_auth, Adef.od_of_codate (get_birth p)) with 2815 [ (True, Some d) -> Date.string_slash_of_date conf d 2816 | _ -> "" ] 2817 | "on_burial_date" -> 2818 match get_burial p with 2819 [ Buried cod -> 2820 match (p_auth, Adef.od_of_codate cod) with 2821 [ (True, Some d) -> 2822 match p_getenv conf.base_env "long_date" with 2823 [ Some "yes" -> (Date.string_of_ondate conf d) ^ (Date.get_wday conf d) 2824 | _ -> Date.string_of_ondate conf d ] 2825 | _ -> "" ] 2826 | _ -> raise Not_found ] 2827 | "slash_burial_date" -> 2828 match get_burial p with 2829 [ Buried cod -> 2830 match (p_auth, Adef.od_of_codate cod) with 2831 [ (True, Some d) -> Date.string_slash_of_date conf d 2832 | _ -> "" ] 2833 | _ -> raise Not_found ] 2834 | "on_cremation_date" -> 2835 match get_burial p with 2836 [ Cremated cod -> 2837 match (p_auth, Adef.od_of_codate cod) with 2838 [ (True, Some d) -> 2839 match p_getenv conf.base_env "long_date" with 2840 [ Some "yes" -> (Date.string_of_ondate conf d) ^ (Date.get_wday conf d) 2841 | _ -> Date.string_of_ondate conf d ] 2842 | _ -> "" ] 2843 | _ -> raise Not_found ] 2844 | "slash_cremation_date" -> 2845 match get_burial p with 2846 [ Cremated cod -> 2847 match (p_auth, Adef.od_of_codate cod) with 2848 [ (True, Some d) -> Date.string_slash_of_date conf d 2849 | _ -> "" ] 2850 | _ -> raise Not_found ] 2851 | "on_death_date" -> 2852 match (p_auth, get_death p) with 2853 [ (True, Death _ d) -> 2854 let d = Adef.date_of_cdate d in 2855 match p_getenv conf.base_env "long_date" with 2856 [ Some "yes" -> (Date.string_of_ondate conf d) ^ (Date.get_wday conf d) 2857 | _ -> Date.string_of_ondate conf d ] 2858 | _ -> "" ] 2859 | "slash_death_date" -> 2860 match (p_auth, get_death p) with 2861 [ (True, Death _ d) -> 2862 let d = Adef.date_of_cdate d in 2863 Date.string_slash_of_date conf d 2864 | _ -> "" ] 2865 | "prev_fam_father" -> 2866 match get_env "prev_fam" env with 2867 [ Vfam _ fam (ifath, _, _) _ -> string_of_int (Adef.int_of_iper ifath) 2868 | _ -> raise Not_found ] 2869 | "prev_fam_index" -> 2870 match get_env "prev_fam" env with 2871 [ Vfam ifam _ _ _ -> string_of_int (Adef.int_of_ifam ifam) 2872 | _ -> raise Not_found ] 2873 | "prev_fam_mother" -> 2874 match get_env "prev_fam" env with 2875 [ Vfam _ fam (_, imoth, _) _ -> string_of_int (Adef.int_of_iper imoth) 2876 | _ -> raise Not_found ] 2877 | "public_name" -> 2878 if not p_auth && (is_hide_names conf p) then "" 2879 else sou base (get_public_name p) 2880 | "qualifier" -> 2881 match get_qualifiers p with 2882 [ [nn :: _] -> 2883 if not p_auth && (is_hide_names conf p) then "" 2884 else sou base nn 2885 | _ -> "" ] 2886 | "sex" -> 2887 (* Pour éviter les traductions bizarre, on ne teste pas p_auth. *) 2888 string_of_int (index_of_sex (get_sex p)) 2889 | "sosa_in_list" -> 2890 match get_env "all_gp" env with 2891 [ Vallgp all_gp -> 2892 match get_link all_gp (get_key_index p) with 2893 [ Some (GP_person s _ _) -> Num.to_string s 2894 | _ -> "" ] 2895 | _ -> raise Not_found ] 2896 | "sosa_link" -> 2897 match get_env "sosa" env with 2898 [ Vsosa x -> 2899 match get_sosa conf base env x p with 2900 [ Some (n, q) -> 2901 Printf.sprintf "m=RL;i1=%d;i2=%d;b1=1;b2=%s" 2902 (Adef.int_of_iper (get_key_index p)) 2903 (Adef.int_of_iper (get_key_index q)) 2904 (Num.to_string n) 2905 | None -> "" ] 2906 | _ -> raise Not_found ] 2907 | "source" -> 2908 match get_env "src" env with 2909 [ Vstring s -> 2910 let env = [('i', fun () -> Util.default_image_name base p)] in 2911 let s = 2912 let wi = 2913 {Wiki.wi_mode = "NOTES"; 2914 Wiki.wi_cancel_links = conf.cancel_links; 2915 Wiki.wi_file_path = Notes.file_path conf base; 2916 Wiki.wi_person_exists = person_exists conf base; 2917 Wiki.wi_always_show_link = conf.wizard || conf.friend} 2918 in 2919 Wiki.syntax_links conf wi s 2920 in 2921 string_with_macros conf env s 2922 | _ -> raise Not_found ] 2923 | "surname" -> 2924 if not p_auth && (is_hide_names conf p) then "x" else p_surname base p 2925 | "surname_begin" -> 2926 if not p_auth && (is_hide_names conf p) then "" 2927 else surname_begin base (p_surname base p) 2928 | "surname_end" -> 2929 if not p_auth && (is_hide_names conf p) then "x" 2930 else surname_end base (p_surname base p) 2931 | "surname_key" -> 2932 if (is_hide_names conf p) && not p_auth then "" 2933 else code_varenv (Name.lower (p_surname base p)) 2934 | "surname_key_val" -> 2935 if (is_hide_names conf p) && not p_auth then "" 2936 else Name.lower (p_surname base p) 2937 | "surname_key_strip" -> 2938 if (is_hide_names conf p) && not p_auth then "" 2939 else Name.strip_c (p_surname base p) '"' 2940 | "title" -> person_title conf base p 2941 | _ -> raise Not_found ] 2942and eval_witness_relation_var conf base env 2943 ((_, fam, (ip1, ip2, _), m_auth) as fcd) loc = 2944 fun 2945 [ [] -> 2946 if not m_auth then VVstring "" 2947 else 2948 let s = 2949 Printf.sprintf 2950 (ftransl conf "witness at marriage of %s and %s") 2951 (referenced_person_title_text conf base (pget conf base ip1)) 2952 (referenced_person_title_text conf base (pget conf base ip2)) 2953 in 2954 VVstring s 2955 | sl -> eval_family_field_var conf base env fcd loc sl ] 2956and eval_family_field_var conf base env 2957 ((ifam, fam, (ifath, imoth, _), m_auth) as fcd) loc 2958= 2959 fun 2960 [ ["father" :: sl] -> 2961 let ep = make_ep conf base ifath in 2962 eval_person_field_var conf base env ep loc sl 2963 | ["marriage_date" :: sl] -> 2964 match Adef.od_of_codate (get_marriage fam) with 2965 [ Some d when m_auth -> eval_date_field_var conf d sl 2966 | _ -> VVstring "" ] 2967 | ["mother" :: sl] -> 2968 let ep = make_ep conf base imoth in 2969 eval_person_field_var conf base env ep loc sl 2970 | [s] -> str_val (eval_str_family_field conf base env fcd loc s) 2971 | _ -> raise Not_found ] 2972and eval_str_family_field conf base env (ifam, _, _, _) loc = 2973 fun 2974 [ "desc_level" -> 2975 match get_env "desc_level_table" env with 2976 [ Vdesclevtab levt -> 2977 let (_, flevt) = Lazy.force levt in 2978 string_of_int (flevt.(Adef.int_of_ifam ifam)) 2979 | _ -> raise Not_found ] 2980 | "index" -> string_of_int (Adef.int_of_ifam ifam) 2981 | "set_infinite_desc_level" -> 2982 match get_env "desc_level_table" env with 2983 [ Vdesclevtab levt -> do { 2984 let (_, flevt) = Lazy.force levt in 2985 flevt.(Adef.int_of_ifam ifam) := infinite; 2986 "" 2987 } 2988 | _ -> raise Not_found ] 2989 | _ -> raise Not_found ] 2990and simple_person_text conf base p p_auth = 2991 if p_auth then 2992 match main_title conf base p with 2993 [ Some t -> titled_person_text conf base p t 2994 | None -> person_text conf base p ] 2995 else if (is_hide_names conf p) then "x x" 2996 else person_text conf base p 2997and string_of_died conf base env p p_auth = 2998 if p_auth then 2999 let is = index_of_sex (get_sex p) in 3000 match get_death p with 3001 [ Death dr _ -> 3002 match dr with 3003 [ Unspecified -> transl_nth conf "died" is 3004 | Murdered -> transl_nth conf "murdered" is 3005 | Killed -> transl_nth conf "killed (in action)" is 3006 | Executed -> transl_nth conf "executed (legally killed)" is 3007 | Disappeared -> transl_nth conf "disappeared" is ] 3008 | DeadYoung -> transl_nth conf "died young" is 3009 | DeadDontKnowWhen -> transl_nth conf "died" is 3010 | _ -> "" ] 3011 else "" 3012and string_of_image_url conf base env (p, p_auth) html = 3013 if p_auth then 3014 let v = 3015 image_and_size conf base p (limited_image_size max_im_wid max_im_wid) 3016 in 3017 match v with 3018 [ Some (True, fname, _) -> 3019 let s = Unix.stat fname in 3020 let b = acces conf base p in 3021 let k = default_image_name base p in 3022 Format.sprintf "%sm=IM%s;d=%d;%s;k=/%s" (commd conf) 3023 (if html then "H" else "") 3024 (int_of_float 3025 (mod_float s.Unix.st_mtime (float_of_int max_int))) 3026 b k 3027 | Some (False, link, _) -> link 3028 | None -> "" ] 3029 else "" 3030and string_of_parent_age conf base (p, p_auth) parent = 3031 match get_parents p with 3032 [ Some ifam -> 3033 let cpl = foi base ifam in 3034 let pp = pget conf base (parent cpl) in 3035 if p_auth && authorized_age conf base pp then 3036 match 3037 (Adef.od_of_codate (get_birth pp), Adef.od_of_codate (get_birth p)) 3038 with 3039 [ (Some (Dgreg d1 _), Some (Dgreg d2 _)) -> 3040 Date.string_of_age conf (CheckItem.time_elapsed d1 d2) 3041 | _ -> "" ] 3042 else "" 3043 | None -> raise Not_found ] 3044and string_of_int_env var env = 3045 match get_env var env with 3046 [ Vint x -> string_of_int x 3047 | _ -> raise Not_found ] 3048and obsolete_eval conf base env (p, p_auth) loc = 3049 fun 3050 [ "married_to" -> 3051 let s = 3052 match get_env "fam" env with 3053 [ Vfam _ fam (_, _, ispouse) m_auth -> 3054 let format = relation_txt conf (get_sex p) fam in 3055 Printf.sprintf (fcapitale format) 3056 (fun _ -> 3057 if m_auth then string_of_marriage_text conf base fam else "") 3058 | _ -> raise Not_found ] 3059 in 3060 obsolete loc "4.08" "married_to" "" (str_val s) 3061 | _ -> raise Not_found ] 3062; 3063 3064value eval_transl conf env upp s c = 3065 match c with 3066 [ "n" | "s" | "w" -> 3067 let n = 3068 match c with 3069 [ "n" -> 3070 (* replaced by %apply;nth([...],sex) *) 3071 match get_env "p" env with 3072 [ Vind p -> 1 - index_of_sex (get_sex p) 3073 | _ -> 2 ] 3074 | "s" -> 3075 match get_env "child" env with 3076 [ Vind p -> index_of_sex (get_sex p) 3077 | _ -> 3078 match get_env "p" env with 3079 [ Vind p -> index_of_sex (get_sex p) 3080 | _ -> 2 ] ] 3081 | "w" -> 3082 match get_env "fam" env with 3083 [ Vfam _ fam _ _ -> 3084 if Array.length (get_witnesses fam) = 1 then 0 else 1 3085 | _ -> 0 ] 3086 | _ -> assert False ] 3087 in 3088 let r = Util.translate_eval (Util.transl_nth conf s n) in 3089 if upp then capitale r else r 3090 | _ -> 3091 Templ.eval_transl conf upp s c ] 3092; 3093 3094value print_foreach conf base print_ast eval_expr = 3095 let eval_int_expr env ep e = 3096 let s = eval_expr env ep e in 3097 try int_of_string s with [ Failure _ -> raise Not_found ] 3098 in 3099 let rec print_foreach env ini_ep loc s sl ell al = 3100 let rec loop ((a, _) as ep) efam = 3101 fun 3102 [ [s] -> print_simple_foreach env ell al ini_ep ep efam loc s 3103 | ["ancestor" :: sl] -> 3104 let ip_ifamo = 3105 match get_env "ancestor" env with 3106 [ Vanc (GP_person _ ip ifamo) -> Some (ip, ifamo) 3107 | Vanc (GP_same _ _ ip) -> Some (ip, None) 3108 | _ -> None ] 3109 in 3110 match ip_ifamo with 3111 [ Some (ip, ifamo) -> 3112 let ep = make_ep conf base ip in 3113 let efam = 3114 match ifamo with 3115 [ Some ifam -> 3116 let (f, c, a) = make_efam conf base ip ifam in 3117 Vfam ifam f c a 3118 | None -> efam ] 3119 in 3120 loop ep efam sl 3121 | _ -> raise Not_found ] 3122 | ["child" :: sl] -> 3123 match get_env "child" env with 3124 [ Vind p -> 3125 let auth = authorized_age conf base p in 3126 let ep = (p, auth) in 3127 loop ep efam sl 3128 | _ -> raise Not_found ] 3129 | ["father" :: sl] -> 3130 match get_parents a with 3131 [ Some ifam -> 3132 let cpl = foi base ifam in 3133 let ((_, p_auth) as ep) = make_ep conf base (get_father cpl) in 3134 let ifath = get_father cpl in 3135 let cpl = (ifath, get_mother cpl, ifath) in 3136 let m_auth = 3137 p_auth && authorized_age conf base (pget conf base ifath) 3138 in 3139 let efam = Vfam ifam (foi base ifam) cpl m_auth in 3140 loop ep efam sl 3141 | None -> 3142 warning_use_has_parents_before_parent loc "father" () ] 3143 | ["mother" :: sl] -> 3144 match get_parents a with 3145 [ Some ifam -> 3146 let cpl = foi base ifam in 3147 let ((_, p_auth) as ep) = make_ep conf base (get_mother cpl) in 3148 let ifath = get_father cpl in 3149 let cpl = (ifath, get_mother cpl, ifath) in 3150 let m_auth = 3151 p_auth && authorized_age conf base (pget conf base ifath) 3152 in 3153 let efam = Vfam ifam (foi base ifam) cpl m_auth in 3154 loop ep efam sl 3155 | None -> 3156 warning_use_has_parents_before_parent loc "mother" () ] 3157 | ["self" :: sl] -> loop ep efam sl 3158 | ["spouse" :: sl] -> 3159 match efam with 3160 [ Vfam _ _ (_, _, ip) _ -> 3161 let ep = make_ep conf base ip in 3162 loop ep efam sl 3163 | _ -> raise Not_found ] 3164 | _ -> raise Not_found ] 3165 in 3166 let efam = get_env "fam" env in 3167 loop ini_ep efam [s :: sl] 3168 and print_simple_foreach env el al ini_ep ep efam loc = 3169 fun 3170 [ "alias" -> print_foreach_alias env al ep 3171 | "ancestor" -> print_foreach_ancestor env al ep 3172 | "ancestor_level" -> print_foreach_ancestor_level env el al ep 3173 | "ancestor_level2" -> print_foreach_ancestor_level2 env al ep 3174 | "ancestor_surname" -> print_foreach_anc_surn env el al loc ep 3175 | "ancestor_tree_line" -> print_foreach_ancestor_tree env el al ep 3176 | "cell" -> print_foreach_cell env el al ep 3177 | "child" -> print_foreach_child env al ep efam 3178 | "cousin_level" -> print_foreach_level "max_cous_level" env al ep 3179 | "descendant_level" -> print_foreach_descendant_level env al ep 3180 | "family" -> print_foreach_family env al ini_ep ep 3181 | "first_name_alias" -> print_foreach_first_name_alias env al ep 3182 | "nobility_title" -> print_foreach_nobility_title env al ep 3183 | "parent" -> print_foreach_parent env al ep 3184 | "qualifier" -> print_foreach_qualifier env al ep 3185 | "related" -> print_foreach_related env al ep 3186 | "relation" -> print_foreach_relation env al ep 3187 | "sorted_list_item" -> print_foreach_sorted_list_item env al ep 3188 | "source" -> print_foreach_source env al ep 3189 | "surname_alias" -> print_foreach_surname_alias env al ep 3190 | "witness" -> print_foreach_witness env al ep efam 3191 | "witness_relation" -> print_foreach_witness_relation env al ep 3192 | _ -> raise Not_found ] 3193 and print_foreach_alias env al ((p, p_auth) as ep) = 3194 if not p_auth && (is_hide_names conf p) then () 3195 else 3196 list_iter_first 3197 (fun first a -> 3198 let env = [("alias", Vstring (sou base a)) :: env] in 3199 let env = [("first", Vbool first) :: env] in 3200 List.iter (print_ast env ep) al) 3201 (get_aliases p) 3202 and print_foreach_ancestor env al ((p, p_auth) as ep) = 3203 match get_env "gpl" env with 3204 [ Vgpl gpl -> 3205 let rec loop first gpl = 3206 match gpl with 3207 [ [] -> () 3208 | [gp :: gl] -> do { 3209 match gp with 3210 [ GP_missing _ _ -> () 3211 | _ -> 3212 let env = 3213 [("ancestor", Vanc gp); 3214 ("first", Vbool first); ("last", Vbool (gl = [])) :: env] 3215 in 3216 List.iter (print_ast env ep) al ]; 3217 loop False gl } ] 3218 in loop True gpl 3219 | _ -> () ] 3220 and print_foreach_ancestor_level env el al ((p, _) as ep) = 3221 let max_level = 3222 match el with 3223 [ [[e]] -> eval_int_expr env ep e 3224 | [] -> 3225 match get_env "max_anc_level" env with 3226 [ Vint n -> n 3227 | _ -> 0 ] 3228 | _ -> raise Not_found ] 3229 in 3230 let mark = Array.make (nb_of_persons base) Num.zero in 3231 loop [GP_person Num.one (get_key_index p) None] 1 0 where rec loop gpl i n = 3232 if i > max_level then () 3233 else 3234 let n = 3235 List.fold_left 3236 (fun n gp -> 3237 match gp with 3238 [ GP_person _ _ _ -> n + 1 3239 | _ -> n ]) 3240 n gpl 3241 in 3242 let env = 3243 [("gpl", Vgpl gpl); ("level", Vint i); ("n", Vint n) :: env] 3244 in 3245 do { 3246 List.iter (print_ast env ep) al; 3247 let gpl = next_generation conf base mark gpl in 3248 loop gpl (succ i) n 3249 } 3250 and print_foreach_ancestor_level2 env al ((p, _) as ep) = 3251 let max_lev = "max_anc_level" in 3252 let max_level = 3253 match get_env max_lev env with 3254 [ Vint n -> n 3255 | _ -> 0 ] 3256 in 3257 let mark = Array.make (nb_of_persons base) Num.zero in 3258 loop [GP_person Num.one (get_key_index p) None] 1 where rec loop gpl i = 3259 if i > max_level then () 3260 else 3261 let env = [("gpl", Vgpl gpl); ("level", Vint i) :: env] in 3262 do { 3263 List.iter (print_ast env ep) al; 3264 for i = 0 to nb_of_persons base - 1 do { mark.(i) := Num.zero }; 3265 let gpl = next_generation2 conf base mark gpl in 3266 loop gpl (succ i) 3267 } 3268 and print_foreach_anc_surn env el al loc ((p, _) as ep) = 3269 let max_level = 3270 match el with 3271 [ [[e]] -> eval_int_expr env ep e 3272 | [] -> 3273 match get_env "max_anc_level" env with 3274 [ Vint n -> n 3275 | _ -> 0 ] 3276 | _ -> raise Not_found ] 3277 in 3278 (* En fonction du type de sortie demandé, on construit *) 3279 (* soit la liste des branches soit la liste éclair. *) 3280 match p_getenv conf.env "t" with 3281 [ Some "E" -> 3282 let list = build_list_eclair conf base max_level p in 3283 List.iter 3284 (fun (a, b, c, d, e, f) -> 3285 let env = 3286 [("ancestor", Vanc_surn (Eclair (a, b, c, d, e, f, loc))) :: env] 3287 in 3288 List.iter (print_ast env ep) al) 3289 list 3290 | Some "F" -> 3291 let list = build_surnames_list conf base max_level p in 3292 List.iter 3293 (fun (a, (((b, c, d), e), f)) -> 3294 let env = 3295 [("ancestor", Vanc_surn (Branch (a, b, c, d, e, f, loc))) :: env] 3296 in 3297 List.iter (print_ast env ep) al) 3298 list 3299 | _ -> () ] 3300 and print_foreach_ancestor_tree env el al ((p, _) as ep) = 3301 let (p, max_level) = 3302 match el with 3303 [ [[e1]; [e2]] -> 3304 let ip = eval_int_expr env ep e1 in 3305 let max_level = eval_int_expr env ep e2 in 3306 (pget conf base (Adef.iper_of_int ip), max_level) 3307 | [[e]] -> 3308 (p, eval_int_expr env ep e) 3309 | [] -> 3310 match get_env "max_anc_level" env with 3311 [ Vint n -> (p, n) 3312 | _ -> (p, 0) ] 3313 | _ -> raise Not_found ] 3314 in 3315 let gen = tree_generation_list conf base max_level p in 3316 loop True gen where rec loop first = 3317 fun 3318 [ [g :: gl] -> 3319 let env = 3320 [("celll", Vcelll g); ("first", Vbool first); 3321 ("last", Vbool (gl = [])) :: env] 3322 in 3323 do { 3324 List.iter (print_ast env ep) al; 3325 loop False gl 3326 } 3327 | [] -> () ] 3328 and print_foreach_cell env el al ((p, _) as ep) = 3329 let celll = 3330 match get_env "celll" env with 3331 [ Vcelll celll -> celll 3332 | _ -> raise Not_found ] 3333 in 3334 list_iter_first 3335 (fun first cell -> 3336 let env = [("cell", Vcell cell); ("first", Vbool first) :: env] in 3337 List.iter (print_ast env ep) al) 3338 celll 3339 and print_foreach_child env al ep = 3340 fun 3341 [ Vfam _ fam _ _ -> 3342 let auth = 3343 List.for_all 3344 (fun ip -> authorized_age conf base (pget conf base ip)) 3345 (Array.to_list (get_children fam)) 3346 in 3347 let env = [("auth", Vbool auth) :: env] in 3348 let n = 3349 let p = 3350 match get_env "p" env with 3351 [ Vind p -> p 3352 | _ -> assert False ] 3353 in 3354 let rec loop i = 3355 if i = Array.length (get_children fam) then -2 3356 else if (get_children fam).(i) = get_key_index p then i 3357 else loop (i + 1) 3358 in 3359 loop 0 3360 in 3361 Array.iteri 3362 (fun i ip -> 3363 let p = pget conf base ip in 3364 let env = [("#loop", Vint 0) :: env] in 3365 let env = [("child", Vind p) :: env] in 3366 let env = [("child_cnt", Vint (i + 1)) :: env] in 3367 let env = 3368 if i = n - 1 && not (is_hidden p) then 3369 [("pos", Vstring "prev") :: env] 3370 else if i = n then [("pos", Vstring "self") :: env] 3371 else if i = n + 1 && not (is_hidden p) then 3372 [("pos", Vstring "next") :: env] 3373 else env 3374 in 3375 let ep = (p, authorized_age conf base p) in 3376 List.iter (print_ast env ep) al) 3377 (get_children fam) 3378 | _ -> () ] 3379 and print_foreach_descendant_level env al ep = 3380 let max_level = 3381 match get_env "max_desc_level" env with 3382 [ Vint n -> n 3383 | _ -> 0 ] 3384 in 3385 loop 0 where rec loop i = 3386 if i > max_level then () 3387 else 3388 let env = [("level", Vint i) :: env] in 3389 do { 3390 List.iter (print_ast env ep) al; 3391 loop (succ i) 3392 } 3393 and print_foreach_family env al ini_ep (p, _) = 3394 loop None 0 where rec loop prev i = 3395 if i = Array.length (get_family p) then () 3396 else 3397 let ifam = (get_family p).(i) in 3398 let fam = foi base ifam in 3399 let ifath = get_father fam in 3400 let imoth = get_mother fam in 3401 let ispouse = spouse (get_key_index p) fam in 3402 let cpl = (ifath, imoth, ispouse) in 3403 let m_auth = 3404 authorized_age conf base (pget conf base ifath) && 3405 authorized_age conf base (pget conf base imoth) 3406 in 3407 let vfam = Vfam ifam fam cpl m_auth in 3408 let env = [("#loop", Vint 0) :: env] in 3409 let env = [("fam", vfam) :: env] in 3410 let env = [("family_cnt", Vint (i + 1)) :: env] in 3411 let env = 3412 match prev with 3413 [ Some vfam -> [("prev_fam", vfam) :: env] 3414 | None -> env ] 3415 in 3416 do { 3417 List.iter (print_ast env ini_ep) al; 3418 loop (Some vfam) (i + 1); 3419 } 3420 and print_foreach_first_name_alias env al ((p, p_auth) as ep) = 3421 if not p_auth && (is_hide_names conf p) then () 3422 else 3423 List.iter 3424 (fun s -> 3425 let env = [("first_name_alias", Vstring (sou base s)) :: env] in 3426 List.iter (print_ast env ep) al) 3427 (get_first_names_aliases p) 3428 and print_foreach_level max_lev env al ((p, _) as ep) = 3429 let max_level = 3430 match get_env max_lev env with 3431 [ Vint n -> n 3432 | _ -> 0 ] 3433 in 3434 loop 1 where rec loop i = 3435 if i > max_level then () 3436 else 3437 let env = [("level", Vint i) :: env] in 3438 do { 3439 List.iter (print_ast env ep) al; 3440 loop (succ i) 3441 } 3442 and print_foreach_nobility_title env al ((p, p_auth) as ep) = 3443 if p_auth then 3444 let titles = nobility_titles_list conf base p in 3445 list_iter_first 3446 (fun first x -> 3447 let env = [("nobility_title", Vtitle p x) :: env] in 3448 let env = [("first", Vbool first) :: env] in 3449 List.iter (print_ast env ep) al) 3450 titles 3451 else () 3452 and print_foreach_parent env al ((a, _) as ep) = 3453 match get_parents a with 3454 [ Some ifam -> 3455 let cpl = foi base ifam in 3456 Array.iter 3457 (fun iper -> 3458 let p = pget conf base iper in 3459 let env = [("parent", Vind p) :: env] in 3460 List.iter (print_ast env ep) al) 3461 (get_parent_array cpl) 3462 | None -> () ] 3463 and print_foreach_qualifier env al ((p, p_auth) as ep) = 3464 if not p_auth && (is_hide_names conf p) then () 3465 else 3466 list_iter_first 3467 (fun first nn -> 3468 let env = [("qualifier", Vstring (sou base nn)) :: env] in 3469 let env = [("first", Vbool first) :: env] in 3470 List.iter (print_ast env ep) al) 3471 (get_qualifiers p) 3472 and print_foreach_relation env al ((p, p_auth) as ep) = 3473 if p_auth then 3474 list_iter_first 3475 (fun first r -> 3476 let env = [("rel", Vrel r None) :: env] in 3477 let env = [("first", Vbool first) :: env] in 3478 List.iter (print_ast env ep) al) 3479 (get_rparents p) 3480 else () 3481 and print_foreach_related env al ((p, p_auth) as ep) = 3482 if p_auth then 3483 let list = 3484 let list = list_uniq (List.sort compare (get_related p)) in 3485 List.fold_left 3486 (fun list ic -> 3487 let c = pget conf base ic in 3488 loop list (get_rparents c) where rec loop list = 3489 fun 3490 [ [r :: rl] -> 3491 match r.r_fath with 3492 [ Some ip when ip = get_key_index p -> 3493 loop [(c, r) :: list] rl 3494 | _ -> 3495 match r.r_moth with 3496 [ Some ip when ip = get_key_index p -> 3497 loop [(c, r) :: list] rl 3498 | _ -> loop list rl ] ] 3499 | [] -> list ]) 3500 [] list 3501 in 3502 let list = 3503 List.sort 3504 (fun (c1, _) (c2, _) -> 3505 let d1 = 3506 match Adef.od_of_codate (get_baptism c1) with 3507 [ None -> Adef.od_of_codate (get_birth c1) 3508 | x -> x ] 3509 in 3510 let d2 = 3511 match Adef.od_of_codate (get_baptism c2) with 3512 [ None -> Adef.od_of_codate (get_birth c2) 3513 | x -> x ] 3514 in 3515 match (d1, d2) with 3516 [ (Some d1, Some d2) -> 3517 if CheckItem.strictly_before d1 d2 then -1 else 1 3518 | _ -> -1 ]) 3519 (List.rev list) 3520 in 3521 List.iter 3522 (fun (c, r) -> 3523 let env = [("rel", Vrel r (Some c)) :: env] in 3524 List.iter (print_ast env ep) al) 3525 list 3526 else () 3527 and print_foreach_sorted_list_item env al ep = 3528 let list = 3529 match get_env "list" env with 3530 [ Vslist l -> SortedList.elements l.val 3531 | _ -> [] ] 3532 in 3533 loop (Vslistlm []) list where rec loop prev_item = 3534 fun 3535 [ [_ :: sll] as gsll -> 3536 let item = Vslistlm gsll in 3537 let env = [("item", item); ("prev_item", prev_item) :: env] in 3538 do { 3539 List.iter (print_ast env ep) al; 3540 loop item sll 3541 } 3542 | [] -> () ] 3543 and print_foreach_source env al ((p, p_auth) as ep) = 3544 let rec insert_loop typ src = 3545 fun 3546 [ [(typ1, src1) :: srcl] -> 3547 if src = src1 then [(typ1 ^ ", " ^ typ, src1) :: srcl] 3548 else [(typ1, src1) :: insert_loop typ src srcl] 3549 | [] -> [(typ, src)] ] 3550 in 3551 let insert typ src srcl = 3552 if src = "" then srcl 3553 else insert_loop (Util.translate_eval typ) src srcl 3554 in 3555 let srcl = 3556 if p_auth then 3557 (* On ajoute les source dans cet ordre : *) 3558 (* psource, naissance, baptême, mariage, fsource, décès, inhumation. *) 3559 let srcl = [] in 3560 let srcl = 3561 insert (transl_nth conf "person/persons" 0) 3562 (sou base (get_psources p)) srcl 3563 in 3564 let srcl = 3565 insert (transl_nth conf "birth" 0) (sou base (get_birth_src p)) srcl 3566 in 3567 let srcl = 3568 insert 3569 (transl_nth conf "baptism" 0) (sou base (get_baptism_src p)) srcl 3570 in 3571 let (srcl, _) = 3572 Array.fold_left 3573 (fun (srcl, i) ifam -> 3574 let fam = foi base ifam in 3575 let isp = Gutil.spouse (get_key_index p) fam in 3576 let sp = poi base isp in 3577 (* On sait que p_auth vaut vrai. *) 3578 let m_auth = authorized_age conf base sp in 3579 if m_auth then 3580 let lab = 3581 if Array.length (get_family p) = 1 then "" 3582 else " " ^ string_of_int i 3583 in 3584 let srcl = 3585 let src_typ = transl_nth conf "marriage/marriages" 0 in 3586 insert (src_typ ^ lab) (sou base (get_marriage_src fam)) srcl 3587 in 3588 let src_typ = transl_nth conf "family/families" 0 in 3589 (insert (src_typ ^ lab) (sou base (get_fsources fam)) srcl, i + 1) 3590 else (srcl, i + 1)) 3591 (srcl, 1) (get_family p) 3592 in 3593 let srcl = 3594 insert (transl_nth conf "death" 0) (sou base (get_death_src p)) srcl 3595 in 3596 let srcl = 3597 insert (transl_nth conf "burial" 0) (sou base (get_burial_src p)) srcl 3598 in 3599 srcl 3600 else [] 3601 in 3602 (* Affiche les sources et met à jour les variables "first" et "last". *) 3603 let rec loop first = 3604 fun 3605 [ [(src_typ, src) :: srcl] -> 3606 let env = 3607 [("first", Vbool first); ("last", Vbool (srcl = [])); 3608 ("src_typ", Vstring src_typ); ("src", Vstring src) :: env] 3609 in 3610 do { 3611 List.iter (print_ast env ep) al; 3612 loop False srcl 3613 } 3614 | [] -> () ] 3615 in loop True srcl 3616 and print_foreach_surname_alias env al ((p, p_auth) as ep) = 3617 if not p_auth && (is_hide_names conf p) then () 3618 else 3619 List.iter 3620 (fun s -> 3621 let env = [("surname_alias", Vstring (sou base s)) :: env] in 3622 List.iter (print_ast env ep) al) 3623 (get_surnames_aliases p) 3624 and print_foreach_witness env al ep = 3625 fun 3626 [ Vfam _ fam _ True -> 3627 list_iter_first 3628 (fun first ip -> 3629 let p = pget conf base ip in 3630 let env = [("witness", Vind p) :: env] in 3631 let env = [("first", Vbool first) :: env] in 3632 List.iter (print_ast env ep) al) 3633 (Array.to_list (get_witnesses fam)) 3634 | _ -> () ] 3635 and print_foreach_witness_relation env al ((p, _) as ep) = 3636 let list = do { 3637 let list = ref [] in 3638 let related = list_uniq (List.sort compare (get_related p)) in 3639 make_list related where rec make_list = 3640 fun 3641 [ [ic :: icl] -> do { 3642 let c = pget conf base ic in 3643 if get_sex c = Male then 3644 Array.iter 3645 (fun ifam -> 3646 let fam = foi base ifam in 3647 if array_mem (get_key_index p) (get_witnesses fam) 3648 then 3649 list.val := [(ifam, fam) :: list.val] 3650 else ()) 3651 (get_family (pget conf base ic)) 3652 else (); 3653 make_list icl 3654 } 3655 | [] -> () ]; 3656 list.val 3657 } 3658 in 3659 let list = 3660 List.sort 3661 (fun (_, fam1) (_, fam2) -> 3662 match 3663 (Adef.od_of_codate (get_marriage fam1), 3664 Adef.od_of_codate (get_marriage fam2)) 3665 with 3666 [ (Some d1, Some d2) -> 3667 if CheckItem.strictly_before d1 d2 then -1 3668 else if CheckItem.strictly_before d2 d1 then 1 3669 else 0 3670 | _ -> 0 ]) 3671 list 3672 in 3673 List.iter 3674 (fun (ifam, fam) -> 3675 let ifath = get_father fam in 3676 let imoth = get_mother fam in 3677 let cpl = (ifath, imoth, imoth) in 3678 let m_auth = 3679 authorized_age conf base (pget conf base ifath) && 3680 authorized_age conf base (pget conf base imoth) 3681 in 3682 if m_auth then 3683 let env = [("fam", Vfam ifam fam cpl True) :: env] in 3684 List.iter (print_ast env ep) al 3685 else ()) 3686 list 3687 in 3688 print_foreach 3689; 3690 3691value eval_predefined_apply conf env f vl = 3692 let vl = List.map (fun [ VVstring s -> s | _ -> raise Not_found ]) vl in 3693 match (f, vl) with 3694 [ ("a_of_b", [s1; s2]) -> Util.translate_eval (transl_a_of_b conf s1 s2) 3695 | ("a_of_b_gr_eq_lev", [s1; s2]) -> 3696 Util.translate_eval (transl_a_of_gr_eq_gen_lev conf s1 s2) 3697 | ("add_in_sorted_list", sl) -> 3698 match get_env "list" env with 3699 [ Vslist l -> do { l.val := SortedList.add sl l.val; "" } 3700 | _ -> raise Not_found ] 3701 | ("hexa", [s]) -> Util.hexa_string s 3702 | ("initial", [s]) -> 3703 if String.length s = 0 then "" 3704 else String.sub s 0 (Util.index_of_next_char s 0) 3705 | ("lazy_print", [v]) -> 3706 match get_env "lazy_print" env with 3707 [ Vlazyp r -> do { r.val := Some v; "" } 3708 | _ -> raise Not_found ] 3709 | ("min", [s :: sl]) -> 3710 try 3711 let m = 3712 List.fold_right (fun s -> min (int_of_string s)) sl (int_of_string s) 3713 in 3714 string_of_int m 3715 with 3716 [ Failure _ -> raise Not_found ] 3717 | ("clean_html_tags", [s]) -> 3718 (* On supprime surtout les balises qui peuvent casser la mise en page. *) 3719 Util.clean_html_tags s 3720 ["<br */?>"; "</?p>"; "</?div>"; "</?span>"; "</?pre>"] 3721 | _ -> raise Not_found ] 3722; 3723 3724value gen_interp_templ menu title templ_fname conf base p = do { 3725 template_file.val := templ_fname ^ ".txt"; 3726 let ep = (p, authorized_age conf base p) in 3727 let emal = 3728 match p_getint conf.env "v" with 3729 [ Some i -> i 3730 | None -> 120 ] 3731 in 3732 let env = 3733 let sosa_ref = Util.find_sosa_ref conf base in 3734 let sosa_ref_l = 3735 let sosa_ref () = sosa_ref in 3736 Lazy.from_fun sosa_ref 3737 in 3738 let t_sosa = 3739 match sosa_ref with 3740 [ Some p -> init_sosa_t conf base p 3741 | _ -> 3742 { tstab = [| |]; 3743 mark = [| |]; 3744 last_zil = []; 3745 sosa_ht = Hashtbl.create 1} ] 3746 in 3747 let desc_level_table_l = 3748 let dlt () = make_desc_level_table conf base emal p in 3749 Lazy.from_fun dlt 3750 in 3751 let desc_level_table_l_save = 3752 let dlt () = make_desc_level_table conf base emal p in 3753 Lazy.from_fun dlt 3754 in 3755 let mal () = 3756 Vint (max_ancestor_level conf base (get_key_index p) emal + 1) 3757 in 3758 let mcl () = Vint (max_cousin_level conf base p) in 3759 let mdl () = Vint (max_descendant_level conf base desc_level_table_l) in 3760 let nldb () = 3761 let bdir = Util.base_path [] (conf.bname ^ ".gwb") in 3762 let fname = Filename.concat bdir "notes_links" in 3763 let db = NotesLinks.read_db_from_file fname in 3764 let db = Notes.merge_possible_aliases conf db in 3765 Vnldb db 3766 in 3767 let all_gp () = Vallgp (get_all_generations conf base p) in 3768 [("p", Vind p); 3769 ("p_auth", Vbool (authorized_age conf base p)); 3770 ("count", Vcnt (ref 0)); 3771 ("list", Vslist (ref SortedList.empty)); 3772 ("desc_mark", Vdmark (ref [| |])); 3773 ("lazy_print", Vlazyp (ref None)); 3774 ("sosa", Vsosa (ref [])); 3775 ("sosa_ref", Vsosa_ref sosa_ref_l); 3776 ("t_sosa", Vt_sosa t_sosa); 3777 ("max_anc_level", Vlazy (Lazy.from_fun mal)); 3778 ("max_cous_level", Vlazy (Lazy.from_fun mcl)); 3779 ("max_desc_level", Vlazy (Lazy.from_fun mdl)); 3780 ("desc_level_table", Vdesclevtab desc_level_table_l); 3781 ("desc_level_table_save", Vdesclevtab desc_level_table_l_save); 3782 ("nldb", Vlazy (Lazy.from_fun nldb)); 3783 ("all_gp", Vlazy (Lazy.from_fun all_gp))] 3784 in 3785 if menu then 3786 (* Petit calcul pour voir si le fichier est vide => on *) 3787 (* ne veut pas utiliser le header avec la barre de menu. *) 3788 let size = 3789 match Util.open_templ conf templ_fname with 3790 [ Some ic -> do { 3791 let fd = Unix.descr_of_in_channel ic in 3792 let stats = Unix.fstat fd in 3793 close_in ic; 3794 stats.Unix.st_size 3795 } 3796 | None -> 0 ] 3797 in 3798 if size = 0 then Hutil.header conf title 3799 else 3800 Hutil.interp_no_header conf base templ_fname 3801 {Templ.eval_var = eval_var conf base; 3802 Templ.eval_transl = eval_transl conf; 3803 Templ.eval_predefined_apply = eval_predefined_apply conf; 3804 Templ.get_vother = get_vother; Templ.set_vother = set_vother; 3805 Templ.print_foreach = print_foreach conf base} 3806 env ep 3807 else 3808 Hutil.interp conf base templ_fname 3809 {Templ.eval_var = eval_var conf base; 3810 Templ.eval_transl = eval_transl conf; 3811 Templ.eval_predefined_apply = eval_predefined_apply conf; 3812 Templ.get_vother = get_vother; Templ.set_vother = set_vother; 3813 Templ.print_foreach = print_foreach conf base} 3814 env ep 3815}; 3816 3817value interp_templ = gen_interp_templ False (fun _ -> ()); 3818value interp_templ_with_menu = gen_interp_templ True; 3819value interp_notempl_with_menu title templ_fname conf base p = do { 3820 (* On envoie le header car on n'est pas dans un template (exple: merge). *) 3821 Hutil.header_without_page_title conf title; 3822 gen_interp_templ True title templ_fname conf base p; 3823}; 3824 3825(* Main *) 3826 3827value print conf base p = 3828 let passwd = 3829 if conf.wizard || conf.friend then None 3830 else 3831 let src = 3832 match get_parents p with 3833 [ Some ifam -> sou base (get_origin_file (foi base ifam)) 3834 | None -> "" ] 3835 in 3836 try Some (src, List.assoc ("passwd_" ^ src) conf.base_env) with 3837 [ Not_found -> None ] 3838 in 3839 match passwd with 3840 [ Some (src, passwd) 3841 when is_that_user_and_password conf.auth_scheme "" passwd = False -> 3842 Util.unauthorized conf src 3843 | _ -> 3844 interp_templ "perso" conf base p ] 3845; 3846 3847value limit_by_tree conf = 3848 match p_getint conf.base_env "max_anc_tree" with 3849 [ Some x -> max 1 x 3850 | None -> 7 ] 3851; 3852 3853value print_ancestors_dag conf base v p = 3854 let v = min (limit_by_tree conf) v in 3855 let set = 3856 loop Dag.Pset.empty v (get_key_index p) where rec loop set lev ip = 3857 let set = Dag.Pset.add ip set in 3858 if lev <= 1 then set 3859 else 3860 match get_parents (pget conf base ip) with 3861 [ Some ifam -> 3862 let cpl = foi base ifam in 3863 let set = loop set (lev - 1) (get_mother cpl) in 3864 loop set (lev - 1) (get_father cpl) 3865 | None -> set ] 3866 in 3867 let elem_txt p = Dag.Item p "" in 3868 (* Récupère les options d'affichage. *) 3869 let options = Util.display_options conf in 3870 let vbar_txt ip = 3871 let p = pget conf base ip in 3872 Printf.sprintf "%sm=A;t=T;v=%d;%s;dag=on;%s" (commd conf) v options 3873 (acces conf base p) 3874 in 3875 let page_title = Util.capitale (Util.transl conf "tree") in 3876 Dag.make_and_print_dag conf base elem_txt vbar_txt True set [] page_title "" 3877; 3878 3879value print_ascend conf base p = 3880 match 3881 (p_getenv conf.env "t", p_getenv conf.env "dag", p_getint conf.env "v") 3882 with 3883 [ (Some "T", Some "on", Some v) -> print_ancestors_dag conf base v p 3884 | _ -> 3885 let templ = 3886 match p_getenv conf.env "t" with 3887 [ Some ("E" | "F" | "H" | "L") -> "anclist" 3888 | Some ("D" | "G" | "M" | "N" | "P" | "Z") -> "ancsosa" 3889 | Some ("A" | "C" | "T") -> "anctree" 3890 | _ -> "ancmenu" ] 3891 in 3892 interp_templ templ conf base p ] 3893; 3894 3895value print_what_links conf base p = 3896 if authorized_age conf base p then do { 3897 let key = 3898 let fn = Name.lower (sou base (get_first_name p)) in 3899 let sn = Name.lower (sou base (get_surname p)) in 3900 (fn, sn, get_occ p) 3901 in 3902 let bdir = Util.base_path [] (conf.bname ^ ".gwb") in 3903 let fname = Filename.concat bdir "notes_links" in 3904 let db = NotesLinks.read_db_from_file fname in 3905 let db = Notes.merge_possible_aliases conf db in 3906 let pgl = links_to_ind conf base db key in 3907 let title h = do { 3908 Wserver.wprint "%s: " (capitale (transl conf "linked pages")); 3909 if h then Wserver.wprint "%s" (simple_person_text conf base p True) 3910 else 3911 Wserver.wprint "<a href=\"%s%s\">%s</a>" (commd conf) 3912 (acces conf base p) (simple_person_text conf base p True) 3913 } 3914 in 3915 Hutil.header conf title; 3916 Hutil.print_link_to_welcome conf True; 3917 Notes.print_linked_list conf base pgl; 3918 Hutil.trailer conf; 3919 } 3920 else Hutil.incorrect_request conf 3921; 3922