1999-12-16 04:25:11 -08:00
|
|
|
(*************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Objective Caml LablTk library *)
|
|
|
|
(* *)
|
|
|
|
(* Francois Rouaix, Francois Pessaux and Jun Furuse *)
|
|
|
|
(* projet Cristal, INRIA Rocquencourt *)
|
|
|
|
(* Jacques Garrigue, Kyoto University RIMS *)
|
|
|
|
(* *)
|
|
|
|
(* Copyright 1999 Institut National de Recherche en Informatique et *)
|
|
|
|
(* en Automatique and Kyoto University. All rights reserved. *)
|
|
|
|
(* This file is distributed under the terms of the GNU Library *)
|
|
|
|
(* General Public License. *)
|
|
|
|
(* *)
|
|
|
|
(*************************************************************************)
|
|
|
|
|
1999-11-30 06:59:39 -08:00
|
|
|
(* $Id$ *)
|
|
|
|
|
|
|
|
open Protocol
|
|
|
|
|
|
|
|
external internal_tracevar : string -> cbid -> unit
|
|
|
|
= "camltk_trace_var"
|
|
|
|
external internal_untracevar : string -> cbid -> unit
|
|
|
|
= "camltk_untrace_var"
|
2000-04-02 18:57:52 -07:00
|
|
|
external set : string -> string -> unit = "camltk_setvar"
|
1999-11-30 06:59:39 -08:00
|
|
|
external get : string -> string = "camltk_getvar"
|
|
|
|
|
|
|
|
|
|
|
|
type textVariable = string
|
|
|
|
|
|
|
|
(* List of handles *)
|
2000-04-02 18:57:52 -07:00
|
|
|
let handles = Hashtbl.create 401
|
1999-11-30 06:59:39 -08:00
|
|
|
|
|
|
|
let add_handle var cbid =
|
|
|
|
try
|
2000-04-02 18:57:52 -07:00
|
|
|
let r = Hashtbl.find handles var in
|
1999-11-30 06:59:39 -08:00
|
|
|
r := cbid :: !r
|
|
|
|
with
|
|
|
|
Not_found ->
|
2000-04-11 20:43:25 -07:00
|
|
|
Hashtbl.add handles ~key:var ~data:(ref [cbid])
|
1999-11-30 06:59:39 -08:00
|
|
|
|
|
|
|
let exceptq x =
|
|
|
|
let rec ex acc = function
|
|
|
|
[] -> acc
|
|
|
|
| y::l when y == x -> ex acc l
|
|
|
|
| y::l -> ex (y::acc) l
|
|
|
|
in
|
|
|
|
ex []
|
|
|
|
|
|
|
|
let rem_handle var cbid =
|
|
|
|
try
|
2000-04-02 18:57:52 -07:00
|
|
|
let r = Hashtbl.find handles var in
|
1999-11-30 06:59:39 -08:00
|
|
|
match exceptq cbid !r with
|
2000-04-02 18:57:52 -07:00
|
|
|
[] -> Hashtbl.remove handles var
|
1999-11-30 06:59:39 -08:00
|
|
|
| remaining -> r := remaining
|
|
|
|
with
|
|
|
|
Not_found -> ()
|
|
|
|
|
|
|
|
(* Used when we "free" the variable (otherwise, old handlers would apply to
|
|
|
|
* new usage of the variable)
|
|
|
|
*)
|
|
|
|
let rem_all_handles var =
|
|
|
|
try
|
2000-04-02 18:57:52 -07:00
|
|
|
let r = Hashtbl.find handles var in
|
2000-04-11 20:43:25 -07:00
|
|
|
List.iter ~f:(internal_untracevar var) !r;
|
2000-04-02 18:57:52 -07:00
|
|
|
Hashtbl.remove handles var
|
1999-11-30 06:59:39 -08:00
|
|
|
with
|
|
|
|
Not_found -> ()
|
|
|
|
|
|
|
|
|
|
|
|
(* Variable trace *)
|
2000-04-16 05:38:28 -07:00
|
|
|
let handle vname ~callback:f =
|
1999-11-30 06:59:39 -08:00
|
|
|
let id = new_function_id() in
|
|
|
|
let wrapped _ =
|
|
|
|
clear_callback id;
|
|
|
|
rem_handle vname id;
|
|
|
|
f() in
|
2000-04-11 20:43:25 -07:00
|
|
|
Hashtbl.add callback_naming_table ~key:id ~data:wrapped;
|
1999-11-30 06:59:39 -08:00
|
|
|
add_handle vname id;
|
|
|
|
if !Protocol.debug then begin
|
|
|
|
prerr_cbid id; prerr_string " for variable "; prerr_endline vname
|
|
|
|
end;
|
|
|
|
internal_tracevar vname id
|
|
|
|
|
|
|
|
(* Avoid space leak (all variables are global in Tcl) *)
|
|
|
|
module StringSet =
|
|
|
|
Set.Make(struct type t = string let compare = compare end)
|
|
|
|
let freelist = ref (StringSet.empty)
|
2000-04-02 18:57:52 -07:00
|
|
|
let memo = Hashtbl.create 101
|
1999-11-30 06:59:39 -08:00
|
|
|
|
|
|
|
(* Added a variable v referenced by widget w *)
|
|
|
|
let add w v =
|
|
|
|
let w = Widget.forget_type w in
|
|
|
|
let r =
|
2000-04-02 18:57:52 -07:00
|
|
|
try Hashtbl.find memo w
|
1999-11-30 06:59:39 -08:00
|
|
|
with
|
|
|
|
Not_found ->
|
|
|
|
let r = ref StringSet.empty in
|
2000-04-11 20:43:25 -07:00
|
|
|
Hashtbl.add memo ~key:w ~data:r;
|
1999-11-30 06:59:39 -08:00
|
|
|
r in
|
2000-04-02 18:57:52 -07:00
|
|
|
r := StringSet.add v !r
|
1999-11-30 06:59:39 -08:00
|
|
|
|
|
|
|
(* to be used with care ! *)
|
|
|
|
let free v =
|
|
|
|
rem_all_handles v;
|
2000-04-02 18:57:52 -07:00
|
|
|
freelist := StringSet.add v !freelist
|
1999-11-30 06:59:39 -08:00
|
|
|
|
|
|
|
(* Free variables associated with a widget *)
|
|
|
|
let freew w =
|
|
|
|
try
|
2000-04-02 18:57:52 -07:00
|
|
|
let r = Hashtbl.find memo w in
|
2000-04-11 20:43:25 -07:00
|
|
|
StringSet.iter ~f:free !r;
|
2000-04-02 18:57:52 -07:00
|
|
|
Hashtbl.remove memo w
|
1999-11-30 06:59:39 -08:00
|
|
|
with
|
|
|
|
Not_found -> ()
|
|
|
|
|
|
|
|
let _ = add_destroy_hook freew
|
|
|
|
|
|
|
|
(* Allocate a new variable *)
|
|
|
|
let counter = ref 0
|
|
|
|
let getv () =
|
|
|
|
let v =
|
|
|
|
if StringSet.is_empty !freelist then begin
|
|
|
|
incr counter;
|
|
|
|
"camlv("^ string_of_int !counter ^")"
|
|
|
|
end
|
|
|
|
else
|
|
|
|
let v = StringSet.choose !freelist in
|
2000-04-02 18:57:52 -07:00
|
|
|
freelist := StringSet.remove v !freelist;
|
1999-11-30 06:59:39 -08:00
|
|
|
v in
|
2000-04-02 18:57:52 -07:00
|
|
|
set v "";
|
1999-11-30 06:59:39 -08:00
|
|
|
v
|
|
|
|
|
|
|
|
let create ?on: w () =
|
|
|
|
let v = getv() in
|
|
|
|
begin
|
|
|
|
match w with
|
|
|
|
Some w -> add w v
|
|
|
|
| None -> ()
|
|
|
|
end;
|
|
|
|
v
|
|
|
|
|
|
|
|
(* to be used with care ! *)
|
|
|
|
let free v =
|
2000-04-02 18:57:52 -07:00
|
|
|
freelist := StringSet.add v !freelist
|
1999-11-30 06:59:39 -08:00
|
|
|
|
|
|
|
let cCAMLtoTKtextVariable s = TkToken s
|
|
|
|
|
|
|
|
let name s = s
|
|
|
|
let coerce s = s
|
|
|
|
|