Blame support/textvariable.ml

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