(* camlp4r ./pa_html.cmo *)
(* $Id: alln.ml,v 4.6.2.1 2006/01/03 12:04:10 ddr Exp $ *)
(* Copyright (c) 1998-2005 INRIA *)
open Def;
open Config;
open Util;
open Gutil;
(* tools *)
value string_start_with ini s =
loop 0 0 where rec loop i1 i2 =
if i1 == String.length ini then True
else if i2 == String.length s then
if ini.[i1] == '_' then loop (i1 + 1) i2 else False
else if s.[i2] == ini.[i1] || s.[i2] == ' ' && ini.[i1] == '_' then
loop (i1 + 1) (i2 + 1)
else False
;
value combine_by_ini ini list =
let list =
loop [] list where rec loop new_list =
fun
[ [] -> new_list
| [(k, s, cnt) :: list] ->
let ini_k =
if String.length k > String.length ini then
String.sub k 0 (String.length ini + 1)
else k ^ String.make (String.length ini + 1 - String.length k) '_'
in
do {
for i = 0 to String.length ini_k - 1 do {
if ini_k.[i] == ' ' then ini_k.[i] := '_' else ()
};
let new_list =
if ini_k = "_" then new_list
else
match new_list with
[ [] -> [(ini_k, [(s, cnt)])]
| [(ini_k1, l) :: ll] ->
if ini_k1 = ini_k then [(ini_k1, [(s, cnt) :: l]) :: ll]
else [(ini_k, [(s, cnt)]); (ini_k1, l) :: ll] ]
in
loop new_list list
} ]
in
List.fold_left (fun new_l (ini_k, l) -> [(ini_k, List.rev l) :: new_l]) []
list
;
value combine_by_count list =
let list =
loop [] list where rec loop new_list =
fun
[ [] -> new_list
| [(_, s, cnt) :: list] ->
let new_list =
match new_list with
[ [] -> [(cnt, [s])]
| [(cnt1, l) :: ll] ->
if cnt1 = cnt then [(cnt1, [s :: l]) :: ll]
else [(cnt, [s]); (cnt1, l) :: ll] ]
in
loop new_list list ]
in
List.fold_left (fun new_l (cnt, l) -> [(cnt, List.rev l) :: new_l]) [] list
;
value alphab_string conf is_surname s =
if is_surname then surname_end s ^ surname_begin s else s
;
(* print *)
value print_title conf base is_surnames ini len =
do {
if len >= 2 then
if is_surnames then
Wserver.wprint (fcapitale (ftransl conf "the %d surnames")) len
else Wserver.wprint (fcapitale (ftransl conf "the %d first names")) len
else if is_surnames then
Wserver.wprint "%s" (capitale (transl_nth conf "surname/surnames" 0))
else
Wserver.wprint "%s"
(capitale (transl_nth conf "first name/first names" 0));
if ini <> "" then
Wserver.wprint " %s %s" (transl conf "starting with")
(String.capitalize ini)
else
Wserver.wprint " (%d %s)" base.data.persons.len
(nominative (transl_nth_def conf "person/persons" 2 1));
}
;
value print_alphabetic_big conf base is_surnames ini list len =
let title _ = print_title conf base is_surnames ini len in
let mode = if is_surnames then "N" else "P" in
do {
header conf title;
List.iter
(fun (ini_k, _) ->
do {
stag "a" "href=\"%sm=%s;tri=A;k=%s\"" (commd conf) mode ini_k begin
Wserver.wprint "%s" (String.capitalize ini_k);
end;
Wserver.wprint "\n";
})
list;
html_p conf;
Wserver.wprint "%s:\n" (capitale (transl conf "the whole list"));
tag "ul" begin
html_li conf;
stag "a" "href=\"%sm=%s;tri=A;o=A;k=%s\"" (commd conf) mode ini begin
Wserver.wprint "%s" (transl conf "long display");
end;
Wserver.wprint "\n";
html_li conf;
stag "a" "href=\"%sm=%s;tri=S;o=A;k=%s\"" (commd conf) mode ini begin
Wserver.wprint "%s" (transl conf "short display");
end;
Wserver.wprint "\n";
html_li conf;
stag "a" "href=\"%sm=%s;tri=S;o=A;k=%s;cgl=on\"" (commd conf) mode ini
begin
Wserver.wprint "%s + %s" (transl conf "short display")
(transl conf "cancel GeneWeb links");
end;
Wserver.wprint "\n";
end;
trailer conf;
}
;
value print_alphabetic_all conf base is_surnames ini list len =
let title _ = print_title conf base is_surnames ini len in
let mode = if is_surnames then "N" else "P" in
do {
header conf title;
List.iter
(fun (ini_k, _) ->
do {
stag "a" "href=\"#%s\"" ini_k begin
Wserver.wprint "%s" (String.capitalize ini_k);
end;
Wserver.wprint "\n";
})
list;
tag "ul" begin
List.iter
(fun (ini_k, l) ->
do {
html_li conf;
stag "a" "name=\"%s\"" ini_k begin
Wserver.wprint "%s" (String.capitalize ini_k);
end;
Wserver.wprint "\n";
tag "ul" begin
List.iter
(fun (s, cnt) ->
do {
html_li conf;
let href =
"m=" ^ mode ^ ";v=" ^ code_varenv (Name.lower s)
in
wprint_geneweb_link conf href
(alphab_string conf is_surnames s);
Wserver.wprint " (%d)\n" cnt;
})
l;
end;
})
list;
end;
trailer conf;
}
;
value print_alphabetic_small conf base is_surnames ini list len =
let title _ = print_title conf base is_surnames ini len in
let mode = if is_surnames then "N" else "P" in
do {
header conf title;
tag "ul" begin
List.iter
(fun (_, s, cnt) ->
do {
html_li conf;
stag "a" "href=\"%sm=%s;v=%s\"" (commd conf) mode
(code_varenv (Name.lower s)) begin
Wserver.wprint "%s" (alphab_string conf is_surnames s);
end;
Wserver.wprint " (%d)\n" cnt;
})
list;
end;
trailer conf;
}
;
value print_frequency_any conf base is_surnames list len =
let title _ = print_title conf base is_surnames "" len in
let mode = if is_surnames then "N" else "P" in
do {
header conf title;
tag "ul" begin
List.iter
(fun (cnt, l) ->
do {
html_li conf;
Wserver.wprint "%d\n" cnt;
tag "ul" begin
List.iter
(fun s ->
do {
html_li conf;
stag "a" "href=\"%sm=%s;v=%s\"" (commd conf) mode
(code_varenv (Name.lower s)) begin
Wserver.wprint "%s"
(alphab_string conf is_surnames s);
end;
Wserver.wprint "\n";
})
l;
end;
})
list;
end;
trailer conf;
}
;
(* selection *)
(* version using the index *)
value select_names conf base is_surnames ini =
let iii =
if is_surnames then base.func.persons_of_surname
else base.func.persons_of_first_name
in
let list =
let start_k =
if String.length ini > 0 && ini.[String.length ini - 1] == '_' then
String.sub ini 0 (String.length ini - 1)
else ini
in
match
try Some (iii.cursor (String.capitalize start_k)) with
[ Not_found -> None ]
with
[ Some istr ->
loop istr [] where rec loop istr list =
let s = nominative (sou base istr) in
let k = Iobase.name_key s in
if string_start_with ini k then
let list =
if s <> "?" then
let my_list = iii.find istr in
let my_list =
if conf.use_restrict then
List.fold_left
(fun l ip ->
if is_restricted conf base ip then l
else [ip :: l])
[] my_list
else my_list
in
let cnt = List.length my_list in
(*let cnt = List.length (iii.find istr) in*)
if cnt = 0 then list
else
match list with
[ [(k1, s1, cnt1) :: list1] ->
if k = k1 then [(k1, s1, cnt1 + cnt) :: list1]
else [(k, s, cnt) :: list]
| [] -> [(k, s, cnt)] ]
else list
in
match try Some (iii.next istr) with [ Not_found -> None ] with
[ Some istr -> loop istr list
| None -> list ]
else list
| None -> [] ]
in
let list =
let lim =
match p_getint conf.env "atleast" with
[ Some x -> x
| None -> 0 ]
in
List.fold_left
(fun list (k, s, cnt) ->
if cnt >= lim then [(k, s, cnt) :: list] else list)
[] list
in
(list, True)
;
value print_frequency conf base is_surnames =
let _ = base.data.strings.array () in
let list =
let (list, _) = select_names conf base is_surnames "" in
List.sort
(fun (k1, _, cnt1) (k2, _, cnt2) ->
if cnt1 > cnt2 then -1
else if cnt1 < cnt2 then 1
else if k1 < k2 then -1
else if k1 > k2 then 1
else 0)
list
in
let len = List.length list in
let list = combine_by_count list in
print_frequency_any conf base is_surnames list len
;
value print_alphabetic conf base is_surnames =
let ini =
match p_getenv conf.env "k" with
[ Some k -> String.lowercase k
| _ -> "" ]
in
let fast =
p_getenv conf.base_env "fast_alphabetic" = Some "yes" && ini = ""
in
let _ =
if fast || String.length ini < 2 then
let _ = base.data.strings.array () in ()
else ()
in
let all =
match p_getenv conf.env "o" with
[ Some "A" -> True
| _ -> False ]
in
let list =
if fast then
let list =
loop [] 'Z' where rec loop list c =
let list = [(String.make 1 c, "", 1) :: list] in
if c = 'A' then list else loop list (Char.chr (Char.code c - 1))
in
list
else
let (list, sorted) = select_names conf base is_surnames ini in
if sorted then list
else Sort.list (fun (k1, _, _) (k2, _, _) -> k1 <= k2) list
in
let len = List.length list in
if fast then
let list = List.map (fun (s, _, _) -> (s, 1)) list in
print_alphabetic_big conf base is_surnames ini list 1
else if len >= 50 then
let list = combine_by_ini ini list in
if all then print_alphabetic_all conf base is_surnames ini list len
else print_alphabetic_big conf base is_surnames ini list len
else print_alphabetic_small conf base is_surnames ini list len
;
(* short print *)
value print_alphabetic_short conf base is_surnames ini list len =
let title _ = print_title conf base is_surnames ini len in
let mode = if is_surnames then "N" else "P" in
let need_ref = len >= 250 in
do {
header conf title;
if need_ref then
List.iter
(fun (ini_k, _) ->
do {
stag "a" "href=\"#%s\"" ini_k begin
Wserver.wprint "%s" (String.capitalize ini_k);
end;
Wserver.wprint "\n";
})
list
else ();
List.iter
(fun (ini_k, l) ->
do {
html_p conf;
list_iter_first
(fun first (s, cnt) ->
let href =
if not conf.cancel_links then
" href=\"" ^ commd conf ^ "m=" ^ mode ^ ";v=" ^
code_varenv (Name.lower s) ^ "\""
else ""
in
let name =
if first && need_ref then " name=" ^ ini_k else ""
in
do {
if not first then Wserver.wprint ",\n" else ();
if href <> "" || name <> "" then
Wserver.wprint "" href name
else ();
Wserver.wprint "%s" (alphab_string conf is_surnames s);
if href <> "" || name <> "" then Wserver.wprint ""
else ();
Wserver.wprint " (%d)" cnt;
})
l;
Wserver.wprint "\n";
})
list;
trailer conf;
}
;
value print_short conf base is_surnames =
let ini =
match p_getenv conf.env "k" with
[ Some k -> String.lowercase k
| _ -> "" ]
in
let _ =
if String.length ini < 2 then let _ = base.data.strings.array () in ()
else ()
in
let list =
let (list, sorted) = select_names conf base is_surnames ini in
if sorted then list
else Sort.list (fun (k1, _, _) (k2, _, _) -> k1 <= k2) list
in
let len = List.length list in
let list = combine_by_ini ini list in
print_alphabetic_short conf base is_surnames ini list len
;
(* main *)
value print_surnames conf base =
match p_getenv conf.env "tri" with
[ Some "F" -> print_frequency conf base True
| Some "S" -> print_short conf base True
| _ -> print_alphabetic conf base True ]
;
value print_first_names conf base =
match p_getenv conf.env "tri" with
[ Some "F" -> print_frequency conf base False
| Some "S" -> print_short conf base False
| _ -> print_alphabetic conf base False ]
;