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