diff options
Diffstat (limited to 'otherlibs/labltk/browser')
-rw-r--r-- | otherlibs/labltk/browser/.cvsignore | 1 | ||||
-rw-r--r-- | otherlibs/labltk/browser/Makefile | 6 | ||||
-rw-r--r-- | otherlibs/labltk/browser/Makefile.nt | 52 | ||||
-rw-r--r-- | otherlibs/labltk/browser/dummyUnix.mli | 32 | ||||
-rw-r--r-- | otherlibs/labltk/browser/dummyWin.mli | 14 | ||||
-rw-r--r-- | otherlibs/labltk/browser/jg_config.ml | 9 | ||||
-rw-r--r-- | otherlibs/labltk/browser/shell.ml | 116 |
7 files changed, 206 insertions, 24 deletions
diff --git a/otherlibs/labltk/browser/.cvsignore b/otherlibs/labltk/browser/.cvsignore index f3f03276e..8ced21de2 100644 --- a/otherlibs/labltk/browser/.cvsignore +++ b/otherlibs/labltk/browser/.cvsignore @@ -1 +1,2 @@ ocamlbrowser +dummy.mli diff --git a/otherlibs/labltk/browser/Makefile b/otherlibs/labltk/browser/Makefile index 9dfed9517..7f2875703 100644 --- a/otherlibs/labltk/browser/Makefile +++ b/otherlibs/labltk/browser/Makefile @@ -40,9 +40,13 @@ install: if test -f ocamlbrowser; then : ; cp ocamlbrowser $(BINDIR); fi clean: - rm -f *.cm? ocamlbrowser *~ *.orig + rm -f *.cm? ocamlbrowser dummy.mli *~ *.orig depend: $(LABLDEP) *.ml *.mli > .depend +dummy.mli: + ln -sf dummyUnix.mli dummy.mli +shell.cmo: dummy.cmi + include .depend diff --git a/otherlibs/labltk/browser/Makefile.nt b/otherlibs/labltk/browser/Makefile.nt new file mode 100644 index 000000000..8b67c8f2e --- /dev/null +++ b/otherlibs/labltk/browser/Makefile.nt @@ -0,0 +1,52 @@ +!include ..\support\Makefile.common.nt + +LABLTKLIB=-I ../lib -I ../support +OTHERSLIB=-I $(OTHERS)/unix -I $(OTHERS)/str -I $(OTHERS)/systhreads +OCAMLTOPLIB=-I $(TOPDIR)/parsing -I $(TOPDIR)/utils -I $(TOPDIR)/typing +INCLUDES=$(OTHERSLIB) $(LABLTKLIB) $(OCAMLTOPLIB) +CLIBS=../support/liblabltk41.lib $(OTHERS)/str/libstr.lib $(OTHERS)/win32unix/libunix.lib $(OTHERS)/systhreads/libthreads.lib + +OBJ = list2.cmo useunix.cmo setpath.cmo lexical.cmo \ + fileselect.cmo searchid.cmo searchpos.cmo shell.cmo \ + viewer.cmo typecheck.cmo editor.cmo main.cmo + +JG = jg_tk.cmo jg_config.cmo jg_bind.cmo jg_completion.cmo \ + jg_box.cmo \ + jg_button.cmo jg_toplevel.cmo jg_text.cmo jg_message.cmo \ + jg_menu.cmo jg_entry.cmo jg_multibox.cmo jg_memo.cmo + +# Default rules + +.SUFFIXES: .ml .mli .cmo .cmi .cmx + +.ml.cmo: + $(LABLCOMP) $(INCLUDES) $< + +.mli.cmi: + $(LABLCOMP) $(INCLUDES) $< + +all: ocamlbrowser + +ocamlbrowser: $(TOPDIR)/toplevel/toplevellib.cma jglib.cma $(OBJ) + $(LABLC) -custom -o ocamlbrowser $(INCLUDES) \ + $(TOPDIR)/toplevel/toplevellib.cma \ + unix.cma threads.cma str.cma tk41.cma jglib.cma $(OBJ) \ + -cclib "$(CLIBS)" $(TKLINKOPT) + +jglib.cma: $(JG) + $(LABLCOMP) -a -o jglib.cma $(JG) + +install: + if exist ocamlbrowser.exe cp ocamlbrowser.exe $(BINDIR) + +clean: + rm -f *.cm? ocamlbrowser dummy.mli *~ *.orig + +depend: + $(LABLDEP) *.ml *.mli > .depend + +dummy.mli: + cp dummyWin.mli dummy.mli +shell.cmo: dummy.cmi + +!include .depend diff --git a/otherlibs/labltk/browser/dummyUnix.mli b/otherlibs/labltk/browser/dummyUnix.mli new file mode 100644 index 000000000..b2ce9e04d --- /dev/null +++ b/otherlibs/labltk/browser/dummyUnix.mli @@ -0,0 +1,32 @@ +(*************************************************************************) +(* *) +(* Objective Caml LablTk library *) +(* *) +(* Jacques Garrigue, Kyoto University RIMS *) +(* *) +(* Copyright 2000 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. *) +(* *) +(*************************************************************************) + +(* $Id$ *) + +module Mutex : sig + type t + external create : unit -> t = "%ignore" + external lock : t -> unit = "%ignore" + external unlock : t -> unit = "%ignore" +end + +module Thread : sig + type t + external create : ('a -> 'b) -> 'a -> t = "caml_input" +end + +module ThreadUnix : sig + open Unix + external read : file_descr -> buf:string -> pos:int -> len:int -> int + = "caml_input" +end diff --git a/otherlibs/labltk/browser/dummyWin.mli b/otherlibs/labltk/browser/dummyWin.mli new file mode 100644 index 000000000..124ada5eb --- /dev/null +++ b/otherlibs/labltk/browser/dummyWin.mli @@ -0,0 +1,14 @@ +(*************************************************************************) +(* *) +(* Objective Caml LablTk library *) +(* *) +(* Jacques Garrigue, Kyoto University RIMS *) +(* *) +(* Copyright 2000 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. *) +(* *) +(*************************************************************************) + +(* $Id$ *) diff --git a/otherlibs/labltk/browser/jg_config.ml b/otherlibs/labltk/browser/jg_config.ml index 63df1387b..49500e2fc 100644 --- a/otherlibs/labltk/browser/jg_config.ml +++ b/otherlibs/labltk/browser/jg_config.ml @@ -13,14 +13,21 @@ (* $Id$ *) +let fixed = + if Sys.os_type = "Win32" then "{Courier New} 8" else "fixed" +let variable = + if Sys.os_type = "Win32" then "Arial 9" else "variable" + let init () = + if Sys.os_type = "Win32" then Option.add path:"*font" fixed; let font = let font = Option.get Widget.default_toplevel name:"variableFont" class:"Font" in - if font = "" then "variable" else font + if font = "" then variable else font in List.iter ["Button"; "Label"; "Menu"; "Menubutton"; "Radiobutton"] fun:(fun cl -> Option.add path:("*" ^ cl ^ ".font") font); + Option.add path:"*Menu.tearOff" "0" priority:`StartupFile; Option.add path:"*Button.padY" "0" priority:`StartupFile; Option.add path:"*Text.highlightThickness" "0" priority:`StartupFile; Option.add path:"*interface.background" "gray85" priority:`StartupFile; diff --git a/otherlibs/labltk/browser/shell.ml b/otherlibs/labltk/browser/shell.ml index 7b27b89a7..f2fbd3a7e 100644 --- a/otherlibs/labltk/browser/shell.ml +++ b/otherlibs/labltk/browser/shell.ml @@ -15,6 +15,7 @@ open Tk open Jg_tk +open Dummy (* Here again, memoize regexps *) @@ -37,6 +38,19 @@ class ['a] history () = object List.nth history pos:((l + count - 1) mod l) end +let dump_mem ?(:pos = 0) ?:len obj = + if not (Obj.is_block obj) then invalid_arg "Shell.dump_mem"; + let len = + match len with + | None -> Obj.size obj * Sys.word_size / 8 - pos + | Some x -> x in + let buf = Buffer.create 256 in + for i = pos to len - 1 do + let c = String.unsafe_get (Obj.obj obj) i in + Buffer.add_string buf (Printf.sprintf "%02x" (Char.code c)) + done; + Buffer.contents buf + (* The shell class. Now encapsulated *) let protect f x = try f x with _ -> () @@ -44,32 +58,52 @@ let protect f x = try f x with _ -> () class shell :textw :prog :args :env = let (in2,out1) = Unix.pipe () and (in1,out2) = Unix.pipe () - and (err1,err2) = Unix.pipe () in + and (err1,err2) = Unix.pipe () + and (sig2,sig1) = Unix.pipe () in object (self) - val pid = Unix.create_process_env name:prog :args :env + val pid = + let env = + if Sys.os_type = "Win32" then + let sigdef = "CAMLSIGPIPE=" ^ dump_mem (Obj.repr sig2) in + Array.append env [|sigdef|] + else env + in + Unix.create_process_env name:prog :args :env stdin:in2 stdout:out2 stderr:err2 val out = Unix.out_channel_of_descr out1 val h = new history () val mutable alive = true val mutable reading = false + val ibuffer = Buffer.create 1024 + val imutex = Mutex.create () + val mutable ithreads = [] method alive = alive method kill = if Winfo.exists textw then Text.configure textw state:`Disabled; if alive then begin alive <- false; protect close_out out; - List.iter fun:(protect Unix.close) [in1; err1; in2; out2; err2]; try - Fileevent.remove_fileinput fd:in1; - Fileevent.remove_fileinput fd:err1; - Unix.kill :pid signal:Sys.sigkill; - Unix.waitpid mode:[] pid; () + if Sys.os_type = "Win32" then begin + ignore (Unix.write sig1 buf:"T" pos:0 len:1); + List.iter fun:(protect Unix.close) [sig1; sig2] + end else begin + List.iter fun:(protect Unix.close) [in1; err1; sig1; sig2]; + Fileevent.remove_fileinput fd:in1; + Fileevent.remove_fileinput fd:err1; + Unix.kill :pid signal:Sys.sigkill; + Unix.waitpid mode:[] pid; () + end with _ -> () end method interrupt = if alive then try reading <- false; - Unix.kill :pid signal:Sys.sigint + if Sys.os_type = "Win32" then begin + ignore (Unix.write sig1 buf:"C" pos:0 len:1); + self#send " " + end else + Unix.kill :pid signal:Sys.sigint with Unix.Unix_error _ -> () method send s = if alive then try @@ -77,12 +111,16 @@ object (self) flush out with Sys_error _ -> () method private read :fd :len = - try + begin try let buf = String.create :len in let len = Unix.read fd :buf pos:0 :len in - self#insert (String.sub buf pos:0 :len); - Text.mark_set textw mark:"input" index:(`Mark"insert",[`Char(-1)]) - with Unix.Unix_error _ -> () + if len > 0 then begin + self#insert (String.sub buf pos:0 :len); + Text.mark_set textw mark:"input" index:(`Mark"insert",[`Char(-1)]) + end; + len + with Unix.Unix_error _ -> 0 + end; method history (dir : [`next|`previous]) = if not h#empty then begin if reading then begin @@ -151,13 +189,38 @@ object (self) end; bind textw events:[`KeyPressDetail"Return"] breakable:true action:(fun _ -> self#return; break()); - begin try - List.iter [in1;err1] fun: - begin fun fd -> - Fileevent.add_fileinput :fd - callback:(fun () -> self#read :fd len:1024) - end - with _ -> () + List.iter fun:Unix.close [in2;out2;err2]; + if Sys.os_type = "Win32" then begin + let fileinput_thread fd = + let buf = String.create len:1024 in + let len = ref 0 in + try while len := ThreadUnix.read fd :buf pos:0 len:1024; !len > 0 do + Mutex.lock imutex; + Buffer.add_substring ibuffer buf pos:0 len:!len; + Mutex.unlock imutex + done with Unix.Unix_error _ -> () + in + ithreads <- List.map [in1; err1] fun:(Thread.create fileinput_thread); + let rec read_buffer () = + Mutex.lock imutex; + if Buffer.length ibuffer > 0 then begin + self#insert (Str.global_replace pat:~"\r\n" with:"\n" + (Buffer.contents ibuffer)); + Buffer.reset ibuffer; + Text.mark_set textw mark:"input" index:(`Mark"insert",[`Char(-1)]) + end; + Mutex.unlock imutex; + ignore (Timer.add ms:100 callback:read_buffer) + in + read_buffer () + end else begin + try + List.iter [in1;err1] fun: + begin fun fd -> + Fileevent.add_fileinput :fd + callback:(fun () -> ignore (self#read :fd len:1024)) + end + with _ -> () end end @@ -175,17 +238,26 @@ let get_all () = shells := all; all -let may_exec prog = +let may_exec_unix prog = try Unix.access name:prog perm:[Unix.X_OK]; true with Unix.Unix_error _ -> false +let may_exec_win prog = + List.exists pred:may_exec_unix [prog; prog^".exe"; prog^".cmo"; prog^".bat"] + +let may_exec = + if Sys.os_type = "Win32" then may_exec_win else may_exec_unix + +let path_sep = if Sys.os_type = "Win32" then ";" else ":" + let f :prog :title = let progargs = List.filter pred:((<>) "") (Str.split sep:~" " prog) in if progargs = [] then () else let prog = List.hd progargs in - let path = try Sys.getenv "PATH" with Not_found -> "/bin:/usr/bin" in - let exec_path = Str.split sep:~":" path in + let path = + try Sys.getenv "PATH" with Not_found -> "/bin" ^ path_sep ^ "/usr/bin" in + let exec_path = Str.split sep:~path_sep path in let exists = if not (Filename.is_implicit prog) then may_exec prog else List.exists exec_path |