+ | [ss;sn] -> {ET.ob = false; ET.os = stage_of_string ss; ET.on = name_of_string sn}
+ | _ -> failwith "oobj_of_string"
+
+let key_of_oobj o = string_of_name o.ET.on
+
+let oobj_selected o = o.ET.ob
+
+let oobj_select o =
+ o.ET.ob <- not o.ET.ob
+
+let oobj_compare o1 o2 =
+ let b = stage_compare o1.ET.os o2.ET.os in
+ if b = 0 then name_compare o1.ET.on o2.ET.on else b
+
+let oobj_union os1 os2 =
+ let error o = ET.EOClash o in
+ list_union error oobj_compare os1 os2
+
+let oobj_of_nobj v n =
+ {ET.ob = n.ET.nb; ET.os = v; ET.on = n.ET.nn}
+
+let rec oobj_match oi ni os ns =
+ match os, ns with
+ | _ , [] -> None
+ | [] , _ -> None
+ | o :: otl, n :: ntl ->
+ let b = name_compare o.ET.on n.ET.nn in
+ if b > 0 then oobj_match oi (succ ni) os ntl else
+ if b < 0 then oobj_match (succ oi) ni otl ns else
+ Some (oi, ni)
+
+(* robj *)
+
+let oobj_of_robj r =
+ let n = match r.ET.rn with
+ | [] -> []
+ | n :: _ -> n.ET.nn
+ in
+ {ET.ob = r.ET.rb; ET.os = r.ET.rs; ET.on = n}
+
+let string_of_robj r =
+ string_of_oobj (oobj_of_robj r)
+
+let key_of_robj r = key_of_oobj (oobj_of_robj r)
+
+let robj_selected r = r.ET.rb
+
+let robj_select r =
+ r.ET.rb <- not r.ET.rb
+
+let robj_expand r =
+ r.ET.rx <- not r.ET.rx
+
+let robj_compare r1 r2 =
+ oobj_compare (oobj_of_robj r1) (oobj_of_robj r2)
+
+let robj_union rs1 rs2 =
+ let error r = ET.ERClash r in
+ list_union error robj_compare rs1 rs2
+
+let rec robj_tops v = function
+ | [] -> [], []
+ | r :: tl ->
+ let ds, ts = robj_tops v tl in
+ if stage_compare v r.ET.rs = 0 then begin
+ if r.ET.rn = [] then oobj_union r.ET.ro ds, ts else
+ let tops = List.rev_map (oobj_of_nobj v) r.ET.rn in
+ ds, oobj_union (List.rev tops) ts
+ end else
+ ds, ts
+
+let robj_split s rs =
+ let rec aux rs os ns = function
+ | [] -> List.rev rs, os, ns
+ | r :: tl ->
+ if stage_compare s r.ET.rs <> 0 then aux (r :: rs) os ns tl else
+ if r.ET.rb then aux rs (oobj_union os r.ET.ro) (nobj_union ns r.ET.rn) tl else
+ let ro, so = list_split oobj_selected oobj_select r.ET.ro in
+ let rn, sn = list_split nobj_selected nobj_select r.ET.rn in
+ if ro = [] && rn = [] then aux rs (oobj_union os so) (nobj_union ns sn) tl else begin
+ r.ET.ro <- ro; r.ET.rn <- rn;
+ aux (r :: rs) (oobj_union os so) (nobj_union ns sn) tl
+ end
+ in
+ aux [] [] [] rs
+
+(* status *)