summaryrefslogtreecommitdiff
path: root/ide
diff options
context:
space:
mode:
authorGravatar Samuel Mimram <samuel.mimram@ens-lyon.org>2004-07-28 21:54:47 +0000
committerGravatar Samuel Mimram <samuel.mimram@ens-lyon.org>2004-07-28 21:54:47 +0000
commit6b649aba925b6f7462da07599fe67ebb12a3460e (patch)
tree43656bcaa51164548f3fa14e5b10de5ef1088574 /ide
Imported Upstream version 8.0pl1upstream/8.0pl1
Diffstat (limited to 'ide')
-rw-r--r--ide/.coqide-gtk2rc49
-rw-r--r--ide/FAQ73
-rw-r--r--ide/blaster_window.ml183
-rw-r--r--ide/command_windows.ml151
-rw-r--r--ide/command_windows.mli22
-rw-r--r--ide/config_lexer.mll68
-rw-r--r--ide/config_parser.mly43
-rw-r--r--ide/coq.ml479
-rw-r--r--ide/coq.mli66
-rw-r--r--ide/coq.pngbin0 -> 9103 bytes
-rw-r--r--ide/coq_commands.ml406
-rw-r--r--ide/coq_tactics.ml131
-rw-r--r--ide/coq_tactics.mli12
-rw-r--r--ide/coqide.ml3386
-rw-r--r--ide/coqide.mli16
-rw-r--r--ide/extract_index.mll31
-rw-r--r--ide/find_phrase.mll66
-rw-r--r--ide/highlight.mll115
-rw-r--r--ide/ideutils.ml307
-rw-r--r--ide/ideutils.mli79
-rw-r--r--ide/index_urls.txt563
-rw-r--r--ide/preferences.ml540
-rw-r--r--ide/preferences.mli67
-rw-r--r--ide/undo.ml178
-rw-r--r--ide/undo.mli35
-rw-r--r--ide/utf8.v56
-rw-r--r--ide/utf8_convert.mll51
-rw-r--r--ide/utils/configwin.ml74
-rw-r--r--ide/utils/configwin.mli300
-rw-r--r--ide/utils/configwin_html_config.ml83
-rw-r--r--ide/utils/configwin_ihm.ml1435
-rw-r--r--ide/utils/configwin_keys.ml4175
-rw-r--r--ide/utils/configwin_messages.ml51
-rw-r--r--ide/utils/configwin_types.ml299
-rw-r--r--ide/utils/editable_cells.ml114
-rw-r--r--ide/utils/okey.ml185
-rw-r--r--ide/utils/okey.mli114
-rw-r--r--ide/utils/uoptions.ml772
-rw-r--r--ide/utils/uoptions.mli148
39 files changed, 14923 insertions, 0 deletions
diff --git a/ide/.coqide-gtk2rc b/ide/.coqide-gtk2rc
new file mode 100644
index 00000000..11c53dad
--- /dev/null
+++ b/ide/.coqide-gtk2rc
@@ -0,0 +1,49 @@
+# Some default functions for CoqIde. You may copy the file in your HOME and
+# edit as you want. See
+# http://developer.gnome.org/doc/API/2.0/gtk/gtk-Resource-Files.html
+# for a complete set of options
+# To set the font of the text windows, edit the .coqiderc file through the menus.
+
+gtk-key-theme-name = "Emacs"
+
+#pixmap_path "/home/"
+
+binding "text" {
+ bind "<ctrl>k" { "set-anchor" ()
+ "move-cursor" (display-line-ends,1,0)
+ "move-cursor" (visual-positions,1,0)
+ "cut-clipboard" ()
+ }
+ bind "<ctrl>w" { "cut-clipboard" () }
+
+# For UTF-8 inputs !
+# bind "F11" {"insert-at-cursor" ("∀")}
+# bind "F12" {"insert-at-cursor" ("∃")}
+}
+class "GtkTextView" binding "text"
+
+
+style "views" {
+base[NORMAL] = "CornSilk"
+# bg_pixmap[NORMAL] = "background.jpg"
+}
+class "GtkTextView" style "views"
+
+widget "*.*.*.*.*.ScriptWindow" style "views"
+widget "*.*.*.*.GoalWindow" style "views"
+widget "*.*.*.*.MessageWindow" style "views"
+
+gtk-font-name = "Sans 12"
+
+style "location" {
+font_name = "Sans 10"
+}
+widget "*location*" style "location"
+
+
+gtk-can-change-accels = 1
+
+style "men" {
+#
+}
+widget "GtkMenu" style "men"
diff --git a/ide/FAQ b/ide/FAQ
new file mode 100644
index 00000000..2079ef6c
--- /dev/null
+++ b/ide/FAQ
@@ -0,0 +1,73 @@
+ CoqIde FAQ
+
+Q0) What is CoqIde?
+R0: A powerfull graphical interface for Coq. See http://coq.inria.fr. for more informations.
+
+Q1) How to enable Emacs keybindings?
+R1: Insert
+ gtk-key-theme-name = "Emacs"
+ in your ".coqide-gtk2rc" file. It may be in the current dir
+ or in $HOME dir. This is done by default.
+
+Q2) How to enable antialiased fonts?
+R2) Set the GDK_USE_XFT variable to 1. This is by default with Gtk >= 2.2.
+ If some of your fonts are not available, set GDK_USE_XFT to 0.
+
+Q4) How to use those Forall and Exists pretty symbols?
+R4) Thanks to the Notation features in Coq, you just need to insert these
+ lines in your Coq Buffer :
+======================================================================
+Notation "∀ x : t, P" := (forall x:t, P) (at level 200, x ident).
+Notation "∃ x : t, P" := (exists x:t, P) (at level 200, x ident).
+======================================================================
+Copy/Paste of these lines from this file will not work outside of CoqIde.
+You need to load a file containing these lines or to enter the "∀"
+using an input method (see Q5). To try it just use "Require utf8" from inside
+CoqIde.
+To enable these notations automatically start coqide with
+ coqide -l utf8
+In the ide subdir of Coq library, you will find a sample utf8.v with some
+pretty simple notations.
+
+Q5) How to define an input method for non ASCII symbols?
+R5)-First solution : type "<CONTROL><SHIFT>2200" to enter a forall in the script widow.
+ 2200 is the hexadecimal code for forall in unicode charts and is encoded as "∀"
+ in UTF-8.
+ 2203 is for exists. See http://www.unicode.org for more codes.
+-Second solution : rebind "<AltGr>a" to forall and "<AltGr>e" to exists.
+ Under X11, you need to use something like
+ xmodmap -e "keycode 24 = a A F13 F13"
+ xmodmap -e "keycode 26 = e E F14 F14"
+ and then to add
+ bind "F13" {"insert-at-cursor" ("∀")}
+ bind "F14" {"insert-at-cursor" ("∃")}
+ to your "binding "text"" section in .coqiderc-gtk2rc.
+ The strange ("∀") argument is the UTF-8 encoding for
+ 0x2200.
+ You can compute these encodings using the lablgtk2 toplevel with
+ Glib.Utf8.from_unichar 0x2200;;
+ Further symbols can be bound on higher Fxx keys or on even on other keys you
+ do not need .
+
+Q6) How to build a custom CoqIde with user ml code?
+R6) Use
+ coqmktop -ide -byte m1.cmo...mi.cmo
+ or
+ coqmktop -ide -opt m1.cmx...mi.cmx
+
+Q7) How to customize the shortcuts for menus?
+R7) Two solutions are offered:
+ - Edit $HOME/.coqide.keys by hand or
+ - Add "gtk-can-change-accels = 1" in your .coqide-gtk2rc file. Then
+ from CoqIde, you may select a menu entry and press the desired
+ shortcut.
+
+Q8) What encoding should I use? What is this \x{iiii} in my file?
+R8) The encoding option is related to the way files are saved.
+ Keep it as UTF-8 until it becomes important for you to exchange files
+ with non UTF-8 aware applications.
+ If you choose something else than UTF-8, then missing characters will
+ be encoded by \x{....} or \x{........} where each dot is an hex. digit.
+ The number between braces is the hexadecimal UNICODE index for the
+ missing character.
+
diff --git a/ide/blaster_window.ml b/ide/blaster_window.ml
new file mode 100644
index 00000000..cca788c2
--- /dev/null
+++ b/ide/blaster_window.ml
@@ -0,0 +1,183 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: blaster_window.ml,v 1.5.2.1 2004/07/16 19:30:19 herbelin Exp $ *)
+
+open Gobject.Data
+open Ideutils
+
+exception Stop
+exception Done
+
+module MyMap = Map.Make (struct type t = string let compare = compare end)
+
+class blaster_window (n:int) =
+ let window = GWindow.window
+ ~allow_grow:true ~allow_shrink:true
+ ~width:320 ~height:200
+ ~title:"Blaster Window" ~show:false ()
+ in
+ let box1 = GPack.vbox ~packing:window#add () in
+ let sw = GBin.scrolled_window ~packing:(box1#pack ~expand:true ~fill:true) () in
+
+ let cols = new GTree.column_list in
+ let argument = cols#add string in
+ let tactic = cols#add string in
+ let status = cols#add boolean in
+ let nb_goals = cols#add string in
+
+ let model = GTree.tree_store cols in
+ let new_arg s =
+ let row = model#append () in
+ model#set ~row ~column:argument s;
+ row
+ in
+ let new_tac arg s =
+ let row = model#append ~parent:arg () in
+ model#set ~row ~column:tactic s;
+ model#set ~row ~column:status false;
+ model#set ~row ~column:nb_goals "?";
+ row
+ in
+ let view = GTree.view ~model ~packing:sw#add () in
+ let _ = view#selection#set_mode `SINGLE in
+ let _ = view#set_rules_hint true in
+
+ let col = GTree.view_column ~title:"Argument" ()
+ ~renderer:(GTree.cell_renderer_text [], ["text",argument]) in
+ let _ = view#append_column col in
+ let col = GTree.view_column ~title:"Tactics" ()
+ ~renderer:(GTree.cell_renderer_text [], ["text",tactic]) in
+ let _ = view#append_column col in
+ let col = GTree.view_column ~title:"Status" ()
+ ~renderer:(GTree.cell_renderer_toggle [], ["active",status]) in
+ let _ = view#append_column col in
+ let col = GTree.view_column ~title:"Delta Goal" ()
+ ~renderer:(GTree.cell_renderer_text [], ["text",nb_goals]) in
+ let _ = view#append_column col in
+
+ let _ = GMisc.separator `HORIZONTAL ~packing:box1#pack () in
+
+ let box2 = GPack.vbox ~spacing: 10 ~border_width: 10 ~packing: box1#pack ()
+ in
+ let button_stop = GButton.button ~label: "Stop" ~packing: box2#add () in
+ let _ = button_stop#connect#clicked ~callback: window#misc#hide in
+
+object(self)
+ val window = window
+ val roots = Hashtbl.create 17
+ val mutable tbl = MyMap.empty
+ val blaster_lock = Mutex.create ()
+ method lock = blaster_lock
+ val blaster_killed = Condition.create ()
+ method blaster_killed = blaster_killed
+ method window = window
+ method set
+ root
+ name
+ (compute:unit -> Coq.tried_tactic)
+ (on_click:unit -> unit)
+ =
+ let root_iter =
+ try Hashtbl.find roots root
+ with Not_found ->
+ let nr = new_arg root in
+ Hashtbl.add roots root nr;
+ nr
+ in
+ let nt = new_tac root_iter name in
+ let old_val = try MyMap.find root tbl with Not_found -> MyMap.empty in
+ tbl <- MyMap.add root (MyMap.add name (nt,compute,on_click) old_val) tbl
+
+ method clear () =
+ model#clear ();
+ tbl <- MyMap.empty;
+ Hashtbl.clear roots;
+
+ method blaster () =
+ view#expand_all ();
+ try MyMap.iter
+ (fun root_name l ->
+ try
+ MyMap.iter
+ (fun name (nt,compute,on_click) ->
+ match compute () with
+ | Coq.Interrupted ->
+ prerr_endline "Interrupted";
+ raise Stop
+ | Coq.Failed ->
+ prerr_endline "Failed";
+ ignore (model#remove nt)
+ (* model#set ~row:nt ~column:status false;
+ model#set ~row:nt ~column:nb_goals "N/A"
+ *)
+ | Coq.Success n ->
+ prerr_endline "Success";
+ model#set ~row:nt ~column:status true;
+ model#set ~row:nt ~column:nb_goals (string_of_int n);
+ if n= -1 then raise Done
+ )
+ l
+ with Done -> ())
+ tbl;
+ Condition.signal blaster_killed;
+ prerr_endline "End of blaster";
+ with Stop ->
+ Condition.signal blaster_killed;
+ prerr_endline "End of blaster (stopped !)";
+
+ initializer
+ ignore (window#event#connect#delete (fun _ -> window#misc#hide(); true));
+ ignore (view#selection#connect#after#changed ~callback:
+ begin fun () ->
+ prerr_endline "selection changed";
+ List.iter
+ (fun path ->let pt = GtkTree.TreePath.to_string path in
+ let it = model#get_iter path in
+ prerr_endline (string_of_bool (model#iter_is_valid it));
+ let name = model#get
+ ~row:(if String.length pt >1 then begin
+ ignore (GtkTree.TreePath.up path);
+ model#get_iter path
+ end else it
+ )
+ ~column:argument in
+ let tactic = model#get ~row:it ~column:tactic in
+ prerr_endline ("Got name: "^name);
+ let success = model#get ~row:it ~column:status in
+ if success then try
+ prerr_endline "Got success";
+ let _,_,f = MyMap.find tactic (MyMap.find name tbl) in
+ f ();
+ (* window#misc#hide () *)
+ with _ -> ()
+ )
+ view#selection#get_selected_rows
+ end);
+
+(* needs lablgtk2 update ignore (view#connect#after#row_activated
+ (fun path vcol ->
+ prerr_endline "Activated";
+ );
+*)
+end
+
+let blaster_window = ref None
+
+let main n = blaster_window := Some (new blaster_window n)
+
+let present_blaster_window () = match !blaster_window with
+ | None -> failwith "No blaster window."
+ | Some c -> c#window#misc#show (* present*) (); c
+
+
+let blaster_window () = match !blaster_window with
+ | None -> failwith "No blaster window."
+ | Some c -> c
+
+
diff --git a/ide/command_windows.ml b/ide/command_windows.ml
new file mode 100644
index 00000000..42b65048
--- /dev/null
+++ b/ide/command_windows.ml
@@ -0,0 +1,151 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: command_windows.ml,v 1.13.2.1 2004/07/16 19:30:19 herbelin Exp $ *)
+
+class command_window () =
+ let window = GWindow.window
+ ~allow_grow:true ~allow_shrink:true
+ ~width:320 ~height:200
+ ~position:`CENTER
+ ~title:"CoqIde queries" ~show:false ()
+ in
+ let accel_group = GtkData.AccelGroup.create () in
+ let vbox = GPack.vbox ~homogeneous:false ~packing:window#add () in
+ let toolbar = GButton.toolbar
+ ~orientation:`HORIZONTAL
+ ~style:`ICONS
+ ~tooltips:true
+ ~packing:(vbox#pack
+ ~expand:false
+ ~fill:false)
+ ()
+ in
+ let notebook = GPack.notebook ~scrollable:true
+ ~packing:(vbox#pack
+ ~expand:true
+ ~fill:true
+ )
+ ()
+ in
+ let _ =
+ toolbar#insert_button
+ ~tooltip:"Hide Window"
+ ~text:"Hide Window"
+ ~icon:(Ideutils.stock_to_widget ~size:`LARGE_TOOLBAR `CLOSE)
+ ~callback:window#misc#hide
+ ()
+ in
+ let new_page_menu =
+ toolbar#insert_button
+ ~tooltip:"New Page"
+ ~text:"New Page"
+ ~icon:(Ideutils.stock_to_widget ~size:`LARGE_TOOLBAR `NEW)
+(*
+ ~callback:window#misc#hide
+*)
+ ()
+ in
+
+ let kill_page_menu =
+ toolbar#insert_button
+ ~tooltip:"Kill Page"
+ ~text:"Kill Page"
+ ~icon:(Ideutils.stock_to_widget ~size:`LARGE_TOOLBAR `DELETE)
+ ~callback:(fun () -> notebook#remove_page notebook#current_page)
+ ()
+ in
+object(self)
+ val window = window
+(*
+ val menubar = menubar
+*)
+ val new_page_menu = new_page_menu
+ val notebook = notebook
+ method window = window
+ method new_command ?command ?term () =
+ let frame = GBin.frame
+ ~shadow_type:`ETCHED_OUT
+ ~packing:notebook#append_page
+ ()
+ in
+ notebook#goto_page (notebook#page_num frame#coerce);
+ let vbox = GPack.vbox ~homogeneous:false ~packing:frame#add () in
+ let hbox = GPack.hbox ~homogeneous:false ~packing:vbox#pack () in
+ let combo = GEdit.combo ~popdown_strings:Coq_commands.state_preserving
+ ~enable_arrow_keys:true
+ ~allow_empty:false
+ ~value_in_list:false (* true is not ok with disable_activate...*)
+ ~packing:hbox#pack
+ ()
+ in
+ combo#disable_activate ();
+ let on_activate c () =
+ if List.mem combo#entry#text Coq_commands.state_preserving then c ()
+ else prerr_endline "Not a state preserving command"
+ in
+ let entry = GEdit.entry ~packing:(hbox#pack ~expand:true) () in
+ entry#misc#set_can_default true;
+ let r_bin =
+ GBin.scrolled_window
+ ~vpolicy:`AUTOMATIC
+ ~hpolicy:`AUTOMATIC
+ ~packing:(vbox#pack ~fill:true ~expand:true) () in
+ let ok_b = GButton.button ~label:"Ok" ~packing:(hbox#pack ~expand:false) () in
+ let result = GText.view ~packing:r_bin#add () in
+ result#misc#set_can_focus true; (* false causes problems for selection *)
+ result#set_editable false;
+ let callback () =
+ let com = combo#entry#text in
+ let phrase =
+ if String.get com (String.length com - 1) = '.'
+ then com ^ " " else com ^ " " ^ entry#text ^" . "
+ in
+ try
+ ignore(Coq.interp false phrase);
+ result#buffer#set_text
+ ("Result for command " ^ phrase ^ ":\n" ^ Ideutils.read_stdout ())
+ with e ->
+ let (s,loc) = Coq.process_exn e in
+ assert (Glib.Utf8.validate s);
+ result#buffer#set_text s
+ in
+ ignore (combo#entry#connect#activate ~callback:(on_activate callback));
+ ignore (ok_b#connect#clicked ~callback:(on_activate callback));
+
+ begin match command,term with
+ | None,None -> ()
+ | Some c, None ->
+ combo#entry#set_text c;
+
+ | Some c, Some t ->
+ combo#entry#set_text c;
+ entry#set_text t
+
+ | None , Some t ->
+ entry#set_text t
+ end;
+ on_activate callback ();
+ entry#misc#grab_focus ();
+ entry#misc#grab_default ();
+ ignore (entry#connect#activate ~callback);
+ ignore (combo#entry#connect#activate ~callback);
+ self#window#present ()
+
+ initializer
+ ignore (new_page_menu#connect#clicked self#new_command);
+ ignore (window#event#connect#delete (fun _ -> window#misc#hide(); true));
+end
+
+let command_window = ref None
+
+let main () = command_window := Some (new command_window ())
+
+let command_window () = match !command_window with
+ | None -> failwith "No command window."
+ | Some c -> c
diff --git a/ide/command_windows.mli b/ide/command_windows.mli
new file mode 100644
index 00000000..014be777
--- /dev/null
+++ b/ide/command_windows.mli
@@ -0,0 +1,22 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: command_windows.mli,v 1.1.2.1 2004/07/16 19:30:19 herbelin Exp $ *)
+
+class command_window :
+ unit ->
+ object
+ method new_command : ?command:string -> ?term:string -> unit -> unit
+ method window : GWindow.window
+ end
+
+val main : unit -> unit
+
+val command_window : unit -> command_window
+
+
diff --git a/ide/config_lexer.mll b/ide/config_lexer.mll
new file mode 100644
index 00000000..1c0720d1
--- /dev/null
+++ b/ide/config_lexer.mll
@@ -0,0 +1,68 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: config_lexer.mll,v 1.4.2.1 2004/07/16 19:30:19 herbelin Exp $ *)
+
+{
+
+ open Lexing
+ open Format
+ open Config_parser
+ open Util
+
+ let string_buffer = Buffer.create 1024
+
+}
+
+let space = [' ' '\010' '\013' '\009' '\012']
+let char = ['A'-'Z' 'a'-'z' '_' '0'-'9']
+let ident = char+
+
+rule token = parse
+ | space+ { token lexbuf }
+ | '#' [^ '\n']* { token lexbuf }
+ | ident { IDENT (lexeme lexbuf) }
+ | '=' { EQUAL }
+ | '"' { Buffer.reset string_buffer;
+ Buffer.add_char string_buffer '"';
+ string lexbuf;
+ let s = Buffer.contents string_buffer in
+ STRING (Scanf.sscanf s "%S" (fun s -> s)) }
+ | _ { let c = lexeme_start lexbuf in
+ eprintf ".coqiderc: invalid character (%d)\n@." c;
+ token lexbuf }
+ | eof { EOF }
+
+and string = parse
+ | '"' { Buffer.add_char string_buffer '"' }
+ | '\\' '"' | _
+ { Buffer.add_string string_buffer (lexeme lexbuf); string lexbuf }
+ | eof { eprintf ".coqiderc: unterminated string\n@." }
+
+{
+
+ let load_file f =
+ let c = open_in f in
+ let lb = from_channel c in
+ let m = Config_parser.prefs token lb in
+ close_in c;
+ m
+
+ let print_file f m =
+ let c = open_out f in
+ let fmt = formatter_of_out_channel c in
+ let rec print_list fmt = function
+ | [] -> ()
+ | s :: sl -> fprintf fmt "%S@ %a" s print_list sl
+ in
+ Stringmap.iter
+ (fun k s -> fprintf fmt "@[<hov 2>%s = %a@]@\n" k print_list s) m;
+ fprintf fmt "@.";
+ close_out c
+
+}
diff --git a/ide/config_parser.mly b/ide/config_parser.mly
new file mode 100644
index 00000000..48005efe
--- /dev/null
+++ b/ide/config_parser.mly
@@ -0,0 +1,43 @@
+/***********************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(***********************************************************************/
+
+/* $Id: config_parser.mly,v 1.2.2.1 2004/07/16 19:30:20 herbelin Exp $ */
+
+%{
+
+ open Parsing
+ open Util
+
+%}
+
+%token <string> IDENT STRING
+%token EQUAL EOF
+
+%type <(string list) Util.Stringmap.t> prefs
+%start prefs
+
+%%
+
+prefs:
+ pref_list EOF { $1 }
+;
+
+pref_list:
+ pref_list pref { let (k,d) = $2 in Stringmap.add k d $1 }
+ | /* epsilon */ { Stringmap.empty }
+;
+
+pref:
+ IDENT EQUAL string_list { ($1, List.rev $3) }
+;
+
+string_list:
+ string_list STRING { $2 :: $1 }
+ | /* epsilon */ { [] }
+;
+
diff --git a/ide/coq.ml b/ide/coq.ml
new file mode 100644
index 00000000..e582f2d9
--- /dev/null
+++ b/ide/coq.ml
@@ -0,0 +1,479 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: coq.ml,v 1.38.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+open Vernac
+open Vernacexpr
+open Pfedit
+open Pp
+open Util
+open Names
+open Term
+open Printer
+open Environ
+open Evarutil
+open Evd
+open Hipattern
+open Tacmach
+open Reductionops
+open Termops
+open Ideutils
+
+let prerr_endline s = if !debug then prerr_endline s else ()
+
+let output = ref (Format.formatter_of_out_channel stdout)
+
+let msg m =
+ let b = Buffer.create 103 in
+ Pp.msg_with (Format.formatter_of_buffer b) m;
+ Buffer.contents b
+
+let msgnl m =
+ (msg m)^"\n"
+
+let init () =
+ (* To hide goal in lower window.
+ Problem: should not hide "xx is assumed"
+ messages *)
+(**)
+ Options.make_silent true;
+(**)
+ Coqtop.init_ide ()
+
+
+let i = ref 0
+
+let version () =
+ let date =
+ if Glib.Utf8.validate Coq_config.date
+ then Coq_config.date
+ else "<date not printable>"
+ in
+ Printf.sprintf
+ "The Coq Proof Assistant, version %s (%s)\
+ \nConfigured on %s\
+ \nArchitecture %s running %s operating system\
+ \nGtk version is %s\
+ \nThis is the %s version (%s is the best one for this architecture and OS)\
+ \n"
+ Coq_config.version date Coq_config.compile_date
+ Coq_config.arch Sys.os_type
+ (let x,y,z = GMain.Main.version in Printf.sprintf "%d.%d.%d" x y z)
+ (if Mltop.get () = Mltop.Native then "native" else "bytecode")
+ (if Coq_config.best="opt" then "native" else "bytecode")
+
+let is_in_coq_lib dir =
+ prerr_endline ("Is it a coq theory ? : "^dir);
+ try
+ let stat = Unix.stat dir in
+ List.exists
+ (fun s ->
+ try
+ let fdir = Filename.concat
+ Coq_config.coqlib
+ (Filename.concat "theories" s)
+ in
+ prerr_endline (" Comparing to: "^fdir);
+ let fstat = Unix.stat fdir in
+ (fstat.Unix.st_dev = stat.Unix.st_dev) &&
+ (fstat.Unix.st_ino = stat.Unix.st_ino) &&
+ (prerr_endline " YES";true)
+ with _ -> prerr_endline " No(because of a local exn)";false
+ )
+ Coq_config.theories_dirs
+ with _ -> prerr_endline " No(because of a global exn)";false
+
+let is_in_coq_path f =
+ try
+ let base = Filename.chop_extension (Filename.basename f) in
+ let _ = Library.locate_qualified_library
+ (Libnames.make_qualid Names.empty_dirpath
+ (Names.id_of_string base)) in
+ prerr_endline (f ^ "is in coq path");
+ true
+ with _ ->
+ prerr_endline (f ^ "is NOT in coq path");
+ false
+
+let is_in_proof_mode () =
+ try ignore (get_pftreestate ()); true with _ -> false
+
+let user_error_loc l s =
+ raise (Stdpp.Exc_located (l, Util.UserError ("CoqIde", s)))
+
+let interp verbosely s =
+ prerr_endline "Starting interp...";
+ prerr_endline s;
+ let pa = Pcoq.Gram.parsable (Stream.of_string s) in
+ let pe = Pcoq.Gram.Entry.parse Pcoq.main_entry pa in
+ match pe with
+ | None -> assert false
+ | Some((loc,vernac) as last) ->
+ match vernac with
+ | VernacDefinition _ | VernacStartTheoremProof _
+ | VernacBeginSection _ | VernacGoal _
+ | VernacDefineModule _ | VernacDeclareModuleType _
+ | VernacDeclareTacticDefinition _
+ when is_in_proof_mode () ->
+ user_error_loc loc (str "CoqIDE do not support nested goals")
+ | VernacDebug _ ->
+ user_error_loc loc (str "Debug mode not available within CoqIDE")
+ | VernacResetName _
+ | VernacResetInitial
+ | VernacBack _
+ | VernacAbort _
+ | VernacAbortAll
+ | VernacRestart
+ | VernacSuspend
+ | VernacResume _
+ | VernacUndo _ ->
+ user_error_loc loc (str "Use CoqIDE navigation instead")
+ | _ ->
+ begin
+ match vernac with
+ | VernacPrintOption _
+ | VernacCheckMayEval _
+ | VernacGlobalCheck _
+ | VernacPrint _
+ | VernacSearch _
+ -> !flash_info
+ "Warning: query commands should not be inserted in scripts"
+ | VernacDefinition (_,_,DefineBody _,_)
+ | VernacInductive _
+ | VernacFixpoint _
+ | VernacCoFixpoint _
+ | VernacEndProof _
+ -> Options.make_silent (not verbosely)
+ | _ -> ()
+ end;
+ Vernac.raw_do_vernac (Pcoq.Gram.parsable (Stream.of_string s));
+ Options.make_silent true;
+ prerr_endline ("...Done with interp of : "^s);
+ last
+
+let interp_and_replace s =
+ let result = interp false s in
+ let msg = read_stdout () in
+ result,msg
+
+let nb_subgoals pf =
+ List.length (fst (Refiner.frontier (Tacmach.proof_of_pftreestate pf)))
+
+type tried_tactic =
+ | Interrupted
+ | Success of int (* nb of goals after *)
+ | Failed
+
+let try_interptac s =
+ try
+ prerr_endline ("Starting try_interptac: "^s);
+ let pf = get_pftreestate () in
+ let pe = Pcoq.Gram.Entry.parse
+ Pcoq.main_entry
+ (Pcoq.Gram.parsable (Stream.of_string s))
+ in match pe with
+ | Some (loc,(VernacSolve (n, tac, _))) ->
+ let tac = Tacinterp.interp tac in
+ let pf' = solve_nth_pftreestate n tac pf in
+ prerr_endline "Success";
+ let nb_goals = nb_subgoals pf' - nb_subgoals pf in
+ Success nb_goals
+ | _ ->
+ prerr_endline "try_interptac: not a tactic"; Failed
+ with
+ | Sys.Break | Stdpp.Exc_located (_,Sys.Break)
+ -> prerr_endline "try_interp: interrupted"; Interrupted
+ | Stdpp.Exc_located (_,e) -> prerr_endline ("try_interp: failed ("^(Printexc.to_string e)); Failed
+ | e -> Failed
+
+let is_tactic = function
+ | VernacSolve _ -> true
+ | _ -> false
+
+
+let rec is_pervasive_exn = function
+ | Out_of_memory | Stack_overflow | Sys.Break -> true
+ | Error_in_file (_,_,e) -> is_pervasive_exn e
+ | Stdpp.Exc_located (_,e) -> is_pervasive_exn e
+ | DuringCommandInterp (_,e) -> is_pervasive_exn e
+ | _ -> false
+
+let print_toplevel_error exc =
+ let (dloc,exc) =
+ match exc with
+ | DuringCommandInterp (loc,ie) ->
+ if loc = dummy_loc then (None,ie) else (Some loc, ie)
+ | _ -> (None, exc)
+ in
+ let (loc,exc) =
+ match exc with
+ | Stdpp.Exc_located (loc, ie) -> (Some loc),ie
+ | Error_in_file (s, (_,fname, loc), ie) -> None, ie
+ | _ -> dloc,exc
+ in
+ match exc with
+ | End_of_input -> str "Please report: End of input",None
+ | Vernacexpr.ProtectedLoop ->
+ str "ProtectedLoop not allowed by coqide!",None
+ | Vernacexpr.Drop -> str "Drop is not allowed by coqide!",None
+ | Vernacexpr.Quit -> str "Quit is not allowed by coqide! Use menus.",None
+ | _ ->
+ (try Cerrors.explain_exn exc with e ->
+ str "Failed to explain error. This is an internal Coq error. Please report.\n"
+ ++ str (Printexc.to_string e)),
+ (if is_pervasive_exn exc then None else loc)
+
+let process_exn e = let s,loc= print_toplevel_error e in (msgnl s,loc)
+
+let interp_last last =
+ prerr_string "*";
+ try
+ vernac_com (States.with_heavy_rollback Vernacentries.interp) last
+ with e ->
+ let s,_ = process_exn e in prerr_endline ("Replay during undo failed because: "^s);
+ raise e
+
+
+type hyp = env * evar_map *
+ ((identifier * string) * constr option * constr) *
+ (string * string)
+type concl = env * evar_map * constr * string
+type goal = hyp list * concl
+
+let prepare_hyp sigma env ((i,c,d) as a) =
+ env, sigma,
+ ((i,string_of_id i),c,d),
+ (msg (pr_var_decl env a), msg (prterm_env_at_top env d))
+
+let prepare_hyps sigma env =
+ assert (rel_context env = []);
+ let hyps =
+ fold_named_context
+ (fun env d acc -> let hyp = prepare_hyp sigma env d in hyp :: acc)
+ env ~init:[]
+ in
+ List.rev hyps
+
+let prepare_goal sigma g =
+ let env = evar_env g in
+ (prepare_hyps sigma env,
+ (env, sigma, g.evar_concl, msg (prterm_env_at_top env g.evar_concl)))
+
+let get_current_goals () =
+ let pfts = get_pftreestate () in
+ let gls = fst (Refiner.frontier (Tacmach.proof_of_pftreestate pfts)) in
+ let sigma = Tacmach.evc_of_pftreestate pfts in
+ List.map (prepare_goal sigma) gls
+
+let get_current_goals_nb () =
+ try List.length (get_current_goals ()) with _ -> 0
+
+
+let print_no_goal () =
+ let pfts = get_pftreestate () in
+ let gls = fst (Refiner.frontier (Tacmach.proof_of_pftreestate pfts)) in
+ assert (gls = []);
+ let sigma = Tacmach.project (Tacmach.top_goal_of_pftreestate pfts) in
+ msg (Proof_trees.pr_subgoals_existential sigma gls)
+
+
+type word_class = Normal | Kwd | Reserved
+
+
+let kwd = [(* "Compile";"Inductive";"Qed";"Type";"end";"Axiom";
+ "Definition";"Load";"Quit";"Variable";"in";"Cases";"FixPoint";
+ "Parameter";"Set";"of";"CoFixpoint";"Grammar";"Proof";"Syntax";
+ "using";"CoInductive";"Hypothesis";"Prop";"Theorem";
+ *)
+ "Add"; "AddPath"; "Axiom"; "Chapter"; "CoFixpoint";
+ "CoInductive"; "Defined"; "Definition";
+ "End"; "Export"; "Fact"; "Fix"; "Fixpoint"; "Global"; "Grammar"; "Hint";
+ "Hypothesis"; "Immediate"; "Implicits"; "Import"; "Inductive";
+ "Infix"; "Lemma"; "Load"; "Local";
+ "Match"; "Module"; "Module Type";
+ "Mutual"; "Parameter"; "Print"; "Proof"; "Qed";
+ "Record"; "Recursive"; "Remark"; "Require"; "Save"; "Scheme";
+ "Section"; "Show"; "Syntactic"; "Syntax"; "Tactic"; "Theorem";
+ "Unset"; "Variable"; "Variables";
+]
+
+let reserved = []
+
+module SHashtbl =
+ Hashtbl.Make
+ (struct
+ type t = string
+ let equal = ( = )
+ let hash = Hashtbl.hash
+ end)
+
+
+let word_tbl = SHashtbl.create 37
+let _ =
+ List.iter (fun w -> SHashtbl.add word_tbl w Kwd) kwd;
+ List.iter (fun w -> SHashtbl.add word_tbl w Reserved) reserved
+
+let word_class s =
+ try
+ SHashtbl.find word_tbl s
+ with Not_found -> Normal
+
+type reset_info = NoReset | Reset of Names.identifier * bool ref
+
+let compute_reset_info = function
+ | VernacDefinition (_, (_,id), DefineBody _, _)
+ | VernacBeginSection (_,id)
+ | VernacDefineModule ((_,id), _, _, _)
+ | VernacDeclareModule ((_,id), _, _, _)
+ | VernacDeclareModuleType ((_,id), _, _)
+ | VernacAssumption (_, (_,((_,id)::_,_))::_)
+ | VernacInductive (_, ((_,id),_,_,_,_) :: _) ->
+ Reset (id, ref true)
+ | VernacDefinition (_, (_,id), ProveBody _, _)
+ | VernacStartTheoremProof (_, (_,id), _, _, _) ->
+ Reset (id, ref false)
+ | _ -> NoReset
+
+let reset_initial () =
+ prerr_endline "Reset initial called"; flush stderr;
+ Vernacentries.abort_refine Lib.reset_initial ()
+
+let reset_to id =
+ prerr_endline ("Reset called with "^(string_of_id id));
+ Vernacentries.abort_refine Lib.reset_name (Util.dummy_loc,id)
+let reset_to_mod id =
+ prerr_endline ("Reset called to Mod/Sect with "^(string_of_id id));
+ Vernacentries.abort_refine Lib.reset_mod (Util.dummy_loc,id)
+
+
+let hyp_menu (env, sigma, ((coqident,ident),_,ast),(s,pr_ast)) =
+ [("clear "^ident),("clear "^ident^".");
+
+ ("apply "^ident),
+ ("apply "^ident^".");
+
+ ("exact "^ident),
+ ("exact "^ident^".");
+
+ ("generalize "^ident),
+ ("generalize "^ident^".");
+
+ ("absurd <"^ident^">"),
+ ("absurd "^
+ pr_ast
+ ^".") ] @
+
+ (if is_equation ast then
+ [ "discriminate "^ident, "discriminate "^ident^".";
+ "injection "^ident, "injection "^ident^"." ]
+ else
+ []) @
+
+ (let _,t = splay_prod env sigma ast in
+ if is_equation t then
+ [ "rewrite "^ident, "rewrite "^ident^".";
+ "rewrite <- "^ident, "rewrite <- "^ident^"." ]
+ else
+ []) @
+
+ [("elim "^ident),
+ ("elim "^ident^".");
+
+ ("inversion "^ident),
+ ("inversion "^ident^".");
+
+ ("inversion clear "^ident),
+ ("inversion_clear "^ident^".")]
+
+let concl_menu (_,_,concl,_) =
+ let is_eq = is_equation concl in
+ ["intro", "intro.";
+ "intros", "intros.";
+ "intuition","intuition." ] @
+
+ (if is_eq then
+ ["reflexivity", "reflexivity.";
+ "discriminate", "discriminate.";
+ "symmetry", "symmetry." ]
+ else
+ []) @
+
+ ["assumption" ,"assumption.";
+ "omega", "omega.";
+ "ring", "ring.";
+ "auto with *", "auto with *.";
+ "eauto with *", "eauto with *.";
+ "tauto", "tauto.";
+ "trivial", "trivial.";
+ "decide equality", "decide equality.";
+
+ "simpl", "simpl.";
+ "subst", "subst.";
+
+ "red", "red.";
+ "split", "split.";
+ "left", "left.";
+ "right", "right.";
+ ]
+
+
+let id_of_name = function
+ | Names.Anonymous -> id_of_string "x"
+ | Names.Name x -> x
+
+let make_cases s =
+ let qualified_name = Libnames.qualid_of_string s in
+ let glob_ref = Nametab.locate qualified_name in
+ match glob_ref with
+ | Libnames.IndRef i ->
+ let _,
+ {
+ Declarations.mind_nparams = np ;
+ Declarations.mind_consnames = carr ;
+ Declarations.mind_nf_lc = tarr }
+ = Global.lookup_inductive i
+ in
+ Util.array_fold_right2
+ (fun n t l ->
+ let (al,_) = Term.decompose_prod t in
+ let al,_ = Util.list_chop (List.length al - np) al in
+ let rec rename avoid = function
+ | [] -> []
+ | (n,_)::l ->
+ let n' = next_global_ident_away true
+ (id_of_name n)
+ avoid
+ in (string_of_id n')::(rename (n'::avoid) l)
+ in
+ let al' = rename [] (List.rev al) in
+ (string_of_id n :: al') :: l
+ )
+ carr
+ tarr
+ []
+ | _ -> raise Not_found
+
+let is_state_preserving = function
+ | VernacPrint _ | VernacPrintOption _ | VernacGlobalCheck _
+ | VernacCheckMayEval _ | VernacSearch _ | VernacLocate _
+ | VernacShow _ | VernacMemOption _ | VernacComments _
+ | VernacChdir None | VernacNop ->
+ prerr_endline "state preserving command found"; true
+ | _ ->
+ false
+
+
+let current_status () =
+ let path = msg (Libnames.pr_dirpath (Lib.cwd ())) in
+ let path = if path = "Top" then "Ready" else "Ready in " ^ String.sub path 4 (String.length path - 4) in
+ try
+ path ^ ", proving " ^ (Names.string_of_id (Pfedit.get_current_proof_name ()))
+ with _ -> path
+
+
diff --git a/ide/coq.mli b/ide/coq.mli
new file mode 100644
index 00000000..bcebd4e6
--- /dev/null
+++ b/ide/coq.mli
@@ -0,0 +1,66 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: coq.mli,v 1.14.2.2 2004/07/18 11:20:15 herbelin Exp $ *)
+
+open Names
+open Term
+open Environ
+open Evd
+
+val version : unit -> string
+
+val init : unit -> string list
+val interp : bool -> string -> Util.loc * Vernacexpr.vernac_expr
+val interp_last : Util.loc * Vernacexpr.vernac_expr -> unit
+val interp_and_replace : string -> (Util.loc * Vernacexpr.vernac_expr) * string
+
+val is_tactic : Vernacexpr.vernac_expr -> bool
+val is_state_preserving : Vernacexpr.vernac_expr -> bool
+
+(* type hyp = (identifier * constr option * constr) * string *)
+
+type hyp = env * evar_map *
+ ((identifier*string) * constr option * constr) * (string * string)
+type concl = env * evar_map * constr * string
+type goal = hyp list * concl
+
+val get_current_goals : unit -> goal list
+
+val get_current_goals_nb : unit -> int
+
+val print_no_goal : unit -> string
+
+val process_exn : exn -> string*(Util.loc option)
+
+type reset_info = NoReset | Reset of Names.identifier * bool ref
+
+val compute_reset_info : Vernacexpr.vernac_expr -> reset_info
+val reset_initial : unit -> unit
+val reset_to : identifier -> unit
+val reset_to_mod : identifier -> unit
+
+val hyp_menu : hyp -> (string * string) list
+val concl_menu : concl -> (string * string) list
+
+val is_in_coq_lib : string -> bool
+val is_in_coq_path : string -> bool
+
+val make_cases : string -> string list list
+
+
+type tried_tactic =
+ | Interrupted
+ | Success of int (* nb of goals after *)
+ | Failed
+
+val try_interptac: string -> tried_tactic
+
+(* Message to display in lower status bar. *)
+
+val current_status : unit -> string
diff --git a/ide/coq.png b/ide/coq.png
new file mode 100644
index 00000000..011203f7
--- /dev/null
+++ b/ide/coq.png
Binary files differ
diff --git a/ide/coq_commands.ml b/ide/coq_commands.ml
new file mode 100644
index 00000000..1169d438
--- /dev/null
+++ b/ide/coq_commands.ml
@@ -0,0 +1,406 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: coq_commands.ml,v 1.15.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+let commands = [
+ [(* "Abort"; *)
+ "Add Abstract Ring A Aplus Amult Aone Azero Ainv Aeq T.";
+ "Add Abstract Semi Ring A Aplus Amult Aone Azero Aeq T.";
+ "Add Field";
+ "Add LoadPath";
+ "Add ML Path";
+ "Add Morphism";
+ "Add Printing If";
+ "Add Printing Let";
+ "Add Rec LoadPath";
+ "Add Rec ML Path";
+ "Add Ring A Aplus Amult Aone Azero Ainv Aeq T [ c1 ... cn ]. ";
+ "Add Semi Ring A Aplus Amult Aone Azero Aeq T [ c1 ... cn ].";
+ "Add Setoid";
+ "Axiom";];
+ [(* "Back"; *) ];
+ ["Canonical Structure";
+ "Chapter";
+ "Coercion";
+ "Coercion Local";
+ "CoFixpoint";
+ "CoInductive";
+ ];
+ ["Declare ML Module";
+ "Defined.";
+ "Definition";
+ "Derive Dependent Inversion";
+ "Derive Dependent Inversion__clear";
+ "Derive Inversion";
+ "Derive Inversion__clear";
+ ];
+ ["End";
+ "End Silent.";
+ "Eval";
+ "Extract Constant";
+ "Extract Inductive";
+ "Extraction Inline";
+ "Extraction Language";
+ "Extraction NoInline";];
+ ["Fact";
+ "Fixpoint";
+ "Focus";];
+ ["Global Variable";
+ "Goal";
+ "Grammar";];
+ ["Hint";
+ "Hint Constructors";
+ "Hint Extern";
+ "Hint Immediate";
+ "Hint Resolve";
+ "Hint Rewrite";
+ "Hint Unfold";
+ "Hypothesis";];
+ ["Identity Coercion";
+ "Implicits";
+ "Inductive";
+ "Infix";
+ ];
+ ["Lemma";
+ "Load";
+ "Load Verbose";
+ "Local";
+ "Ltac";
+ ];
+ ["Module";
+ "Module Type";
+ "Mutual Inductive";];
+ ["Notation";];
+ ["Opaque";];
+ ["Parameter";
+ "Proof."];
+ ["Qed.";
+ ];
+ ["Read Module";
+ "Record";
+ "Remark";
+ "Remove LoadPath";
+ "Remove Printing If";
+ "Remove Printing Let";
+ "Require";
+ "Require Export";
+ "Require Import";
+ "Reset Extraction Inline";
+ "Restore State";
+ ];
+ [ "Save.";
+ "Scheme";
+ "Section";
+ "Set Extraction AutoInline";
+ "Set Extraction Optimize";
+ "Set Hyps__limit";
+ "Set Implicit Arguments";
+ "Set Printing Coercion";
+ "Set Printing Coercions";
+ "Set Printing Synth";
+ "Set Printing Wildcard";
+ "Set Silent.";
+ "Set Undo";
+ (*"Show";
+ "Show Conjectures";
+ "Show Implicits";
+ "Show Intro";
+ "Show Intros";
+ "Show Programs";
+ "Show Proof";
+ "Show Script";
+ "Show Tree";*)
+ "Structure";
+ (* "Suspend"; *)
+ "Syntactic Definition";
+ "Syntax";];
+ [
+ "Test Printing If";
+ "Test Printing Let";
+ "Test Printing Synth";
+ "Test Printing Wildcard";
+ "Theorem";
+ "Time";
+ "Transparent";];
+ [(* "Undo"; *)
+ "Unfocus";
+ "Unset Extraction AutoInline";
+ "Unset Extraction Optimize";
+ "Unset Hyps__limit";
+ "Unset Implicit Arguments";
+ "Unset Printing Coercion";
+ "Unset Printing Coercions";
+ "Unset Printing Synth";
+ "Unset Printing Wildcard";
+ "Unset Silent.";
+ "Unset Undo";];
+ ["Variable";
+ "Variables";];
+ ["Write State";];
+]
+
+let state_preserving = [
+ "Check";
+ "Eval";
+ "Eval compute in";
+ "Extraction";
+ "Extraction Library";
+ "Extraction Module";
+ "Inspect";
+ "Locate";
+ "Print";
+ "Print All.";
+ "Print Classes";
+ "Print Coercion Paths";
+ "Print Coercions";
+ "Print Extraction Inline";
+ "Print Grammar";
+ "Print Graph";
+ "Print Hint";
+ "Print Hint *";
+ "Print HintDb";
+ "Print Implicit";
+ "Print LoadPath";
+ "Print ML Modules";
+ "Print ML Path";
+ "Print Module";
+ "Print Module Type";
+ "Print Modules";
+ "Print Proof";
+ "Print Scope";
+ "Print Scopes.";
+ "Print Section";
+
+ "Print Table Printing If.";
+ "Print Table Printing Let.";
+ "Print Tables.";
+ "Print Term";
+
+ "Print Visibility";
+
+ "Pwd.";
+
+ "Recursive Extraction";
+ "Recursive Extraction Library";
+
+ "Search";
+ "SearchAbout";
+ "SearchPattern";
+ "SearchRewrite";
+
+ "Show";
+ "Show Conjectures";
+ "Show Implicits";
+ "Show Intro";
+ "Show Intros";
+ "Show Proof";
+ "Show Script";
+ "Show Tree";
+
+ "Test Printing If";
+ "Test Printing Let";
+ "Test Printing Synth";
+ "Test Printing Wildcard";
+]
+
+
+let tactics =
+ [
+ [
+ "abstract";
+ "absurd";
+ "apply";
+ "apply __ with";
+ "assert";
+ "assert (__:__)";
+ "assert (__:=__)";
+ "assumption";
+ "auto";
+ "auto with";
+ "autorewrite";
+ ];
+
+ [
+ "case";
+ "case __ with";
+ "casetype";
+ "cbv";
+ "cbv in";
+ "change";
+ "change __ in";
+ "clear";
+ "clearbody";
+ "cofix";
+ "compare";
+ "compute";
+ "compute in";
+ "congruence";
+ "constructor";
+ "constructor __ with";
+ "contradiction";
+ "cut";
+ "cutrewrite";
+ ];
+
+ [
+ "decide equality";
+ "decompose";
+ "decompose record";
+ "decompose sum";
+ "dependent inversion";
+ "dependent inversion __ with";
+ "dependent inversion__clear";
+ "dependent inversion__clear __ with";
+ "dependent rewrite ->";
+ "dependent rewrite <-";
+ "destruct";
+ "discriminate";
+ "do";
+ "double induction";
+ ];
+
+ [
+ "eapply";
+ "eauto";
+ "eauto with";
+ "eexact";
+ "elim";
+ "elim __ using";
+ "elim __ with";
+ "elimtype";
+ "exact";
+ "exists";
+ ];
+
+ [
+ "fail";
+ "field";
+ "first";
+ "firstorder";
+ "firstorder using";
+ "firstorder with";
+ "fix";
+ "fix __ with";
+ "fold";
+ "fold __ in";
+ "fourier";
+ "functional induction";
+ ];
+
+ [
+ "generalize";
+ "generalize dependent";
+ ];
+
+ [
+ "hnf";
+ ];
+
+ [
+ "idtac";
+ "induction";
+ "info";
+ "injection";
+ "instantiate (__:=__)";
+ "intro";
+ "intro after";
+ "intro __ after";
+ "intros";
+ "intros until";
+ "intuition";
+ "inversion";
+ "inversion __ in";
+ "inversion __ using";
+ "inversion __ using __ in";
+ "inversion__clear";
+ "inversion__clear __ in";
+ ];
+
+ [
+ "jp <n>";
+ "jp";
+ ];
+
+ [
+ "lapply";
+ "lazy";
+ "lazy in";
+ "left";
+ ];
+
+ [
+ "move __ after";
+ ];
+
+ [
+ "omega";
+ ];
+
+ [
+ "pattern";
+ "pose";
+ "pose __:=__)";
+ "progress";
+ ];
+
+ [
+ "quote";
+ ];
+
+ [
+ "red";
+ "red in";
+ "refine";
+ "reflexivity";
+ "rename __ into";
+ "repeat";
+ "replace __ with";
+ "rewrite";
+ "rewrite __ in";
+ "rewrite <-";
+ "rewrite <- __ in";
+ "right";
+ "ring";
+ ];
+
+ [
+ "set";
+ "set (__:=__)";
+ "setoid__replace";
+ "setoid__rewrite";
+ "simpl";
+ "simpl __ in";
+ "simple destruct";
+ "simple induction";
+ "simple inversion";
+ "simplify__eq";
+ "solve";
+ "split";
+(* "split__Rabs";
+ "split__Rmult";
+*)
+ "subst";
+ "symmetry";
+ "symmetry in";
+ ];
+
+ [
+ "tauto";
+ "transitivity";
+ "trivial";
+ "try";
+ ];
+
+ [
+ "unfold";
+ "unfold __ in";
+ ];
+]
+
+
diff --git a/ide/coq_tactics.ml b/ide/coq_tactics.ml
new file mode 100644
index 00000000..4dd20b47
--- /dev/null
+++ b/ide/coq_tactics.ml
@@ -0,0 +1,131 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: coq_tactics.ml,v 1.2.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+let tactics = [
+ "Abstract";
+ "Absurd";
+ "Apply";
+ "Apply ... with";
+ "Assert";
+ "Assumption";
+ "Auto";
+ "AutoRewrite";
+ "Binding list";
+ "Case";
+ "Case ... with";
+ "Cbv";
+ "Change";
+ "Change ... in";
+ "Clear";
+ "ClearBody";
+ "Compare";
+ "Compute";
+ "Constructor";
+ "Constructor ... with";
+ "Contradiction";
+ "Conversion tactics";
+ "Cut";
+ "CutRewrite";
+ "Decide Equality";
+ "Decompose";
+ "Decompose Record";
+ "Decompose Sum";
+ "Dependent Inversion";
+ "Dependent Inversion ... with";
+ "Dependent Inversion_clear";
+ "Dependent Inversion_clear ... with";
+ "Dependent Rewrite ->";
+ "Dependent Rewrite <-";
+ "Derive Inversion";
+ "Destruct";
+ "Discriminate";
+ "DiscrR";
+ "Do";
+ "Double Induction";
+ "EApply";
+ "EAuto";
+ "Elim ... using";
+ "Elim ... with";
+ "ElimType";
+ "Exact";
+ "Exists";
+ "Fail";
+ "Field";
+ "First";
+ "Fold";
+ "Fourier";
+ "Generalize";
+ "Generalize Dependent";
+ "Print Hint";
+ "Hnf";
+ "Idtac";
+ "Induction";
+ "Info";
+ "Injection";
+ "Intro";
+ "Intro ... after";
+ "Intro after";
+ "Intros";
+ "Intros pattern";
+ "Intros until";
+ "Intuition";
+ "Inversion";
+ "Inversion ... in";
+ "Inversion ... using";
+ "Inversion ... using ... in";
+ "Inversion_clear";
+ "Inversion_clear ... in";
+ "LApply";
+ "Lazy";
+ "Left";
+ "LetTac";
+ "Move";
+ "NewDestruct";
+ "NewInduction";
+ "Omega";
+ "Orelse";
+ "Pattern";
+ "Pose";
+ "Prolog";
+ "Quote";
+ "Red";
+ "Refine";
+ "Reflexivity";
+ "Rename";
+ "Repeat";
+ "Replace ... with";
+ "Rewrite";
+ "Rewrite ->";
+ "Rewrite -> ... in";
+ "Rewrite <-";
+ "Rewrite <- ... in";
+ "Rewrite ... in";
+ "Right";
+ "Ring";
+ "Setoid_replace";
+ "Setoid_rewrite";
+ "Simpl";
+ "Simple Inversion";
+ "Simplify_eq";
+ "Solve";
+ "Split";
+ "SplitAbsolu";
+ "SplitRmult";
+ "Subst";
+ "Symmetry";
+ "Tacticals";
+ "Tauto";
+ "Transitivity";
+ "Trivial";
+ "Try";
+ "tactic macros";
+ "Unfold";
+ "Unfold ... in";
+]
diff --git a/ide/coq_tactics.mli b/ide/coq_tactics.mli
new file mode 100644
index 00000000..8d603346
--- /dev/null
+++ b/ide/coq_tactics.mli
@@ -0,0 +1,12 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: coq_tactics.mli,v 1.1.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+val tactics : string list
+
diff --git a/ide/coqide.ml b/ide/coqide.ml
new file mode 100644
index 00000000..2169862e
--- /dev/null
+++ b/ide/coqide.ml
@@ -0,0 +1,3386 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: coqide.ml,v 1.99.2.2 2004/07/18 11:20:15 herbelin Exp $ *)
+
+open Preferences
+open Vernacexpr
+open Coq
+open Ideutils
+
+let out_some s = match s with
+ | None -> failwith "Internal error in out_some" | Some f -> f
+
+let cb_ = ref None
+let cb () = ((out_some !cb_):GData.clipboard)
+let last_cb_content = ref ""
+
+let (message_view:GText.view option ref) = ref None
+let (proof_view:GText.view option ref) = ref None
+
+let (_notebook:GPack.notebook option ref) = ref None
+let notebook () = out_some !_notebook
+
+
+(* Tabs contain the name of the edited file and 2 status informations:
+ Saved state + Focused proof buffer *)
+let decompose_tab w =
+ let vbox = new GPack.box ((Gobject.try_cast w "GtkBox"):Gtk.box Gtk.obj) in
+ let l = vbox#children in
+ match l with
+ | [img;lbl] ->
+ let img = new GMisc.image
+ ((Gobject.try_cast img#as_widget "GtkImage"):
+ Gtk.image Gtk.obj)
+ in
+ let lbl = GMisc.label_cast lbl in
+ vbox,img,lbl
+ | _ -> assert false
+
+let set_tab_label i n =
+ let nb = notebook () in
+ let _,_,lbl = decompose_tab (nb#get_tab_label(nb#get_nth_page i))#as_widget
+ in
+ lbl#set_use_markup true;
+ (* lbl#set_text n *) lbl#set_label n
+
+
+let set_tab_image ~icon i =
+ let nb = notebook () in
+ let _,img,_ = decompose_tab (nb#get_tab_label(nb#get_nth_page i))#as_widget
+ in
+ img#set_icon_size `SMALL_TOOLBAR;
+ img#set_stock icon
+
+let set_current_tab_image ~icon = set_tab_image ~icon (notebook())#current_page
+
+let set_current_tab_label n = set_tab_label (notebook())#current_page n
+
+let get_tab_label i =
+ let nb = notebook () in
+ let _,_,lbl = decompose_tab (nb#get_tab_label(nb#get_nth_page i))#as_widget
+ in
+ lbl#text
+
+let get_full_tab_label i =
+ let nb = notebook () in
+ let _,_,lbl = decompose_tab (nb#get_tab_label(nb#get_nth_page i))#as_widget
+ in
+ lbl
+
+let get_current_tab_label () = get_tab_label (notebook())#current_page
+
+let get_current_page () =
+ let i = (notebook())#current_page in
+ (notebook())#get_nth_page i
+
+(* This function must remove "focused proof" decoration *)
+let reset_tab_label i =
+ set_tab_label i (get_tab_label i)
+
+let to_do_on_page_switch = ref []
+
+module Vector = struct
+ exception Found of int
+ type 'a t = ('a option) array ref
+ let create () = ref [||]
+ let length t = Array.length !t
+ let get t i = out_some (Array.get !t i)
+ let set t i v = Array.set !t i (Some v)
+ let remove t i = Array.set !t i None
+ let append t e = t := Array.append !t [|Some e|]; (Array.length !t)-1
+ let iter f t = Array.iter (function | None -> () | Some x -> f x) !t
+ let find_or_fail f t =
+ let test i = function | None -> () | Some e -> if f e then raise (Found i) in
+ Array.iteri test t
+
+ let exists f t =
+ let l = Array.length !t in
+ let rec test i =
+ (i < l) && (((!t.(i) <> None) && f (out_some !t.(i))) || test (i+1))
+ in
+ test 0
+end
+
+type 'a viewable_script =
+ {view : Undo.undoable_view;
+ mutable analyzed_view : 'a option;
+ }
+
+
+class type analyzed_views=
+object('self)
+ val mutable act_id : GtkSignal.id option
+ val current_all : 'self viewable_script
+ val mutable deact_id : GtkSignal.id option
+ val input_buffer : GText.buffer
+ val input_view : Undo.undoable_view
+ val last_array : string array
+ val mutable last_index : bool
+ val message_buffer : GText.buffer
+ val message_view : GText.view
+ val proof_buffer : GText.buffer
+ val proof_view : GText.view
+ val mutable is_active : bool
+ val mutable read_only : bool
+ val mutable filename : string option
+ val mutable stats : Unix.stats option
+ val mutable detached_views : GWindow.window list
+ method without_auto_complete : 'a 'b. ('a -> 'b) -> 'a -> 'b
+ method set_auto_complete : bool -> unit
+
+ method kill_detached_views : unit -> unit
+ method add_detached_view : GWindow.window -> unit
+ method remove_detached_view : GWindow.window -> unit
+
+ method view : Undo.undoable_view
+ method filename : string option
+ method stats : Unix.stats option
+ method set_filename : string option -> unit
+ method update_stats : unit
+ method revert : unit
+ method auto_save : unit
+ method save : string -> bool
+ method save_as : string -> bool
+ method read_only : bool
+ method set_read_only : bool -> unit
+ method is_active : bool
+ method activate : unit -> unit
+ method active_keypress_handler : GdkEvent.Key.t -> bool
+ method backtrack_to : GText.iter -> unit
+ method backtrack_to_no_lock : GText.iter -> unit
+ method clear_message : unit
+ method deactivate : unit -> unit
+ method disconnected_keypress_handler : GdkEvent.Key.t -> bool
+ method electric_handler : GtkSignal.id
+ method find_phrase_starting_at :
+ GText.iter -> (GText.iter * GText.iter) option
+ method get_insert : GText.iter
+ method get_start_of_input : GText.iter
+ method go_to_insert : unit
+ method indent_current_line : unit
+ method insert_command : string -> string -> unit
+ method tactic_wizard : string list -> unit
+ method insert_message : string -> unit
+ method insert_this_phrase_on_success :
+ bool -> bool -> bool -> string -> string -> bool
+ method process_next_phrase : bool -> bool -> bool -> bool
+ method process_until_iter_or_error : GText.iter -> unit
+ method process_until_end_or_error : unit
+ method recenter_insert : unit
+ method reset_initial : unit
+ method send_to_coq :
+ bool -> bool -> string ->
+ bool -> bool -> bool -> (Util.loc * Vernacexpr.vernac_expr) option
+ method set_message : string -> unit
+ method show_goals : unit
+ method show_goals_full : unit
+ method undo_last_step : unit
+ method help_for_keyword : unit -> unit
+ method complete_at_offset : int -> bool
+
+ method blaster : unit -> unit
+end
+
+let (input_views:analyzed_views viewable_script Vector.t) = Vector.create ()
+
+
+let signals_to_crash = [Sys.sigabrt; Sys.sigalrm; Sys.sigfpe; Sys.sighup;
+ Sys.sigill; Sys.sigpipe; Sys.sigquit;
+ (* Sys.sigsegv; Sys.sigterm;*) Sys.sigusr2]
+
+let crash_save i =
+(* ignore (Unix.sigprocmask Unix.SIG_BLOCK signals_to_crash);*)
+ Pervasives.prerr_endline "Trying to save all buffers in .crashcoqide files";
+ let count = ref 0 in
+ Vector.iter
+ (function {view=view; analyzed_view = Some av } ->
+ (let filename = match av#filename with
+ | None ->
+ incr count;
+ "Unnamed_coqscript_"^(string_of_int !count)^".crashcoqide"
+ | Some f -> f^".crashcoqide"
+ in
+ try
+ if try_export filename (view#buffer#get_text ()) then
+ Pervasives.prerr_endline ("Saved "^filename)
+ else Pervasives.prerr_endline ("Could not save "^filename)
+ with _ -> Pervasives.prerr_endline ("Could not save "^filename))
+ | _ -> Pervasives.prerr_endline "Unanalyzed view found. Please report."
+ )
+ input_views;
+ Pervasives.prerr_endline "Done. Please report.";
+ if i <> 127 then exit i
+
+let ignore_break () =
+ List.iter
+ (fun i ->
+ try Sys.set_signal i (Sys.Signal_handle crash_save)
+ with _ -> prerr_endline "Signal ignored (normal if Win32)")
+ signals_to_crash;
+ Sys.set_signal Sys.sigint Sys.Signal_ignore
+
+(* Locking machinery for Coq kernel *)
+let coq_computing = Mutex.create ()
+
+(* To prevent Coq from interrupting during undoing...*)
+let coq_may_stop = Mutex.create ()
+
+let break () =
+ prerr_endline "User break received:";
+ if not (Mutex.try_lock coq_computing) then
+ begin
+ prerr_endline " trying to stop computation:";
+ if Mutex.try_lock coq_may_stop then begin
+ Util.interrupt := true;
+ prerr_endline " interrupt flag set. Computation should stop soon...";
+ Mutex.unlock coq_may_stop
+ end else prerr_endline " interruption refused (may not stop now)";
+ end
+ else begin
+ Mutex.unlock coq_computing;
+ prerr_endline " ignored (not computing)"
+ end
+
+let full_do_if_not_computing text f x =
+ ignore
+ (Thread.create
+ (async
+ (fun () ->
+ if Mutex.try_lock coq_computing
+ then
+ begin
+ prerr_endline ("Launching thread " ^ text);
+ let w = Blaster_window.blaster_window () in
+ if not (Mutex.try_lock w#lock) then begin
+ break ();
+ let lck = Mutex.create () in
+ Mutex.lock lck;
+ prerr_endline "Waiting on blaster...";
+ Condition.wait w#blaster_killed lck;
+ prerr_endline "Waiting on blaster ok";
+ Mutex.unlock lck
+ end else Mutex.unlock w#lock;
+ let idle =
+ Glib.Timeout.add ~ms:300
+ ~callback:(fun () -> !pulse ();true) in
+ begin
+ prerr_endline "Getting lock";
+ try
+ f x;
+ Glib.Timeout.remove idle;
+ prerr_endline "Releasing lock";
+ Mutex.unlock coq_computing;
+ with e ->
+ Glib.Timeout.remove idle;
+ prerr_endline "Releasing lock (on error)";
+ Mutex.unlock coq_computing;
+ raise e
+ end
+ end
+ else
+ prerr_endline
+ "Discarded order (computations are ongoing)"))
+ ())
+
+let do_if_not_computing text f x =
+ ignore (full_do_if_not_computing text f x)
+
+
+let add_input_view tv =
+ Vector.append input_views tv
+
+let get_input_view i =
+ if 0 <= i && i < Vector.length input_views
+ then
+ Vector.get input_views i
+ else raise Not_found
+
+let active_view = ref None
+
+let get_active_view () = Vector.get input_views (out_some !active_view)
+
+let set_active_view i =
+ (match !active_view with None -> () | Some i ->
+ reset_tab_label i);
+ (notebook ())#goto_page i;
+ let txt = get_current_tab_label () in
+ set_current_tab_label ("<span background=\"light green\">"^txt^"</span>");
+ active_view := Some i
+
+let set_current_view i = (notebook ())#goto_page i
+
+let kill_input_view i =
+ let v = Vector.get input_views i in
+ (match v.analyzed_view with
+ | Some v -> v#kill_detached_views ()
+ | None -> ());
+ v.view#destroy ();
+ v.analyzed_view <- None;
+ Vector.remove input_views i
+
+let get_current_view_page () = (notebook ())#current_page
+let get_current_view () = Vector.get input_views (notebook ())#current_page
+let remove_current_view_page () =
+ let c = (notebook ())#current_page in
+ kill_input_view c;
+ ((notebook ())#get_nth_page c)#misc#hide ()
+
+
+let is_word_char c =
+ Glib.Unichar.isalnum c || c = underscore || c = prime || c = arobase
+
+let starts_word it =
+ prerr_endline ("Starts word ? '"^(Glib.Utf8.from_unichar it#char)^"'");
+ (not it#copy#nocopy#backward_char ||
+ (let c = it#backward_char#char in
+ not (is_word_char c)))
+
+let ends_word it =
+ (not it#copy#nocopy#forward_char ||
+ let c = it#forward_char#char in
+ not (Glib.Unichar.isalnum c || c = underscore || c = prime || c = arobase)
+ )
+
+let inside_word it =
+ let c = it#char in
+ not (starts_word it) &&
+ not (ends_word it) &&
+ (Glib.Unichar.isalnum c || c = underscore || c = prime || c = arobase)
+
+let is_on_word_limit it = inside_word it || ends_word it
+
+let rec find_word_start it =
+ prerr_endline "Find word start";
+ if not it#nocopy#backward_char then
+ (prerr_endline "find_word_start: cannot backward"; it)
+ else if is_word_char it#char
+ then find_word_start it
+ else (it#nocopy#forward_char;
+ prerr_endline ("Word start at: "^(string_of_int it#offset));it)
+let find_word_start (it:GText.iter) = find_word_start it#copy
+
+let rec find_word_end it =
+ prerr_endline "Find word end";
+ if let c = it#char in c<>0 && is_word_char c
+ then begin
+ ignore (it#nocopy#forward_char);
+ find_word_end it
+ end else (prerr_endline ("Word end at: "^(string_of_int it#offset));it)
+let find_word_end it = find_word_end it#copy
+
+
+let get_word_around it =
+ let start = find_word_start it in
+ let stop = find_word_end it in
+ start,stop
+
+
+let rec complete_backward w (it:GText.iter) =
+ prerr_endline "Complete backward...";
+ match it#backward_search w with
+ | None -> (prerr_endline "backward_search failed";None)
+ | Some (start,stop) ->
+ prerr_endline ("complete_backward got a match:"^(string_of_int start#offset)^(string_of_int stop#offset));
+ if starts_word start then
+ let ne = find_word_end stop in
+ if ne#compare stop = 0
+ then complete_backward w start
+ else Some (start,stop,ne)
+ else complete_backward w start
+
+let rec complete_forward w (it:GText.iter) =
+ prerr_endline "Complete forward...";
+ match it#forward_search w with
+ | None -> None
+ | Some (start,stop) ->
+ if starts_word start then
+ let ne = find_word_end stop in
+ if ne#compare stop = 0 then
+ complete_forward w stop
+ else Some (stop,stop,ne)
+ else complete_forward w stop
+
+(* Reset this to None on page change ! *)
+let (last_completion:(string*int*int*bool) option ref) = ref None
+
+let () = to_do_on_page_switch :=
+ (fun i -> last_completion := None)::!to_do_on_page_switch
+
+let rec complete input_buffer w (offset:int) =
+ match !last_completion with
+ | Some (lw,loffset,lpos,backward)
+ when lw=w && loffset=offset ->
+ begin
+ let iter = input_buffer#get_iter (`OFFSET lpos) in
+ if backward then
+ match complete_backward w iter with
+ | None ->
+ last_completion :=
+ Some (lw,loffset,
+ (find_word_end
+ (input_buffer#get_iter (`OFFSET loffset)))#offset ,
+ false);
+ None
+ | Some (ss,start,stop) as result ->
+ last_completion :=
+ Some (w,offset,ss#offset,true);
+ result
+ else
+ match complete_forward w iter with
+ | None ->
+ last_completion := None;
+ None
+ | Some (ss,start,stop) as result ->
+ last_completion :=
+ Some (w,offset,ss#offset,false);
+ result
+ end
+ | _ -> begin
+ match complete_backward w (input_buffer#get_iter (`OFFSET offset)) with
+ | None ->
+ last_completion :=
+ Some (w,offset,(find_word_end (input_buffer#get_iter
+ (`OFFSET offset)))#offset,false);
+ complete input_buffer w offset
+ | Some (ss,start,stop) as result ->
+ last_completion := Some (w,offset,ss#offset,true);
+ result
+ end
+
+let get_current_word () =
+ let av = out_some ((get_current_view ()).analyzed_view) in
+ match GtkBase.Clipboard.wait_for_text (cb ())#as_clipboard with
+ | None ->
+ prerr_endline "None selected";
+ let it = av#get_insert in
+ let start = find_word_start it in
+ let stop = find_word_end start in
+ av#view#buffer#move_mark `SEL_BOUND start;
+ av#view#buffer#move_mark `INSERT stop;
+ av#view#buffer#get_text ~slice:true ~start ~stop ()
+ | Some t ->
+ prerr_endline "Some selected";
+ prerr_endline t;
+ t
+
+
+let input_channel b ic =
+ let buf = String.create 1024 and len = ref 0 in
+ while len := input ic buf 0 1024; !len > 0 do
+ Buffer.add_substring b buf 0 !len
+ done
+
+let with_file name ~f =
+ let ic = open_in_gen [Open_rdonly;Open_creat] 0o644 name in
+ try f ic; close_in ic with exn ->
+ close_in ic; !flash_info ("Error: "^Printexc.to_string exn)
+
+type info = {start:GText.mark;
+ stop:GText.mark;
+ ast:Util.loc * Vernacexpr.vernac_expr;
+ reset_info:Coq.reset_info;
+ }
+
+exception Size of int
+let (processed_stack:info Stack.t) = Stack.create ()
+let push x = Stack.push x processed_stack
+let pop () = try Stack.pop processed_stack with Stack.Empty -> raise (Size 0)
+let top () = try Stack.top processed_stack with Stack.Empty -> raise (Size 0)
+let is_empty () = Stack.is_empty processed_stack
+
+
+(* push a new Coq phrase *)
+
+let update_on_end_of_proof id =
+ let lookup_lemma = function
+ | { ast = _, ( VernacDefinition (_, _, ProveBody _, _)
+ | VernacDeclareTacticDefinition _
+ | VernacStartTheoremProof _) ;
+ reset_info = Reset (_, r) } ->
+ if not !r then begin
+ prerr_endline "Toggling Reset info to true";
+ r := true; raise Exit end
+ else begin
+ prerr_endline "Toggling Changing Reset id";
+ r := false
+ end
+ | { ast = _, (VernacAbort _ | VernacAbortAll | VernacGoal _) } -> raise Exit
+ | _ -> ()
+ in
+ try Stack.iter lookup_lemma processed_stack with Exit -> ()
+
+let update_on_end_of_segment id =
+ let lookup_section = function
+ | { ast = _, ( VernacBeginSection id'
+ | VernacDefineModule (id',_,_,None)
+ | VernacDeclareModule (id',_,_,None)
+ | VernacDeclareModuleType (id',_,None));
+ reset_info = Reset (_, r) }
+ when id = id' -> raise Exit
+ | { reset_info = Reset (_, r) } -> r := false
+ | _ -> ()
+ in
+ try Stack.iter lookup_section processed_stack with Exit -> ()
+
+let push_phrase start_of_phrase_mark end_of_phrase_mark ast =
+ let x = {start = start_of_phrase_mark;
+ stop = end_of_phrase_mark;
+ ast = ast;
+ reset_info = Coq.compute_reset_info (snd ast)
+ }
+ in
+ push x;
+ match snd ast with
+ | VernacEndProof (Proved (_, None)) -> update_on_end_of_proof ()
+ | VernacEndSegment id -> update_on_end_of_segment id
+ | _ -> ()
+
+let repush_phrase x =
+ let x = { x with reset_info = Coq.compute_reset_info (snd x.ast) } in
+ push x;
+ match snd x.ast with
+ | VernacEndProof (Proved (_, None)) -> update_on_end_of_proof ()
+ | VernacEndSegment id -> update_on_end_of_segment id
+ | _ -> ()
+
+(* For electric handlers *)
+exception Found
+
+(* For find_phrase_starting_at *)
+exception Stop of int
+
+let activate_input i =
+ (match !active_view with
+ | None -> ()
+ | Some n ->
+ let a_v = out_some (Vector.get input_views n).analyzed_view in
+ a_v#deactivate ();
+ a_v#reset_initial
+ );
+ let activate_function = (out_some (Vector.get input_views i).analyzed_view)#activate in
+ activate_function ();
+ set_active_view i
+
+let warning msg =
+ GToolbox.message_box ~title:"Warning"
+ ~icon:(let img = GMisc.image () in
+ img#set_stock `DIALOG_WARNING;
+ img#set_icon_size `DIALOG;
+ img#coerce)
+ msg
+
+
+class analyzed_view index =
+ let {view = input_view_} as current_all_ = get_input_view index in
+ let proof_view_ = out_some !proof_view in
+ let message_view_ = out_some !message_view in
+object(self)
+ val current_all = current_all_
+ val input_view = current_all_.view
+ val proof_view = out_some !proof_view
+ val message_view = out_some !message_view
+ val input_buffer = input_view_#buffer
+ val proof_buffer = proof_view_#buffer
+ val message_buffer = message_view_#buffer
+ val mutable is_active = false
+ val mutable read_only = false
+ val mutable filename = None
+ val mutable stats = None
+ val mutable last_modification_time = 0.
+ val mutable last_auto_save_time = 0.
+ val mutable detached_views = []
+
+ val mutable auto_complete_on = !current.auto_complete
+
+ method private toggle_auto_complete =
+ auto_complete_on <- not auto_complete_on
+ method set_auto_complete t = auto_complete_on <- t
+ method without_auto_complete : 'a 'b. ('a -> 'b) -> 'a -> 'b = fun f x ->
+ let old = auto_complete_on in
+ self#set_auto_complete false;
+ let y = f x in
+ self#set_auto_complete old;
+ y
+ method add_detached_view (w:GWindow.window) =
+ detached_views <- w::detached_views
+ method remove_detached_view (w:GWindow.window) =
+ detached_views <- List.filter (fun e -> w#misc#get_oid<>e#misc#get_oid) detached_views
+
+ method kill_detached_views () =
+ List.iter (fun w -> w#destroy ()) detached_views;
+ detached_views <- []
+
+ method view = input_view
+ method filename = filename
+ method stats = stats
+ method set_filename f =
+ filename <- f;
+ match f with
+ | Some f -> stats <- my_stat f
+ | None -> ()
+
+ method update_stats =
+ match filename with
+ | Some f -> stats <- my_stat f
+ | _ -> ()
+
+ method revert =
+ match filename with
+ | Some f -> begin
+ let do_revert () = begin
+ !push_info "Reverting buffer";
+ try
+ if is_active then self#reset_initial;
+ let b = Buffer.create 1024 in
+ with_file f ~f:(input_channel b);
+ let s = try_convert (Buffer.contents b) in
+ input_buffer#set_text s;
+ self#update_stats;
+ input_buffer#place_cursor input_buffer#start_iter;
+ input_buffer#set_modified false;
+ !pop_info ();
+ !flash_info "Buffer reverted";
+ Highlight.highlight_all input_buffer;
+ with _ ->
+ !pop_info ();
+ !flash_info "Warning: could not revert buffer";
+ end
+ in
+ if input_buffer#modified then
+ match (GToolbox.question_box
+ ~title:"Modified buffer changed on disk"
+ ~buttons:["Revert from File";
+ "Overwrite File";
+ "Disable Auto Revert"]
+ ~default:0
+ ~icon:(stock_to_widget `DIALOG_WARNING)
+ "Some unsaved buffers changed on disk"
+ )
+ with 1 -> do_revert ()
+ | 2 -> if self#save f then !flash_info "Overwritten" else
+ !flash_info "Could not overwrite file"
+ | _ ->
+ prerr_endline "Auto revert set to false";
+ !current.global_auto_revert <- false;
+ disconnect_revert_timer ()
+ else do_revert ()
+ end
+ | None -> ()
+
+ method save f =
+ if try_export f (input_buffer#get_text ()) then begin
+ filename <- Some f;
+ input_buffer#set_modified false;
+ stats <- my_stat f;
+ (match self#auto_save_name with
+ | None -> ()
+ | Some fn -> try Sys.remove fn with _ -> ());
+ true
+ end
+ else false
+
+ method private auto_save_name =
+ match filename with
+ | None -> None
+ | Some f ->
+ let dir = Filename.dirname f in
+ let base = (fst !current.auto_save_name) ^
+ (Filename.basename f) ^
+ (snd !current.auto_save_name)
+ in Some (Filename.concat dir base)
+
+ method private need_auto_save =
+ input_buffer#modified &&
+ last_modification_time > last_auto_save_time
+
+ method auto_save =
+ if self#need_auto_save then begin
+ match self#auto_save_name with
+ | None -> ()
+ | Some fn ->
+ try
+ last_auto_save_time <- Unix.time();
+ prerr_endline ("Autosave time : "^(string_of_float (Unix.time())));
+ if try_export fn (input_buffer#get_text ()) then begin
+ !flash_info ~delay:1000 "Autosaved"
+ end
+ else warning
+ ("Autosave failed (check if " ^ fn ^ " is writable)")
+ with _ ->
+ warning ("Autosave: unexpected error while writing "^fn)
+ end
+
+ method save_as f =
+ if Sys.file_exists f then
+ match (GToolbox.question_box ~title:"File exists on disk"
+ ~buttons:["Overwrite";
+ "Cancel";]
+ ~default:1
+ ~icon:
+ (let img = GMisc.image () in
+ img#set_stock `DIALOG_WARNING;
+ img#set_icon_size `DIALOG;
+ img#coerce)
+ ("File "^f^"already exists")
+ )
+ with 1 -> self#save f
+ | _ -> false
+ else self#save f
+
+ method set_read_only b = read_only<-b
+ method read_only = read_only
+ method is_active = is_active
+ method insert_message s =
+ message_buffer#insert s;
+ message_view#misc#draw None
+
+ method set_message s =
+ message_buffer#set_text s;
+ message_view#misc#draw None
+
+ method clear_message = message_buffer#set_text ""
+ val mutable last_index = true
+ val last_array = [|"";""|]
+ method get_start_of_input = input_buffer#get_iter_at_mark (`NAME "start_of_input")
+
+ method get_insert = get_insert input_buffer
+
+ method recenter_insert =
+ (* BUG : to investigate further:
+ FIXED : Never call GMain.* in thread !
+ PLUS : GTK BUG ??? Cannot be called from a thread...
+ ADDITION: using sync instead of async causes deadlock...*)
+ ignore (GtkThread.async (
+ input_view#scroll_to_mark
+ ~use_align:false
+ ~yalign:0.75
+ ~within_margin:0.25)
+ `INSERT)
+
+
+ method indent_current_line =
+ let get_nb_space it =
+ let it = it#copy in
+ let nb_sep = ref 0 in
+ let continue = ref true in
+ while !continue do
+ if it#char = space then begin
+ incr nb_sep;
+ if not it#nocopy#forward_char then continue := false;
+ end else continue := false
+ done;
+ !nb_sep
+ in
+ let previous_line = self#get_insert in
+ if previous_line#nocopy#backward_line then begin
+ let previous_line_spaces = get_nb_space previous_line in
+ let current_line_start = self#get_insert#set_line_offset 0 in
+ let current_line_spaces = get_nb_space current_line_start in
+ if input_buffer#delete_interactive
+ ~start:current_line_start
+ ~stop:(current_line_start#forward_chars current_line_spaces)
+ ()
+ then
+ let current_line_start = self#get_insert#set_line_offset 0 in
+ input_buffer#insert
+ ~iter:current_line_start
+ (String.make previous_line_spaces ' ')
+ end
+
+
+ method show_goals =
+ try
+ proof_view#buffer#set_text "";
+ let s = Coq.get_current_goals () in
+ match s with
+ | [] -> proof_buffer#insert (Coq.print_no_goal ())
+ | (hyps,concl)::r ->
+ let goal_nb = List.length s in
+ proof_buffer#insert (Printf.sprintf "%d subgoal%s\n"
+ goal_nb
+ (if goal_nb<=1 then "" else "s"));
+ List.iter
+ (fun ((_,_,_,(s,_)) as hyp) ->
+ proof_buffer#insert (s^"\n"))
+ hyps;
+ proof_buffer#insert (String.make 38 '_' ^ "(1/"^
+ (string_of_int goal_nb)^
+ ")\n")
+ ;
+ let _,_,_,sconcl = concl in
+ proof_buffer#insert sconcl;
+ proof_buffer#insert "\n";
+ let my_mark = `NAME "end_of_conclusion" in
+ proof_buffer#move_mark
+ ~where:((proof_buffer#get_iter_at_mark `INSERT)) my_mark;
+ proof_buffer#insert "\n\n";
+ let i = ref 1 in
+ List.iter
+ (function (_,(_,_,_,concl)) ->
+ incr i;
+ proof_buffer#insert (String.make 38 '_' ^"("^
+ (string_of_int !i)^
+ "/"^
+ (string_of_int goal_nb)^
+ ")\n");
+ proof_buffer#insert concl;
+ proof_buffer#insert "\n\n";
+ )
+ r;
+ ignore (proof_view#scroll_to_mark my_mark)
+ with e -> prerr_endline ("Don't worry be happy despite: "^Printexc.to_string e)
+
+
+ val mutable full_goal_done = true
+
+ method show_goals_full =
+ if not full_goal_done then
+ begin
+ try
+ proof_view#buffer#set_text "";
+ let s = Coq.get_current_goals () in
+ let last_shown_area = proof_buffer#create_tag [`BACKGROUND "light green"]
+ in
+ match s with
+ | [] -> proof_buffer#insert (Coq.print_no_goal ())
+ | (hyps,concl)::r ->
+ let goal_nb = List.length s in
+ proof_buffer#insert (Printf.sprintf "%d subgoal%s\n"
+ goal_nb
+ (if goal_nb<=1 then "" else "s"));
+ let coq_menu commands =
+ let tag = proof_buffer#create_tag []
+ in
+ ignore
+ (tag#connect#event ~callback:
+ (fun ~origin ev it ->
+ begin match GdkEvent.get_type ev with
+ | `BUTTON_PRESS ->
+ let ev = (GdkEvent.Button.cast ev) in
+ if (GdkEvent.Button.button ev) = 3
+ then begin
+ let loc_menu = GMenu.menu () in
+ let factory = new GMenu.factory loc_menu in
+ let add_coq_command (cp,ip) =
+ ignore
+ (factory#add_item cp
+ ~callback:
+ (fun () -> ignore
+ (self#insert_this_phrase_on_success
+ true
+ true
+ false
+ ("progress "^ip^"\n")
+ (ip^"\n"))
+ )
+ )
+ in
+ List.iter add_coq_command commands;
+ loc_menu#popup
+ ~button:3
+ ~time:(GdkEvent.Button.time ev);
+ end
+ | `MOTION_NOTIFY ->
+ proof_buffer#remove_tag
+ ~start:proof_buffer#start_iter
+ ~stop:proof_buffer#end_iter
+ last_shown_area;
+ prerr_endline "Before find_tag_limits";
+
+ let s,e = find_tag_limits tag
+ (new GText.iter it)
+ in
+ prerr_endline "After find_tag_limits";
+ proof_buffer#apply_tag
+ ~start:s
+ ~stop:e
+ last_shown_area;
+
+ prerr_endline "Applied tag";
+ ()
+ | _ -> ()
+ end;false
+ )
+ );
+ tag
+ in
+ List.iter
+ (fun ((_,_,_,(s,_)) as hyp) ->
+ let tag = coq_menu (hyp_menu hyp) in
+ proof_buffer#insert ~tags:[tag] (s^"\n"))
+ hyps;
+ proof_buffer#insert
+ (String.make 38 '_' ^"(1/"^
+ (string_of_int goal_nb)^
+ ")\n")
+ ;
+ let tag = coq_menu (concl_menu concl) in
+ let _,_,_,sconcl = concl in
+ proof_buffer#insert ~tags:[tag] sconcl;
+ proof_buffer#insert "\n";
+ let my_mark = `NAME "end_of_conclusion" in
+ proof_buffer#move_mark
+ ~where:((proof_buffer#get_iter_at_mark `INSERT)) my_mark;
+ proof_buffer#insert "\n\n";
+ let i = ref 1 in
+ List.iter
+ (function (_,(_,_,_,concl)) ->
+ incr i;
+ proof_buffer#insert
+ (String.make 38 '_' ^"("^
+ (string_of_int !i)^
+ "/"^
+ (string_of_int goal_nb)^
+ ")\n");
+ proof_buffer#insert concl;
+ proof_buffer#insert "\n\n";
+ )
+ r;
+ ignore (proof_view#scroll_to_mark my_mark) ;
+ full_goal_done <- true;
+ with e -> prerr_endline (Printexc.to_string e)
+ end
+
+ method send_to_coq verbosely replace phrase show_output show_error localize =
+ try
+ full_goal_done <- false;
+ prerr_endline "Send_to_coq starting now";
+ if replace then begin
+ let r,info =
+(* full_do_if_not_computing "coq eval and replace" *)
+ Coq.interp_and_replace ("Info " ^ phrase)
+ in
+ let msg = read_stdout () in
+ self#insert_message (if show_output then msg else "");
+
+ Some r
+
+ end else begin
+ let r = Some (Coq.interp verbosely phrase) in
+ let msg = read_stdout () in
+ self#insert_message (if show_output then msg else "");
+ r
+ end
+ with e ->
+ (if show_error then
+ let (s,loc) = Coq.process_exn e in
+ assert (Glib.Utf8.validate s);
+ self#set_message s;
+ message_view#misc#draw None;
+ if localize then
+ (match Util.option_app Util.unloc loc with
+ | None -> ()
+ | Some (start,stop) ->
+ let convert_pos = byte_offset_to_char_offset phrase in
+ let start = convert_pos start in
+ let stop = convert_pos stop in
+ let i = self#get_start_of_input in
+ let starti = i#forward_chars start in
+ let stopi = i#forward_chars stop in
+ input_buffer#apply_tag_by_name "error"
+ ~start:starti
+ ~stop:stopi;
+ input_buffer#place_cursor starti;
+ ));
+ None
+
+ method find_phrase_starting_at (start:GText.iter) =
+ prerr_endline "find_phrase_starting_at starting now";
+ let trash_bytes = ref "" in
+ let end_iter = start#copy in
+ let lexbuf_function s count =
+ let i = ref 0 in
+ let n_trash = String.length !trash_bytes in
+ String.blit !trash_bytes 0 s 0 n_trash;
+ i := n_trash;
+ try
+ while !i <= count - 1 do
+ let c = end_iter#char in
+ if c = 0 then raise (Stop !i);
+ let c' = Glib.Utf8.from_unichar c in
+ let n = String.length c' in
+ if (n<=0) then exit (-2);
+ if n > count - !i then
+ begin
+ let ri = count - !i in
+ String.blit c' 0 s !i ri;
+ trash_bytes := String.sub c' ri (n-ri);
+ i := count ;
+ end else begin
+ String.blit c' 0 s !i n;
+ i:= !i + n
+ end;
+ if not end_iter#nocopy#forward_char then
+ raise (Stop !i)
+ done;
+ count
+ with Stop x ->
+ x
+ in
+ try
+ trash_bytes := "";
+ let phrase = Find_phrase.get (Lexing.from_function lexbuf_function)
+ in
+ end_iter#nocopy#set_offset (start#offset + !Find_phrase.length);
+ Some (start,end_iter)
+ with
+ | Find_phrase.EOF s ->
+ (* Phrase is at the end of the buffer*)
+ let si = start#offset in
+ let ei = si + !Find_phrase.length in
+ end_iter#nocopy#set_offset (ei - 1);
+ input_buffer#insert ~iter:end_iter "\n";
+ Some (input_buffer#get_iter (`OFFSET si),
+ input_buffer#get_iter (`OFFSET ei))
+ | _ -> None
+
+ method complete_at_offset (offset:int) =
+ prerr_endline ("Completion at offset : " ^ string_of_int offset);
+ let it () = input_buffer#get_iter (`OFFSET offset) in
+ let iit = it () in
+ let start = find_word_start iit in
+ if ends_word iit then
+ let w = input_buffer#get_text
+ ~start
+ ~stop:iit
+ ()
+ in
+ if String.length w <> 0 then begin
+ prerr_endline ("Completion of prefix : '" ^ w^"'");
+ match complete input_buffer w start#offset with
+ | None -> false
+ | Some (ss,start,stop) ->
+ let completion = input_buffer#get_text ~start ~stop () in
+ ignore (input_buffer#delete_selection ());
+ ignore (input_buffer#insert_interactive completion);
+ input_buffer#move_mark `SEL_BOUND (it())#backward_char;
+ true
+ end else false
+ else false
+
+
+ method process_next_phrase verbosely display_goals do_highlight =
+ begin
+ try
+ self#clear_message;
+ prerr_endline "process_next_phrase starting now";
+ if do_highlight then begin
+ !push_info "Coq is computing";
+ input_view#set_editable false;
+ end;
+ begin match (self#find_phrase_starting_at self#get_start_of_input)
+ with
+ | None ->
+ if do_highlight then begin
+ input_view#set_editable true;
+ !pop_info ();
+ end; false
+ | Some(start,stop) ->
+ prerr_endline "process_next_phrase : to_process highlight";
+ let b = input_buffer in
+ if do_highlight then begin
+ input_buffer#apply_tag_by_name ~start ~stop "to_process";
+ prerr_endline "process_next_phrase : to_process applied";
+ end;
+ prerr_endline "process_next_phrase : getting phrase";
+ let phrase = start#get_slice ~stop in
+ let r =
+ match self#send_to_coq verbosely false phrase true true true with
+ | Some ast ->
+ begin
+ b#move_mark ~where:stop (`NAME "start_of_input");
+ b#apply_tag_by_name "processed" ~start ~stop;
+ if (self#get_insert#compare) stop <= 0 then
+ begin
+ b#place_cursor stop;
+ self#recenter_insert
+ end;
+ let start_of_phrase_mark = `MARK (b#create_mark start) in
+ let end_of_phrase_mark = `MARK (b#create_mark stop) in
+ push_phrase
+ start_of_phrase_mark
+ end_of_phrase_mark ast;
+ if display_goals then self#show_goals;
+ true
+ end
+ | None -> false
+ in
+ if do_highlight then begin
+ b#remove_tag_by_name ~start ~stop "to_process" ;
+ input_view#set_editable true;
+ !pop_info ();
+ end;
+ r;
+ end
+ with e -> raise e
+ end
+
+ method insert_this_phrase_on_success
+ show_output show_msg localize coqphrase insertphrase =
+ match self#send_to_coq false false coqphrase show_output show_msg localize with
+ | Some ast ->
+ begin
+ let stop = self#get_start_of_input in
+ if stop#starts_line then
+ input_buffer#insert ~iter:stop insertphrase
+ else input_buffer#insert ~iter:stop ("\n"^insertphrase);
+ let start = self#get_start_of_input in
+ input_buffer#move_mark ~where:stop (`NAME "start_of_input");
+ input_buffer#apply_tag_by_name "processed" ~start ~stop;
+ if (self#get_insert#compare) stop <= 0 then
+ input_buffer#place_cursor stop;
+ let start_of_phrase_mark = `MARK (input_buffer#create_mark start)
+ in
+ let end_of_phrase_mark = `MARK (input_buffer#create_mark stop) in
+ push_phrase start_of_phrase_mark end_of_phrase_mark ast;
+ self#show_goals;
+ (*Auto insert save on success...
+ try (match Coq.get_current_goals () with
+ | [] ->
+ (match self#send_to_coq "Save.\n" true true true with
+ | Some ast ->
+ begin
+ let stop = self#get_start_of_input in
+ if stop#starts_line then
+ input_buffer#insert ~iter:stop "Save.\n"
+ else input_buffer#insert ~iter:stop "\nSave.\n";
+ let start = self#get_start_of_input in
+ input_buffer#move_mark ~where:stop (`NAME "start_of_input");
+ input_buffer#apply_tag_by_name "processed" ~start ~stop;
+ if (self#get_insert#compare) stop <= 0 then
+ input_buffer#place_cursor stop;
+ let start_of_phrase_mark = `MARK (input_buffer#create_mark start)
+ in
+ let end_of_phrase_mark = `MARK (input_buffer#create_mark stop) in
+ push_phrase start_of_phrase_mark end_of_phrase_mark ast
+ end
+ | None -> ())
+ | _ -> ())
+ with _ -> ()*)
+ true
+ end
+ | None -> self#insert_message ("Unsuccessfully tried: "^coqphrase);
+ false
+
+ method process_until_iter_or_error stop =
+ let stop' = `OFFSET stop#offset in
+ let start = self#get_start_of_input#copy in
+ let start' = `OFFSET start#offset in
+ input_buffer#apply_tag_by_name
+ ~start
+ ~stop
+ "to_process";
+ input_view#set_editable false;
+ !push_info "Coq is computing";
+ process_pending ();
+ (try
+ while ((stop#compare self#get_start_of_input>=0)
+ && (self#process_next_phrase false false false))
+ do Util.check_for_interrupt () done
+ with Sys.Break ->
+ prerr_endline "Interrupted during process_until_iter_or_error");
+ self#show_goals;
+ (* Start and stop might be invalid if an eol was added at eof *)
+ let start = input_buffer#get_iter start' in
+ let stop = input_buffer#get_iter stop' in
+ input_buffer#remove_tag_by_name ~start ~stop "to_process" ;
+ input_view#set_editable true;
+ !pop_info()
+
+ method process_until_end_or_error =
+ self#process_until_iter_or_error input_buffer#end_iter
+
+ method reset_initial =
+ Stack.iter
+ (function inf ->
+ let start = input_buffer#get_iter_at_mark inf.start in
+ let stop = input_buffer#get_iter_at_mark inf.stop in
+ input_buffer#move_mark ~where:start (`NAME "start_of_input");
+ input_buffer#remove_tag_by_name "processed" ~start ~stop;
+ input_buffer#delete_mark inf.start;
+ input_buffer#delete_mark inf.stop;
+ )
+ processed_stack;
+ Stack.clear processed_stack;
+ self#clear_message;
+ Coq.reset_initial ()
+
+
+ (* backtrack Coq to the phrase preceding iterator [i] *)
+ method backtrack_to_no_lock i =
+ prerr_endline "Backtracking_to iter starts now.";
+ (* re-synchronize Coq to the current state of the stack *)
+ let rec synchro () =
+ if is_empty () then
+ Coq.reset_initial ()
+ else begin
+ let t = pop () in
+ begin match t.reset_info with
+ | Reset (id, ({contents=true} as v)) -> v:=false;
+ (match snd t.ast with
+ | VernacBeginSection _ | VernacDefineModule _
+ | VernacDeclareModule _ | VernacDeclareModuleType _
+ | VernacEndSegment _
+ -> reset_to_mod id
+ | _ -> reset_to id)
+ | _ -> synchro ()
+ end;
+ interp_last t.ast;
+ repush_phrase t
+ end
+ in
+ let add_undo t = match t with | Some n -> Some (succ n) | None -> None
+ in
+ (* pop Coq commands until we reach iterator [i] *)
+ let rec pop_commands done_smthg undos =
+ if is_empty () then
+ done_smthg, undos
+ else
+ let t = top () in
+ if i#compare (input_buffer#get_iter_at_mark t.stop) < 0 then begin
+ ignore (pop ());
+ let undos = if is_tactic (snd t.ast) then add_undo undos else None in
+ pop_commands true undos
+ end else
+ done_smthg, undos
+ in
+ let done_smthg, undos = pop_commands false (Some 0) in
+ prerr_endline "Popped commands";
+ if done_smthg then
+ begin
+ try
+ (match undos with
+ | None -> synchro ()
+ | Some n -> try Pfedit.undo n with _ -> synchro ());
+ let start = if is_empty () then input_buffer#start_iter
+ else input_buffer#get_iter_at_mark (top ()).stop
+ in
+ prerr_endline "Removing (long) processed tag...";
+ input_buffer#remove_tag_by_name
+ ~start
+ ~stop:self#get_start_of_input
+ "processed";
+ prerr_endline "Moving (long) start_of_input...";
+ input_buffer#move_mark ~where:start (`NAME "start_of_input");
+ self#show_goals;
+ clear_stdout ();
+ self#clear_message;
+ with _ ->
+ !push_info "WARNING: undo failed badly -> Coq might be in an inconsistent state.
+Please restart and report NOW.";
+ end
+ else prerr_endline "backtrack_to : discarded (...)"
+
+ method backtrack_to i =
+ if Mutex.try_lock coq_may_stop then
+ (!push_info "Undoing...";self#backtrack_to_no_lock i ; Mutex.unlock coq_may_stop;
+ !pop_info ())
+ else prerr_endline "backtrack_to : discarded (lock is busy)"
+
+ method go_to_insert =
+ let point = self#get_insert in
+ if point#compare self#get_start_of_input>=0
+ then self#process_until_iter_or_error point
+ else self#backtrack_to point
+
+ method undo_last_step =
+ if Mutex.try_lock coq_may_stop then
+ (!push_info "Undoing last step...";
+ (try
+ let last_command = top () in
+ let start = input_buffer#get_iter_at_mark last_command.start in
+ let update_input () =
+ prerr_endline "Removing processed tag...";
+ input_buffer#remove_tag_by_name
+ ~start
+ ~stop:(input_buffer#get_iter_at_mark last_command.stop)
+ "processed";
+ prerr_endline "Moving start_of_input";
+ input_buffer#move_mark
+ ~where:start
+ (`NAME "start_of_input");
+ input_buffer#place_cursor start;
+ self#recenter_insert;
+ self#show_goals;
+ self#clear_message
+ in
+ begin match last_command with
+ | {ast=_, (VernacSolve _ | VernacTime (VernacSolve _))} ->
+ begin
+ try Pfedit.undo 1; ignore (pop ()); update_input ()
+ with _ -> self#backtrack_to_no_lock start
+ end
+ | {ast=_,t;reset_info=Reset (id, {contents=true})} ->
+ ignore (pop ());
+ (match t with
+ | VernacBeginSection _ | VernacDefineModule _
+ | VernacDeclareModule _ | VernacDeclareModuleType _
+ | VernacEndSegment _
+ -> reset_to_mod id
+ | _ -> reset_to id);
+ update_input ()
+ | { ast = _, ( VernacStartTheoremProof _
+ | VernacGoal _
+ | VernacDeclareTacticDefinition _
+ | VernacDefinition (_,_,ProveBody _,_));
+ reset_info=Reset(id,{contents=false})} ->
+ ignore (pop ());
+ (try
+ Pfedit.delete_current_proof ()
+ with e ->
+ begin
+ prerr_endline "WARNING : found a closed environment";
+ raise e
+ end);
+ update_input ()
+ | { ast = (_, a) } when is_state_preserving a ->
+ ignore (pop ());
+ update_input ()
+ | _ ->
+ self#backtrack_to_no_lock start
+ end;
+ with
+ | Size 0 -> (* !flash_info "Nothing to Undo"*)()
+ );
+ !pop_info ();
+ Mutex.unlock coq_may_stop)
+ else prerr_endline "undo_last_step discarded"
+
+
+ method blaster () =
+
+ ignore (Thread.create
+ (fun () ->
+ prerr_endline "Blaster called";
+ let c = Blaster_window.present_blaster_window () in
+ if Mutex.try_lock c#lock then begin
+ c#clear ();
+ let current_gls = try get_current_goals () with _ -> [] in
+ let gls_nb = List.length current_gls in
+
+ let set_goal i (s,t) =
+ let gnb = string_of_int i in
+ let s = gnb ^":"^s in
+ let t' = gnb ^": progress "^t in
+ let t'' = gnb ^": "^t in
+ c#set
+ ("Goal "^gnb)
+ s
+ (fun () -> try_interptac t')
+ (fun () -> self#insert_command t'' t'')
+ in
+ let set_current_goal (s,t) =
+ c#set
+ "Goal 1"
+ s
+ (fun () -> try_interptac ("progress "^t))
+ (fun () -> self#insert_command t t)
+ in
+ begin match current_gls with
+ | [] -> ()
+ | (hyp_l,current_gl)::r ->
+ List.iter set_current_goal (concl_menu current_gl);
+ List.iter
+ (fun hyp ->
+ List.iter set_current_goal (hyp_menu hyp))
+ hyp_l;
+ let i = ref 2 in
+ List.iter
+ (fun (hyp_l,gl) ->
+ List.iter (set_goal !i) (concl_menu gl);
+ incr i)
+ r
+ end;
+ let _ = c#blaster () in
+ Mutex.unlock c#lock
+ end else prerr_endline "Blaster discarded")
+ ())
+
+ method insert_command cp ip =
+ self#clear_message;
+ ignore (self#insert_this_phrase_on_success true false false cp ip)
+
+ method tactic_wizard l =
+ self#clear_message;
+ ignore
+ (List.exists
+ (fun p ->
+ self#insert_this_phrase_on_success true false false
+ ("progress "^p^".\n") (p^".\n")) l)
+
+ method active_keypress_handler k =
+ let state = GdkEvent.Key.state k in
+ begin
+ match state with
+ | l when List.mem `MOD1 l ->
+ let k = GdkEvent.Key.keyval k in
+ if GdkKeysyms._Return=k
+ then ignore(
+ if (input_buffer#insert_interactive "\n") then
+ begin
+ let i= self#get_insert#backward_word_start in
+ prerr_endline "active_kp_hf: Placing cursor";
+ self#process_until_iter_or_error i
+ end);
+ true
+ | l when List.mem `CONTROL l ->
+ let k = GdkEvent.Key.keyval k in
+ if GdkKeysyms._Break=k
+ then break ();
+ false
+ | l ->
+ if GdkEvent.Key.keyval k = GdkKeysyms._Tab then begin
+ prerr_endline "active_kp_handler for Tab";
+ self#indent_current_line;
+ true
+ end else false
+ end
+ method disconnected_keypress_handler k =
+ match GdkEvent.Key.state k with
+ | l when List.mem `CONTROL l ->
+ let k = GdkEvent.Key.keyval k in
+ if GdkKeysyms._c=k
+ then break ();
+ false
+ | l -> false
+
+
+ val mutable deact_id = None
+ val mutable act_id = None
+
+ method deactivate () =
+ is_active <- false;
+ (match act_id with None -> ()
+ | Some id ->
+ reset_initial ();
+ input_view#misc#disconnect id;
+ prerr_endline "DISCONNECTED old active : ";
+ print_id id;
+ );
+ deact_id <- Some
+ (input_view#event#connect#key_press self#disconnected_keypress_handler);
+ prerr_endline "CONNECTED inactive : ";
+ print_id (out_some deact_id)
+
+ method activate () =
+ is_active <- true;
+ (match deact_id with None -> ()
+ | Some id -> input_view#misc#disconnect id;
+ prerr_endline "DISCONNECTED old inactive : ";
+ print_id id
+ );
+ act_id <- Some
+ (input_view#event#connect#key_press self#active_keypress_handler);
+ prerr_endline "CONNECTED active : ";
+ print_id (out_some act_id);
+ let dir = (match
+ (out_some ((Vector.get input_views index).analyzed_view))
+ #filename
+ with
+ | None -> ()
+ | Some f ->
+ if not (is_in_coq_path f) then
+ begin
+ let dir = Filename.dirname f in
+ ignore (Coq.interp false
+ (Printf.sprintf "Add LoadPath \"%s\". " dir))
+ end)
+ in ()
+
+
+
+ method electric_handler =
+ input_buffer#connect#insert_text ~callback:
+ (fun it x ->
+ begin try
+ if last_index then begin
+ last_array.(0)<-x;
+ if (last_array.(1) ^ last_array.(0) = ".\n") then raise Found
+ end else begin
+ last_array.(1)<-x;
+ if (last_array.(0) ^ last_array.(1) = ".\n") then raise Found
+ end
+ with Found ->
+ begin
+ ignore (self#process_next_phrase false true true)
+ end;
+ end;
+ last_index <- not last_index;)
+
+ method private electric_paren tag =
+ let oparen_code = Glib.Utf8.to_unichar "(" (ref 0) in
+ let cparen_code = Glib.Utf8.to_unichar ")" (ref 0) in
+ ignore (input_buffer#connect#insert_text ~callback:
+ (fun it x ->
+ input_buffer#remove_tag
+ ~start:input_buffer#start_iter
+ ~stop:input_buffer#end_iter
+ tag;
+ if x = "" then () else
+ match x.[String.length x - 1] with
+ | ')' ->
+ let hit = self#get_insert in
+ let count = ref 0 in
+ if hit#nocopy#backward_find_char
+ (fun c ->
+ if c = oparen_code && !count = 0 then true
+ else if c = cparen_code then
+ (incr count;false)
+ else if c = oparen_code then
+ (decr count;false)
+ else false
+ )
+ then
+ begin
+ prerr_endline "Found matching parenthesis";
+ input_buffer#apply_tag tag ~start:hit ~stop:hit#forward_char
+ end
+ else ()
+ | _ -> ())
+ )
+
+ method help_for_keyword () =
+
+ browse_keyword (self#insert_message) (get_current_word ())
+
+ initializer
+ ignore (message_buffer#connect#insert_text
+ ~callback:(fun it s -> ignore
+ (message_view#scroll_to_mark
+ ~use_align:false
+ ~within_margin:0.49
+ `INSERT)));
+ ignore (input_buffer#connect#insert_text
+ ~callback:(fun it s ->
+ if (it#compare self#get_start_of_input)<0
+ then GtkSignal.stop_emit ();
+ if String.length s > 1 then
+ (prerr_endline "insert_text: Placing cursor";input_buffer#place_cursor it)));
+ ignore (input_buffer#connect#after#apply_tag
+ ~callback:(fun tag ~start ~stop ->
+ if (start#compare self#get_start_of_input)>=0
+ then
+ input_buffer#remove_tag_by_name
+ ~start
+ ~stop
+ "processed"
+ )
+ );
+ ignore (input_buffer#connect#after#insert_text
+ ~callback:(fun it s ->
+ if auto_complete_on &&
+ String.length s = 1 && s <> " " && s <> "\n"
+ then
+ let v = out_some (get_current_view ()).analyzed_view
+ in
+ let has_completed =
+ v#complete_at_offset
+ ((v#view#buffer#get_iter `SEL_BOUND)#offset)
+ in
+ if has_completed then
+ input_buffer#move_mark `SEL_BOUND (input_buffer#get_iter `SEL_BOUND)#forward_char;
+
+
+ )
+ );
+ ignore (input_buffer#connect#modified_changed
+ ~callback:
+ (fun () ->
+ if input_buffer#modified then
+ set_tab_image index
+ ~icon:(match (out_some (current_all.analyzed_view))#filename with
+ | None -> `SAVE_AS
+ | Some _ -> `SAVE
+ )
+ else set_tab_image index ~icon:`YES;
+ ));
+ ignore (input_buffer#connect#changed
+ ~callback:(fun () ->
+ last_modification_time <- Unix.time ();
+ let r = input_view#visible_rect in
+ let stop =
+ input_view#get_iter_at_location
+ ~x:(Gdk.Rectangle.x r + Gdk.Rectangle.width r)
+ ~y:(Gdk.Rectangle.y r + Gdk.Rectangle.height r)
+ in
+ input_buffer#remove_tag_by_name
+ ~start:self#get_start_of_input
+ ~stop
+ "error";
+ Highlight.highlight_around_current_line
+ input_buffer
+ )
+ );
+ ignore (input_buffer#add_selection_clipboard (cb()));
+ let paren_highlight_tag = input_buffer#create_tag ~name:"paren" [`BACKGROUND "purple"] in
+ self#electric_paren paren_highlight_tag;
+ ignore (input_buffer#connect#after#mark_set
+ ~callback:(fun it (m:Gtk.text_mark) ->
+ !set_location
+ (Printf.sprintf
+ "Line: %5d Char: %3d" (self#get_insert#line + 1)
+ (self#get_insert#line_offset + 1));
+ match GtkText.Mark.get_name m with
+ | Some "insert" ->
+ input_buffer#remove_tag
+ ~start:input_buffer#start_iter
+ ~stop:input_buffer#end_iter
+ paren_highlight_tag;
+ | Some s ->
+ prerr_endline (s^" moved")
+ | None -> () )
+ );
+ ignore (input_buffer#connect#insert_text
+ (fun it s ->
+ prerr_endline "Should recenter ?";
+ if String.contains s '\n' then begin
+ prerr_endline "Should recenter : yes";
+ self#recenter_insert
+ end))
+end
+
+let create_input_tab filename =
+ let b = GText.buffer () in
+ let tablabel = GMisc.label () in
+ let v_box = GPack.hbox ~homogeneous:false () in
+ let image = GMisc.image ~packing:v_box#pack () in
+ let label = GMisc.label ~text:filename ~packing:v_box#pack () in
+ let fr1 = GBin.frame ~shadow_type:`ETCHED_OUT
+ ~packing:((notebook ())#append_page
+ ~tab_label:v_box#coerce) ()
+ in
+ let sw1 = GBin.scrolled_window
+ ~vpolicy:`AUTOMATIC
+ ~hpolicy:`AUTOMATIC
+ ~packing:fr1#add ()
+ in
+ let tv1 = Undo.undoable_view ~buffer:b ~packing:(sw1#add) () in
+ prerr_endline ("Language: "^ b#start_iter#language);
+ tv1#misc#set_name "ScriptWindow";
+ let _ = tv1#set_editable true in
+ let _ = tv1#set_wrap_mode `NONE in
+ b#place_cursor ~where:(b#start_iter);
+ ignore (tv1#event#connect#button_press ~callback:
+ (fun ev -> GdkEvent.Button.button ev = 3));
+(* ignore (tv1#event#connect#button_press ~callback:
+ (fun ev ->
+ if (GdkEvent.Button.button ev=2) then
+ (try
+ prerr_endline "Paste invoked";
+ GtkSignal.emit_unit
+ (get_current_view()).view#as_view
+ GtkText.View.Signals.paste_clipboard;
+ true
+ with _ -> false)
+ else false
+ ));*)
+ tv1#misc#grab_focus ();
+ ignore (tv1#buffer#create_mark
+ ~name:"start_of_input"
+ tv1#buffer#start_iter);
+ ignore (tv1#buffer#create_tag
+ ~name:"kwd"
+ [`FOREGROUND "blue"]);
+ ignore (tv1#buffer#create_tag
+ ~name:"decl"
+ [`FOREGROUND "orange red"]);
+ ignore (tv1#buffer#create_tag
+ ~name:"comment"
+ [`FOREGROUND "brown"]);
+ ignore (tv1#buffer#create_tag
+ ~name:"reserved"
+ [`FOREGROUND "dark red"]);
+ ignore (tv1#buffer#create_tag
+ ~name:"error"
+ [`UNDERLINE `DOUBLE ; `FOREGROUND "red"]);
+ ignore (tv1#buffer#create_tag
+ ~name:"to_process"
+ [`BACKGROUND "light blue" ;`EDITABLE false]);
+ ignore (tv1#buffer#create_tag
+ ~name:"processed"
+ [`BACKGROUND "light green" ;`EDITABLE false]);
+ ignore (tv1#buffer#create_tag
+ ~name:"found"
+ [`BACKGROUND "blue"; `FOREGROUND "white"]);
+ tv1
+
+
+let last_make = ref "";;
+let last_make_index = ref 0;;
+let search_compile_error_regexp =
+ Str.regexp
+ "File \"\\([^\"]+\\)\", line \\([0-9]+\\), characters \\([0-9]+\\)-\\([0-9]+\\)";;
+
+let search_next_error () =
+ let _ = Str.search_forward search_compile_error_regexp !last_make !last_make_index in
+ let f = Str.matched_group 1 !last_make
+ and l = int_of_string (Str.matched_group 2 !last_make)
+ and b = int_of_string (Str.matched_group 3 !last_make)
+ and e = int_of_string (Str.matched_group 4 !last_make)
+ and msg_index = Str.match_beginning ()
+ in
+ last_make_index := Str.group_end 4;
+ (f,l,b,e,
+ String.sub !last_make msg_index (String.length !last_make - msg_index))
+
+let main files =
+ (* Statup preferences *)
+ load_pref ();
+
+ (* Main window *)
+ let w = GWindow.window
+ ~wm_class:"CoqIde" ~wm_name:"CoqIde"
+ ~allow_grow:true ~allow_shrink:true
+ ~width:!current.window_width ~height:!current.window_height
+ ~title:"CoqIde" ()
+ in
+(*
+ let icon_image = Filename.concat lib_ide "coq.ico" in
+ let icon = GdkPixbuf.from_file icon_image in
+ w#set_icon (Some icon);
+*)
+ let vbox = GPack.vbox ~homogeneous:false ~packing:w#add () in
+
+
+ (* Menu bar *)
+ let menubar = GMenu.menu_bar ~packing:vbox#pack () in
+
+ (* Toolbar *)
+ let toolbar = GButton.toolbar
+ ~orientation:`HORIZONTAL
+ ~style:`ICONS
+ ~tooltips:true
+ ~packing:(* handle#add *)
+ (vbox#pack ~expand:false ~fill:false)
+ ()
+ in
+ show_toolbar :=
+ (fun b -> if b then toolbar#misc#show () else toolbar#misc#hide ());
+
+ let factory = new GMenu.factory ~accel_path:"<CoqIde MenuBar>/" menubar in
+ let accel_group = factory#accel_group in
+
+ (* File Menu *)
+ let file_menu = factory#add_submenu "_File" in
+
+ let file_factory = new GMenu.factory ~accel_path:"<CoqIde MenuBar>/File/" file_menu ~accel_group in
+
+ (* File/Load Menu *)
+ let load f =
+ let f = absolute_filename f in
+ try
+ prerr_endline "Loading file starts";
+ Vector.find_or_fail
+ (function
+ | {analyzed_view=Some av} ->
+ (match av#filename with
+ | None -> false
+ | Some fn -> same_file f fn)
+ | _ -> false)
+ !input_views;
+ prerr_endline "Loading: must open";
+ let b = Buffer.create 1024 in
+ prerr_endline "Loading: get raw content";
+ with_file f ~f:(input_channel b);
+ prerr_endline "Loading: convert content";
+ let s = do_convert (Buffer.contents b) in
+ prerr_endline "Loading: create view";
+ let view = create_input_tab (Glib.Convert.filename_to_utf8
+ (Filename.basename f))
+ in
+ prerr_endline "Loading: change font";
+ view#misc#modify_font !current.text_font;
+ prerr_endline "Loading: adding view";
+ let index = add_input_view {view = view;
+ analyzed_view = None;
+ }
+ in
+ let av = (new analyzed_view index) in
+ prerr_endline "Loading: register view";
+ (get_input_view index).analyzed_view <- Some av;
+ prerr_endline "Loading: set filename";
+ av#set_filename (Some f);
+ prerr_endline "Loading: stats";
+ av#update_stats;
+ let input_buffer = view#buffer in
+ prerr_endline "Loading: fill buffer";
+ input_buffer#set_text s;
+ input_buffer#place_cursor input_buffer#start_iter;
+ prerr_endline ("Loading: switch to view "^ string_of_int index);
+ set_current_view index;
+ set_tab_image index ~icon:`YES;
+ prerr_endline "Loading: highlight";
+ Highlight.highlight_all input_buffer;
+ input_buffer#set_modified false;
+ prerr_endline "Loading: clear undo";
+ av#view#clear_undo;
+ prerr_endline "Loading: success"
+ with
+ | Vector.Found i -> set_current_view i
+ | e -> !flash_info ("Load failed: "^(Printexc.to_string e))
+ in
+ let load_m = file_factory#add_item "_Open/Create"
+ ~key:GdkKeysyms._O in
+ let load_f () =
+ match select_file ~title:"Load file" () with
+ | None -> ()
+ | (Some f) as fn -> load f
+ in
+ ignore (load_m#connect#activate (load_f));
+
+ (* File/Save Menu *)
+ let save_m = file_factory#add_item "_Save"
+ ~key:GdkKeysyms._S in
+
+
+ let save_f () =
+ let current = get_current_view () in
+ try
+ (match (out_some current.analyzed_view)#filename with
+ | None ->
+ begin match GToolbox.select_file ~title:"Save file" ()
+ with
+ | None -> ()
+ | Some f ->
+ if (out_some current.analyzed_view)#save_as f then begin
+ set_current_tab_label (Filename.basename f);
+ !flash_info ("File " ^ f ^ " saved")
+ end
+ else warning ("Save Failed (check if " ^ f ^ " is writable)")
+ end
+ | Some f ->
+ if (out_some current.analyzed_view)#save f then
+ !flash_info ("File " ^ f ^ " saved")
+ else warning ("Save Failed (check if " ^ f ^ " is writable)")
+
+ )
+ with
+ | e -> warning "Save: unexpected error"
+ in
+ ignore (save_m#connect#activate save_f);
+
+ (* File/Save As Menu *)
+ let saveas_m = file_factory#add_item "S_ave as"
+ in
+ let saveas_f () =
+ let current = get_current_view () in
+ try (match (out_some current.analyzed_view)#filename with
+ | None ->
+ begin match GToolbox.select_file ~title:"Save file as" ()
+ with
+ | None -> ()
+ | Some f ->
+ if (out_some current.analyzed_view)#save_as f then begin
+ set_current_tab_label (Filename.basename f);
+ !flash_info "Saved"
+ end
+ else !flash_info "Save Failed"
+ end
+ | Some f ->
+ begin match GToolbox.select_file
+ ~dir:(ref (Filename.dirname f))
+ ~filename:(Filename.basename f)
+ ~title:"Save file as" ()
+ with
+ | None -> ()
+ | Some f ->
+ if (out_some current.analyzed_view)#save_as f then begin
+ set_current_tab_label (Filename.basename f);
+ !flash_info "Saved"
+ end else !flash_info "Save Failed"
+ end);
+ with e -> !flash_info "Save Failed"
+ in
+ ignore (saveas_m#connect#activate saveas_f);
+
+ (* File/Save All Menu *)
+ let saveall_m = file_factory#add_item "Sa_ve All" in
+ let saveall_f () =
+ Vector.iter
+ (function
+ | {view = view ; analyzed_view = Some av} as full ->
+ begin match av#filename with
+ | None -> ()
+ | Some f ->
+ ignore (av#save f)
+ end
+ | _ -> ()
+ ) input_views
+ in
+ let has_something_to_save () =
+ Vector.exists
+ (function
+ | {view=view} -> view#buffer#modified
+ )
+ input_views
+ in
+ ignore (saveall_m#connect#activate saveall_f);
+
+ (* File/Revert Menu *)
+ let revert_m = file_factory#add_item "_Revert All Buffers" in
+ let revert_f () =
+ Vector.iter
+ (function
+ {view = view ; analyzed_view = Some av} as full ->
+ (try
+ match av#filename,av#stats with
+ | Some f,Some stats ->
+ let new_stats = Unix.stat f in
+ if new_stats.Unix.st_mtime > stats.Unix.st_mtime
+ then av#revert
+ | Some _, None -> av#revert
+ | _ -> ()
+ with _ -> av#revert)
+ | _ -> ()
+ ) input_views
+ in
+ ignore (revert_m#connect#activate revert_f);
+
+ (* File/Close Menu *)
+ let close_m = file_factory#add_item "_Close Buffer" in
+ let close_f () =
+ let v = out_some !active_view in
+ let act = get_current_view_page () in
+ if v = act then !flash_info "Cannot close an active view"
+ else remove_current_view_page ()
+ in
+ ignore (close_m#connect#activate close_f);
+
+ (* File/Print Menu *)
+ let print_f () =
+ let v = get_current_view () in
+ let av = out_some v.analyzed_view in
+ match av#filename with
+ | None ->
+ !flash_info "Cannot print: this buffer has no name"
+ | Some f ->
+ let cmd =
+ "cd " ^ Filename.dirname f ^ "; " ^
+ !current.cmd_coqdoc ^ " -ps " ^ Filename.basename f ^
+ " | " ^ !current.cmd_print
+ in
+ let s,_ = run_command av#insert_message cmd in
+ !flash_info (cmd ^ if s = Unix.WEXITED 0 then " succeeded" else " failed")
+ in
+ let print_m = file_factory#add_item "_Print" ~callback:print_f in
+
+ (* File/Export to Menu *)
+ let export_f kind () =
+ let v = get_current_view () in
+ let av = out_some v.analyzed_view in
+ match av#filename with
+ | None ->
+ !flash_info "Cannot print: this buffer has no name"
+ | Some f ->
+ let basef = Filename.basename f in
+ let output =
+ let basef_we = try Filename.chop_extension basef with _ -> basef in
+ match kind with
+ | "latex" -> basef_we ^ ".tex"
+ | "dvi" | "ps" | "html" -> basef_we ^ "." ^ kind
+ | _ -> assert false
+ in
+ let cmd =
+ "cd " ^ Filename.dirname f ^ "; " ^
+ !current.cmd_coqdoc ^ " --" ^ kind ^ " -o " ^ output ^ " " ^ basef
+ in
+ let s,_ = run_command av#insert_message cmd in
+ !flash_info (cmd ^
+ if s = Unix.WEXITED 0
+ then " succeeded"
+ else " failed")
+ in
+ let file_export_m = file_factory#add_submenu "E_xport to" in
+
+ let file_export_factory = new GMenu.factory ~accel_path:"<CoqIde MenuBar>/Export/" file_export_m ~accel_group in
+ let export_html_m =
+ file_export_factory#add_item "_Html" ~callback:(export_f "html")
+ in
+ let export_latex_m =
+ file_export_factory#add_item "_LaTeX" ~callback:(export_f "latex")
+ in
+ let export_dvi_m =
+ file_export_factory#add_item "_Dvi" ~callback:(export_f "dvi")
+ in
+ let export_ps_m =
+ file_export_factory#add_item "_Ps" ~callback:(export_f "ps")
+ in
+
+ (* File/Rehighlight Menu *)
+ let rehighlight_m = file_factory#add_item "Reh_ighlight" ~key:GdkKeysyms._L in
+ ignore (rehighlight_m#connect#activate
+ (fun () ->
+ Highlight.highlight_all
+ (get_current_view()).view#buffer;
+ (out_some (get_current_view()).analyzed_view)#recenter_insert));
+
+ (* File/Quit Menu *)
+ let quit_f () =
+ save_pref();
+ if has_something_to_save () then
+ match (GToolbox.question_box ~title:"Quit"
+ ~buttons:["Save Named Buffers and Quit";
+ "Quit without Saving";
+ "Don't Quit"]
+ ~default:0
+ ~icon:
+ (let img = GMisc.image () in
+ img#set_stock `DIALOG_WARNING;
+ img#set_icon_size `DIALOG;
+ img#coerce)
+ "There are unsaved buffers"
+ )
+ with 1 -> saveall_f () ; exit 0
+ | 2 -> exit 0
+ | _ -> ()
+ else exit 0
+ in
+ let quit_m = file_factory#add_item "_Quit" ~key:GdkKeysyms._Q
+ ~callback:quit_f
+ in
+ ignore (w#event#connect#delete (fun _ -> quit_f (); true));
+
+ (* Edit Menu *)
+ let edit_menu = factory#add_submenu "_Edit" in
+ let edit_f = new GMenu.factory ~accel_path:"<CoqIde MenuBar>/Edit/" edit_menu ~accel_group in
+ ignore(edit_f#add_item "_Undo" ~key:GdkKeysyms._u ~callback:
+ (do_if_not_computing "undo"
+ (fun () ->
+ ignore ((out_some ((get_current_view()).analyzed_view))#
+ without_auto_complete
+ (fun () -> (get_current_view()).view#undo) ()))));
+ ignore(edit_f#add_item "_Clear Undo Stack"
+ (* ~key:GdkKeysyms._exclam *)
+ ~callback:
+ (fun () ->
+ ignore (get_current_view()).view#clear_undo));
+ ignore(edit_f#add_separator ());
+ ignore(edit_f#add_item "Cut" ~key:GdkKeysyms._X ~callback:
+ (do_if_not_computing "cut"
+ (fun () -> GtkSignal.emit_unit
+ (get_current_view()).view#as_view
+ GtkText.View.S.cut_clipboard)));
+ ignore(edit_f#add_item "Copy" ~key:GdkKeysyms._C ~callback:
+ (fun () -> GtkSignal.emit_unit
+ (get_current_view()).view#as_view
+ GtkText.View.S.copy_clipboard));
+ ignore(edit_f#add_item "Paste" ~key:GdkKeysyms._V ~callback:
+ (do_if_not_computing "paste"
+ (fun () ->
+ try GtkSignal.emit_unit
+ (get_current_view()).view#as_view
+ GtkText.View.S.paste_clipboard
+ with _ -> prerr_endline "EMIT PASTE FAILED")));
+ ignore (edit_f#add_separator ());
+
+
+(*
+ let toggle_auto_complete_i =
+ edit_f#add_check_item "_Auto Completion"
+ ~active:!current.auto_complete
+ ~callback:
+ in
+*)
+(*
+ auto_complete :=
+ (fun b -> match (get_current_view()).analyzed_view with
+ | Some av -> av#set_auto_complete b
+ | None -> ());
+*)
+
+ let last_found = ref None in
+ let search_backward = ref false in
+ let find_w = GWindow.window
+ (* ~wm_class:"CoqIde" ~wm_name:"CoqIde" *)
+ (* ~allow_grow:true ~allow_shrink:true *)
+ (* ~width:!current.window_width ~height:!current.window_height *)
+ ~position:`CENTER
+ ~title:"CoqIde search/replace" ()
+ in
+ let find_box = GPack.table
+ ~columns:3 ~rows:5
+ ~col_spacings:10 ~row_spacings:10 ~border_width:10
+ ~homogeneous:false ~packing:find_w#add () in
+
+ let find_lbl =
+ GMisc.label ~text:"Find:"
+ ~xalign:1.0
+ ~packing:(find_box#attach ~left:0 ~top:0 ~fill:`X) ()
+ in
+ let find_entry = GEdit.entry
+ ~editable: true
+ ~packing: (find_box#attach ~left:1 ~top:0 ~expand:`X)
+ ()
+ in
+ let replace_lbl =
+ GMisc.label ~text:"Replace with:"
+ ~xalign:1.0
+ ~packing:(find_box#attach ~left:0 ~top:1 ~fill:`X) ()
+ in
+ let replace_entry = GEdit.entry
+ ~editable: true
+ ~packing: (find_box#attach ~left:1 ~top:1 ~expand:`X)
+ ()
+ in
+ let case_sensitive_check =
+ GButton.check_button
+ ~label:"case sensitive"
+ ~active:true
+ ~packing: (find_box#attach ~left:1 ~top:2)
+ ()
+ in
+(*
+ let find_backwards_check =
+ GButton.check_button
+ ~label:"search backwards"
+ ~active:false
+ ~packing: (find_box#attach ~left:1 ~top:3)
+ ()
+ in
+*)
+ let close_find_button =
+ GButton.button
+ ~label:"Close"
+ ~packing: (find_box#attach ~left:2 ~top:0)
+ ()
+ in
+ let replace_button =
+ GButton.button
+ ~label:"Replace"
+ ~packing: (find_box#attach ~left:2 ~top:1)
+ ()
+ in
+ let replace_find_button =
+ GButton.button
+ ~label:"Replace and find"
+ ~packing: (find_box#attach ~left:2 ~top:2)
+ ()
+ in
+ let find_again_button =
+ GButton.button
+ ~label:"_Find again"
+ ~packing: (find_box#attach ~left:2 ~top:3)
+ ()
+ in
+ let find_again_backward_button =
+ GButton.button
+ ~label:"Find _backward"
+ ~packing: (find_box#attach ~left:2 ~top:4)
+ ()
+ in
+ let last_find () =
+ let v = (get_current_view()).view in
+ let b = v#buffer in
+ let start,stop =
+ match !last_found with
+ | None -> let i = b#get_iter_at_mark `INSERT in (i,i)
+ | Some(start,stop) ->
+ let start = b#get_iter_at_mark start
+ and stop = b#get_iter_at_mark stop
+ in
+ b#remove_tag_by_name ~start ~stop "found";
+ last_found:=None;
+ start,stop
+ in
+ (v,b,start,stop)
+ in
+ let do_replace () =
+ let v = (get_current_view()).view in
+ let b = v#buffer in
+ match !last_found with
+ | None -> ()
+ | Some(start,stop) ->
+ let start = b#get_iter_at_mark start
+ and stop = b#get_iter_at_mark stop
+ in
+ b#delete ~start ~stop;
+ b#insert ~iter:start replace_entry#text;
+ last_found:=None
+ in
+ let find_from (v : Undo.undoable_view)
+ (b : GText.buffer) (starti : GText.iter) text =
+ prerr_endline ("Searching for " ^ text);
+ match (if !search_backward then starti#backward_search text
+ else starti#forward_search text)
+ with
+ | None -> ()
+ | Some(start,stop) ->
+ b#apply_tag_by_name "found" ~start ~stop;
+ let start = `MARK (b#create_mark start)
+ and stop = `MARK (b#create_mark stop)
+ in
+ v#scroll_to_mark ~use_align:false ~yalign:0.75 ~within_margin:0.25
+ stop;
+ last_found := Some(start,stop)
+ in
+ let do_find () =
+ let (v,b,starti,_) = last_find () in
+ find_from v b starti find_entry#text
+ in
+ let do_replace_find () =
+ do_replace();
+ do_find()
+ in
+ let close_find () =
+ let (v,b,_,stop) = last_find () in
+ b#place_cursor stop;
+ find_w#misc#hide();
+ v#coerce#misc#grab_focus()
+ in
+ to_do_on_page_switch :=
+ (fun i -> if find_w#misc#visible then close_find())::
+ !to_do_on_page_switch;
+ let find_again_forward () =
+ search_backward := false;
+ let (v,b,start,_) = last_find () in
+ let start = start#forward_chars 1 in
+ find_from v b start find_entry#text
+ in
+ let find_again_backward () =
+ search_backward := true;
+ let (v,b,start,_) = last_find () in
+ let start = start#backward_chars 1 in
+ find_from v b start find_entry#text
+ in
+ let key_find ev =
+ let s = GdkEvent.Key.state ev and k = GdkEvent.Key.keyval ev in
+ if k = GdkKeysyms._Escape then
+ begin
+ let (v,b,_,stop) = last_find () in
+ find_w#misc#hide();
+ v#coerce#misc#grab_focus();
+ true
+ end
+ else if k = GdkKeysyms._Return then
+ begin
+ close_find();
+ true
+ end
+ else if List.mem `CONTROL s && k = GdkKeysyms._f then
+ begin
+ find_again_forward ();
+ true
+ end
+ else if List.mem `CONTROL s && k = GdkKeysyms._b then
+ begin
+ find_again_backward ();
+ true
+ end
+ else false (* to let default callback execute *)
+ in
+ let find_f ~backward () =
+ search_backward := backward;
+ find_w#show ();
+ find_w#present ();
+ find_entry#misc#grab_focus ()
+ in
+ let find_i = edit_f#add_item "_Find in buffer"
+ ~key:GdkKeysyms._F
+ ~callback:(find_f ~backward:false)
+ in
+ let find_back_i = edit_f#add_item "Find _backwards"
+ ~key:GdkKeysyms._B
+ ~callback:(find_f ~backward:true)
+ in
+ let _ = close_find_button#connect#clicked close_find in
+ let _ = replace_button#connect#clicked do_replace in
+ let _ = replace_find_button#connect#clicked do_replace_find in
+ let _ = find_again_button#connect#clicked find_again_forward in
+ let _ = find_again_backward_button#connect#clicked find_again_backward in
+ let _ = find_entry#connect#changed do_find in
+ let _ = find_entry#event#connect#key_press ~callback:key_find in
+ let _ = find_w#event#connect#delete (fun _ -> find_w#misc#hide(); true) in
+(*
+ let search_if = edit_f#add_item "Search _forward"
+ ~key:GdkKeysyms._greater
+ in
+ let search_ib = edit_f#add_item "Search _backward"
+ ~key:GdkKeysyms._less
+ in
+*)
+(*
+ let complete_i = edit_f#add_item "_Complete"
+ ~key:GdkKeysyms._comma
+ ~callback:
+ (do_if_not_computing
+ (fun b ->
+ let v = out_some (get_current_view ()).analyzed_view
+
+ in v#complete_at_offset
+ ((v#view#buffer#get_iter `SEL_BOUND)#offset)
+ ))
+ in
+ complete_i#misc#set_state `INSENSITIVE;
+*)
+
+ ignore(edit_f#add_item "Complete Word" ~key:GdkKeysyms._slash ~callback:
+ (do_if_not_computing "complete word"
+ (fun () ->
+ ignore (
+ let av = out_some ((get_current_view()).analyzed_view) in
+ av#complete_at_offset (av#get_insert)#offset
+ ))));
+
+ ignore(edit_f#add_separator ());
+ (* external editor *)
+ let _ =
+ edit_f#add_item "External editor" ~callback:
+ (fun () ->
+ let av = out_some ((get_current_view()).analyzed_view) in
+ match av#filename with
+ | None -> ()
+ | Some f ->
+ save_f ();
+ let l,r = !current.cmd_editor in
+ let _ = run_command av#insert_message (l ^ f ^ r) in
+ av#revert)
+ in
+ let _ = edit_f#add_separator () in
+ (* Preferences *)
+ let reset_revert_timer () =
+ disconnect_revert_timer ();
+ if !current.global_auto_revert then
+ revert_timer := Some
+ (GMain.Timeout.add ~ms:!current.global_auto_revert_delay
+ ~callback:
+ (fun () ->
+ do_if_not_computing "revert" (fun () -> revert_f ()) ();
+ true))
+ in reset_revert_timer (); (* to enable statup preferences timer *)
+
+ let auto_save_f () =
+ Vector.iter
+ (function
+ {view = view ; analyzed_view = Some av} as full ->
+ (try
+ av#auto_save
+ with _ -> ())
+ | _ -> ()
+ )
+ input_views
+ in
+
+ let reset_auto_save_timer () =
+ disconnect_auto_save_timer ();
+ if !current.auto_save then
+ auto_save_timer := Some
+ (GMain.Timeout.add ~ms:!current.auto_save_delay
+ ~callback:
+ (fun () ->
+ do_if_not_computing "autosave" (fun () -> auto_save_f ()) ();
+ true))
+ in reset_auto_save_timer (); (* to enable statup preferences timer *)
+
+
+ let edit_prefs_m =
+ edit_f#add_item "_Preferences"
+ ~callback:(fun () -> configure ();reset_revert_timer ())
+ in
+(*
+ let save_prefs_m =
+ configuration_factory#add_item "_Save preferences"
+ ~callback:(fun () -> save_pref ())
+ in
+*)
+ (* Navigation Menu *)
+ let navigation_menu = factory#add_submenu "_Navigation" in
+ let navigation_factory =
+ new GMenu.factory navigation_menu
+ ~accel_path:"<CoqIde MenuBar>/Navigation/"
+ ~accel_group
+ ~accel_modi:!current.modifier_for_navigation
+ in
+ let do_or_activate f () =
+ let current = get_current_view () in
+ let analyzed_view = out_some current.analyzed_view in
+ if analyzed_view#is_active then
+ ignore (f analyzed_view)
+ else
+ begin
+ !flash_info "New proof started";
+ activate_input (notebook ())#current_page;
+ ignore (f analyzed_view)
+ end
+ in
+
+ let do_or_activate f =
+ do_if_not_computing "do_or_activate" (do_or_activate (fun av -> f av ; !pop_info();!push_info (Coq.current_status())))
+ in
+
+ let add_to_menu_toolbar text ~tooltip ?key ~callback icon =
+ begin
+ match key with None -> ()
+ | Some key -> ignore (navigation_factory#add_item text ~key ~callback)
+ end;
+ ignore (toolbar#insert_button
+ ~tooltip
+ ~text:tooltip
+ ~icon:(stock_to_widget ~size:`LARGE_TOOLBAR icon)
+ ~callback
+ ())
+ in
+ add_to_menu_toolbar
+ "_Save"
+ ~tooltip:"Save current buffer"
+ (* ~key:GdkKeysyms._Down *)
+ ~callback:save_f
+ `SAVE;
+ add_to_menu_toolbar
+ "_Forward"
+ ~tooltip:"Forward one command"
+ ~key:GdkKeysyms._Down
+ ~callback:(do_or_activate (fun a -> a#process_next_phrase true true true))
+ `GO_DOWN;
+ add_to_menu_toolbar "_Backward"
+ ~tooltip:"Backward one command"
+ ~key:GdkKeysyms._Up
+ ~callback:(do_or_activate (fun a -> a#undo_last_step))
+ `GO_UP;
+(*
+ add_to_menu_toolbar
+ "_Forward to"
+ ~tooltip:"Forward to"
+ ~key:GdkKeysyms._Right
+ ~callback:(do_or_activate (fun a -> a#process_until_insert_or_error))
+ `GOTO_LAST;
+ add_to_menu_toolbar
+ "_Backward to"
+ ~tooltip:"Backward to"
+ ~key:GdkKeysyms._Left
+ ~callback:(do_or_activate (fun a-> a#backtrack_to_insert))
+ `GOTO_FIRST;
+*)
+ add_to_menu_toolbar
+ "_Go to"
+ ~tooltip:"Go to cursor"
+ ~key:GdkKeysyms._Right
+ ~callback:(do_or_activate (fun a-> a#go_to_insert))
+ `JUMP_TO;
+ add_to_menu_toolbar
+ "_Start"
+ ~tooltip:"Go to start"
+ ~key:GdkKeysyms._Home
+ ~callback:(do_or_activate (fun a -> a#reset_initial))
+ `GOTO_TOP;
+ add_to_menu_toolbar
+ "_End"
+ ~tooltip:"Go to end"
+ ~key:GdkKeysyms._End
+ ~callback:(do_or_activate (fun a -> a#process_until_end_or_error))
+ `GOTO_BOTTOM;
+ add_to_menu_toolbar "_Interrupt"
+ ~tooltip:"Interrupt computations"
+ ~key:GdkKeysyms._Break
+ ~callback:break
+ `STOP
+ ;
+
+ (* Tactics Menu *)
+ let tactics_menu = factory#add_submenu "_Try Tactics" in
+ let tactics_factory =
+ new GMenu.factory tactics_menu
+ ~accel_path:"<CoqIde MenuBar>/Tactics/"
+ ~accel_group
+ ~accel_modi:!current.modifier_for_tactics
+ in
+ let do_if_active_raw f () =
+ let current = get_current_view () in
+ let analyzed_view = out_some current.analyzed_view in
+ if analyzed_view#is_active then ignore (f analyzed_view)
+ in
+ let do_if_active f = do_if_not_computing "do_if_active" (do_if_active_raw f) in
+
+(*
+ let blaster_i =
+ tactics_factory#add_item "_Blaster"
+ ~key:GdkKeysyms._b
+ ~callback: (do_if_active_raw (fun a -> a#blaster ()))
+ (* Custom locking mechanism! *)
+ in
+ blaster_i#misc#set_state `INSENSITIVE;
+*)
+
+ ignore (tactics_factory#add_item "_auto"
+ ~key:GdkKeysyms._a
+ ~callback:(do_if_active (fun a -> a#insert_command "progress auto.\n" "auto.\n"))
+ );
+ ignore (tactics_factory#add_item "_auto with *"
+ ~key:GdkKeysyms._asterisk
+ ~callback:(do_if_active (fun a -> a#insert_command
+ "progress auto with *.\n"
+ "auto with *.\n")));
+ ignore (tactics_factory#add_item "_eauto"
+ ~key:GdkKeysyms._e
+ ~callback:(do_if_active (fun a -> a#insert_command
+ "progress eauto.\n"
+ "eauto.\n"))
+ );
+ ignore (tactics_factory#add_item "_eauto with *"
+ ~key:GdkKeysyms._ampersand
+ ~callback:(do_if_active (fun a -> a#insert_command
+ "progress eauto with *.\n"
+ "eauto with *.\n"))
+ );
+ ignore (tactics_factory#add_item "_intuition"
+ ~key:GdkKeysyms._i
+ ~callback:(do_if_active (fun a -> a#insert_command
+ "progress intuition.\n"
+ "intuition.\n"))
+ );
+ ignore (tactics_factory#add_item "_omega"
+ ~key:GdkKeysyms._o
+ ~callback:(do_if_active (fun a -> a#insert_command
+ "omega.\n" "omega.\n"))
+ );
+ ignore (tactics_factory#add_item "_simpl"
+ ~key:GdkKeysyms._s
+ ~callback:(do_if_active (fun a -> a#insert_command "progress simpl.\n" "simpl.\n" ))
+ );
+ ignore (tactics_factory#add_item "_tauto"
+ ~key:GdkKeysyms._p
+ ~callback:(do_if_active (fun a -> a#insert_command "tauto.\n" "tauto.\n" ))
+ );
+ ignore (tactics_factory#add_item "_trivial"
+ ~key:GdkKeysyms._v
+ ~callback:(do_if_active( fun a -> a#insert_command "progress trivial.\n" "trivial.\n" ))
+ );
+
+
+ ignore (toolbar#insert_button
+ ~tooltip:"Proof Wizard"
+ ~text:"Wizard"
+ ~icon:(stock_to_widget ~size:`LARGE_TOOLBAR `DIALOG_INFO)
+ ~callback:(do_if_active (fun a -> a#tactic_wizard
+ !current.automatic_tactics
+ ))
+ ());
+
+ ignore (tactics_factory#add_item "<Proof _Wizard>"
+ ~key:GdkKeysyms._dollar
+ ~callback:(do_if_active (fun a -> a#tactic_wizard
+ !current.automatic_tactics
+ ))
+ );
+
+ ignore (tactics_factory#add_separator ());
+ let add_simple_template (factory: GMenu.menu GMenu.factory)
+ (menu_text, text) =
+ let text =
+ let l = String.length text - 1 in
+ if String.get text l = '.'
+ then text ^"\n"
+ else text ^" "
+ in
+ ignore (factory#add_item menu_text
+ ~callback:
+ (do_if_not_computing "simple template"
+ (fun () -> let {view = view } = get_current_view () in
+ ignore (view#buffer#insert_interactive text))))
+ in
+ List.iter
+ (fun l ->
+ match l with
+ | [] -> ()
+ | [s] -> add_simple_template tactics_factory ("_"^s, s)
+ | s::_ ->
+ let a = "_@..." in
+ a.[1] <- s.[0];
+ let f = tactics_factory#add_submenu a in
+ let ff = new GMenu.factory f ~accel_group in
+ List.iter
+ (fun x ->
+ add_simple_template
+ ff
+ ((String.sub x 0 1)^
+ "_"^
+ (String.sub x 1 (String.length x - 1)),
+ x))
+ l
+ )
+ Coq_commands.tactics;
+
+ (* Templates Menu *)
+ let templates_menu = factory#add_submenu "Te_mplates" in
+ let templates_factory = new GMenu.factory templates_menu
+ ~accel_path:"<CoqIde MenuBar>/Templates/"
+ ~accel_group
+ ~accel_modi:!current.modifier_for_templates
+ in
+ let add_complex_template (menu_text, text, offset, len, key) =
+ (* Templates/Lemma *)
+ let callback = do_if_not_computing "complex template"
+ (fun () ->
+ let {view = view } = get_current_view () in
+ if view#buffer#insert_interactive text then begin
+ let iter = view#buffer#get_iter_at_mark `INSERT in
+ ignore (iter#nocopy#backward_chars offset);
+ view#buffer#move_mark `INSERT iter;
+ ignore (iter#nocopy#backward_chars len);
+ view#buffer#move_mark `SEL_BOUND iter;
+ end)
+ in
+ ignore (templates_factory#add_item menu_text ~callback ?key)
+ in
+ add_complex_template
+ ("_Lemma __", "Lemma new_lemma : .\nProof.\n\nSave.\n",
+ 19, 9, Some GdkKeysyms._L);
+ add_complex_template
+ ("_Theorem __", "Theorem new_theorem : .\nProof.\n\nSave.\n",
+ 19, 11, Some GdkKeysyms._T);
+ add_complex_template
+ ("_Definition __", "Definition ident := .\n",
+ 6, 5, Some GdkKeysyms._D);
+ add_complex_template
+ ("_Inductive __", "Inductive ident : :=\n | : .\n",
+ 14, 5, Some GdkKeysyms._I);
+ add_complex_template
+ ("_Fixpoint __", "Fixpoint ident (_ : _) {struct _} : _ :=\n.\n",
+ 29, 5, Some GdkKeysyms._F);
+ add_complex_template("_Scheme __",
+ "Scheme new_scheme := Induction for _ Sort _
+with _ := Induction for _ Sort _.\n",61,10, Some GdkKeysyms._S);
+
+ (* Template for match *)
+ let callback () =
+ let w = get_current_word () in
+ try
+ let cases = Coq.make_cases w
+ in
+ let print c = function
+ | [x] -> Format.fprintf c " | %s => _@\n" x
+ | x::l -> Format.fprintf c " | (%s%a) => _@\n" x
+ (print_list (fun c s -> Format.fprintf c " %s" s)) l
+ | [] -> assert false
+ in
+ let b = Buffer.create 1024 in
+ let fmt = Format.formatter_of_buffer b in
+ Format.fprintf fmt "@[match var with@\n%aend@]@."
+ (print_list print) cases;
+ let s = Buffer.contents b in
+ prerr_endline s;
+ let {view = view } = get_current_view () in
+ ignore (view#buffer#delete_selection ());
+ let m = view#buffer#create_mark
+ (view#buffer#get_iter `INSERT)
+ in
+ if view#buffer#insert_interactive s then
+ let i = view#buffer#get_iter (`MARK m) in
+ let _ = i#nocopy#forward_chars 9 in
+ view#buffer#place_cursor i;
+ view#buffer#move_mark ~where:(i#backward_chars 3)
+ `SEL_BOUND
+ with Not_found -> !flash_info "Not an inductive type"
+ in
+ ignore (templates_factory#add_item "match ..."
+ ~key:GdkKeysyms._C
+ ~callback
+ );
+
+(*
+ let add_simple_template (factory: GMenu.menu GMenu.factory)
+ (menu_text, text) =
+ let text =
+ let l = String.length text - 1 in
+ if String.get text l = '.'
+ then text ^"\n"
+ else text ^" "
+ in
+ ignore (factory#add_item menu_text
+ ~callback:
+ (do_if_not_computing "simple template"
+ (fun () -> let {view = view } = get_current_view () in
+ ignore (view#buffer#insert_interactive text))))
+ in
+*)
+ ignore (templates_factory#add_separator ());
+(*
+ List.iter (add_simple_template templates_factory)
+ [ "_auto", "auto ";
+ "_auto with *", "auto with * ";
+ "_eauto", "eauto ";
+ "_eauto with *", "eauto with * ";
+ "_intuition", "intuition ";
+ "_omega", "omega ";
+ "_simpl", "simpl ";
+ "_tauto", "tauto ";
+ "tri_vial", "trivial ";
+ ];
+ ignore (templates_factory#add_separator ());
+*)
+ List.iter
+ (fun l ->
+ match l with
+ | [] -> ()
+ | [s] -> add_simple_template templates_factory ("_"^s, s)
+ | s::_ ->
+ let a = "_@..." in
+ a.[1] <- s.[0];
+ let f = templates_factory#add_submenu a in
+ let ff = new GMenu.factory f ~accel_group in
+ List.iter
+ (fun x ->
+ add_simple_template
+ ff
+ ((String.sub x 0 1)^
+ "_"^
+ (String.sub x 1 (String.length x - 1)),
+ x))
+ l
+ )
+ Coq_commands.commands;
+
+ (* Queries Menu *)
+ let queries_menu = factory#add_submenu "_Queries" in
+ let queries_factory = new GMenu.factory queries_menu ~accel_group
+ ~accel_path:"<CoqIde MenuBar>/Queries"
+ ~accel_modi:[]
+ in
+
+ (* Command/Show commands *)
+ let _ =
+ queries_factory#add_item "_SearchAbout " ~key:GdkKeysyms._F2
+ ~callback:(fun () -> let term = get_current_word () in
+ (Command_windows.command_window ())#new_command
+ ~command:"SearchAbout"
+ ~term
+ ())
+ in
+ let _ =
+ queries_factory#add_item "_Check " ~key:GdkKeysyms._F3
+ ~callback:(fun () -> let term = get_current_word () in
+ (Command_windows.command_window ())#new_command
+ ~command:"Check"
+ ~term
+ ())
+ in
+ let _ =
+ queries_factory#add_item "_Print " ~key:GdkKeysyms._F4
+ ~callback:(fun () -> let term = get_current_word () in
+ (Command_windows.command_window ())#new_command
+ ~command:"Print"
+ ~term
+ ())
+ in
+
+ (* Externals *)
+ let externals_menu = factory#add_submenu "_Compile" in
+ let externals_factory = new GMenu.factory externals_menu
+ ~accel_path:"<CoqIde MenuBar>/Compile/"
+ ~accel_group
+ ~accel_modi:[]
+ in
+
+ (* Command/Compile Menu *)
+ let compile_f () =
+ let v = get_current_view () in
+ let av = out_some v.analyzed_view in
+ save_f ();
+ match av#filename with
+ | None ->
+ !flash_info "Active buffer has no name"
+ | Some f ->
+ let s,res = run_command
+ av#insert_message
+ (!current.cmd_coqc ^ " " ^ f)
+ in
+ if s = Unix.WEXITED 0 then
+ !flash_info (f ^ " successfully compiled")
+ else begin
+ !flash_info (f ^ " failed to compile");
+ activate_input (notebook ())#current_page;
+ av#process_until_end_or_error;
+ av#insert_message "Compilation output:\n";
+ av#insert_message res
+ end
+ in
+ let compile_m =
+ externals_factory#add_item "_Compile Buffer" ~callback:compile_f
+ in
+
+ (* Command/Make Menu *)
+ let make_f () =
+ let v = get_active_view () in
+ let av = out_some v.analyzed_view in
+(*
+ save_f ();
+*)
+ av#insert_message "Command output:\n";
+ let s,res = run_command av#insert_message !current.cmd_make in
+ last_make := res;
+ last_make_index := 0;
+ !flash_info (!current.cmd_make ^ if s = Unix.WEXITED 0 then " succeeded" else " failed")
+ in
+ let make_m = externals_factory#add_item "_Make"
+ ~key:GdkKeysyms._F6
+ ~callback:make_f
+ in
+
+
+ (* Compile/Next Error *)
+ let next_error () =
+ try
+ let file,line,start,stop,error_msg = search_next_error () in
+ load file;
+ let v = get_current_view () in
+ let av = out_some v.analyzed_view in
+ let input_buffer = v.view#buffer in
+(*
+ let init = input_buffer#start_iter in
+ let i = init#forward_lines (line-1) in
+*)
+(*
+ let convert_pos = byte_offset_to_char_offset phrase in
+ let start = convert_pos start in
+ let stop = convert_pos stop in
+*)
+(*
+ let starti = i#forward_chars start in
+ let stopi = i#forward_chars stop in
+*)
+ let starti = input_buffer#get_iter_at_byte ~line:(line-1) start in
+ let stopi = input_buffer#get_iter_at_byte ~line:(line-1) stop in
+ input_buffer#apply_tag_by_name "error"
+ ~start:starti
+ ~stop:stopi;
+ input_buffer#place_cursor starti;
+ av#set_message error_msg;
+ v.view#misc#grab_focus ()
+ with Not_found ->
+ last_make_index := 0;
+ let v = get_current_view () in
+ let av = out_some v.analyzed_view in
+ av#set_message "No more errors.\n"
+ in
+ let next_error_m =
+ externals_factory#add_item "_Next error"
+ ~key:GdkKeysyms._F7
+ ~callback:next_error in
+
+
+ (* Command/CoqMakefile Menu*)
+ let coq_makefile_f () =
+ let v = get_active_view () in
+ let av = out_some v.analyzed_view in
+ let s,res = run_command av#insert_message !current.cmd_coqmakefile in
+ !flash_info
+ (!current.cmd_coqmakefile ^ if s = Unix.WEXITED 0 then " succeeded" else " failed")
+ in
+ let _ = externals_factory#add_item "_Make makefile" ~callback:coq_makefile_f
+ in
+ (* Windows Menu *)
+ let configuration_menu = factory#add_submenu "_Windows" in
+ let configuration_factory = new GMenu.factory configuration_menu ~accel_path:"<CoqIde MenuBar>/Windows" ~accel_group
+ in
+ let queries_show_m =
+ configuration_factory#add_item
+ "Show _Query Window"
+ (*
+ ~key:GdkKeysyms._F12
+ *)
+ ~callback:(Command_windows.command_window ())#window#present
+ in
+ let toolbar_show_m =
+ configuration_factory#add_item
+ "Show/Hide _Toolbar"
+ ~callback:(fun () ->
+ !current.show_toolbar <- not !current.show_toolbar;
+ !show_toolbar !current.show_toolbar)
+ in
+ let detach_menu = configuration_factory#add_item
+ "Detach _Script Window"
+ ~callback:
+ (do_if_not_computing "detach script window"
+ (fun () ->
+ let nb = notebook () in
+ if nb#misc#toplevel#get_oid=w#coerce#get_oid then
+ begin
+ let nw = GWindow.window ~show:true () in
+ let parent = out_some nb#misc#parent in
+ ignore (nw#connect#destroy
+ ~callback:
+ (fun () -> nb#misc#reparent parent));
+ nw#add_accel_group accel_group;
+ nb#misc#reparent nw#coerce
+ end
+ ))
+ in
+ let detach_current_view =
+ configuration_factory#add_item
+ "Detach _View"
+ ~callback:
+ (do_if_not_computing "detach view"
+ (fun () ->
+ match get_current_view () with
+ | {view=v;analyzed_view=Some av} ->
+ let w = GWindow.window ~show:true
+ ~width:(!current.window_width/2)
+ ~height:(!current.window_height)
+ ~title:(match av#filename with
+ | None -> "*Unnamed*"
+ | Some f -> f)
+ ()
+ in
+ let sb = GBin.scrolled_window
+ ~packing:w#add ()
+ in
+ let nv = GText.view
+ ~buffer:v#buffer
+ ~packing:sb#add
+ ()
+ in
+ nv#misc#modify_font
+ !current.text_font;
+ ignore (w#connect#destroy
+ ~callback:
+ (fun () -> av#remove_detached_view w));
+ av#add_detached_view w
+ | _ -> ()
+
+ ))
+ in
+ (* Help Menu *)
+
+ let help_menu = factory#add_submenu "_Help" in
+ let help_factory = new GMenu.factory help_menu
+ ~accel_path:"<CoqIde MenuBar>/Help/"
+ ~accel_modi:[]
+ ~accel_group in
+ let _ = help_factory#add_item "Browse Coq _Manual"
+ ~callback:
+ (fun () ->
+ let av = out_some ((get_current_view ()).analyzed_view) in
+ browse av#insert_message (!current.doc_url ^ "main.html")) in
+ let _ = help_factory#add_item "Browse Coq _Library"
+ ~callback:
+ (fun () ->
+ let av = out_some ((get_current_view ()).analyzed_view) in
+ browse av#insert_message !current.library_url) in
+ let _ =
+ help_factory#add_item "Help for _keyword" ~key:GdkKeysyms._F1
+ ~callback:(fun () ->
+ let av = out_some ((get_current_view ()).analyzed_view) in
+ av#help_for_keyword ())
+ in
+ let _ = help_factory#add_separator () in
+(*
+ let faq_m = help_factory#add_item "_FAQ" in
+*)
+ let about_m = help_factory#add_item "_About" in
+
+ (* End of menu *)
+
+ (* The vertical Separator between Scripts and Goals *)
+ let hb = GPack.paned `HORIZONTAL ~border_width:3 ~packing:vbox#add () in
+ _notebook := Some (GPack.notebook ~scrollable:true
+ ~packing:hb#add1
+ ());
+ let nb = notebook () in
+ let fr2 = GBin.frame ~shadow_type:`ETCHED_OUT ~packing:hb#add2 () in
+ let hb2 = GPack.paned `VERTICAL ~border_width:3 ~packing:fr2#add () in
+ let sw2 = GBin.scrolled_window
+ ~vpolicy:`AUTOMATIC
+ ~hpolicy:`AUTOMATIC
+ ~packing:(hb2#add) () in
+ let sw3 = GBin.scrolled_window
+ ~vpolicy:`AUTOMATIC
+ ~hpolicy:`AUTOMATIC
+ ~packing:(hb2#add) () in
+ let lower_hbox = GPack.hbox ~homogeneous:false ~packing:vbox#pack () in
+ let status_bar = GMisc.statusbar ~packing:(lower_hbox#pack ~expand:true) ()
+ in
+ let search_lbl = GMisc.label ~text:"Search:"
+ ~show:false
+ ~packing:(lower_hbox#pack ~expand:false) ()
+ in
+ let search_history = ref [] in
+ let search_input = GEdit.combo ~popdown_strings:!search_history
+ ~enable_arrow_keys:true
+ ~show:false
+ ~packing:(lower_hbox#pack ~expand:false) ()
+ in
+ search_input#disable_activate ();
+ let ready_to_wrap_search = ref false in
+
+ let start_of_search = ref None in
+ let start_of_found = ref None in
+ let end_of_found = ref None in
+ let search_forward = ref true in
+ let matched_word = ref None in
+
+ let memo_search () =
+ matched_word := Some search_input#entry#text
+
+(* if not (List.mem search_input#entry#text !search_history) then
+ (search_history :=
+ search_input#entry#text::!search_history;
+ search_input#set_popdown_strings !search_history);
+ start_of_search := None;
+ ready_to_wrap_search := false
+*)
+
+ in
+ let end_search () =
+ prerr_endline "End Search";
+ memo_search ();
+ let v = (get_current_view ()).view in
+ v#buffer#move_mark `SEL_BOUND (v#buffer#get_iter_at_mark `INSERT);
+ v#coerce#misc#grab_focus ();
+ search_input#entry#set_text "";
+ search_lbl#misc#hide ();
+ search_input#misc#hide ()
+ in
+ let end_search_focus_out () =
+ prerr_endline "End Search(focus out)";
+ memo_search ();
+ let v = (get_current_view ()).view in
+ v#buffer#move_mark `SEL_BOUND (v#buffer#get_iter_at_mark `INSERT);
+ search_input#entry#set_text "";
+ search_lbl#misc#hide ();
+ search_input#misc#hide ()
+ in
+ ignore (search_input#entry#connect#activate ~callback:end_search);
+ ignore (search_input#entry#event#connect#key_press
+ ~callback:(fun k -> let kv = GdkEvent.Key.keyval k in
+ if
+ kv = GdkKeysyms._Right
+ || kv = GdkKeysyms._Up
+ || kv = GdkKeysyms._Left
+ || (kv = GdkKeysyms._g
+ && (List.mem `CONTROL (GdkEvent.Key.state k)))
+ then end_search ();
+ false));
+ ignore (search_input#entry#event#connect#focus_out
+ ~callback:(fun _ -> end_search_focus_out (); false));
+ to_do_on_page_switch :=
+ (fun i ->
+ start_of_search := None;
+ ready_to_wrap_search:=false)::!to_do_on_page_switch;
+
+(* TODO : make it work !!! *)
+ let rec search_f () =
+ search_lbl#misc#show ();
+ search_input#misc#show ();
+
+ prerr_endline "search_f called";
+ if !start_of_search = None then begin
+ (* A full new search is starting *)
+ start_of_search :=
+ Some ((get_current_view ()).view#buffer#create_mark
+ ((get_current_view ()).view#buffer#get_iter_at_mark `INSERT));
+ start_of_found := !start_of_search;
+ end_of_found := !start_of_search;
+ matched_word := Some "";
+ end;
+ let txt = search_input#entry#text in
+ let v = (get_current_view ()).view in
+ let iit = v#buffer#get_iter_at_mark `SEL_BOUND
+ and insert_iter = v#buffer#get_iter_at_mark `INSERT
+ in
+ prerr_endline ("SELBOUND="^(string_of_int iit#offset));
+ prerr_endline ("INSERT="^(string_of_int insert_iter#offset));
+
+ (match
+ if !search_forward then iit#forward_search txt
+ else let npi = iit#forward_chars (Glib.Utf8.length txt) in
+ match
+ (npi#offset = (v#buffer#get_iter_at_mark `INSERT)#offset),
+ (let t = iit#get_text ~stop:npi in
+ !flash_info (t^"\n"^txt);
+ t = txt)
+ with
+ | true,true ->
+ (!flash_info "T,T";iit#backward_search txt)
+ | false,true -> !flash_info "F,T";Some (iit,npi)
+ | _,false ->
+ (iit#backward_search txt)
+
+ with
+ | None ->
+ if !ready_to_wrap_search then begin
+ ready_to_wrap_search := false;
+ !flash_info "Search wrapped";
+ v#buffer#place_cursor
+ (if !search_forward then v#buffer#start_iter else
+ v#buffer#end_iter);
+ search_f ()
+ end else begin
+ if !search_forward then !flash_info "Search at end"
+ else !flash_info "Search at start";
+ ready_to_wrap_search := true
+ end
+ | Some (start,stop) ->
+ prerr_endline "search: before moving marks";
+ prerr_endline ("SELBOUND="^(string_of_int (v#buffer#get_iter_at_mark `SEL_BOUND)#offset));
+ prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset));
+
+ v#buffer#move_mark `SEL_BOUND start;
+ v#buffer#move_mark `INSERT stop;
+ prerr_endline "search: after moving marks";
+ prerr_endline ("SELBOUND="^(string_of_int (v#buffer#get_iter_at_mark `SEL_BOUND)#offset));
+ prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset));
+ v#scroll_to_mark `SEL_BOUND
+ )
+ in
+ ignore (search_input#entry#event#connect#key_release
+ ~callback:
+ (fun ev ->
+ if GdkEvent.Key.keyval ev = GdkKeysyms._Escape then begin
+ let v = (get_current_view ()).view in
+ (match !start_of_search with
+ | None ->
+ prerr_endline "search_key_rel: Placing sel_bound";
+ v#buffer#move_mark
+ `SEL_BOUND
+ (v#buffer#get_iter_at_mark `INSERT)
+ | Some mk -> let it = v#buffer#get_iter_at_mark
+ (`MARK mk) in
+ prerr_endline "search_key_rel: Placing cursor";
+ v#buffer#place_cursor it;
+ start_of_search := None
+ );
+ search_input#entry#set_text "";
+ v#coerce#misc#grab_focus ();
+ end;
+ false
+ ));
+ ignore (search_input#entry#connect#changed search_f);
+
+(*
+ ignore (search_if#connect#activate
+ ~callback:(fun b ->
+ search_forward:= true;
+ search_input#entry#coerce#misc#grab_focus ();
+ search_f ();
+ )
+ );
+ ignore (search_ib#connect#activate
+ ~callback:(fun b ->
+ search_forward:= false;
+
+ (* Must restore the SEL_BOUND mark after
+ grab_focus ! *)
+ let v = (get_current_view ()).view in
+ let old_sel = v#buffer#get_iter_at_mark `SEL_BOUND
+ in
+ search_input#entry#coerce#misc#grab_focus ();
+ v#buffer#move_mark `SEL_BOUND old_sel;
+ search_f ();
+ ));
+*)
+ let status_context = status_bar#new_context "Messages" in
+ let flash_context = status_bar#new_context "Flash" in
+ ignore (status_context#push "Ready");
+ status := Some status_bar;
+ push_info := (fun s -> ignore (status_context#push s));
+ pop_info := (fun () -> status_context#pop ());
+ flash_info := (fun ?(delay=5000) s -> flash_context#flash ~delay s);
+
+ (* Location display *)
+ let l = GMisc.label
+ ~text:"Line: 1 Char: 1"
+ ~packing:lower_hbox#pack () in
+ l#coerce#misc#set_name "location";
+ set_location := l#set_text;
+
+ (* Progress Bar *)
+ pulse :=
+ (let pb = GRange.progress_bar ~pulse_step:0.2 ~packing:lower_hbox#pack ()
+ in pb#set_text "CoqIde started";pb)#pulse;
+ let tv2 = GText.view ~packing:(sw2#add) () in
+ tv2#misc#set_name "GoalWindow";
+ let _ = tv2#set_editable false in
+ let tb2 = tv2#buffer in
+ let tv3 = GText.view ~packing:(sw3#add) () in
+ tv2#misc#set_name "MessageWindow";
+ let _ = tv2#set_wrap_mode `CHAR in
+ let _ = tv3#set_wrap_mode `WORD in
+ let _ = tv3#set_editable false in
+ let _ = GtkBase.Widget.add_events tv2#as_widget
+ [`ENTER_NOTIFY;`POINTER_MOTION] in
+ let _ = tv2#event#connect#motion_notify
+ ~callback:
+ (fun e ->
+ (do_if_not_computing "motion notify"
+ (fun e ->
+ let win = match tv2#get_window `WIDGET with
+ | None -> assert false
+ | Some w -> w
+ in
+ let x,y = Gdk.Window.get_pointer_location win in
+ let b_x,b_y = tv2#window_to_buffer_coords
+ ~tag:`WIDGET
+ ~x
+ ~y
+ in
+ let it = tv2#get_iter_at_location ~x:b_x ~y:b_y in
+ let tags = it#tags in
+ List.iter
+ ( fun t ->
+ ignore (GtkText.Tag.event
+ t#as_tag
+ tv2#as_widget
+ e
+ it#as_iter))
+ tags;
+ false)) e;
+ false)
+ in
+ change_font :=
+ (fun fd ->
+ tv2#misc#modify_font fd;
+ tv3#misc#modify_font fd;
+ Vector.iter
+ (fun {view=view} -> view#misc#modify_font fd)
+ input_views;
+ );
+ let about (b:GText.buffer) =
+ (try
+ let image = Filename.concat lib_ide "coq.png" in
+ let startup_image = GdkPixbuf.from_file image in
+ b#insert_pixbuf ~iter:b#start_iter
+ ~pixbuf:startup_image;
+ b#insert ~iter:b#start_iter "\t\t";
+ with _ -> ());
+ let about_string =
+ "\nCoqIDE: an Integrated Development Environment for Coq\n\
+ \nMain author : Benjamin Monate\
+ \nContributors : Jean-Christophe Filliâtre\
+ \n Pierre Letouzey, Claude Marché\n\
+ \nFeature wish or bug report: use Web interface\n\
+ \n\thttp://coq.inria.fr/bin/coq-bugs\n\
+ \nVersion information\
+ \n-------------------\n"
+ in
+ if Glib.Utf8.validate about_string
+ then b#insert about_string;
+ let coq_version = Coq.version () in
+ if Glib.Utf8.validate coq_version
+ then b#insert coq_version;
+
+ in
+ about tv2#buffer;
+ w#add_accel_group accel_group;
+ (* Remove default pango menu for textviews *)
+ ignore (tv2#event#connect#button_press ~callback:
+ (fun ev -> GdkEvent.Button.button ev = 3));
+ ignore (tv3#event#connect#button_press ~callback:
+ (fun ev -> GdkEvent.Button.button ev = 3));
+ tv2#misc#set_can_focus true;
+ tv3#misc#set_can_focus true;
+ ignore (tv2#buffer#create_mark
+ ~name:"end_of_conclusion"
+ tv2#buffer#start_iter);
+ ignore (tv3#buffer#create_tag
+ ~name:"error"
+ [`FOREGROUND "red"]);
+ w#show ();
+ message_view := Some tv3;
+ proof_view := Some tv2;
+ tv2#misc#modify_font !current.text_font;
+ tv3#misc#modify_font !current.text_font;
+ ignore (about_m#connect#activate
+ ~callback:(fun () -> tv2#buffer#set_text ""; about tv2#buffer));
+(*
+ ignore (faq_m#connect#activate
+ ~callback:(fun () ->
+ load (Filename.concat lib_ide "FAQ")));
+
+*)
+ resize_window := (fun () ->
+ w#resize
+ ~width:!current.window_width
+ ~height:!current.window_height);
+
+ ignore (w#misc#connect#size_allocate
+ (let old_w = ref 0
+ and old_h = ref 0 in
+ fun {Gtk.width=w;Gtk.height=h} ->
+ if !old_w <> w or !old_h <> h then
+ begin
+ old_h := h;
+ old_w := w;
+ hb#set_position (w/2);
+ hb2#set_position (h/2);
+ !current.window_height <- h;
+ !current.window_width <- w;
+ end
+ ));
+ ignore(nb#connect#switch_page
+ ~callback:
+ (fun i ->
+ prerr_endline ("switch_page: starts " ^ string_of_int i);
+ List.iter (function f -> f i) !to_do_on_page_switch;
+ prerr_endline "switch_page: success")
+ );
+ ignore(tv2#event#connect#enter_notify
+ (fun _ ->
+ if !current.contextual_menus_on_goal then
+ begin
+ let w = (out_some (get_active_view ()).analyzed_view) in
+ !push_info "Computing advanced goal's menus";
+ prerr_endline "Entering Goal Window. Computing Menus....";
+ w#show_goals_full;
+ prerr_endline "....Done with Goal menu";
+ !pop_info();
+ end;
+ false;
+ ));
+ if List.length files >=1 then
+ begin
+ List.iter (fun f ->
+ if Sys.file_exists f then load f else
+ if Filename.check_suffix f ".v"
+ then load f
+ else load (f^".v")) files;
+ activate_input 0
+ end
+ else
+ begin
+ let view = create_input_tab "*Unnamed Buffer*" in
+ let index = add_input_view {view = view;
+ analyzed_view = None;
+ }
+ in
+ (get_input_view index).analyzed_view <- Some (new analyzed_view index);
+ activate_input index;
+ set_tab_image index ~icon:`YES;
+ view#misc#modify_font !current.text_font
+ end;
+
+;;
+
+let start () =
+ let files = Coq.init () in
+ ignore_break ();
+ GtkMain.Rc.add_default_file (Filename.concat lib_ide ".coqide-gtk2rc");
+ (try
+ GtkMain.Rc.add_default_file (Filename.concat System.home ".coqide-gtk2rc");
+ with Not_found -> ());
+ ignore (GtkMain.Main.init ());
+ GtkData.AccelGroup.set_default_mod_mask
+ (Some [`CONTROL;`SHIFT;`MOD1;`MOD3;`MOD4]);
+ cb_ := Some (GData.clipboard Gdk.Atom.primary);
+ ignore (
+ Glib.Message.set_log_handler ~domain:"Gtk" ~levels:[`ERROR;`FLAG_FATAL;
+ `WARNING;`CRITICAL]
+ (fun ~level msg -> failwith ("Coqide internal error: " ^ msg)));
+ Command_windows.main ();
+ Blaster_window.main 9;
+ main files;
+ while true do
+ try
+ GtkThread.main ()
+ with
+ | Sys.Break -> prerr_endline "Interrupted." ; flush stderr
+ | e ->
+ Pervasives.prerr_endline ("CoqIde unexpected error:" ^ (Printexc.to_string e));
+ flush stderr;
+ crash_save 127
+ done
+
diff --git a/ide/coqide.mli b/ide/coqide.mli
new file mode 100644
index 00000000..15e28fea
--- /dev/null
+++ b/ide/coqide.mli
@@ -0,0 +1,16 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: coqide.mli,v 1.1.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+(* The CoqIde main module. The following function [start] will parse the
+ command line, initialize the load path, load the input
+ state, load the files given on the command line, load the ressource file,
+ produce the output state if any, and finally will launch the interface. *)
+
+val start : unit -> unit
diff --git a/ide/extract_index.mll b/ide/extract_index.mll
new file mode 100644
index 00000000..4a8c37f1
--- /dev/null
+++ b/ide/extract_index.mll
@@ -0,0 +1,31 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: extract_index.mll,v 1.2.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+{
+ open Lexing
+}
+
+(* additional lexer to extract URL from Coq manual's index *)
+
+rule entry = parse
+ | "<LI><TT>" [^ ',']* "</TT>, "
+ { let s = lexeme lexbuf in
+ let n = String.length s in
+ String.sub s 8 (n - 15), extract_index_url lexbuf }
+ | "<LI>" [^ ',']* ", "
+ { let s = lexeme lexbuf in
+ let n = String.length s in
+ String.sub s 4 (n - 6), extract_index_url lexbuf }
+
+and extract_index_url = parse
+ | "<A HREF=\"" [^ '"']* '"'
+ { let s = lexeme lexbuf in
+ let n = String.length s in
+ String.sub s 9 (n - 10) }
diff --git a/ide/find_phrase.mll b/ide/find_phrase.mll
new file mode 100644
index 00000000..8081474f
--- /dev/null
+++ b/ide/find_phrase.mll
@@ -0,0 +1,66 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: find_phrase.mll,v 1.8.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+{
+ exception Lex_error of string
+ let length = ref 0
+ let buff = Buffer.create 513
+ exception EOF of string
+
+}
+
+let phrase_sep = '.'
+
+rule next_phrase = parse
+ | "(*" { incr length; incr length;
+ skip_comment lexbuf;
+ next_phrase lexbuf}
+ | '"'[^'"']*'"' { let lexeme = Lexing.lexeme lexbuf in
+ let ulen = Glib.Utf8.length lexeme in
+ length := !length + ulen;
+ Buffer.add_string buff lexeme;
+ next_phrase lexbuf
+ }
+ | phrase_sep[' ''\n''\t''\r'] {
+ length := !length + 2;
+ Buffer.add_string buff (Lexing.lexeme lexbuf);
+ Buffer.contents buff}
+
+ | phrase_sep eof{
+ length := !length + 2;
+ Buffer.add_string buff (Lexing.lexeme lexbuf);
+ Buffer.add_char buff '\n';
+ raise (EOF(Buffer.contents buff))}
+ | _
+ {
+ let c = Lexing.lexeme_char lexbuf 0 in
+ if Ideutils.is_char_start c then incr length;
+ Buffer.add_char buff c ;
+ next_phrase lexbuf
+ }
+ | eof { raise (Lex_error "Phrase should end with . followed by a separator") }
+and skip_comment = parse
+ | "*)" {incr length; incr length; ()}
+ | "(*" {incr length; incr length;
+ skip_comment lexbuf;
+ skip_comment lexbuf}
+ | _ { if Ideutils.is_char_start (Lexing.lexeme_char lexbuf 0) then
+ incr length;
+ skip_comment lexbuf}
+ | eof { raise (Lex_error "No closing *)") }
+
+
+{
+ let get lb =
+ Buffer.reset buff;
+ length := 0;
+ next_phrase lb
+
+}
diff --git a/ide/highlight.mll b/ide/highlight.mll
new file mode 100644
index 00000000..21063459
--- /dev/null
+++ b/ide/highlight.mll
@@ -0,0 +1,115 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: highlight.mll,v 1.14.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+{
+
+ open Lexing
+
+ type color = string
+
+ type highlight_order = int * int * color
+
+ let comment_start = ref 0
+
+}
+
+let space =
+ [' ' '\010' '\013' '\009' '\012']
+let firstchar =
+ ['$' 'A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255']
+let identchar =
+ ['$' 'A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255' '\'' '0'-'9']
+let ident = firstchar identchar*
+
+let keyword =
+ "Add" | "CoInductive" | "Defined" |
+ "End" | "Export" | "Extraction" | "Hint" |
+ "Implicits" | "Import" |
+ "Infix" | "Load" | "match" | "Module" | "Module Type" |
+ "Proof" | "Qed" |
+ "Record" | "Require" | "Save" | "Scheme" |
+ "Section" | "Unset" |
+ "Set"
+
+let declaration =
+ "Lemma" | "Axiom" | "CoFixpoint" | "Definition" |
+ "Fixpoint" | "Hypothesis" |
+ "Inductive" | "Parameter" | "Theorem" |
+ "Variable" | "Variables"
+
+rule next_order = parse
+ | "(*" { comment_start := lexeme_start lexbuf; comment lexbuf }
+ | keyword { lexeme_start lexbuf,lexeme_end lexbuf, "kwd" }
+ | declaration space+ ident (space* ',' space* ident)*
+ { lexeme_start lexbuf, lexeme_end lexbuf, "decl" }
+ | _ { next_order lexbuf}
+ | eof { raise End_of_file }
+
+and comment = parse
+ | "*)" { !comment_start,lexeme_end lexbuf,"comment" }
+ | "(*" { ignore (comment lexbuf); comment lexbuf }
+ | _ { comment lexbuf }
+ | eof { raise End_of_file }
+
+{
+ open Ideutils
+
+ let highlighting = ref false
+
+ let highlight_slice (input_buffer:GText.buffer) (start:GText.iter) stop =
+ if !highlighting then prerr_endline "Rejected highlight"
+ else begin
+ highlighting := true;
+ prerr_endline "Highlighting slice now";
+ input_buffer#remove_tag_by_name ~start ~stop "error";
+ input_buffer#remove_tag_by_name ~start ~stop "kwd";
+ input_buffer#remove_tag_by_name ~start ~stop "decl";
+ input_buffer#remove_tag_by_name ~start ~stop "comment";
+
+ (try begin
+ let offset = start#offset in
+ let s = start#get_slice ~stop in
+ let convert_pos = byte_offset_to_char_offset s in
+ let lb = Lexing.from_string s in
+ try
+ while true do
+ let b,e,o=next_order lb in
+ let b,e = convert_pos b,convert_pos e in
+ let start = input_buffer#get_iter_at_char (offset + b) in
+ let stop = input_buffer#get_iter_at_char (offset + e) in
+ input_buffer#apply_tag_by_name ~start ~stop o
+ done
+ with End_of_file -> ()
+ end
+ with _ -> ());
+ highlighting := false
+ end
+
+ let highlight_current_line input_buffer =
+ try
+ let i = get_insert input_buffer in
+ highlight_slice input_buffer (i#set_line_offset 0) i
+ with _ -> ()
+
+ let highlight_around_current_line input_buffer =
+ try
+ let i = get_insert input_buffer in
+ highlight_slice input_buffer
+ (i#backward_lines 10)
+ (ignore (i#nocopy#forward_lines 10);i)
+
+ with _ -> ()
+
+ let highlight_all input_buffer =
+ try
+ highlight_slice input_buffer input_buffer#start_iter input_buffer#end_iter
+ with _ -> ()
+
+}
diff --git a/ide/ideutils.ml b/ide/ideutils.ml
new file mode 100644
index 00000000..8ec0e9e4
--- /dev/null
+++ b/ide/ideutils.ml
@@ -0,0 +1,307 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: ideutils.ml,v 1.30.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+
+open Preferences
+
+exception Forbidden
+
+(* status bar and locations *)
+
+let status = ref None
+let push_info = ref (function s -> failwith "not ready")
+let pop_info = ref (function s -> failwith "not ready")
+let flash_info = ref (fun ?delay s -> failwith "not ready")
+
+let set_location = ref (function s -> failwith "not ready")
+
+let pulse = ref (function () -> failwith "not ready")
+
+
+let debug = Options.debug
+
+let prerr_endline s =
+ if !debug then (prerr_endline s;flush stderr)
+let prerr_string s =
+ if !debug then (prerr_string s;flush stderr)
+
+let lib_ide = Filename.concat Coq_config.coqlib "ide"
+
+let get_insert input_buffer = input_buffer#get_iter_at_mark `INSERT
+
+let is_char_start c = let code = Char.code c in code < 0x80 || code >= 0xc0
+
+let byte_offset_to_char_offset s byte_offset =
+ if (byte_offset < String.length s) then begin
+ let count_delta = ref 0 in
+ for i = 0 to byte_offset do
+ let code = Char.code s.[i] in
+ if code >= 0x80 && code < 0xc0 then incr count_delta
+ done;
+ byte_offset - !count_delta
+ end
+ else begin
+ let count_delta = ref 0 in
+ for i = 0 to String.length s - 1 do
+ let code = Char.code s.[i] in
+ if code >= 0x80 && code < 0xc0 then incr count_delta
+ done;
+ byte_offset - !count_delta
+ end
+
+let process_pending () =
+ prerr_endline "Pending process";()
+(* try
+ while Glib.Main.pending () do
+ ignore (Glib.Main.iteration false)
+ done
+ with e ->
+ prerr_endline "Pending problems : expect a crash very soon";
+ raise e
+*)
+
+let print_id id =
+ prerr_endline ("GOT sig id :"^(string_of_int (Obj.magic id)))
+
+
+let do_convert s =
+ Utf8_convert.f
+ (if Glib.Utf8.validate s then begin
+ prerr_endline "Input is UTF-8";s
+ end else
+ let from_loc () =
+ let _,char_set = Glib.Convert.get_charset () in
+ !flash_info
+ ("Converting from locale ("^char_set^")");
+ Glib.Convert.convert_with_fallback ~to_codeset:"UTF-8" ~from_codeset:char_set s
+ in
+ let from_manual () =
+ !flash_info
+ ("Converting from "^ !current.encoding_manual);
+ Glib.Convert.convert s ~to_codeset:"UTF-8" ~from_codeset:!current.encoding_manual
+ in
+ if !current.encoding_use_utf8 || !current.encoding_use_locale then begin
+ try
+ from_loc ()
+ with _ -> from_manual ()
+ end else begin
+ try
+ from_manual ()
+ with _ -> from_loc ()
+ end)
+
+let try_convert s =
+ try
+ do_convert s
+ with _ ->
+ "(* Fatal error: wrong encoding in input.
+Please choose a correct encoding in the preference panel.*)";;
+
+
+let try_export file_name s =
+ try let s =
+ try if !current.encoding_use_utf8 then begin
+ (prerr_endline "UTF-8 is enforced" ;s)
+ end else if !current.encoding_use_locale then begin
+ let is_unicode,char_set = Glib.Convert.get_charset () in
+ if is_unicode then
+ (prerr_endline "Locale is UTF-8" ;s)
+ else
+ (prerr_endline ("Locale is "^char_set);
+ Glib.Convert.convert_with_fallback ~from_codeset:"UTF-8" ~to_codeset:char_set s)
+ end else
+ (prerr_endline ("Manual charset is "^ !current.encoding_manual);
+ Glib.Convert.convert_with_fallback ~from_codeset:"UTF-8" ~to_codeset:!current.encoding_manual s)
+ with e -> (prerr_endline ("Error ("^(Printexc.to_string e)^") in transcoding: falling back to UTF-8") ;s)
+ in
+ let oc = open_out file_name in
+ output_string oc s;
+ close_out oc;
+ true
+ with e -> prerr_endline (Printexc.to_string e);false
+
+let my_stat f = try Some (Unix.stat f) with _ -> None
+
+let revert_timer = ref None
+let disconnect_revert_timer () = match !revert_timer with
+ | None -> ()
+ | Some id -> GMain.Timeout.remove id; revert_timer := None
+
+let auto_save_timer = ref None
+let disconnect_auto_save_timer () = match !auto_save_timer with
+ | None -> ()
+ | Some id -> GMain.Timeout.remove id; auto_save_timer := None
+
+let highlight_timer = ref None
+let set_highlight_timer f =
+ match !highlight_timer with
+ | None ->
+ revert_timer :=
+ Some (GMain.Timeout.add ~ms:2000
+ ~callback:(fun () -> f (); highlight_timer := None; true))
+ | Some id ->
+ GMain.Timeout.remove id;
+ revert_timer :=
+ Some (GMain.Timeout.add ~ms:2000
+ ~callback:(fun () -> f (); highlight_timer := None; true))
+
+
+(* Get back the standard coq out channels *)
+let read_stdout,clear_stdout =
+ let out_buff = Buffer.create 100 in
+ Pp_control.std_ft := Format.formatter_of_buffer out_buff;
+ (fun () -> Format.pp_print_flush !Pp_control.std_ft ();
+ let r = Buffer.contents out_buff in
+ Buffer.clear out_buff; r),
+ (fun () ->
+ Format.pp_print_flush !Pp_control.std_ft (); Buffer.clear out_buff)
+
+
+let last_dir = ref ""
+let select_file ~title ?(dir = last_dir) ?(filename="") () =
+ let fs =
+ if Filename.is_relative filename then begin
+ if !dir <> "" then
+ let filename = Filename.concat !dir filename in
+ GWindow.file_selection ~show_fileops:true ~modal:true ~title ~filename ()
+ else
+ GWindow.file_selection ~show_fileops:true ~modal:true ~title ()
+ end else begin
+ dir := Filename.dirname filename;
+ GWindow.file_selection ~show_fileops:true ~modal:true ~title ~filename ()
+ end
+ in
+ fs#complete ~filter:"";
+ ignore (fs#connect#destroy ~callback: GMain.Main.quit);
+ let file = ref None in
+ ignore (fs#ok_button#connect#clicked ~callback:
+ begin fun () ->
+ file := Some fs#filename;
+ dir := Filename.dirname fs#filename;
+ fs#destroy ()
+ end);
+ ignore (fs # cancel_button # connect#clicked ~callback:fs#destroy);
+ fs # show ();
+ GMain.Main.main ();
+ !file
+
+
+let find_tag_start (tag :GText.tag) (it:GText.iter) =
+ let it = it#copy in
+ let tag = Some tag in
+ while not (it#begins_tag tag) && it#nocopy#backward_char do
+ ()
+ done;
+ it
+let find_tag_stop (tag :GText.tag) (it:GText.iter) =
+ let it = it#copy in
+ let tag = Some tag in
+ while not (it#ends_tag tag) && it#nocopy#forward_char do
+ ()
+ done;
+ it
+let find_tag_limits (tag :GText.tag) (it:GText.iter) =
+ (find_tag_start tag it , find_tag_stop tag it)
+
+(* explanations ?? *)
+let async =
+ if Sys.os_type <> "Unix" then GtkThread.async else
+ (fun x -> x)
+
+let stock_to_widget ?(size=`DIALOG) s =
+ let img = GMisc.image ()
+ in img#set_stock s;
+ img#coerce
+
+let rec print_list print fmt = function
+ | [] -> ()
+ | [x] -> print fmt x
+ | x :: r -> print fmt x; print_list print fmt r
+
+
+let run_command f c =
+ let result = Buffer.create 127 in
+ let cin,cout,cerr = Unix.open_process_full c (Unix.environment ()) in
+ let buff = String.make 127 ' ' in
+ let buffe = String.make 127 ' ' in
+ let n = ref 0 in
+ let ne = ref 0 in
+
+ while n:= input cin buff 0 127 ; ne := input cerr buffe 0 127 ;
+ !n+ !ne <> 0
+ do
+ let r = try_convert (String.sub buff 0 !n) in
+ f r;
+ Buffer.add_string result r;
+ let r = try_convert (String.sub buffe 0 !ne) in
+ f r;
+ Buffer.add_string result r
+ done;
+ (Unix.close_process_full (cin,cout,cerr), Buffer.contents result)
+
+let browse f url =
+ let l,r = !current.cmd_browse in
+ let (s,res) = run_command f (l ^ url ^ r) in
+ ()
+
+let url_for_keyword =
+ let ht = Hashtbl.create 97 in
+ begin try
+ let cin = open_in (Filename.concat lib_ide "index_urls.txt") in
+ try while true do
+ let s = input_line cin in
+ try
+ let i = String.index s ',' in
+ let k = String.sub s 0 i in
+ let u = String.sub s (i + 1) (String.length s - i - 1) in
+ Hashtbl.add ht k u
+ with _ ->
+ ()
+ done with End_of_file ->
+ close_in cin
+ with _ ->
+ ()
+ end;
+ (Hashtbl.find ht : string -> string)
+
+
+let browse_keyword f text =
+ try let u = url_for_keyword text in browse f (!current.doc_url ^ u)
+ with _ -> ()
+
+
+let underscore = Glib.Utf8.to_unichar "_" (ref 0)
+
+let arobase = Glib.Utf8.to_unichar "@" (ref 0)
+let prime = Glib.Utf8.to_unichar "'" (ref 0)
+let bn = Glib.Utf8.to_unichar "\n" (ref 0)
+let space = Glib.Utf8.to_unichar " " (ref 0)
+let tab = Glib.Utf8.to_unichar "\t" (ref 0)
+
+
+(*
+ checks if two file names refer to the same (existing) file
+*)
+
+let same_file f1 f2 =
+ try
+ let s1 = Unix.stat f1
+ and s2 = Unix.stat f2
+ in
+ (s1.Unix.st_dev = s2.Unix.st_dev) &&
+ (s1.Unix.st_ino = s2.Unix.st_ino)
+ with
+ Unix.Unix_error _ -> false
+
+let absolute_filename f =
+ if Filename.is_relative f then
+ Filename.concat (Sys.getcwd ()) f
+ else f
+
diff --git a/ide/ideutils.mli b/ide/ideutils.mli
new file mode 100644
index 00000000..7c225e0e
--- /dev/null
+++ b/ide/ideutils.mli
@@ -0,0 +1,79 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: ideutils.mli,v 1.6.2.1 2004/07/16 19:30:20 herbelin Exp $ *)
+
+val async : ('a -> unit) -> 'a -> unit
+val browse : (string -> unit) -> string -> unit
+val browse_keyword : (string -> unit) -> string -> unit
+val byte_offset_to_char_offset : string -> int -> int
+val clear_stdout : unit -> unit
+val debug : bool ref
+val disconnect_revert_timer : unit -> unit
+val disconnect_auto_save_timer : unit -> unit
+val do_convert : string -> string
+val find_tag_limits : GText.tag -> GText.iter -> GText.iter * GText.iter
+val find_tag_start : GText.tag -> GText.iter -> GText.iter
+val find_tag_stop : GText.tag -> GText.iter -> GText.iter
+val get_insert : < get_iter_at_mark : [> `INSERT] -> 'a; .. > -> 'a
+
+val is_char_start : char -> bool
+
+val lib_ide : string
+val my_stat : string -> Unix.stats option
+
+val prerr_endline : string -> unit
+val prerr_string : string -> unit
+val print_id : 'a -> unit
+
+val process_pending : unit -> unit
+val read_stdout : unit -> string
+val revert_timer : GMain.Timeout.id option ref
+val auto_save_timer : GMain.Timeout.id option ref
+val select_file :
+ title:string ->
+ ?dir:string ref -> ?filename:string -> unit -> string option
+val set_highlight_timer : (unit -> 'a) -> unit
+val try_convert : string -> string
+val try_export : string -> string -> bool
+val stock_to_widget : ?size:Gtk.Tags.icon_size -> GtkStock.id -> GObj.widget
+
+open Format
+val print_list : (formatter -> 'a -> unit) -> formatter -> 'a list -> unit
+
+val run_command : (string -> unit) -> string -> Unix.process_status*string
+
+
+val prime : Glib.unichar
+val underscore : Glib.unichar
+val arobase : Glib.unichar
+val bn : Glib.unichar
+val space : Glib.unichar
+val tab : Glib.unichar
+
+
+val status : GMisc.statusbar option ref
+val push_info : (string -> unit) ref
+val pop_info : (unit -> unit) ref
+val flash_info : (?delay:int -> string -> unit) ref
+
+val set_location : (string -> unit) ref
+
+val pulse : (unit -> unit) ref
+
+
+(*
+ checks if two file names refer to the same (existing) file
+*)
+
+val same_file : string -> string -> bool
+
+(*
+ returns an absolute filename equivalent to given filename
+*)
+val absolute_filename : string -> string
diff --git a/ide/index_urls.txt b/ide/index_urls.txt
new file mode 100644
index 00000000..fea61809
--- /dev/null
+++ b/ide/index_urls.txt
@@ -0,0 +1,563 @@
++,node.0.2.0.html#@default146
+-,node.0.2.1.html#@default247
+2,node.1.2.9.html#@default514
+;,node.1.2.12.html#@default547
+?,node.1.0.6.html#@default358
+?,node.1.2.1.html#@default410
+&,node.0.2.0.html#@default164
+{A}+{B},node.0.2.0.html#@default174
+{x:A & (P x)},node.0.2.0.html#@default163
+{x:A | (P x)},node.0.2.0.html#@default157
+|,node.0.2.0.html#@default158
+A*B,node.0.2.0.html#@default150
+A+{B},node.0.2.0.html#@default178
+A+B,node.0.2.0.html#@default145
+Abort,node.1.1.0.html#@default385
+Absolute names,node.0.1.6.html#@default85
+Abstract,node.1.2.12.html#@default559
+Absurd,node.1.2.3.html#@default442
+Acc,node.0.2.0.html#@default215
+Acc_inv,node.0.2.0.html#@default216
+Acc_rec,node.0.2.0.html#@default217
+Add Abstract Ring,node.3.7.4.html#@default643
+Add Abstract Semi Ring,node.3.7.4.html#@default644
+Add Field,node.1.2.10.html#@default526
+Add LoadPath,node.1.0.4.html#@default338
+Add ML Path,node.1.0.4.html#@default342
+Add Morphism,node.3.8.2.html#@default647
+Add Printing If,node.0.1.1.html#@default67
+Add Printing Let,node.0.1.1.html#@default63
+Add Rec LoadPath,node.1.0.4.html#@default339
+Add Rec ML Path,node.1.0.4.html#@default343
+Add Ring,node.1.2.10.html#@default523
+Add Semi Ring,node.1.2.10.html#@default524
+Add Setoid,node.3.8.1.html#@default646
+All,node.0.2.0.html#@default110
+AllT,node.0.2.0.html#@default224
+Apply,node.1.2.2.html#@default427
+Apply ... with,node.1.2.2.html#@default428
+Arithmetical notations,node.0.2.1.html#@default244
+Arity,node.0.3.4.html#@default288
+Assert,node.1.2.2.html#@default433
+Associativity,node.2.0.1.html#@default571
+Assumption,node.1.2.2.html#@default412
+Auto,node.1.2.10.html#@default515
+AutoRewrite,node.1.2.10.html#@default528
+Axiom,node.0.0.2.html#@default24
+abstractions,node.0.0.1.html#@default16
+absurd,node.0.2.0.html#@default121
+absurd_set,node.0.2.0.html#@default188
+all,node.0.2.0.html#@default109
+allT,node.0.2.0.html#@default223
+and,node.0.2.0.html#@default99
+and_rec,node.0.2.0.html#@default189
+applications,node.0.0.1.html#@default18
+Back,node.1.0.5.html#@default348
+Bad Magic Number,node.1.0.3.html#@default331
+Begin Silent,node.1.0.7.html#@default366
+Binding list,node.1.2.2.html#@default441
+beta-reduction,node.0.3.2.html#@default274
+bool,node.0.2.0.html#@default135
+bool_choice,node.0.2.0.html#@default181
+byte-code,node.3.0.0.html#@default574
+Calculus of (Co)Inductive Constructions,node.0.3.html#@default255
+Canonical Structure,node.0.1.7.html#@default91
+Case,node.1.2.6.html#@default468
+Case ... with,node.1.2.6.html#@default469
+Cases,node.3.2.html#@default593
+Cases...of...end,node.0.0.1.html#@default21
+Cbv,node.1.2.4.html#@default445
+Cd,node.1.0.4.html#@default337
+Change,node.1.2.2.html#@default438
+Change ... in,node.1.2.2.html#@default440
+Chapter,node.0.1.3.html#@default73
+Check,node.1.0.1.html#@default308
+Choice,node.0.2.0.html#@default179
+Choice2,node.0.2.0.html#@default180
+CIC,node.0.3.html#@default254
+Clear,node.1.2.2.html#@default414
+ClearBody,node.1.2.2.html#@default415
+Coercion,node.3.3.5.html#@default601
+Coercion Local,node.3.3.5.html#@default602
+Coercions,node.0.1.8.html#@default92
+and sections,node.3.3.9.html#@default616
+classes,node.3.3.1.html#@default596
+FUNCLASS,node.3.3.2.html#@default597
+identity,node.3.3.3.html#@default599
+inheritance graph,node.3.3.4.html#@default600
+presentation,node.3.3.html#@default595
+SORTCLASS,node.3.3.2.html#@default598
+CoFixpoint,node.0.0.2.html#@default40
+CoInductive,node.0.0.2.html#@default38
+Comments,node.0.0.0.html#@default2
+Compare,node.1.2.8.html#@default489
+Compiled files,node.1.0.3.html#@default327
+Compute,node.1.2.4.html#@default447
+Connectives,node.0.2.0.html#@default94
+Constant,node.0.0.2.html#@default31
+Constructor,node.1.2.5.html#@default455
+Constructor ... with,node.1.2.5.html#@default456
+Context,node.0.3.1.html#@default263
+Contradiction,node.1.2.3.html#@default443
+Contributions,node.0.2.2.html#@default253
+Conversion rules,node.0.3.2.html#@default273
+Conversion tactics,node.1.2.4.html#@default444
+coqdep,node.3.1.1.html#@default582
+coq_Makefile,node.3.1.2.html#@default584
+coqmktop,node.3.1.0.html#@default579
+coq-tex,node.3.1.3.html#@default586
+coqweb,node.3.1.3.html#@default587
+Correctness,node.3.5.html#@default619
+Cut,node.1.2.2.html#@default434
+CutRewrite,node.1.2.7.html#@default482
+congr_eqT,node.0.2.0.html#@default241
+conj,node.0.2.0.html#@default100
+coqc,node.3.0.html#@default573
+coqtop,node.3.0.html#@default572
+Datatypes,node.0.2.0.html#@default132
+Debugger,node.3.1.0.html#@default580
+Decide Equality,node.1.2.8.html#@default488
+Declarations,node.0.0.2.html#@default23
+Declare ML Module,node.1.0.3.html#@default333
+Decompose,node.1.2.6.html#@default473
+Decompose Record,node.1.2.6.html#@default475
+Decompose Sum,node.1.2.6.html#@default474
+Defined,node.0.0.2.html#@default48
+Definition,node.0.0.2.html#@default33
+Definitions,node.0.0.2.html#@default29
+Dependencies,node.3.1.1.html#@default581
+Dependent Inversion,node.1.2.9.html#@default501
+Dependent Inversion ... with,node.1.2.9.html#@default503
+Dependent Inversion_clear,node.1.2.9.html#@default502
+Dependent Inversion_clear ... with,node.1.2.9.html#@default504
+Dependent Rewrite ->,node.1.2.8.html#@default495
+Dependent Rewrite <-,node.1.2.8.html#@default496
+Derive Dependent Inversion,node.1.2.9.html#@default511
+Derive Dependent Inversion_clear,node.1.2.9.html#@default512
+Derive Inversion,node.1.2.9.html#@default508
+Derive Inversion_clear,node.1.2.9.html#@default509
+Derive Inversion_clear ... with,node.1.2.9.html#@default510
+Destruct,node.1.2.6.html#@default466
+Discriminate,node.1.2.8.html#@default490
+DiscrR,node.0.2.1.html#@default250
+Do,node.1.2.12.html#@default542
+Double Induction,node.1.2.6.html#@default472
+Drop,node.1.0.7.html#@default365
+delta-reduction,node.0.0.2.html#@default30
+EApply,node.1.2.2.html#@default429
+EAuto,node.1.2.10.html#@default517
+Elim ... using,node.1.2.6.html#@default463
+Elim ... with,node.1.2.6.html#@default462
+Singleton elimination,node.0.3.4.html#@default294
+Elimination sorts,node.0.3.4.html#@default291
+ElimType,node.1.2.6.html#@default464
+Emacs,node.3.1.5.html#@default589
+EmptyT,node.0.2.0.html#@default233
+End,node.0.1.3.html#@default74
+End Silent,node.1.0.7.html#@default368
+Environment,node.0.0.2.html#@default32
+Environment variables,node.3.0.3.html#@default577
+Equality,node.0.2.0.html#@default118
+Eval,node.1.0.1.html#@default309
+EX,node.0.2.0.html#@default113
+EXT,node.0.2.0.html#@default229
+Ex,node.0.2.0.html#@default112
+Ex2,node.0.2.0.html#@default116
+Exact,node.1.2.1.html#@default408
+Exc,node.0.2.0.html#@default182
+Except,node.0.2.0.html#@default187
+Exists,node.1.2.5.html#@default458
+Explicitation of implicit arguments,node.0.1.7.html#@default88
+ExT,node.0.2.0.html#@default228
+ExT2,node.0.2.0.html#@default231
+Extensive grammars,node.1.0.6.html#@default362
+Extract Constant,node.3.6.1.html#@default637
+Extract Inductive,node.3.6.1.html#@default638
+Extraction,node.3.6.html#@default623
+Extraction,node.1.0.1.html#@default310
+Extraction Inline,node.3.6.1.html#@default633
+Extraction Language,node.3.6.1.html#@default628
+Extraction Module,node.3.6.0.html#@default626
+Extraction NoInline,node.3.6.1.html#@default634
+eq,node.0.2.0.html#@default119
+eq_add_S,node.0.2.0.html#@default193
+eq_ind_r,node.0.2.0.html#@default126
+eq_rec,node.0.2.0.html#@default186
+eq_rec_r,node.0.2.0.html#@default127
+eq_rect,node.0.2.0.html#@default128
+eq_rect_r,node.0.2.0.html#@default129
+eq_S,node.0.2.0.html#@default190
+eqT,node.0.2.0.html#@default236
+eqT_ind_r,node.0.2.0.html#@default242
+eqT_rec_r,node.0.2.0.html#@default243
+error,node.0.2.0.html#@default184
+ex,node.0.2.0.html#@default111
+ex2,node.0.2.0.html#@default115
+ex_intro,node.0.2.0.html#@default114
+ex_intro2,node.0.2.0.html#@default117
+exist,node.0.2.0.html#@default160
+exist2,node.0.2.0.html#@default162
+existS,node.0.2.0.html#@default166
+existS2,node.0.2.0.html#@default170
+exT,node.0.2.0.html#@default227
+exT2,node.0.2.0.html#@default232
+exT_intro,node.0.2.0.html#@default230
+Fact,node.0.0.2.html#@default44
+Fail,node.1.2.12.html#@default540
+False,node.0.2.0.html#@default97
+False_rec,node.0.2.0.html#@default185
+Field,node.1.2.10.html#@default525
+First,node.1.2.12.html#@default553
+Fix,node.0.3.4.html#@default298
+Fix_F,node.0.2.0.html#@default219
+Fix_F_eq,node.0.2.0.html#@default222
+Fix_F_inv,node.0.2.0.html#@default221
+Fixpoint,node.0.0.2.html#@default39
+Focus,node.1.1.1.html#@default392
+Fold,node.1.2.4.html#@default453
+Fourier,node.1.2.10.html#@default527
+Fst,node.0.2.0.html#@default155
+f_equal,node.0.2.0.html#@default124
+f_equal<I>i</I>,node.0.2.0.html#@default130
+false,node.0.2.0.html#@default137
+fix_eq,node.0.2.0.html#@default220
+fst,node.0.2.0.html#@default153
+Gallina,node.0.0.html#@default0
+gallina,node.3.1.6.html#@default591
+Generalize,node.1.2.2.html#@default436
+Generalize Dependent,node.1.2.2.html#@default437
+Global Variable,node.3.5.2.html#@default620
+Goal,node.0.0.2.html#@default50
+Grammar,node.1.0.6.html#@default361
+ge,node.0.2.0.html#@default208
+gen,node.0.2.0.html#@default226
+goal,node.1.2.html#@default405
+gt,node.0.2.0.html#@default209
+Head normal form,node.0.3.2.html#@default286
+Hint,node.1.2.11.html#@default531
+Hint Rewrite,node.1.2.10.html#@default529
+Hints databases,node.1.2.11.html#@default530
+Hints Immediate,node.1.2.11.html#@default533
+Hints Resolve,node.1.2.11.html#@default532
+Hints Unfold,node.1.2.11.html#@default534
+Hnf,node.1.2.4.html#@default449
+HTML,node.3.1.4.html#@default588
+Hypothesis,node.0.0.2.html#@default28
+I,node.0.2.0.html#@default96
+Identity Coercion,node.3.3.5.html#@default605
+Idtac,node.1.2.12.html#@default538
+IF,node.0.2.0.html#@default107
+proof of,node.3.5.html#@default618
+Implicit Arguments Off,node.1.0.6.html#@default355
+Implicit Arguments On,node.1.0.6.html#@default354
+Implicits,node.1.0.6.html#@default356
+Induction,node.1.2.6.html#@default465
+Inductive,node.0.0.2.html#@default36
+Inductive definitions,node.0.0.2.html#@default35
+Infix,node.1.0.6.html#@default363
+Info,node.1.2.12.html#@default557
+Injection,node.1.2.8.html#@default492
+Inspect,node.1.0.0.html#@default305
+Intro,node.1.2.2.html#@default418
+Intro ... after,node.1.2.2.html#@default426
+Intro after,node.1.2.2.html#@default425
+Intros,node.1.2.2.html#@default422
+Intros pattern,node.1.2.6.html#@default471
+Intros until,node.1.2.2.html#@default423
+Intuition,node.1.2.10.html#@default520
+Inversion,node.1.2.9.html#@default497
+Inversion ... in,node.1.2.9.html#@default499
+Inversion ... using,node.1.2.9.html#@default505
+Inversion ... using ... in,node.1.2.9.html#@default506
+Inversion_clear,node.1.2.9.html#@default498
+Inversion_clear ... in,node.1.2.9.html#@default500
+IsSucc,node.0.2.0.html#@default195
+if ... then ... else,node.0.1.1.html#@default55
+iff,node.0.2.0.html#@default106
+implicit arguments,node.0.1.7.html#@default86
+inl,node.0.2.0.html#@default147
+inleft,node.0.2.0.html#@default176
+inr,node.0.2.0.html#@default148
+inright,node.0.2.0.html#@default177
+iota-reduction,node.0.3.2.html#@default275
+LApply,node.1.2.2.html#@default430
+Lazy,node.1.2.4.html#@default446
+Left,node.1.2.5.html#@default459
+Lemma,node.0.0.2.html#@default42
+LetTac,node.1.2.2.html#@default431
+Lexical conventions,node.0.0.0.html#@default1
+Libraries,node.0.1.5.html#@default82
+Load,node.1.0.2.html#@default325
+Load Verbose,node.1.0.2.html#@default326
+Loadpath,node.1.0.4.html#@default335
+Local,node.0.0.2.html#@default34
+Local definitions,node.0.0.1.html#@default19
+Locate,node.1.0.1.html#@default323
+Locate Library,node.1.0.4.html#@default346
+Logical paths,node.0.1.5.html#@default83
+le,node.0.2.0.html#@default204
+le_n,node.0.2.0.html#@default205
+le_S,node.0.2.0.html#@default206
+left,node.0.2.0.html#@default172
+let ... in,node.0.1.1.html#@default56
+let-in,node.0.0.1.html#@default20
+local context,node.1.1.html#@default372
+lt,node.0.2.0.html#@default207
+Makefile,node.3.1.2.html#@default583
+Man pages,node.3.1.7.html#@default592
+ML-like patterns,node.0.1.1.html#@default54
+Module,node.0.1.4.html#@default75
+Module Type,node.0.1.4.html#@default78
+Move,node.1.2.2.html#@default416
+Mutual Inductive,node.0.0.2.html#@default37
+mult,node.0.2.0.html#@default201
+mult_n_O,node.0.2.0.html#@default202
+mult_n_Sm,node.0.2.0.html#@default203
+NewDestruct,node.1.2.6.html#@default467
+NewInduction,node.1.2.6.html#@default461
+None,node.0.2.0.html#@default143
+Normal form,node.0.3.2.html#@default285
+Notation,node.2.0.0.html#@default569
+Notations for real numbers,node.0.2.1.html#@default249
+n_Sn,node.0.2.0.html#@default197
+nat,node.0.2.0.html#@default138
+nat_case,node.0.2.0.html#@default210
+nat_double_ind,node.0.2.0.html#@default211
+native code,node.3.0.0.html#@default575
+not,node.0.2.0.html#@default98
+not_eq_S,node.0.2.0.html#@default194
+notT,node.0.2.0.html#@default235
+O,node.0.2.0.html#@default139
+O_S,node.0.2.0.html#@default196
+Omega,node.1.2.10.html#@default521
+Opaque,node.1.0.1.html#@default311
+Options of the command line,node.3.0.4.html#@default578
+Orelse,node.1.2.12.html#@default544
+option,node.0.2.0.html#@default141
+or,node.0.2.0.html#@default103
+or_introl,node.0.2.0.html#@default104
+or_intror,node.0.2.0.html#@default105
+Parameter,node.0.0.2.html#@default25
+Pattern,node.1.2.4.html#@default454
+Peano's arithmetic notations,node.0.2.1.html#@default248
+Pose,node.1.2.2.html#@default432
+Positivity,node.0.3.4.html#@default287
+Precedences,node.2.0.1.html#@default570
+Pretty printing,node.1.0.6.html#@default360
+Print,node.1.0.0.html#@default302
+Print All,node.1.0.0.html#@default304
+Print Classes,node.3.3.6.html#@default606
+Print Coercion Paths,node.3.3.6.html#@default609
+Print Coercions,node.3.3.6.html#@default607
+Print Extraction Inline,node.3.6.1.html#@default635
+Print Graph,node.3.3.6.html#@default608
+Print Hint,node.1.2.11.html#@default535
+Print HintDb,node.1.2.11.html#@default536
+Print LoadPath,node.1.0.4.html#@default341
+Print ML Modules,node.1.0.3.html#@default334
+Print ML Path,node.1.0.4.html#@default344
+Print Module,node.0.1.4.html#@default80
+Print Module Type,node.0.1.4.html#@default81
+Print Modules,node.1.0.3.html#@default332
+Print Proof,node.1.0.0.html#@default303
+Print Section,node.1.0.0.html#@default306
+Print Table Printing If,node.0.1.1.html#@default70
+Print Table Printing Let,node.0.1.1.html#@default66
+Programming,node.0.2.0.html#@default131
+Prolog,node.1.2.10.html#@default518
+Prompt,node.1.1.html#@default371
+Proof,node.0.0.2.html#@default45
+Proof editing,node.1.1.html#@default370
+Proof General,node.3.1.5.html#@default590
+Proof term,node.1.1.html#@default373
+Prop,node.0.0.1.html#@default11
+Pwd,node.1.0.4.html#@default336
+pair,node.0.2.0.html#@default152
+plus,node.0.2.0.html#@default198
+plus_n_O,node.0.2.0.html#@default199
+plus_n_Sm,node.0.2.0.html#@default200
+pred,node.0.2.0.html#@default191
+pred_Sn,node.0.2.0.html#@default192
+prod,node.0.2.0.html#@default149
+products,node.0.0.1.html#@default17
+proj1,node.0.2.0.html#@default101
+proj2,node.0.2.0.html#@default102
+projS1,node.0.2.0.html#@default167
+projS2,node.0.2.0.html#@default168
+Qed,node.0.0.2.html#@default47
+Qualified identifiers,node.0.1.6.html#@default84
+Quantifiers,node.0.2.0.html#@default108
+Quit,node.1.0.7.html#@default364
+Quote,node.1.2.9.html#@default513
+?,node.0.1.7.html#@default90
+Read Module,node.1.0.3.html#@default328
+Record,node.0.1.0.html#@default52
+Recursion,node.0.2.0.html#@default213
+Recursive arguments,node.0.3.4.html#@default300
+Recursive Extraction,node.3.6.0.html#@default625
+Recursive Extraction Module,node.3.6.0.html#@default627
+Red,node.1.2.4.html#@default448
+Refine,node.1.2.1.html#@default409
+Reflexivity,node.1.2.7.html#@default484
+Remark,node.0.0.2.html#@default43
+Remove LoadPath,node.1.0.4.html#@default340
+Remove Printing If,node.0.1.1.html#@default68
+Remove Printing Let,node.0.1.1.html#@default64
+Rename,node.1.2.2.html#@default417
+Replace ... with,node.1.2.7.html#@default483
+Require,node.1.0.3.html#@default329
+Require Export,node.1.0.3.html#@default330
+Reset,node.1.0.5.html#@default347
+Reset Extraction Inline,node.3.6.1.html#@default636
+Reset Initial,node.1.0.5.html#@default350
+Resource file,node.3.0.2.html#@default576
+Restart,node.1.1.1.html#@default391
+Restore State,node.1.0.5.html#@default349
+Resume,node.1.1.0.html#@default387
+Rewrite,node.1.2.7.html#@default476
+Rewrite ->,node.1.2.7.html#@default477
+Rewrite -> ... in,node.1.2.7.html#@default480
+Rewrite <-,node.1.2.7.html#@default478
+Rewrite <- ... in,node.1.2.7.html#@default481
+Rewrite ... in,node.1.2.7.html#@default479
+Right,node.1.2.5.html#@default460
+Ring,node.1.2.10.html#@default522
+refl_eqT,node.0.2.0.html#@default237
+refl_equal,node.0.2.0.html#@default120
+right,node.0.2.0.html#@default173
+S,node.0.2.0.html#@default140
+Save,node.0.0.2.html#@default49
+Scheme,node.1.2.13.html#@default561
+Script file,node.1.0.2.html#@default324
+Search,node.1.0.1.html#@default313
+Search ... inside ...,node.1.0.1.html#@default317
+Search ... outside ...,node.1.0.1.html#@default320
+SearchAbout,node.1.0.1.html#@default314
+SearchPattern,node.1.0.1.html#@default315
+SearchPattern ... outside ...,node.1.0.1.html#@default321
+SearchRewrite,node.1.0.1.html#@default316
+SearchRewrite ... inside ...,node.1.0.1.html#@default319
+SearchRewrite ... outside ...,node.1.0.1.html#@default322
+Section,node.0.1.3.html#@default72
+Sections,node.0.1.3.html#@default71
+Set,node.0.0.1.html#@default10
+Set Extraction AutoInline,node.3.6.1.html#@default631
+Set Extraction Optimize,#@default629
+Set Hyps_limit,node.1.1.2.html#@default402
+Set Implicit Arguments,node.0.1.7.html#@default87
+Set Printing Coercion,node.3.3.7.html#@default612
+Set Printing Coercions,node.3.3.7.html#@default610
+Set Printing Synth,node.0.1.1.html#@default60
+Set Printing Wildcard,node.0.1.1.html#@default57
+Set Undo,node.1.1.1.html#@default389
+Setoid_replace,node.3.8.html#@default645
+Setoid_rewrite,node.3.8.3.html#@default649
+Show,node.1.1.2.html#@default394
+Show Conjectures,node.1.1.2.html#@default399
+Show Implicits,node.1.1.2.html#@default395
+Show Intro,node.1.1.2.html#@default400
+Show Intros,node.1.1.2.html#@default401
+Show Programs,node.3.5.2.html#@default621
+Show Proof,node.1.1.2.html#@default398
+Show Script,node.1.1.2.html#@default396
+Show Tree,node.1.1.2.html#@default397
+Silent mode,node.1.0.7.html#@default367
+Simpl,node.1.2.4.html#@default450
+Simple Inversion,node.1.2.9.html#@default507
+Simplify_eq,node.1.2.8.html#@default494
+Small inductive type,node.0.3.4.html#@default292
+Snd,node.0.2.0.html#@default156
+Solve,node.1.2.12.html#@default555
+Some,node.0.2.0.html#@default142
+Sorts,node.0.0.1.html#@default8
+Split,node.1.2.5.html#@default457
+SplitAbsolu,node.0.2.1.html#@default251
+SplitRmult,node.0.2.1.html#@default252
+Strong elimination,node.0.3.4.html#@default293
+Structure,node.3.3.8.html#@default615
+Subst,node.1.2.7.html#@default487
+Substitution,node.0.3.0.html#@default262
+Suspend,node.1.1.0.html#@default386
+Symmetry,node.1.2.7.html#@default485
+Syntactic Definition,node.0.1.7.html#@default89
+Syntax,node.1.0.6.html#@default359
+sig,node.0.2.0.html#@default159
+sig2,node.0.2.0.html#@default161
+sigS,node.0.2.0.html#@default165
+sigS2,node.0.2.0.html#@default169
+snd,node.0.2.0.html#@default154
+sort,node.0.0.1.html#@default7
+specif,node.0.0.1.html#@default14
+subgoal,node.1.2.html#@default406
+sum,node.0.2.0.html#@default144
+sum_eqT,node.0.2.0.html#@default238
+sumbool,node.0.2.0.html#@default171
+sumor,node.0.2.0.html#@default175
+sym_eq,node.0.2.0.html#@default122
+sym_not_eq,node.0.2.0.html#@default125
+sym_not_eqT,node.0.2.0.html#@default239
+Tactic Definition,node.1.2.14.html#@default563
+Tacticals,node.1.2.12.html#@default537
+Do,node.1.2.12.html#@default543
+Fail,node.1.2.12.html#@default541
+First,node.1.2.12.html#@default554
+Solve,node.1.2.12.html#@default556
+Idtac,node.1.2.12.html#@default539
+Info,node.1.2.12.html#@default558
+Orelse,node.1.2.12.html#@default545
+Repeat,node.1.2.12.html#@default546
+Try,node.1.2.12.html#@default552
+Tactics,node.1.2.html#@default404
+Tauto,node.1.2.10.html#@default519
+Terms,node.0.0.1.html#@default5
+Test Printing If,node.0.1.1.html#@default69
+Test Printing Let,node.0.1.1.html#@default65
+Test Printing Synth,node.0.1.1.html#@default62
+Test Printing Wildcard,node.0.1.1.html#@default59
+Theorem,node.0.0.2.html#@default41
+Theories,node.0.2.html#@default93
+Time,node.1.0.7.html#@default369
+Transitivity,node.1.2.7.html#@default486
+Transparent,node.1.0.1.html#@default312
+Trivial,node.1.2.10.html#@default516
+True,node.0.2.0.html#@default95
+Try,node.1.2.12.html#@default551
+Type,node.0.0.1.html#@default9
+Type of constructor,node.0.3.4.html#@default289
+Typing rules,node.0.3.1.html#@default265
+Ax,node.0.3.1.html#@default266
+Cases,node.0.3.4.html#@default296
+Const,node.0.3.1.html#@default268
+Conv,node.0.3.2.html#@default282
+Fix,node.0.3.4.html#@default299
+Lam,node.0.3.1.html#@default270
+Let,node.0.3.1.html#@default272
+Prod,node.0.3.1.html#@default269
+Var,node.0.3.1.html#@default267
+tactic macros,node.1.2.14.html#@default562
+trans_eq,node.0.2.0.html#@default123
+trans_eqT,node.0.2.0.html#@default240
+true,node.0.2.0.html#@default136
+tt,node.0.2.0.html#@default134
+Undo,node.1.1.1.html#@default388
+Unfocus,node.1.1.1.html#@default393
+Unfold,node.1.2.4.html#@default451
+Unfold ... in,node.1.2.4.html#@default452
+UnitT,node.0.2.0.html#@default234
+Unset Extraction AutoInline,node.3.6.1.html#@default632
+Unset Extraction Optimize,#@default630
+Unset Hyps_limit,node.1.1.2.html#@default403
+Unset Implicit Arguments,node.1.0.6.html#@default353
+Unset Printing Coercion,node.3.3.7.html#@default613
+Unset Printing Coercions,node.3.3.7.html#@default611
+Unset Printing Synth,node.0.1.1.html#@default61
+Unset Printing Wildcard,node.0.1.1.html#@default58
+Unset Undo,node.1.1.1.html#@default390
+unit,node.0.2.0.html#@default133
+Variable,node.0.0.2.html#@default26
+Variables,node.0.0.2.html#@default27
+value,node.0.2.0.html#@default183
+Well founded induction,node.0.2.0.html#@default214
+Well foundedness,node.0.2.0.html#@default212
+Write State,node.1.0.5.html#@default351
+well_founded,node.0.2.0.html#@default218
diff --git a/ide/preferences.ml b/ide/preferences.ml
new file mode 100644
index 00000000..8743b99b
--- /dev/null
+++ b/ide/preferences.ml
@@ -0,0 +1,540 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: preferences.ml,v 1.27.2.2 2004/07/16 19:30:20 herbelin Exp $ *)
+
+open Configwin
+open Printf
+open Util
+
+let pref_file = Filename.concat System.home ".coqiderc"
+
+let accel_file = Filename.concat System.home ".coqide.keys"
+
+let mod_to_str (m:Gdk.Tags.modifier) =
+ match m with
+ | `MOD1 -> "MOD1"
+ | `MOD2 -> "MOD2"
+ | `MOD3 -> "MOD3"
+ | `MOD4 -> "MOD4"
+ | `MOD5 -> "MOD5"
+ | `BUTTON1 -> "BUTTON1"
+ | `BUTTON2 -> "BUTTON2"
+ | `BUTTON3 -> "BUTTON3"
+ | `BUTTON4 -> "BUTTON4"
+ | `BUTTON5 -> "BUTTON5"
+ | `CONTROL -> "CONTROL"
+ | `LOCK -> "LOCK"
+ | `SHIFT -> "SHIFT"
+
+let (str_to_mod:string -> Gdk.Tags.modifier) =
+ function
+ | "MOD1" -> `MOD1
+ | "MOD2" -> `MOD2
+ | "MOD3" -> `MOD3
+ | "MOD4" -> `MOD4
+ | "MOD5" -> `MOD5
+ | "BUTTON1" -> `BUTTON1
+ | "BUTTON2" -> `BUTTON2
+ | "BUTTON3" -> `BUTTON3
+ | "BUTTON4" -> `BUTTON4
+ | "BUTTON5" -> `BUTTON5
+ | "CONTROL" -> `CONTROL
+ | "LOCK" -> `LOCK
+ | "SHIFT" -> `SHIFT
+ | s -> `MOD1
+
+type pref =
+ {
+ mutable cmd_coqc : string;
+ mutable cmd_make : string;
+ mutable cmd_coqmakefile : string;
+ mutable cmd_coqdoc : string;
+
+ mutable global_auto_revert : bool;
+ mutable global_auto_revert_delay : int;
+
+ mutable auto_save : bool;
+ mutable auto_save_delay : int;
+ mutable auto_save_name : string * string;
+
+ mutable encoding_use_locale : bool;
+ mutable encoding_use_utf8 : bool;
+ mutable encoding_manual : string;
+
+ mutable automatic_tactics : string list;
+ mutable cmd_print : string;
+
+ mutable modifier_for_navigation : Gdk.Tags.modifier list;
+ mutable modifier_for_templates : Gdk.Tags.modifier list;
+ mutable modifier_for_tactics : Gdk.Tags.modifier list;
+ mutable modifiers_valid : Gdk.Tags.modifier list;
+
+ mutable cmd_browse : string * string;
+ mutable cmd_editor : string * string;
+
+ mutable text_font : Pango.font_description;
+
+ mutable doc_url : string;
+ mutable library_url : string;
+
+ mutable show_toolbar : bool;
+ mutable contextual_menus_on_goal : bool;
+ mutable window_width : int;
+ mutable window_height :int;
+ mutable query_window_width : int;
+ mutable query_window_height : int;
+(*
+ mutable use_utf8_notation : bool;
+*)
+ mutable auto_complete : bool;
+ }
+
+let (current:pref ref) =
+ ref {
+ cmd_coqc = "coqc";
+ cmd_make = "make";
+ cmd_coqmakefile = "coq_makefile -o makefile *.v";
+ cmd_coqdoc = "coqdoc -q -g";
+ cmd_print = "lpr";
+
+ global_auto_revert = false;
+ global_auto_revert_delay = 10000;
+
+ auto_save = false;
+ auto_save_delay = 10000;
+ auto_save_name = "#","#";
+
+ encoding_use_locale = true;
+ encoding_use_utf8 = false;
+ encoding_manual = "ISO_8859-1";
+
+ automatic_tactics = ["trivial"; "tauto"; "auto"; "omega";
+ "auto with *"; "intuition" ];
+
+ modifier_for_navigation = [`CONTROL; `MOD1];
+ modifier_for_templates = [`MOD4];
+ modifier_for_tactics = [`CONTROL; `MOD1];
+ modifiers_valid = [`SHIFT; `CONTROL; `MOD1; `MOD4];
+
+
+ cmd_browse =
+ if Sys.os_type = "Win32"
+ then "C:\\PROGRA~1\\INTERN~1\\IEXPLORE ", ""
+ else "netscape -remote \"OpenURL(", ")\"";
+ cmd_editor =
+ if Sys.os_type = "Win32"
+ then "NOTEPAD ", ""
+ else "emacs ", "";
+
+ text_font = Pango.Font.from_string "sans 12";
+
+ doc_url = "http://coq.inria.fr/doc/";
+ library_url = "http://coq.inria.fr/library/";
+
+ show_toolbar = true;
+ contextual_menus_on_goal = true;
+ window_width = 800;
+ window_height = 600;
+ query_window_width = 600;
+ query_window_height = 400;
+(*
+ use_utf8_notation = false;
+*)
+ auto_complete = false
+ }
+
+
+let change_font = ref (fun f -> ())
+
+let show_toolbar = ref (fun x -> ())
+
+let auto_complete = ref (fun x -> ())
+
+let contextual_menus_on_goal = ref (fun x -> ())
+
+let resize_window = ref (fun () -> ())
+
+let save_pref () =
+ (try GtkData.AccelMap.save accel_file
+ with _ -> ());
+ let p = !current in
+ try
+ let add = Stringmap.add in
+ let (++) x f = f x in
+ Stringmap.empty ++
+ add "cmd_coqc" [p.cmd_coqc] ++
+ add "cmd_make" [p.cmd_make] ++
+ add "cmd_coqmakefile" [p.cmd_coqmakefile] ++
+ add "cmd_coqdoc" [p.cmd_coqdoc] ++
+ add "global_auto_revert" [string_of_bool p.global_auto_revert] ++
+ add "global_auto_revert_delay"
+ [string_of_int p.global_auto_revert_delay] ++
+ add "auto_save" [string_of_bool p.auto_save] ++
+ add "auto_save_delay" [string_of_int p.auto_save_delay] ++
+ add "auto_save_name" [fst p.auto_save_name; snd p.auto_save_name] ++
+
+ add "encoding_use_locale" [string_of_bool p.encoding_use_locale] ++
+ add "encoding_use_utf8" [string_of_bool p.encoding_use_utf8] ++
+ add "encoding_manual" [p.encoding_manual] ++
+
+ add "automatic_tactics"
+ (List.rev p.automatic_tactics) ++
+ add "cmd_print" [p.cmd_print] ++
+ add "modifier_for_navigation"
+ (List.map mod_to_str p.modifier_for_navigation) ++
+ add "modifier_for_templates"
+ (List.map mod_to_str p.modifier_for_templates) ++
+ add "modifier_for_tactics"
+ (List.map mod_to_str p.modifier_for_tactics) ++
+ add "modifiers_valid"
+ (List.map mod_to_str p.modifiers_valid) ++
+ add "cmd_browse" [fst p.cmd_browse; snd p.cmd_browse] ++
+ add "cmd_editor" [fst p.cmd_editor; snd p.cmd_editor] ++
+
+ add "text_font" [Pango.Font.to_string p.text_font] ++
+
+ add "doc_url" [p.doc_url] ++
+ add "library_url" [p.library_url] ++
+ add "show_toolbar" [string_of_bool p.show_toolbar] ++
+ add "contextual_menus_on_goal"
+ [string_of_bool p.contextual_menus_on_goal] ++
+ add "window_height" [string_of_int p.window_height] ++
+ add "window_width" [string_of_int p.window_width] ++
+ add "query_window_height" [string_of_int p.query_window_height] ++
+ add "query_window_width" [string_of_int p.query_window_width] ++
+ add "auto_complete" [string_of_bool p.auto_complete] ++
+ Config_lexer.print_file pref_file
+ with _ -> prerr_endline "Could not save preferences."
+
+
+let load_pref () =
+ (try GtkData.AccelMap.load accel_file with _ -> ());
+ let p = !current in
+ try
+ let m = Config_lexer.load_file pref_file in
+ let np = { p with cmd_coqc = p.cmd_coqc } in
+ let set k f = try let v = Stringmap.find k m in f v with _ -> () in
+ let set_hd k f = set k (fun v -> f (List.hd v)) in
+ let set_bool k f = set_hd k (fun v -> f (bool_of_string v)) in
+ let set_int k f = set_hd k (fun v -> f (int_of_string v)) in
+ let set_pair k f = set k (function [v1;v2] -> f v1 v2 | _ -> raise Exit) in
+ set_hd "cmd_coqc" (fun v -> np.cmd_coqc <- v);
+ set_hd "cmd_make" (fun v -> np.cmd_make <- v);
+ set_hd "cmd_coqmakefile" (fun v -> np.cmd_coqmakefile <- v);
+ set_hd "cmd_coqdoc" (fun v -> np.cmd_coqdoc <- v);
+ set_bool "global_auto_revert" (fun v -> np.global_auto_revert <- v);
+ set_int "global_auto_revert_delay"
+ (fun v -> np.global_auto_revert_delay <- v);
+ set_bool "auto_save" (fun v -> np.auto_save <- v);
+ set_int "auto_save_delay" (fun v -> np.auto_save_delay <- v);
+ set_pair "auto_save_name" (fun v1 v2 -> np.auto_save_name <- (v1,v2));
+ set_bool "encoding_use_locale" (fun v -> np.encoding_use_locale <- v);
+ set_bool "encoding_use_utf8" (fun v -> np.encoding_use_utf8 <- v);
+ set_hd "encoding_manual" (fun v -> np.encoding_manual <- v);
+ set "automatic_tactics"
+ (fun v -> np.automatic_tactics <- v);
+ set_hd "cmd_print" (fun v -> np.cmd_print <- v);
+ set "modifier_for_navigation"
+ (fun v -> np.modifier_for_navigation <- List.map str_to_mod v);
+ set "modifier_for_templates"
+ (fun v -> np.modifier_for_templates <- List.map str_to_mod v);
+ set "modifier_for_tactics"
+ (fun v -> np.modifier_for_tactics <- List.map str_to_mod v);
+ set "modifiers_valid"
+ (fun v -> np.modifiers_valid <- List.map str_to_mod v);
+ set_pair "cmd_browse" (fun v1 v2 -> np.cmd_browse <- (v1,v2));
+ set_pair "cmd_editor" (fun v1 v2 -> np.cmd_editor <- (v1,v2));
+ set_hd "text_font" (fun v -> np.text_font <- Pango.Font.from_string v);
+ set_hd "doc_url" (fun v -> np.doc_url <- v);
+ set_hd "library_url" (fun v -> np.library_url <- v);
+ set_bool "show_toolbar" (fun v -> np.show_toolbar <- v);
+ set_bool "contextual_menus_on_goal"
+ (fun v -> np.contextual_menus_on_goal <- v);
+ set_int "window_width" (fun v -> np.window_width <- v);
+ set_int "window_height" (fun v -> np.window_height <- v);
+ set_int "query_window_width" (fun v -> np.query_window_width <- v);
+ set_int "query_window_height" (fun v -> np.query_window_height <- v);
+ set_bool "auto_complete" (fun v -> np.auto_complete <- v);
+ current := np;
+(*
+ Format.printf "in laod_pref: current.text_font = %s@." (Pango.Font.to_string !current.text_font);
+*)
+ with e ->
+ prerr_endline ("Could not load preferences ("^
+ (Printexc.to_string e)^").")
+
+
+let configure () =
+ let cmd_coqc =
+ string
+ ~f:(fun s -> !current.cmd_coqc <- s)
+ " coqc" !current.cmd_coqc in
+ let cmd_make =
+ string
+ ~f:(fun s -> !current.cmd_make <- s)
+ " make" !current.cmd_make in
+ let cmd_coqmakefile =
+ string
+ ~f:(fun s -> !current.cmd_coqmakefile <- s)
+ "coqmakefile" !current.cmd_coqmakefile in
+ let cmd_coqdoc =
+ string
+ ~f:(fun s -> !current.cmd_coqdoc <- s)
+ " coqdoc" !current.cmd_coqdoc in
+ let cmd_print =
+ string
+ ~f:(fun s -> !current.cmd_print <- s)
+ " Print ps" !current.cmd_print in
+
+ let config_font =
+ let box = GPack.hbox () in
+ let w = GMisc.font_selection () in
+ w#set_preview_text
+ "Goal (∃n : nat, n ≤ 0)∧(∀x,y,z, x∈y⋃z↔x∈y∨x∈z).";
+ box#pack w#coerce;
+ ignore (w#misc#connect#realize
+ ~callback:(fun () -> w#set_font_name
+ (Pango.Font.to_string !current.text_font)));
+ custom
+ ~label:"Fonts for text"
+ box
+ (fun () ->
+ let fd = w#font_name in
+ !current.text_font <- (Pango.Font.from_string fd) ;
+(*
+ Format.printf "in config_font: current.text_font = %s@." (Pango.Font.to_string !current.text_font);
+*)
+ !change_font !current.text_font)
+ true
+ in
+(*
+ let show_toolbar =
+ bool
+ ~f:(fun s ->
+ !current.show_toolbar <- s;
+ !show_toolbar s)
+ "Show toolbar" !current.show_toolbar
+ in
+ let window_height =
+ string
+ ~f:(fun s -> !current.window_height <- (try int_of_string s with _ -> 600);
+ !resize_window ();
+ )
+ "Window height"
+ (string_of_int !current.window_height)
+ in
+ let window_width =
+ string
+ ~f:(fun s -> !current.window_width <-
+ (try int_of_string s with _ -> 800))
+ "Window width"
+ (string_of_int !current.window_width)
+ in
+*)
+ let auto_complete =
+ bool
+ ~f:(fun s ->
+ !current.auto_complete <- s;
+ !auto_complete s)
+ "Auto Complete" !current.auto_complete
+ in
+
+(* let use_utf8_notation =
+ bool
+ ~f:(fun b ->
+ !current.use_utf8_notation <- b;
+ )
+ "Use Unicode Notation: " !current.use_utf8_notation
+ in
+*)
+(*
+ let config_appearance = [show_toolbar; window_width; window_height] in
+*)
+ let global_auto_revert =
+ bool
+ ~f:(fun s -> !current.global_auto_revert <- s)
+ "Enable global auto revert" !current.global_auto_revert
+ in
+ let global_auto_revert_delay =
+ string
+ ~f:(fun s -> !current.global_auto_revert_delay <-
+ (try int_of_string s with _ -> 10000))
+ "Global auto revert delay (ms)"
+ (string_of_int !current.global_auto_revert_delay)
+ in
+
+ let auto_save =
+ bool
+ ~f:(fun s -> !current.auto_save <- s)
+ "Enable auto save" !current.auto_save
+ in
+ let auto_save_delay =
+ string
+ ~f:(fun s -> !current.auto_save_delay <-
+ (try int_of_string s with _ -> 10000))
+ "Auto save delay (ms)"
+ (string_of_int !current.auto_save_delay)
+ in
+
+ let encodings =
+ combo
+ "File charset encoding "
+ ~f:(fun s ->
+ match s with
+ | "UTF-8" ->
+ !current.encoding_use_utf8 <- true;
+ !current.encoding_use_locale <- false
+ | "LOCALE" ->
+ !current.encoding_use_utf8 <- false;
+ !current.encoding_use_locale <- true
+ | _ ->
+ !current.encoding_use_utf8 <- false;
+ !current.encoding_use_locale <- false;
+ !current.encoding_manual <- s;
+ )
+ ~new_allowed: true
+ ["UTF-8";"LOCALE";!current.encoding_manual]
+ (if !current.encoding_use_utf8 then "UTF-8"
+ else if !current.encoding_use_locale then "LOCALE" else !current.encoding_manual)
+ in
+ let modifier_for_tactics =
+ modifiers
+ ~allow:!current.modifiers_valid
+ ~f:(fun l -> !current.modifier_for_tactics <- l)
+ "Modifiers for Tactics Menu"
+ !current.modifier_for_tactics
+ in
+ let modifier_for_templates =
+ modifiers
+ ~allow:!current.modifiers_valid
+ ~f:(fun l -> !current.modifier_for_templates <- l)
+ "Modifiers for Templates Menu"
+ !current.modifier_for_templates
+ in
+ let modifier_for_navigation =
+ modifiers
+ ~allow:!current.modifiers_valid
+ ~f:(fun l -> !current.modifier_for_navigation <- l)
+ "Modifiers for Navigation Menu"
+ !current.modifier_for_navigation
+ in
+ let modifiers_valid =
+ modifiers
+ ~f:(fun l -> !current.modifiers_valid <- l)
+ "Allowed modifiers"
+ !current.modifiers_valid
+ in
+ let mod_msg =
+ string
+ "Needs restart to apply!"
+ ~editable:false
+ ""
+ in
+
+ let cmd_editor =
+ string
+ ~f:(fun s ->
+ !current.cmd_editor <-
+ try
+ let i = String.index s '%' in
+ let pre = (String.sub s 0 i) in
+ if String.length s - 1 = i then
+ pre,""
+ else
+ let post = String.sub s (i+2) (String.length s - i - 2) in
+ prerr_endline pre;
+ prerr_endline post;
+ pre,post
+ with Not_found -> s,""
+ )
+ ~help:"(%s for file name)"
+ "External editor"
+ ((fst !current.cmd_editor)^"%s"^(snd !current.cmd_editor))
+ in
+ let cmd_browse =
+ string
+ ~f:(fun s ->
+ !current.cmd_browse <-
+ try
+ let i = String.index s '%' in
+ let pre = (String.sub s 0 i) in
+ if String.length s - 1 = i then
+ pre,""
+ else
+ let post = String.sub s (i+2) (String.length s - i - 2) in
+ prerr_endline pre;
+ prerr_endline post;
+ pre,post
+ with Not_found -> s,""
+ )
+ ~help:"(%s for url)"
+ " Browser"
+ ((fst !current.cmd_browse)^"%s"^(snd !current.cmd_browse))
+ in
+ let doc_url =
+ string ~f:(fun s -> !current.doc_url <- s) " Manual URL" !current.doc_url in
+ let library_url =
+ string ~f:(fun s -> !current.library_url <- s) "Library URL" !current.library_url in
+
+ let automatic_tactics =
+ strings
+ ~f:(fun l -> !current.automatic_tactics <- l)
+ ~add:(fun () -> ["<edit me>"])
+ "Wizard tactics to try in order"
+ !current.automatic_tactics
+
+ in
+
+ let contextual_menus_on_goal =
+ bool
+ ~f:(fun s ->
+ !current.contextual_menus_on_goal <- s;
+ !contextual_menus_on_goal s)
+ "Contextual menus on goal" !current.contextual_menus_on_goal
+ in
+
+ let misc = [contextual_menus_on_goal;auto_complete] in
+
+(* ATTENTION !!!!! L'onglet Fonts doit etre en premier pour eviter un bug !!!!
+ (shame on Benjamin) *)
+ let cmds =
+ [Section("Fonts",
+ [config_font]);
+ Section("Files",
+ [global_auto_revert;global_auto_revert_delay;
+ auto_save; auto_save_delay; (* auto_save_name*)
+ encodings;
+ ]);
+(*
+ Section("Appearance",
+ config_appearance);
+*)
+ Section("Externals",
+ [cmd_coqc;cmd_make;cmd_coqmakefile; cmd_coqdoc; cmd_print;
+ cmd_editor;
+ cmd_browse;doc_url;library_url]);
+ Section("Tactics Wizard",
+ [automatic_tactics]);
+ Section("Shortcuts",
+ [modifiers_valid; modifier_for_tactics;
+ modifier_for_templates; modifier_for_navigation;mod_msg]);
+ Section("Misc",
+ misc)]
+ in
+(*
+ Format.printf "before edit: current.text_font = %s@." (Pango.Font.to_string !current.text_font);
+*)
+ let x = edit ~width:500 "Customizations" cmds in
+(*
+ Format.printf "after edit: current.text_font = %s@." (Pango.Font.to_string !current.text_font);
+*)
+ match x with
+ | Return_apply | Return_ok -> save_pref ()
+ | Return_cancel -> ()
+
diff --git a/ide/preferences.mli b/ide/preferences.mli
new file mode 100644
index 00000000..b4be283d
--- /dev/null
+++ b/ide/preferences.mli
@@ -0,0 +1,67 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: preferences.mli,v 1.8.2.1 2004/07/16 19:30:21 herbelin Exp $ *)
+
+type pref =
+ {
+ mutable cmd_coqc : string;
+ mutable cmd_make : string;
+ mutable cmd_coqmakefile : string;
+ mutable cmd_coqdoc : string;
+
+ mutable global_auto_revert : bool;
+ mutable global_auto_revert_delay : int;
+
+ mutable auto_save : bool;
+ mutable auto_save_delay : int;
+ mutable auto_save_name : string * string;
+
+ mutable encoding_use_locale : bool;
+ mutable encoding_use_utf8 : bool;
+ mutable encoding_manual : string;
+
+ mutable automatic_tactics : string list;
+ mutable cmd_print : string;
+
+ mutable modifier_for_navigation : Gdk.Tags.modifier list;
+ mutable modifier_for_templates : Gdk.Tags.modifier list;
+ mutable modifier_for_tactics : Gdk.Tags.modifier list;
+ mutable modifiers_valid : Gdk.Tags.modifier list;
+
+ mutable cmd_browse : string * string;
+ mutable cmd_editor : string * string;
+
+ mutable text_font : Pango.font_description;
+
+ mutable doc_url : string;
+ mutable library_url : string;
+
+ mutable show_toolbar : bool;
+ mutable contextual_menus_on_goal : bool;
+ mutable window_width : int;
+ mutable window_height : int;
+ mutable query_window_width : int;
+ mutable query_window_height : int;
+(*
+ mutable use_utf8_notation : bool;
+*)
+ mutable auto_complete : bool;
+ }
+
+val save_pref : unit -> unit
+val load_pref : unit -> unit
+
+val current : pref ref
+
+val configure : unit -> unit
+
+val change_font : ( Pango.font_description -> unit) ref
+val show_toolbar : (bool -> unit) ref
+val auto_complete : (bool -> unit) ref
+val resize_window : (unit -> unit) ref
diff --git a/ide/undo.ml b/ide/undo.ml
new file mode 100644
index 00000000..54449515
--- /dev/null
+++ b/ide/undo.ml
@@ -0,0 +1,178 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: undo.ml,v 1.8.2.1 2004/07/16 19:30:21 herbelin Exp $ *)
+
+open GText
+open Ideutils
+type action =
+ | Insert of string * int * int (* content*pos*length *)
+ | Delete of string * int * int (* content*pos*length *)
+
+let neg act = match act with
+ | Insert (s,i,l) -> Delete (s,i,l)
+ | Delete (s,i,l) -> Insert (s,i,l)
+
+class undoable_view (tv:Gtk.text_view Gtk.obj) =
+ let undo_lock = ref true in
+object(self)
+ inherit GText.view tv as super
+ val history = (Stack.create () : action Stack.t)
+ val redo = (Queue.create () : action Queue.t)
+ val nredo = (Stack.create () : action Stack.t)
+
+ method private dump_debug =
+ if false (* !debug *) then begin
+ prerr_endline "==========Stack top=============";
+ Stack.iter
+ (fun e -> match e with
+ | Insert(s,p,l) ->
+ Printf.eprintf "Insert of '%s' at %d (length %d)\n" s p l
+ | Delete(s,p,l) ->
+ Printf.eprintf "Delete '%s' from %d (length %d)\n" s p l)
+ history;
+ Printf.eprintf "Stack size %d\n" (Stack.length history);
+ prerr_endline "==========Stack Bottom==========";
+ prerr_endline "==========Queue start=============";
+ Queue.iter
+ (fun e -> match e with
+ | Insert(s,p,l) ->
+ Printf.eprintf "Insert of '%s' at %d (length %d)\n" s p l
+ | Delete(s,p,l) ->
+ Printf.eprintf "Delete '%s' from %d (length %d)\n" s p l)
+ redo;
+ Printf.eprintf "Stack size %d\n" (Queue.length redo);
+ prerr_endline "==========Queue End=========="
+
+ end
+
+ method clear_undo = Stack.clear history; Stack.clear nredo; Queue.clear redo
+
+ method undo = if !undo_lock then begin
+ undo_lock := false;
+ prerr_endline "UNDO";
+ try begin
+ let r =
+ match Stack.pop history with
+ | Insert(s,p,l) as act ->
+ let start = self#buffer#get_iter_at_char p in
+ (self#buffer#delete_interactive
+ ~start
+ ~stop:(start#forward_chars l)
+ ()) or
+ (Stack.push act history; false)
+ | Delete(s,p,l) as act ->
+ let iter = self#buffer#get_iter_at_char p in
+ (self#buffer#insert_interactive ~iter s) or
+ (Stack.push act history; false)
+ in if r then begin
+ process_pending ();
+ let act = Stack.pop history in
+ Queue.push act redo;
+ Stack.push act nredo
+ end;
+ undo_lock := true;
+ r
+ end
+ with Stack.Empty ->
+ undo_lock := true;
+ false
+ end else
+ (prerr_endline "UNDO DISCARDED"; true)
+
+ method redo = prerr_endline "REDO"; true
+ initializer
+(* INCORRECT: is called even while undoing...
+ ignore (self#buffer#connect#mark_set
+ ~callback:
+ (fun it tm -> if !undo_lock && not (Queue.is_empty redo) then begin
+ Stack.iter (fun e -> Stack.push (neg e) history) nredo;
+ Stack.clear nredo;
+ Queue.iter (fun e -> Stack.push e history) redo;
+ Queue.clear redo;
+ end)
+ );
+*)
+ ignore (self#buffer#connect#insert_text
+ ~callback:
+ (fun it s ->
+ if !undo_lock && not (Queue.is_empty redo) then begin
+ Stack.iter (fun e -> Stack.push (neg e) history) nredo;
+ Stack.clear nredo;
+ Queue.iter (fun e -> Stack.push e history) redo;
+ Queue.clear redo;
+ end;
+ let pos = it#offset in
+(* if Stack.is_empty history or
+ s=" " or s="\t" or s="\n" or
+ (match Stack.top history with
+ | Insert(old,opos,olen) ->
+ opos + olen <> pos
+ | _ -> true)
+ then *)
+ Stack.push (Insert(s,it#offset,Glib.Utf8.length s)) history
+ (*else begin
+ match Stack.pop history with
+ | Insert(olds,offset,len) ->
+ Stack.push
+ (Insert(olds^s,
+ offset,
+ len+(Glib.Utf8.length s)))
+ history
+ | _ -> assert false
+ end*);
+ self#dump_debug
+ ));
+ ignore (self#buffer#connect#delete_range
+ ~callback:
+ (fun ~start ~stop ->
+ if !undo_lock && not (Queue.is_empty redo) then begin
+ Queue.iter (fun e -> Stack.push e history) redo;
+ Queue.clear redo;
+ end;
+ let start_offset = start#offset in
+ let stop_offset = stop#offset in
+ let s = self#buffer#get_text ~start ~stop () in
+(* if Stack.is_empty history or (match Stack.top history with
+ | Delete(old,opos,olen) ->
+ olen=1 or opos <> start_offset
+ | _ -> true
+ )
+ then
+*) Stack.push
+ (Delete(s,
+ start_offset,
+ stop_offset - start_offset
+ ))
+ history
+ (* else begin
+ match Stack.pop history with
+ | Delete(olds,offset,len) ->
+ Stack.push
+ (Delete(olds^s,
+ offset,
+ len+(Glib.Utf8.length s)))
+ history
+ | _ -> assert false
+
+ end*);
+ self#dump_debug
+ ))
+end
+
+let undoable_view ?(buffer:GText.buffer option) =
+ GtkText.View.make_params []
+ ~cont:(GContainer.pack_container
+ ~create:
+ (fun pl -> let w = match buffer with
+ | None -> GtkText.View.create []
+ | Some b -> GtkText.View.create_with_buffer b#as_buffer
+ in
+ Gobject.set_params w pl; ((new undoable_view w):undoable_view)))
+
+
diff --git a/ide/undo.mli b/ide/undo.mli
new file mode 100644
index 00000000..6c7492ab
--- /dev/null
+++ b/ide/undo.mli
@@ -0,0 +1,35 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: undo.mli,v 1.4.2.1 2004/07/16 19:30:21 herbelin Exp $ *)
+
+(* An undoable view class *)
+
+class undoable_view : Gtk.text_view Gtk.obj ->
+object
+ inherit GText.view
+ method undo : bool
+ method redo : bool
+ method clear_undo : unit
+end
+
+val undoable_view :
+ ?buffer:GText.buffer ->
+ ?editable:bool ->
+ ?cursor_visible:bool ->
+ ?justification:GtkEnums.justification ->
+ ?wrap_mode:GtkEnums.wrap_mode ->
+ ?border_width:int ->
+ ?width:int ->
+ ?height:int ->
+ ?packing:(GObj.widget -> unit) ->
+ ?show:bool ->
+ unit ->
+ undoable_view
+
+
diff --git a/ide/utf8.v b/ide/utf8.v
new file mode 100644
index 00000000..574f2e65
--- /dev/null
+++ b/ide/utf8.v
@@ -0,0 +1,56 @@
+(* -*- coding:utf-8 -* *)
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* Logic *)
+Notation "∀ x , P" :=
+ (forall x , P) (at level 200, x ident) : type_scope.
+Notation "∀ x y , P" :=
+ (forall x y , P) (at level 200, x ident, y ident) : type_scope.
+Notation "∀ x y z , P" :=
+ (forall x y z , P) (at level 200, x ident, y ident, z ident) : type_scope.
+Notation "∀ x y z u , P" :=
+ (forall x y z u , P) (at level 200, x ident, y ident, z ident, u ident) : type_scope.
+Notation "∀ x : t , P" :=
+ (forall x : t , P) (at level 200, x ident) : type_scope.
+Notation "∀ x y : t , P" :=
+ (forall x y : t , P) (at level 200, x ident, y ident) : type_scope.
+Notation "∀ x y z : t , P" :=
+ (forall x y z : t , P) (at level 200, x ident, y ident, z ident) : type_scope.
+Notation "∀ x y z u : t , P" :=
+ (forall x y z u : t , P) (at level 200, x ident, y ident, z ident, u ident) : type_scope.
+
+Notation "∃ x , P" := (exists x , P) (at level 200, x ident) : type_scope.
+Notation "∃ x : t , P" := (exists x : t, P) (at level 200, x ident) : type_scope.
+
+Notation "x ∨ y" := (x \/ y) (at level 85, right associativity) : type_scope.
+Notation "x ∧ y" := (x /\ y) (at level 80, right associativity) : type_scope.
+Notation "x → y" := (x -> y) (at level 90, right associativity): type_scope.
+Notation "x ↔ y" := (x <-> y) (at level 95, no associativity): type_scope.
+Notation "⌉ x" := (~x) (at level 75, right associativity) : type_scope.
+
+
+(* Abstraction *)
+(* Not nice
+Notation "'λ' x : T , y" := ([x:T] y) (at level 1, x,T,y at level 10).
+Notation "'λ' x := T , y" := ([x:=T] y) (at level 1, x,T,y at level 10).
+*)
+
+(* Arithmetic *)
+Notation "x ≤ y" := (le x y) (at level 70, no associativity).
+Notation "x ≥ y" := (ge x y) (at level 70, no associativity).
+
+(* test *)
+(*
+Goal ∀ x, True -> (∃ y , x ≥ y + 1) ∨ x ≤ 0.
+*)
+
+(* Integer Arithmetic *)
+(* TODO
+Notation "x ≤ y" := (Zle x y) (at level 1, y at level 10).
+*)
diff --git a/ide/utf8_convert.mll b/ide/utf8_convert.mll
new file mode 100644
index 00000000..4c88adc5
--- /dev/null
+++ b/ide/utf8_convert.mll
@@ -0,0 +1,51 @@
+(************************************************************************)
+(* v * The Coq Proof Assistant / The Coq Development Team *)
+(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
+(* \VV/ **************************************************************)
+(* // * This file is distributed under the terms of the *)
+(* * GNU Lesser General Public License Version 2.1 *)
+(************************************************************************)
+
+(* $Id: utf8_convert.mll,v 1.1.2.1 2004/07/16 19:30:21 herbelin Exp $ *)
+
+{
+ open Lexing
+ let b = Buffer.create 127
+
+}
+
+(* Replace all occurences of \x{iiii} and \x{iiiiiiii} by UTF-8 valid chars *)
+
+let digit = ['0'-'9''A'-'Z''a'-'z']
+let short = digit digit digit digit
+let long = short short
+
+rule entry = parse
+ | "\\x{" (short | long ) '}'
+ { let s = lexeme lexbuf in
+ let n = String.length s in
+ let code =
+ try Glib.Utf8.from_unichar
+ (int_of_string ("0x"^(String.sub s 3 (n - 4))))
+ with _ -> s
+ in
+ let c = if Glib.Utf8.validate code then code else s in
+ Buffer.add_string b c;
+ entry lexbuf
+ }
+ | _
+ { let s = lexeme lexbuf in
+ Buffer.add_string b s;
+ entry lexbuf}
+ | eof
+ {
+ let s = Buffer.contents b in Buffer.reset b ; s
+ }
+
+
+{
+ let f s =
+ let lb = from_string s in
+ Buffer.reset b;
+ entry lb
+}
diff --git a/ide/utils/configwin.ml b/ide/utils/configwin.ml
new file mode 100644
index 00000000..de6a7c57
--- /dev/null
+++ b/ide/utils/configwin.ml
@@ -0,0 +1,74 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+type parameter_kind = Configwin_types.parameter_kind
+
+type configuration_structure =
+ Configwin_types.configuration_structure =
+ Section of string * parameter_kind list
+ | Section_list of string * configuration_structure list
+
+type return_button =
+ Configwin_types.return_button =
+ Return_apply
+ | Return_ok
+ | Return_cancel
+
+module KeyOption = Configwin_types.KeyOption
+
+let string = Configwin_ihm.string
+let text = Configwin_ihm.text
+let strings = Configwin_ihm.strings
+let list = Configwin_ihm.list
+let bool = Configwin_ihm.bool
+let filename = Configwin_ihm.filename
+let filenames = Configwin_ihm.filenames
+let color = Configwin_ihm.color
+let font = Configwin_ihm.font
+let combo = Configwin_ihm.combo
+let custom = Configwin_ihm.custom
+let date = Configwin_ihm.date
+let hotkey = Configwin_ihm.hotkey
+let modifiers = Configwin_ihm.modifiers
+let html = Configwin_ihm.html
+
+let edit
+ ?(apply=(fun () -> ()))
+ title ?(width=400) ?(height=400)
+ conf_struct_list =
+ Configwin_ihm.edit ~with_apply: true ~apply title ~width ~height conf_struct_list
+
+let get = Configwin_ihm.edit ~with_apply: false ~apply: (fun () -> ())
+
+let simple_edit
+ ?(apply=(fun () -> ()))
+ title ?width ?height
+ param_list = Configwin_ihm.simple_edit ~with_apply: true ~apply title ?width ?height param_list
+
+let simple_get = Configwin_ihm.simple_edit
+ ~with_apply: false ~apply: (fun () -> ())
+
+let box = Configwin_ihm.box
+
+let tabbed_box = Configwin_ihm.tabbed_box
diff --git a/ide/utils/configwin.mli b/ide/utils/configwin.mli
new file mode 100644
index 00000000..078befc6
--- /dev/null
+++ b/ide/utils/configwin.mli
@@ -0,0 +1,300 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(** This module is the interface of the Configwin library. *)
+
+(** {2 Types} *)
+
+(** This type represents the different kinds of parameters. *)
+type parameter_kind;;
+
+(** This type represents the structure of the configuration window. *)
+type configuration_structure =
+ | Section of string * parameter_kind list
+ (** label of the section, parameters *)
+ | Section_list of string * configuration_structure list
+ (** label of the section, list of the sub sections *)
+;;
+
+(** To indicate what button pushed the user when the window is closed. *)
+type return_button =
+ Return_apply
+ (** The user clicked on Apply at least once before
+ closing the window with Cancel or the window manager. *)
+ | Return_ok
+ (** The user closed the window with the ok button. *)
+ | Return_cancel
+ (** The user closed the window with the cancel
+ button or the window manager but never clicked
+ on the apply button.*)
+
+
+(** {2 The key option class (to use with the {!Uoptions} library)} *)
+
+module KeyOption : sig
+ val string_to_key : string -> (Gdk.Tags.modifier list * int)
+ val key_to_string : (Gdk.Tags.modifier list * int) -> string
+ val t : (Gdk.Tags.modifier list * int) Uoptions.option_class
+end
+
+(** {2 Functions to create parameters} *)
+
+(** [string label value] creates a string parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param expand indicate if the entry widget must expand or not (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+*)
+val string : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: (string -> unit) -> string -> string -> parameter_kind
+
+(** [bool label value] creates a boolean parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+*)
+val bool : ?editable: bool -> ?help: string ->
+ ?f: (bool -> unit) -> string -> bool -> parameter_kind
+
+(** [strings label value] creates a string list parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+ @param add the function returning a list of strings when the user wants to add strings
+ (default returns an empty list).
+ @param eq the comparison function, used not to have doubles in list. Default
+ is [Pervasives.(=)]. If you want to allow doubles in the list, give a function
+ always returning false.
+*)
+val strings : ?editable: bool -> ?help: string ->
+ ?f: (string list -> unit) ->
+ ?eq: (string -> string -> bool) ->
+ ?add: (unit -> string list) ->
+ string -> string list -> parameter_kind
+
+(** [list label f_strings value] creates a list parameter.
+ [f_strings] is a function taking a value and returning a list
+ of strings to display it. The list length should be the same for
+ any value, and the same as the titles list length. The [value]
+ is the initial list.
+ @param editable indicate if the value is editable (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+ @param eq the comparison function, used not to have doubles in list. Default
+ is [Pervasives.(=)]. If you want to allow doubles in the list, give a function
+ always returning false.
+ @param edit an optional function to use to edit an element of the list.
+ The function returns an element, no matter if element was changed or not.
+ When this function is given, a "Edit" button appears next to the list.
+ @param add the function returning a list of values when the user wants to add values
+ (default returns an empty list).
+ @param titles an optional list of titles for the list. If the [f_strings]
+ function returns a list with more than one element, then you must give
+ a list of titles.
+ @param color an optional function returning the optional color for a given element.
+ This color is used to display the element in the list. The default function returns
+ no color for any element.
+*)
+val list : ?editable: bool -> ?help: string ->
+ ?f: ('a list -> unit) ->
+ ?eq: ('a -> 'a -> bool) ->
+ ?edit: ('a -> 'a) ->
+ ?add: (unit -> 'a list) ->
+ ?titles: string list ->
+ ?color: ('a -> string option) ->
+ string ->
+ ('a -> string list) ->
+ 'a list ->
+ parameter_kind
+
+(** [color label value] creates a color parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param expand indicate if the entry widget must expand or not (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+*)
+val color : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: (string -> unit) -> string -> string -> parameter_kind
+
+(** [font label value] creates a font parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param expand indicate if the entry widget must expand or not (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+*)
+val font : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: (string -> unit) -> string -> string -> parameter_kind
+
+(** [combo label choices value] creates a combo parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param expand indicate if the entry widget must expand or not (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+ @param new_allowed indicate if a entry not in the list of choices is accepted
+ (default is [false]).
+ @param blank_allowed indicate if the empty selection [""] is accepted
+ (default is [false]).
+*)
+val combo : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: (string -> unit) ->
+ ?new_allowed: bool -> ?blank_allowed: bool ->
+ string -> string list -> string -> parameter_kind
+
+(** [text label value] creates a text parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param expand indicate if the box for the text must expand or not (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+*)
+val text : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: (string -> unit) -> string -> string -> parameter_kind
+
+(** Same as {!Configwin.text} but html bindings are available
+ in the text widget. Use the [configwin_html_config] utility
+ to edit your bindings.
+*)
+val html : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: (string -> unit) -> string -> string -> parameter_kind
+
+(** [filename label value] creates a filename parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param expand indicate if the entry widget must expand or not (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+*)
+val filename : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: (string -> unit) -> string -> string -> parameter_kind
+
+(** [filenames label value] creates a filename list parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+ @param eq the comparison function, used not to have doubles in list. Default
+ is [Pervasives.(=)]. If you want to allow doubles in the list, give a function
+ always returning false.
+*)
+val filenames : ?editable: bool -> ?help: string ->
+ ?f: (string list -> unit) ->
+ ?eq: (string -> string -> bool) ->
+ string -> string list -> parameter_kind
+
+(** [date label value] creates a date parameter.
+ @param editable indicate if the value is editable (default is [true]).
+ @param expand indicate if the entry widget must expand or not (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+ @param f_string the function used to display the date as a string. The parameter
+ is a tupe [(day,month,year)], where [month] is between [0] and [11]. The default
+ function creates the string [year/month/day].
+*)
+val date : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: ((int * int * int) -> unit) ->
+ ?f_string: ((int * int * int -> string)) ->
+ string -> (int * int * int) -> parameter_kind
+
+(** [hotkey label value] creates a hot key parameter.
+ A hot key is defined by a list of modifiers and a key code.
+ @param editable indicate if the value is editable (default is [true]).
+ @param expand indicate if the entry widget must expand or not (default is [true]).
+ @param help an optional help message.
+ @param f the function called to apply the value (default function does nothing).
+*)
+val hotkey : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?f: ((Gdk.Tags.modifier list * int) -> unit) ->
+ string -> (Gdk.Tags.modifier list * int) -> parameter_kind
+
+val modifiers : ?editable: bool -> ?expand: bool -> ?help: string ->
+ ?allow:(Gdk.Tags.modifier list) ->
+ ?f: (Gdk.Tags.modifier list -> unit) ->
+ string -> Gdk.Tags.modifier list -> parameter_kind
+
+
+(** [custom box f expand] creates a custom parameter, with
+ the given [box], the [f] function is called when the user
+ wants to apply his changes, and [expand] indicates if the box
+ must expand in its father.
+ @param label if a value is specified, a the box is packed into a frame.
+*)
+val custom : ?label: string -> GPack.box -> (unit -> unit) -> bool -> parameter_kind
+
+(** {2 Functions creating configuration windows and boxes} *)
+
+(** This function takes a configuration structure and creates a window
+ to configure the various parameters.
+ @param apply this function is called when the apply button is clicked, after
+ giving new values to parameters.
+*)
+val edit :
+ ?apply: (unit -> unit) ->
+ string ->
+ ?width:int ->
+ ?height:int ->
+ configuration_structure list ->
+ return_button
+
+(** This function takes a configuration structure and creates a window used
+ to get the various parameters from the user. It is the same window as edit but
+ there is no apply button.*)
+val get :
+ string ->
+ ?width:int ->
+ ?height:int ->
+ configuration_structure list ->
+ return_button
+
+(** This function takes a list of parameter specifications and
+ creates a window to configure the various parameters.
+ @param apply this function is called when the apply button is clicked, after
+ giving new values to parameters.*)
+val simple_edit :
+ ?apply: (unit -> unit) ->
+ string ->
+ ?width:int ->
+ ?height:int ->
+ parameter_kind list -> return_button
+
+(** This function takes a list of parameter specifications and
+ creates a window to configure the various parameters,
+ without Apply button.*)
+val simple_get :
+ string ->
+ ?width:int ->
+ ?height:int ->
+ parameter_kind list -> return_button
+
+(** Create a [GPack.box] with the list of given parameters,
+ and the given list of buttons (defined by their label and callback).
+ Before calling the callback of a button, the [apply] function
+ of each parameter is called.
+*)
+val box : parameter_kind list ->
+ (string * (unit -> unit)) list -> GPack.box
+
+(** Create a [GPack.box] with the list of given configuration structure list,
+ and the given list of buttons (defined by their label and callback).
+ Before calling the callback of a button, the [apply] function
+ of each parameter is called.
+*)
+val tabbed_box : configuration_structure list ->
+ (string * (unit -> unit)) list -> GPack.box
diff --git a/ide/utils/configwin_html_config.ml b/ide/utils/configwin_html_config.ml
new file mode 100644
index 00000000..fc2913d1
--- /dev/null
+++ b/ide/utils/configwin_html_config.ml
@@ -0,0 +1,83 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(** The HTML editor bindings configurator. *)
+
+module C = Configwin_ihm
+open Configwin_types
+open Uoptions
+
+let simple_get = C.simple_edit
+ ~with_apply: false ~apply: (fun () -> ())
+
+let params_hb hb =
+ let p_key = C.hotkey
+ ~f: (fun k -> hb.html_key <- k) Configwin_messages.mKey
+ hb.html_key
+ in
+ let p_begin = C.string
+ ~f: (fun s -> hb.html_begin <- s)
+ Configwin_messages.html_begin
+ hb.html_begin
+ in
+ let p_end = C.string
+ ~f: (fun s -> hb.html_end <- s)
+ Configwin_messages.html_end
+ hb.html_end
+ in
+ [ p_key ; p_begin ; p_end ]
+
+let edit_hb hb =
+ ignore (simple_get Configwin_messages.mEdit (params_hb hb));
+ hb
+
+let add () =
+ let hb = { html_key = KeyOption.string_to_key "C-a" ;
+ html_begin = "" ;
+ html_end = "" ;
+ }
+ in
+ match simple_get Configwin_messages.mAdd (params_hb hb) with
+ Return_ok -> [hb]
+ | _ -> []
+
+let main () =
+ ignore (GMain.Main.init ());
+ let (ini, bindings) = C.html_config_file_and_option () in
+ let param = C.list
+ ~f: (fun l -> bindings =:= l ; Uoptions.save_with_help ini)
+ ~eq: (fun hb1 hb2 -> hb1.html_key = hb2.html_key)
+ ~edit: edit_hb
+ ~add: add
+ ~titles: [ Configwin_messages.mKey ; Configwin_messages.html_begin ;
+ Configwin_messages.html_end ]
+ Configwin_messages.shortcuts
+ (fun hb -> [ KeyOption.key_to_string hb.html_key ;
+ hb.html_begin ; hb.html_end ])
+ !!bindings
+ in
+ ignore (simple_get ~width: 300 ~height: 400
+ Configwin_messages.html_config [param])
+
+let _ = main ()
diff --git a/ide/utils/configwin_ihm.ml b/ide/utils/configwin_ihm.ml
new file mode 100644
index 00000000..03ca706c
--- /dev/null
+++ b/ide/utils/configwin_ihm.ml
@@ -0,0 +1,1435 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(** This module contains the gui functions of Confgiwin.*)
+
+open Configwin_types
+
+module O = Uoptions
+
+
+(** The file where the html config is. *)
+let file_html_config = Filename.concat Configwin_messages.home ".configwin_html"
+
+(** Return the ini file for the html config, and the option for bindings. *)
+let html_config_file_and_option () =
+ let ini = O.create_options_file file_html_config in
+ let bindings = O.define_option ini ["bindings"]
+ ""
+ (O.list_option Configwin_types.Html_binding.t)
+ [ { html_key = KeyOption.string_to_key "A-b" ;
+ html_begin = "<b>";
+ html_end = "</b>" ;
+ } ;
+ { html_key = KeyOption.string_to_key "A-i" ;
+ html_begin = "<i>";
+ html_end = "</i>" ;
+ }
+ ]
+ in
+ O.load ini ;
+ (ini, bindings)
+
+
+(** This variable contains the last directory where the user selected a file.*)
+let last_dir = ref "";;
+
+(** This function allows the user to select a file and returns the
+ selected file name. An optional function allows to change the
+ behaviour of the ok button.
+ A VOIR : mutli-selection ? *)
+let select_files ?dir
+ ?(fok : (string -> unit) option)
+ the_title =
+ let files = ref ([] : string list) in
+ let fs = GWindow.file_selection ~modal:true
+ ~title: the_title () in
+ (* we set the previous directory, if no directory is given *)
+ (
+ match dir with
+ None ->
+ if !last_dir <> "" then
+ let _ = fs#set_filename !last_dir in
+ ()
+ else
+ ()
+ | Some dir ->
+ let _ = fs#set_filename !last_dir in
+ ()
+ );
+
+ let _ = fs # connect#destroy ~callback: GMain.Main.quit in
+ let _ = fs # ok_button # connect#clicked ~callback:
+ (match fok with
+ None ->
+ (fun () -> files := [fs#filename] ; fs#destroy ())
+ | Some f ->
+ (fun () -> f fs#filename)
+ )
+ in
+ let _ = fs # cancel_button # connect#clicked ~callback:fs#destroy in
+ fs # show ();
+ GMain.Main.main ();
+ match !files with
+ | [] ->
+ []
+ | [""] ->
+ []
+ | l ->
+ (* we keep the directory in last_dir *)
+ last_dir := Filename.dirname (List.hd l);
+ l
+;;
+
+(** Make the user select a date. *)
+let select_date title (day,mon,year) =
+ let v_opt = ref None in
+ let window = GWindow.dialog ~modal:true ~title () in
+ let hbox = GPack.hbox ~border_width:10 ~packing:window#vbox#add () in
+ let cal = GMisc.calendar ~packing: (hbox#pack ~expand: true) () in
+ cal#select_month ~month: mon ~year: year ;
+ cal#select_day day;
+ let bbox = window#action_area in
+
+ let bok = GButton.button ~label: Configwin_messages.mOk
+ ~packing:(bbox#pack ~expand:true ~padding:4) ()
+ in
+ let bcancel = GButton.button ~label: Configwin_messages.mCancel
+ ~packing:(bbox#pack ~expand:true ~padding:4) ()
+ in
+ ignore (bok#connect#clicked ~callback:
+ (fun () -> v_opt := Some (cal#date); window#destroy ()));
+ ignore(bcancel#connect#clicked ~callback: window#destroy);
+
+ bok#grab_default ();
+ ignore(window#connect#destroy ~callback: GMain.Main.quit);
+ window#set_position `CENTER;
+ window#show ();
+ GMain.Main.main ();
+ !v_opt
+
+
+(** This class builds a frame with a clist and two buttons :
+ one to add items and one to remove the selected items.
+ The class takes in parameter a function used to add items and
+ a string list ref which is used to store the content of the clist.
+ At last, a title for the frame is also in parameter, so that
+ each instance of the class creates a frame. *)
+class ['a] list_selection_box (listref : 'a list ref)
+ titles_opt
+ help_opt
+ f_edit_opt
+ f_strings
+ f_color
+ (eq : 'a -> 'a -> bool)
+ add_function title editable =
+ let wev = GBin.event_box () in
+ let wf = GBin.frame ~label: title ~packing: wev#add () in
+ let hbox = GPack.hbox ~packing: wf#add () in
+ (* the scroll window and the clist *)
+ let wscroll = GBin.scrolled_window
+ ~vpolicy: `AUTOMATIC
+ ~hpolicy: `AUTOMATIC
+ ~packing: (hbox#pack ~expand: true) ()
+ in
+ let wlist = match titles_opt with
+ None ->
+ GList.clist ~selection_mode: `MULTIPLE
+ ~titles_show: false
+ ~packing: wscroll#add ()
+ | Some l ->
+ GList.clist ~selection_mode: `MULTIPLE
+ ~titles: l
+ ~titles_show: true
+ ~packing: wscroll#add ()
+ in
+ let _ =
+ match help_opt with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (wf#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wev#coerce ~text: help ~privat: help
+ in (* the vbox for the buttons *)
+ let vbox_buttons = GPack.vbox () in
+ let _ =
+ if editable then
+ let _ = hbox#pack ~expand: false vbox_buttons#coerce in
+ ()
+ else
+ ()
+ in
+ let wb_add = GButton.button
+ ~label: Configwin_messages.mAdd
+ ~packing: (vbox_buttons#pack ~expand:false ~padding:2)
+ ()
+ in
+ let wb_edit = GButton.button
+ ~label: Configwin_messages.mEdit
+ ()
+ in
+ let _ = match f_edit_opt with
+ None -> ()
+ | Some _ -> vbox_buttons#pack ~expand:false ~padding:2 wb_edit#coerce
+ in
+ let wb_up = GButton.button
+ ~label: Configwin_messages.mUp
+ ~packing: (vbox_buttons#pack ~expand:false ~padding:2)
+ ()
+ in
+ let wb_remove = GButton.button
+ ~label: Configwin_messages.mRemove
+ ~packing: (vbox_buttons#pack ~expand:false ~padding:2)
+ ()
+ in
+ object (self)
+ (** the list of selected rows *)
+ val mutable list_select = []
+
+ (** This method returns the frame created. *)
+ method box = wev
+
+ method update l =
+ (* set the new list in the provided listref *)
+ listref := l;
+ (* insert the elements in the clist *)
+ wlist#freeze ();
+ wlist#clear ();
+ List.iter
+ (fun ele ->
+ ignore (wlist#append (f_strings ele));
+ match f_color ele with
+ None -> ()
+ | Some c ->
+ try wlist#set_row ~foreground: (`NAME c) (wlist#rows - 1)
+ with _ -> ()
+ )
+ !listref;
+
+ (match titles_opt with
+ None -> wlist#columns_autosize ()
+ | Some _ -> GToolbox.autosize_clist wlist);
+ wlist#thaw ();
+ (* the list of selectd elements is now empty *)
+ list_select <- []
+
+ (** Move up the selected rows. *)
+ method up_selected =
+ let rec iter n selrows l =
+ match selrows with
+ [] -> (l, [])
+ | m :: qrows ->
+ match l with
+ [] -> ([],[])
+ | [_] -> (l,[])
+ | e1 :: e2 :: q when m = n + 1 ->
+ let newl, newrows = iter (n+1) qrows (e1 :: q) in
+ (e2 :: newl, n :: newrows)
+ | e1 :: q ->
+ let newl, newrows = iter (n+1) selrows q in
+ (e1 :: newl, newrows)
+ in
+ let sorted_select = List.sort compare list_select in
+ let new_list, new_rows = iter 0 sorted_select !listref in
+ self#update new_list;
+ List.iter (fun n -> wlist#select n 0) new_rows
+
+ (** Make the user edit the first selected row. *)
+ method edit_selected f_edit =
+ let sorted_select = List.sort compare list_select in
+ match sorted_select with
+ [] -> ()
+ | n :: _ ->
+ try
+ let ele = List.nth !listref n in
+ let ele2 = f_edit ele in
+ let rec iter m = function
+ [] -> []
+ | e :: q ->
+ if n = m then
+ ele2 :: q
+ else
+ e :: (iter (m+1) q)
+ in
+ self#update (iter 0 !listref);
+ wlist#select n 0
+ with
+ Not_found ->
+ ()
+
+ initializer
+ (** create the functions called when the buttons are clicked *)
+ let f_add () =
+ (* get the files to add with the function provided *)
+ let l = add_function () in
+ (* remove from the list the ones which are already in
+ the listref, using the eq predicate *)
+ let l2 = List.fold_left
+ (fun acc -> fun ele ->
+ if List.exists (eq ele) acc then
+ acc
+ else
+ acc @ [ele])
+ !listref
+ l
+ in
+ self#update l2
+ in
+ let f_remove () =
+ (* remove the selected items from the listref and the clist *)
+ let rec iter n = function
+ [] -> []
+ | h :: q ->
+ if List.mem n list_select then
+ iter (n+1) q
+ else
+ h :: (iter (n+1) q)
+ in
+ let new_list = iter 0 !listref in
+ self#update new_list
+ in
+ (* connect the functions to the buttons *)
+ ignore (wb_add#connect#clicked f_add);
+ ignore (wb_remove#connect#clicked f_remove);
+ ignore (wb_up#connect#clicked (fun () -> self#up_selected));
+ (
+ match f_edit_opt with
+ None -> ()
+ | Some f -> ignore (wb_edit#connect#clicked (fun () -> self#edit_selected f))
+ );
+ (* connect the selection and deselection of items in the clist *)
+ let f_select ~row ~column ~event =
+ try
+ list_select <- row :: list_select
+ with
+ Failure _ ->
+ ()
+ in
+ let f_unselect ~row ~column ~event =
+ try
+ let new_list_select = List.filter (fun n -> n <> row) list_select in
+ list_select <- new_list_select
+ with
+ Failure _ ->
+ ()
+ in
+ (* connect the select and deselect events *)
+ ignore(wlist#connect#select_row f_select);
+ ignore(wlist#connect#unselect_row f_unselect);
+
+ (* initialize the clist with the listref *)
+ self#update !listref
+ end;;
+
+
+(** This class is used to build a box for a string parameter.*)
+class string_param_box param =
+ let hbox = GPack.hbox () in
+ let wev = GBin.event_box ~packing: (hbox#pack ~expand: false ~padding: 2) () in
+ let wl = GMisc.label ~text: param.string_label ~packing: wev#add () in
+ let we = GEdit.entry
+ ~editable: param.string_editable
+ ~packing: (hbox#pack ~expand: param.string_expand ~padding: 2)
+ ()
+ in
+ let _ =
+ match param.string_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wev#coerce ~text: help ~privat: help
+ in
+ let _ = we#set_text param.string_value in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = we#text in
+ if new_value <> param.string_value then
+ let _ = param.string_f_apply new_value in
+ param.string_value <- new_value
+ else
+ ()
+ end ;;
+
+(** This class is used to build a box for a combo parameter.*)
+class combo_param_box param =
+ let hbox = GPack.hbox () in
+ let wev = GBin.event_box ~packing: (hbox#pack ~expand: false ~padding: 2) () in
+ let wl = GMisc.label ~text: param.combo_label ~packing: wev#add () in
+ let wc = GEdit.combo
+ ~popdown_strings: param.combo_choices
+ ~value_in_list: (not param.combo_new_allowed)
+(* ~ok_if_empty: param.combo_blank_allowed*)
+ ~packing: (hbox#pack ~expand: param.combo_expand ~padding: 2)
+ ()
+ in
+ let _ =
+ match param.combo_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback:tooltips#destroy);
+ tooltips#set_tip wev#coerce ~text: help ~privat: help
+ in
+ let _ = wc#entry#set_editable param.combo_editable in
+ let _ = wc#entry#set_text param.combo_value in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = wc#entry#text in
+ if new_value <> param.combo_value then
+ let _ = param.combo_f_apply new_value in
+ param.combo_value <- new_value
+ else
+ ()
+ end ;;
+
+(** Class used to pack a custom box. *)
+class custom_param_box param =
+ let top =
+ match param.custom_framed with
+ None -> param.custom_box#coerce
+ | Some l ->
+ let wf = GBin.frame ~label: l () in
+ wf#add param.custom_box#coerce;
+ wf#coerce
+ in
+ object (self)
+ method box = top
+ method apply = param.custom_f_apply ()
+ end
+
+(** This class is used to build a box for a color parameter.*)
+class color_param_box param =
+ let v = ref param.color_value in
+ let hbox = GPack.hbox () in
+ let wb = GButton.button ~label: param.color_label
+ ~packing: (hbox#pack ~expand: false ~padding: 2) ()
+ in
+ let w_test = GMisc.arrow
+ ~kind: `RIGHT
+ ~shadow: `OUT
+ ~width: 20
+ ~height: 20
+ ~packing: (hbox#pack ~expand: false ~padding: 2 )
+ ()
+ in
+ let we = GEdit.entry
+ ~editable: param.color_editable
+ ~packing: (hbox#pack ~expand: param.color_expand ~padding: 2)
+ ()
+ in
+ let _ =
+ match param.color_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wb#coerce ~text: help ~privat: help
+ in
+ let set_color s =
+ let style = w_test#misc#style#copy in
+ (
+ try style#set_bg [ (`NORMAL, `NAME s) ; ]
+ with _ -> ()
+ );
+ w_test#misc#set_style style
+ in
+ let _ = set_color !v in
+ let _ = we#set_text !v in
+ let f_sel () =
+ let dialog = GWindow.color_selection_dialog
+ ~title: param.color_label
+ ~modal: true
+ ~show: true
+ ()
+ in
+ let wb_ok = dialog#ok_button in
+ let wb_cancel = dialog#cancel_button in
+ let _ = dialog#connect#destroy GMain.Main.quit in
+ let _ = wb_ok#connect#clicked
+ (fun () ->
+ (* let color = dialog#colorsel#get_color in
+ let r = int_of_float (ceil (color.Gtk.red *. 255.)) in
+ let g = int_of_float (ceil (color.Gtk.green *. 255.)) in
+ let b = int_of_float (ceil (color.Gtk.blue *. 255.)) in
+ let s = Printf.sprintf "#%2X%2X%2X" r g b in
+ let _ =
+ for i = 1 to (String.length s) - 1 do
+ if s.[i] = ' ' then s.[i] <- '0'
+ done
+ in
+ we#set_text s ;
+ set_color s;*)
+ dialog#destroy ()
+ )
+ in
+ let _ = wb_cancel#connect#clicked dialog#destroy in
+ GMain.Main.main ()
+ in
+ let _ =
+ if param.color_editable then ignore (wb#connect#clicked f_sel)
+ in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = we#text in
+ if new_value <> param.color_value then
+ let _ = param.color_f_apply new_value in
+ param.color_value <- new_value
+ else
+ ()
+ end ;;
+
+(** This class is used to build a box for a font parameter.*)
+class font_param_box param =
+ let v = ref param.font_value in
+ let hbox = GPack.hbox () in
+ let wb = GButton.button ~label: param.font_label
+ ~packing: (hbox#pack ~expand: false ~padding: 2) ()
+ in
+ let we = GEdit.entry
+ ~editable: false
+ ~packing: (hbox#pack ~expand: param.font_expand ~padding: 2)
+ ()
+ in
+ let _ =
+ match param.font_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wb#coerce ~text: help ~privat: help
+ in
+ let set_entry_font font_opt =
+ match font_opt with
+ None -> ()
+ | Some s ->
+ let style = we#misc#style#copy in
+ (
+ try
+ let font = Gdk.Font.load_fontset s in
+ style#set_font font
+ with _ -> ()
+ );
+ we#misc#set_style style
+ in
+ let _ = set_entry_font (Some !v) in
+ let _ = we#set_text !v in
+ let f_sel () =
+ let dialog = GWindow.font_selection_dialog
+ ~title: param.font_label
+ ~modal: true
+ ~show: true
+ ()
+ in
+ dialog#selection#set_font_name !v;
+ let wb_ok = dialog#ok_button in
+ let wb_cancel = dialog#cancel_button in
+ let _ = dialog#connect#destroy GMain.Main.quit in
+ let _ = wb_ok#connect#clicked
+ (fun () ->
+ let font_opt = dialog#selection#font_name in
+(* we#set_text (match font_opt with None -> "" | Some s -> s) ;
+ set_entry_font font_opt;*)
+ dialog#destroy ()
+ )
+ in
+ let _ = wb_cancel#connect#clicked dialog#destroy in
+ GMain.Main.main ()
+ in
+ let _ = if param.font_editable then ignore (wb#connect#clicked f_sel) in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = we#text in
+ if new_value <> param.font_value then
+ let _ = param.font_f_apply new_value in
+ param.font_value <- new_value
+ else
+ ()
+ end ;;
+
+(** This class is used to build a box for a text parameter.*)
+class text_param_box param =
+ let hbox = GPack.hbox ~height: 100 () in
+ let wev = GBin.event_box ~packing: (hbox#pack ~expand: false ~padding: 2) () in
+ let wl = GMisc.label ~text: param.string_label ~packing: wev#add () in
+ let wscroll = GBin.scrolled_window
+ ~vpolicy: `AUTOMATIC
+ ~hpolicy: `AUTOMATIC
+ ~packing: (hbox#pack ~expand: true ~padding: 2) ()
+ in
+ let wt = GText.view ~packing:wscroll#add () in
+(* let _ = wt#coerce#misc#set_size_request ~height:100 in *)
+ let _ = wt#set_editable param.string_editable in
+ let _ =
+ match param.string_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wev#coerce ~text: help ~privat: help
+ in
+ let _ = wt#buffer#insert param.string_value in
+
+ object (self)
+ val wt = wt
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = wt#buffer#get_text () in
+ if new_value <> param.string_value then
+ let _ = param.string_f_apply new_value in
+ param.string_value <- new_value
+ else
+ ()
+ end ;;
+
+(** This class is used to build a box a html parameter. *)
+class html_param_box param =
+ object (self)
+ inherit text_param_box param
+
+ method private exec html_start html_end () =
+ let s,e = wt#buffer#selection_bounds in
+ if s#compare e = 0 then
+ wt#buffer#insert (html_start^html_end)
+ else begin
+ ignore (wt#buffer#insert ~iter:e html_end);
+ ignore (wt#buffer#insert ~iter:s html_start);
+ wt#buffer#place_cursor
+ (e#forward_chars (String.length (html_start^html_end)))
+ end
+ initializer
+ let (_,html_bindings) = html_config_file_and_option () in
+ let add_shortcut hb =
+ let (mods, k) = hb.html_key in
+ Okey.add wt ~mods k (self#exec hb.html_begin hb.html_end)
+ in
+ List.iter add_shortcut (O.(!!) html_bindings)
+ end
+
+(** This class is used to build a box for a boolean parameter.*)
+class bool_param_box param =
+ let wchk = GButton.check_button
+ ~label: param.bool_label
+ ()
+ in
+ let _ =
+ match param.bool_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (wchk#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wchk#coerce ~text: help ~privat: help
+ in
+ let _ = wchk#set_active param.bool_value in
+ let _ = wchk#misc#set_sensitive param.bool_editable in
+
+ object (self)
+ (** This method returns the check button ready to be packed. *)
+ method box = wchk#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = wchk#active in
+ if new_value <> param.bool_value then
+ let _ = param.bool_f_apply new_value in
+ param.bool_value <- new_value
+ else
+ ()
+ end ;;
+
+(** This class is used to build a box for a file name parameter.*)
+class filename_param_box param =
+ let hbox = GPack.hbox () in
+ let wb = GButton.button ~label: param.string_label
+ ~packing: (hbox#pack ~expand: false ~padding: 2) ()
+ in
+ let we = GEdit.entry
+ ~editable: param.string_editable
+ ~packing: (hbox#pack ~expand: param.string_expand ~padding: 2)
+ ()
+ in
+ let _ =
+ match param.string_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wb#coerce ~text: help ~privat: help
+ in
+ let _ = we#set_text param.string_value in
+
+ let f_click () =
+ match select_files param.string_label with
+ [] ->
+ ()
+ | f :: _ ->
+ we#set_text f
+ in
+ let _ =
+ if param.string_editable then
+ let _ = wb#connect#clicked f_click in
+ ()
+ else
+ ()
+ in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = we#text in
+ if new_value <> param.string_value then
+ let _ = param.string_f_apply new_value in
+ param.string_value <- new_value
+ else
+ ()
+ end ;;
+
+(** This class is used to build a box for a hot key parameter.*)
+class hotkey_param_box param =
+ let hbox = GPack.hbox () in
+ let wev = GBin.event_box ~packing: (hbox#pack ~expand: false ~padding: 2) () in
+ let wl = GMisc.label ~text: param.hk_label
+ ~packing: wev#add ()
+ in
+ let we = GEdit.entry
+ ~editable: false
+ ~packing: (hbox#pack ~expand: param.hk_expand ~padding: 2)
+ ()
+ in
+ let value = ref param.hk_value in
+ let _ =
+ match param.hk_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wev#coerce ~text: help ~privat: help
+ in
+ let _ = we#set_text (KeyOption.key_to_string param.hk_value) in
+ let mods_we_dont_care = [`MOD2 ; `MOD3 ; `MOD4 ; `MOD5 ; `LOCK] in
+ let capture ev =
+ let key = GdkEvent.Key.keyval ev in
+ let modifiers = GdkEvent.Key.state ev in
+ let mods = List.filter
+ (fun m -> not (List.mem m mods_we_dont_care))
+ modifiers
+ in
+ value := (mods, key);
+ we#set_text (KeyOption.key_to_string !value);
+ false
+ in
+ let _ =
+ if param.hk_editable then
+ ignore (we#event#connect#key_press capture)
+ else
+ ()
+ in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = !value in
+ if new_value <> param.hk_value then
+ let _ = param.hk_f_apply new_value in
+ param.hk_value <- new_value
+ else
+ ()
+ end ;;
+
+class modifiers_param_box param =
+ let hbox = GPack.hbox () in
+ let wev = GBin.event_box ~packing: (hbox#pack ~expand: false ~padding: 2) () in
+ let wl = GMisc.label ~text: param.md_label
+ ~packing: wev#add ()
+ in
+ let we = GEdit.entry
+ ~editable: false
+ ~packing: (hbox#pack ~expand: param.md_expand ~padding: 2)
+ ()
+ in
+ let value = ref param.md_value in
+ let _ =
+ match param.md_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wev#coerce ~text: help ~privat: help
+ in
+ let _ = we#set_text (KeyOption.modifiers_to_string param.md_value) in
+ let mods_we_care = param.md_allow in
+ let capture ev =
+ let modifiers = GdkEvent.Key.state ev in
+ let mods = List.filter
+ (fun m -> (List.mem m mods_we_care))
+ modifiers
+ in
+ value := mods;
+ we#set_text (KeyOption.modifiers_to_string !value);
+ false
+ in
+ let _ =
+ if param.md_editable then
+ ignore (we#event#connect#key_press capture)
+ else
+ ()
+ in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ let new_value = !value in
+ if new_value <> param.md_value then
+ let _ = param.md_f_apply new_value in
+ param.md_value <- new_value
+ else
+ ()
+ end ;;
+
+(** This class is used to build a box for a date parameter.*)
+class date_param_box param =
+ let v = ref param.date_value in
+ let hbox = GPack.hbox () in
+ let wb = GButton.button ~label: param.date_label
+ ~packing: (hbox#pack ~expand: false ~padding: 2) ()
+ in
+ let we = GEdit.entry
+ ~editable: false
+ ~packing: (hbox#pack ~expand: param.date_expand ~padding: 2)
+ ()
+ in
+ let _ =
+ match param.date_help with
+ None -> ()
+ | Some help ->
+ let tooltips = GData.tooltips () in
+ ignore (hbox#connect#destroy ~callback: tooltips#destroy);
+ tooltips#set_tip wb#coerce ~text: help ~privat: help
+ in
+ let _ = we#set_text (param.date_f_string param.date_value) in
+
+ let f_click () =
+ match select_date param.date_label !v with
+ None -> ()
+ | Some (y,m,d) ->
+ v := (d,m,y) ;
+ we#set_text (param.date_f_string (d,m,y))
+ in
+ let _ =
+ if param.date_editable then
+ let _ = wb#connect#clicked f_click in
+ ()
+ else
+ ()
+ in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = hbox#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ if !v <> param.date_value then
+ let _ = param.date_f_apply !v in
+ param.date_value <- !v
+ else
+ ()
+ end ;;
+
+(** This class is used to build a box for a parameter whose values are a list.*)
+class ['a] list_param_box (param : 'a list_param) =
+ let listref = ref param.list_value in
+ let frame_selection = new list_selection_box
+ listref
+ param.list_titles
+ param.list_help
+ param.list_f_edit
+ param.list_strings
+ param.list_color
+ param.list_eq
+ param.list_f_add param.list_label param.list_editable
+ in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = frame_selection#box#coerce
+ (** This method applies the new value of the parameter. *)
+ method apply =
+ param.list_f_apply !listref ;
+ param.list_value <- !listref
+ end ;;
+
+(** This class is used to build a box from a configuration structure
+ and adds the page to the given notebook. *)
+class configuration_box conf_struct (notebook : GPack.notebook) =
+ (* we build different widgets, according to the conf_struct parameter *)
+ let main_box = GPack.vbox () in
+ let (label, child_boxes) =
+ match conf_struct with
+ Section (label, param_list) ->
+ let f parameter =
+ match parameter with
+ String_param p ->
+ let box = new string_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Combo_param p ->
+ let box = new combo_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Text_param p ->
+ let box = new text_param_box p in
+ let _ = main_box#pack ~expand: p.string_expand ~padding: 2 box#box in
+ box
+ | Bool_param p ->
+ let box = new bool_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Filename_param p ->
+ let box = new filename_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | List_param f ->
+ let box = f () in
+ let _ = main_box#pack ~expand: true ~padding: 2 box#box in
+ box
+ | Custom_param p ->
+ let box = new custom_param_box p in
+ let _ = main_box#pack ~expand: p.custom_expand ~padding: 2 box#box in
+ box
+ | Color_param p ->
+ let box = new color_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Font_param p ->
+ let box = new font_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Date_param p ->
+ let box = new date_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Hotkey_param p ->
+ let box = new hotkey_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Modifiers_param p ->
+ let box = new modifiers_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Html_param p ->
+ let box = new html_param_box p in
+ let _ = main_box#pack ~expand: p.string_expand ~padding: 2 box#box in
+ box
+ in
+ let list_children_boxes = List.map f param_list in
+
+ (label, list_children_boxes)
+
+ | Section_list (label, struct_list) ->
+ let wnote = GPack.notebook
+ (*homogeneous_tabs: true*)
+ ~scrollable: true
+ ~show_tabs: true
+ ~tab_border: 3
+ ~packing: (main_box#pack ~expand: true)
+ ()
+ in
+ (* we create all the children boxes *)
+ let f structure =
+ let new_box = new configuration_box structure wnote in
+ new_box
+ in
+ let list_child_boxes = List.map f struct_list in
+ (label, list_child_boxes)
+
+ in
+ let page_label = GMisc.label ~text: label () in
+ let _ = notebook#append_page
+ ~tab_label: page_label#coerce
+ main_box#coerce
+ in
+
+ object (self)
+ (** This method returns the main box ready to be packed. *)
+ method box = main_box#coerce
+ (** This method make the new values of the paramters applied, recursively in
+ all boxes.*)
+ method apply =
+ List.iter (fun box -> box#apply) child_boxes
+ end
+;;
+
+(** Create a vbox with the list of given configuration structure list,
+ and the given list of buttons (defined by their label and callback).
+ Before calling the callback of a button, the [apply] function
+ of each parameter is called.
+*)
+let tabbed_box conf_struct_list buttons =
+ let vbox = GPack.vbox () in
+ let wnote = GPack.notebook
+ (*homogeneous_tabs: true*)
+ ~scrollable: true
+ ~show_tabs: true
+ ~tab_border: 3
+ ~packing: (vbox#pack ~expand: true)
+ ()
+ in
+ let list_param_box =
+ List.map (fun conf_struct -> new configuration_box conf_struct wnote)
+ conf_struct_list
+ in
+ let f_apply () =
+ List.iter (fun param_box -> param_box#apply) list_param_box ;
+ in
+ let hbox_buttons = GPack.hbox ~packing: (vbox#pack ~expand: false ~padding: 4) () in
+ let rec iter_buttons ?(grab=false) = function
+ [] ->
+ ()
+ | (label, callb) :: q ->
+ let b = GButton.button ~label: label
+ ~packing:(hbox_buttons#pack ~expand:true ~fill: true ~padding:4) ()
+ in
+ ignore (b#connect#clicked ~callback:
+ (fun () -> f_apply (); callb ()));
+ (* If it's the first button then give it the focus *)
+ if grab then b#grab_default ();
+
+ iter_buttons q
+ in
+ iter_buttons ~grab: true buttons;
+
+ vbox
+
+(** This function takes a configuration structure list and creates a window
+ to configure the various parameters. *)
+let edit ?(with_apply=true)
+ ?(apply=(fun () -> ()))
+ title ?(width=400) ?(height=400)
+ conf_struct_list =
+ let return = ref Return_cancel in
+ let window = GWindow.window
+ ~position:`CENTER
+ ~modal: true ~title: title
+ ~width: width ~height: height ()
+ in
+ let _ = window#connect#destroy ~callback: GMain.Main.quit in
+ let vbox = GPack.vbox ~packing: window#add () in
+ let wnote = GPack.notebook
+ (*homogeneous_tabs: true*)
+ ~scrollable: true
+ ~show_tabs: true
+ ~tab_border: 3
+ ~packing: (vbox#pack ~expand: true)
+ ()
+ in
+ let list_param_box =
+ List.map (fun conf_struct -> new configuration_box conf_struct wnote)
+ conf_struct_list
+ in
+
+ let hbox_buttons = GPack.hbox ~packing: (vbox#pack ~expand: false ~padding: 4) () in
+ let bApply = GButton.button
+ ~stock:`APPLY
+ ~label: Configwin_messages.mApply
+ ()
+ in
+ if with_apply then hbox_buttons#pack ~expand: true ~padding: 3 bApply#coerce;
+ let bOk = GButton.button
+ ~stock:`OK
+ ~label: Configwin_messages.mOk
+ ~packing: (hbox_buttons#pack ~expand: true ~padding: 3)
+ ()
+ in
+ let bCancel = GButton.button
+ ~stock:`CANCEL
+ ~label: Configwin_messages.mCancel
+ ~packing: (hbox_buttons#pack ~expand: true ~padding: 3)
+ ()
+ in
+ (* we connect the click on the apply button *)
+ let f_apply () =
+ List.iter (fun param_box -> param_box#apply) list_param_box ;
+ apply ();
+ return := Return_apply
+ in
+ let _ = bApply#connect#clicked f_apply in
+ (* we connect the click on the ok button : the same than apply but we then close the window *)
+ let f_ok () =
+ List.iter (fun param_box -> param_box#apply) list_param_box ;
+ return := Return_ok ;
+ window#destroy ()
+ in
+ let _ = bOk#connect#clicked f_ok in
+ (* we connect the click on the cancel button : close the window *)
+ let f_cancel () = window#destroy () in
+ let _ = bCancel#connect#clicked f_cancel in
+
+ let _ = window#event#connect#key_press ~callback:
+ (fun k -> if GdkEvent.Key.keyval k = GdkKeysyms._Escape then f_cancel ();false)
+ in
+ let _ = window#show () in
+ GMain.Main.main () ;
+ !return
+
+
+(** Create a vbox with the list of given parameters,
+ and the given list of buttons (defined by their label and callback).
+ Before calling the callback of a button, the [apply] function
+ of each parameter is called.
+*)
+let box param_list buttons =
+ let main_box = GPack.vbox () in
+ let f parameter =
+ match parameter with
+ String_param p ->
+ let box = new string_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Combo_param p ->
+ let box = new combo_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Text_param p ->
+ let box = new text_param_box p in
+ let _ = main_box#pack ~expand: p.string_expand ~padding: 2 box#box in
+ box
+ | Bool_param p ->
+ let box = new bool_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Filename_param p ->
+ let box = new filename_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | List_param f ->
+ let box = f () in
+ let _ = main_box#pack ~expand: true ~padding: 2 box#box in
+ box
+ | Custom_param p ->
+ let box = new custom_param_box p in
+ let _ = main_box#pack ~expand: p.custom_expand ~padding: 2 box#box in
+ box
+ | Color_param p ->
+ let box = new color_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Font_param p ->
+ let box = new font_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Date_param p ->
+ let box = new date_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Hotkey_param p ->
+ let box = new hotkey_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Modifiers_param p ->
+ let box = new modifiers_param_box p in
+ let _ = main_box#pack ~expand: false ~padding: 2 box#box in
+ box
+ | Html_param p ->
+ let box = new html_param_box p in
+ let _ = main_box#pack ~expand: p.string_expand ~padding: 2 box#box in
+ box
+ in
+ let list_param_box = List.map f param_list in
+ let f_apply () =
+ List.iter (fun param_box -> param_box#apply) list_param_box
+ in
+ let hbox_buttons = GPack.hbox ~packing: (main_box#pack ~expand: false ~padding: 4) () in
+ let rec iter_buttons ?(grab=false) = function
+ [] ->
+ ()
+ | (label, callb) :: q ->
+ let b = GButton.button ~label: label
+ ~packing:(hbox_buttons#pack ~expand:true ~fill: true ~padding:4) ()
+ in
+ ignore (b#connect#clicked ~callback:
+ (fun () -> f_apply (); callb ()));
+ (* If it's the first button then give it the focus *)
+ if grab then b#grab_default ();
+
+ iter_buttons q
+ in
+ iter_buttons ~grab: true buttons;
+
+ main_box
+
+
+(** This function takes a list of parameter specifications and
+ creates a window to configure the various parameters.*)
+let simple_edit ?(with_apply=true)
+ ?(apply=(fun () -> ()))
+ title ?width ?height
+ param_list =
+ let return = ref Return_cancel in
+ let window = GWindow.window ~modal: true ~title: title () in
+ let _ = match width, height with
+ None, None -> ()
+ | Some w, None -> window#misc#set_size_request ~width: w ()
+ | None, Some h -> window#misc#set_size_request ~height: h ()
+ | Some w, Some h -> window#misc#set_size_request ~width: w ~height: h ()
+ in
+ let _ = window#connect#destroy ~callback: GMain.Main.quit in
+ let buttons =
+ (if with_apply then
+ [Configwin_messages.mApply, fun () -> apply (); return := Return_apply]
+ else
+ []
+ ) @ [
+ (Configwin_messages.mOk, fun () -> return := Return_ok ; window#destroy ()) ;
+ (Configwin_messages.mCancel, window#destroy) ;
+ ]
+ in
+ let box = box param_list buttons in
+ window#add box#coerce;
+ let _ = window#show () in
+ GMain.Main.main () ;
+ !return
+
+let edit_string l s =
+ match GToolbox.input_string ~title: l ~text: s Configwin_messages.mValue with
+ None -> s
+ | Some s2 -> s2
+
+(** Create a string param. *)
+let string ?(editable=true) ?(expand=true) ?help ?(f=(fun _ -> ())) label v =
+ String_param
+ {
+ string_label = label ;
+ string_help = help ;
+ string_value = v ;
+ string_editable = editable ;
+ string_f_apply = f ;
+ string_expand = expand ;
+ }
+
+(** Create a bool param. *)
+let bool ?(editable=true) ?help ?(f=(fun _ -> ())) label v =
+ Bool_param
+ {
+ bool_label = label ;
+ bool_help = help ;
+ bool_value = v ;
+ bool_editable = editable ;
+ bool_f_apply = f ;
+ }
+
+(** Create a list param. *)
+let list ?(editable=true) ?help
+ ?(f=(fun (_:'a list) -> ()))
+ ?(eq=Pervasives.(=))
+ ?(edit:('a -> 'a) option)
+ ?(add=(fun () -> ([] : 'a list)))
+ ?titles ?(color=(fun (_:'a) -> (None : string option)))
+ label (f_strings : 'a -> string list) v =
+ List_param
+ (fun () ->
+ Obj.magic
+ (new list_param_box
+ {
+ list_label = label ;
+ list_help = help ;
+ list_value = v ;
+ list_editable = editable ;
+ list_titles = titles;
+ list_eq = eq ;
+ list_strings = f_strings ;
+ list_color = color ;
+ list_f_edit = edit ;
+ list_f_add = add ;
+ list_f_apply = f ;
+ }
+ )
+ )
+
+(** Create a strings param. *)
+let strings ?(editable=true) ?help
+ ?(f=(fun _ -> ()))
+ ?(eq=Pervasives.(=))
+ ?(add=(fun () -> [])) label v =
+ list ~editable ?help ~f ~eq ~edit: (edit_string label) ~add label (fun s -> [s]) v
+
+(** Create a color param. *)
+let color ?(editable=true) ?(expand=true) ?help ?(f=(fun _ -> ())) label v =
+ Color_param
+ {
+ color_label = label ;
+ color_help = help ;
+ color_value = v ;
+ color_editable = editable ;
+ color_f_apply = f ;
+ color_expand = expand ;
+ }
+
+(** Create a font param. *)
+let font ?(editable=true) ?(expand=true) ?help ?(f=(fun _ -> ())) label v =
+ Font_param
+ {
+ font_label = label ;
+ font_help = help ;
+ font_value = v ;
+ font_editable = editable ;
+ font_f_apply = f ;
+ font_expand = expand ;
+ }
+
+(** Create a combo param. *)
+let combo ?(editable=true) ?(expand=true) ?help ?(f=(fun _ -> ()))
+ ?(new_allowed=false)
+ ?(blank_allowed=false) label choices v =
+ Combo_param
+ {
+ combo_label = label ;
+ combo_help = help ;
+ combo_value = v ;
+ combo_editable = editable ;
+ combo_choices = choices ;
+ combo_new_allowed = new_allowed ;
+ combo_blank_allowed = blank_allowed ;
+ combo_f_apply = f ;
+ combo_expand = expand ;
+ }
+
+(** Create a text param. *)
+let text ?(editable=true) ?(expand=true) ?help ?(f=(fun _ -> ())) label v =
+ Text_param
+ {
+ string_label = label ;
+ string_help = help ;
+ string_value = v ;
+ string_editable = editable ;
+ string_f_apply = f ;
+ string_expand = expand ;
+ }
+
+(** Create a html param. *)
+let html ?(editable=true) ?(expand=true) ?help ?(f=(fun _ -> ())) label v =
+ Html_param
+ {
+ string_label = label ;
+ string_help = help ;
+ string_value = v ;
+ string_editable = editable ;
+ string_f_apply = f ;
+ string_expand = expand ;
+ }
+
+(** Create a filename param. *)
+let filename ?(editable=true) ?(expand=true)?help ?(f=(fun _ -> ())) label v =
+ Filename_param
+ {
+ string_label = label ;
+ string_help = help ;
+ string_value = v ;
+ string_editable = editable ;
+ string_f_apply = f ;
+ string_expand = expand ;
+ }
+
+(** Create a filenames param.*)
+let filenames ?(editable=true) ?help ?(f=(fun _ -> ()))
+ ?(eq=Pervasives.(=))
+ label v =
+ let add () = select_files label in
+ list ~editable ?help ~f ~eq ~add label (fun s -> [s]) v
+
+(** Create a date param. *)
+let date ?(editable=true) ?(expand=true) ?help ?(f=(fun _ -> ()))
+ ?(f_string=(fun(d,m,y)-> Printf.sprintf "%d/%d/%d" y (m+1) d))
+ label v =
+ Date_param
+ {
+ date_label = label ;
+ date_help = help ;
+ date_value = v ;
+ date_editable = editable ;
+ date_f_string = f_string ;
+ date_f_apply = f ;
+ date_expand = expand ;
+ }
+
+(** Create a hot key param. *)
+let hotkey ?(editable=true) ?(expand=true) ?help ?(f=(fun _ -> ())) label v =
+ Hotkey_param
+ {
+ hk_label = label ;
+ hk_help = help ;
+ hk_value = v ;
+ hk_editable = editable ;
+ hk_f_apply = f ;
+ hk_expand = expand ;
+ }
+
+let modifiers
+ ?(editable=true)
+ ?(expand=true)
+ ?help
+ ?(allow=[`CONTROL;`SHIFT;`LOCK;`MOD1;`MOD1;`MOD2;`MOD3;`MOD4;`MOD5])
+ ?(f=(fun _ -> ())) label v =
+ Modifiers_param
+ {
+ md_label = label ;
+ md_help = help ;
+ md_value = v ;
+ md_editable = editable ;
+ md_f_apply = f ;
+ md_expand = expand ;
+ md_allow = allow ;
+ }
+
+(** Create a custom param.*)
+let custom ?label box f expand =
+ Custom_param
+ {
+ custom_box = box ;
+ custom_f_apply = f ;
+ custom_expand = expand ;
+ custom_framed = label ;
+ }
diff --git a/ide/utils/configwin_keys.ml b/ide/utils/configwin_keys.ml
new file mode 100644
index 00000000..9c867845
--- /dev/null
+++ b/ide/utils/configwin_keys.ml
@@ -0,0 +1,4175 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(** Key codes
+
+ Ce fichier provient de X11/keysymdef.h
+ les noms des symboles deviennent : XK_ -> xk_
+
+ Thanks to Fabrice Le Fessant.
+*)
+
+let xk_VoidSymbol = 0xFFFFFF (** void symbol *)
+
+
+(** TTY Functions, cleverly chosen to map to ascii, for convenience of
+ programming, but could have been arbitrary (at the cost of lookup
+ tables in client code.
+*)
+
+let xk_BackSpace = 0xFF08 (** back space, back char *)
+let xk_Tab = 0xFF09
+let xk_Linefeed = 0xFF0A (** Linefeed, LF *)
+let xk_Clear = 0xFF0B
+let xk_Return = 0xFF0D (** Return, enter *)
+let xk_Pause = 0xFF13 (** Pause, hold *)
+let xk_Scroll_Lock = 0xFF14
+let xk_Sys_Req = 0xFF15
+let xk_Escape = 0xFF1B
+let xk_Delete = 0xFFFF (** Delete, rubout *)
+
+
+
+(** International & multi-key character composition *)
+
+let xk_Multi_key = 0xFF20 (** Multi-key character compose *)
+
+(** Japanese keyboard support *)
+
+let xk_Kanji = 0xFF21 (** Kanji, Kanji convert *)
+let xk_Muhenkan = 0xFF22 (** Cancel Conversion *)
+let xk_Henkan_Mode = 0xFF23 (** Start/Stop Conversion *)
+let xk_Henkan = 0xFF23 (** Alias for Henkan_Mode *)
+let xk_Romaji = 0xFF24 (** to Romaji *)
+let xk_Hiragana = 0xFF25 (** to Hiragana *)
+let xk_Katakana = 0xFF26 (** to Katakana *)
+let xk_Hiragana_Katakana = 0xFF27 (** Hiragana/Katakana toggle *)
+let xk_Zenkaku = 0xFF28 (** to Zenkaku *)
+let xk_Hankaku = 0xFF29 (** to Hankaku *)
+let xk_Zenkaku_Hankaku = 0xFF2A (** Zenkaku/Hankaku toggle *)
+let xk_Touroku = 0xFF2B (** Add to Dictionary *)
+let xk_Massyo = 0xFF2C (** Delete from Dictionary *)
+let xk_Kana_Lock = 0xFF2D (** Kana Lock *)
+let xk_Kana_Shift = 0xFF2E (** Kana Shift *)
+let xk_Eisu_Shift = 0xFF2F (** Alphanumeric Shift *)
+let xk_Eisu_toggle = 0xFF30 (** Alphanumeric toggle *)
+
+(** = 0xFF31 thru = 0xFF3F are under xk_KOREAN *)
+
+(** Cursor control & motion *)
+
+let xk_Home = 0xFF50
+let xk_Left = 0xFF51 (** Move left, left arrow *)
+let xk_Up = 0xFF52 (** Move up, up arrow *)
+let xk_Right = 0xFF53 (** Move right, right arrow *)
+let xk_Down = 0xFF54 (** Move down, down arrow *)
+let xk_Prior = 0xFF55 (** Prior, previous *)
+let xk_Page_Up = 0xFF55
+let xk_Next = 0xFF56 (** Next *)
+let xk_Page_Down = 0xFF56
+let xk_End = 0xFF57 (** EOL *)
+let xk_Begin = 0xFF58 (** BOL *)
+
+
+(** Misc Functions *)
+
+let xk_Select = 0xFF60 (** Select, mark *)
+let xk_Print = 0xFF61
+let xk_Execute = 0xFF62 (** Execute, run, do *)
+let xk_Insert = 0xFF63 (** Insert, insert here *)
+let xk_Undo = 0xFF65 (** Undo, oops *)
+let xk_Redo = 0xFF66 (** redo, again *)
+let xk_Menu = 0xFF67
+let xk_Find = 0xFF68 (** Find, search *)
+let xk_Cancel = 0xFF69 (** Cancel, stop, abort, exit *)
+let xk_Help = 0xFF6A (** Help *)
+let xk_Break = 0xFF6B
+let xk_Mode_switch = 0xFF7E (** Character set switch *)
+let xk_script_switch = 0xFF7E (** Alias for mode_switch *)
+let xk_Num_Lock = 0xFF7F
+
+(** Keypad Functions, keypad numbers cleverly chosen to map to ascii *)
+
+let xk_KP_Space = 0xFF80 (** space *)
+let xk_KP_Tab = 0xFF89
+let xk_KP_Enter = 0xFF8D (** enter *)
+let xk_KP_F1 = 0xFF91 (** PF1, KP_A, ... *)
+let xk_KP_F2 = 0xFF92
+let xk_KP_F3 = 0xFF93
+let xk_KP_F4 = 0xFF94
+let xk_KP_Home = 0xFF95
+let xk_KP_Left = 0xFF96
+let xk_KP_Up = 0xFF97
+let xk_KP_Right = 0xFF98
+let xk_KP_Down = 0xFF99
+let xk_KP_Prior = 0xFF9A
+let xk_KP_Page_Up = 0xFF9A
+let xk_KP_Next = 0xFF9B
+let xk_KP_Page_Down = 0xFF9B
+let xk_KP_End = 0xFF9C
+let xk_KP_Begin = 0xFF9D
+let xk_KP_Insert = 0xFF9E
+let xk_KP_Delete = 0xFF9F
+let xk_KP_Equal = 0xFFBD (** equals *)
+let xk_KP_Multiply = 0xFFAA
+let xk_KP_Add = 0xFFAB
+let xk_KP_Separator = 0xFFAC (** separator, often comma *)
+let xk_KP_Subtract = 0xFFAD
+let xk_KP_Decimal = 0xFFAE
+let xk_KP_Divide = 0xFFAF
+
+let xk_KP_0 = 0xFFB0
+let xk_KP_1 = 0xFFB1
+let xk_KP_2 = 0xFFB2
+let xk_KP_3 = 0xFFB3
+let xk_KP_4 = 0xFFB4
+let xk_KP_5 = 0xFFB5
+let xk_KP_6 = 0xFFB6
+let xk_KP_7 = 0xFFB7
+let xk_KP_8 = 0xFFB8
+let xk_KP_9 = 0xFFB9
+
+
+
+(*
+ * Auxilliary Functions; note the duplicate definitions for left and right
+ * function keys; Sun keyboards and a few other manufactures have such
+ * function key groups on the left and/or right sides of the keyboard.
+ * We've not found a keyboard with more than 35 function keys total.
+ *)
+
+let xk_F1 = 0xFFBE
+let xk_F2 = 0xFFBF
+let xk_F3 = 0xFFC0
+let xk_F4 = 0xFFC1
+let xk_F5 = 0xFFC2
+let xk_F6 = 0xFFC3
+let xk_F7 = 0xFFC4
+let xk_F8 = 0xFFC5
+let xk_F9 = 0xFFC6
+let xk_F10 = 0xFFC7
+let xk_F11 = 0xFFC8
+let xk_L1 = 0xFFC8
+let xk_F12 = 0xFFC9
+let xk_L2 = 0xFFC9
+let xk_F13 = 0xFFCA
+let xk_L3 = 0xFFCA
+let xk_F14 = 0xFFCB
+let xk_L4 = 0xFFCB
+let xk_F15 = 0xFFCC
+let xk_L5 = 0xFFCC
+let xk_F16 = 0xFFCD
+let xk_L6 = 0xFFCD
+let xk_F17 = 0xFFCE
+let xk_L7 = 0xFFCE
+let xk_F18 = 0xFFCF
+let xk_L8 = 0xFFCF
+let xk_F19 = 0xFFD0
+let xk_L9 = 0xFFD0
+let xk_F20 = 0xFFD1
+let xk_L10 = 0xFFD1
+let xk_F21 = 0xFFD2
+let xk_R1 = 0xFFD2
+let xk_F22 = 0xFFD3
+let xk_R2 = 0xFFD3
+let xk_F23 = 0xFFD4
+let xk_R3 = 0xFFD4
+let xk_F24 = 0xFFD5
+let xk_R4 = 0xFFD5
+let xk_F25 = 0xFFD6
+let xk_R5 = 0xFFD6
+let xk_F26 = 0xFFD7
+let xk_R6 = 0xFFD7
+let xk_F27 = 0xFFD8
+let xk_R7 = 0xFFD8
+let xk_F28 = 0xFFD9
+let xk_R8 = 0xFFD9
+let xk_F29 = 0xFFDA
+let xk_R9 = 0xFFDA
+let xk_F30 = 0xFFDB
+let xk_R10 = 0xFFDB
+let xk_F31 = 0xFFDC
+let xk_R11 = 0xFFDC
+let xk_F32 = 0xFFDD
+let xk_R12 = 0xFFDD
+let xk_F33 = 0xFFDE
+let xk_R13 = 0xFFDE
+let xk_F34 = 0xFFDF
+let xk_R14 = 0xFFDF
+let xk_F35 = 0xFFE0
+let xk_R15 = 0xFFE0
+
+(** Modifiers *)
+
+let xk_Shift_L = 0xFFE1 (** Left shift *)
+let xk_Shift_R = 0xFFE2 (** Right shift *)
+let xk_Control_L = 0xFFE3 (** Left control *)
+let xk_Control_R = 0xFFE4 (** Right control *)
+let xk_Caps_Lock = 0xFFE5 (** Caps lock *)
+let xk_Shift_Lock = 0xFFE6 (** Shift lock *)
+
+let xk_Meta_L = 0xFFE7 (** Left meta *)
+let xk_Meta_R = 0xFFE8 (** Right meta *)
+let xk_Alt_L = 0xFFE9 (** Left alt *)
+let xk_Alt_R = 0xFFEA (** Right alt *)
+let xk_Super_L = 0xFFEB (** Left super *)
+let xk_Super_R = 0xFFEC (** Right super *)
+let xk_Hyper_L = 0xFFED (** Left hyper *)
+let xk_Hyper_R = 0xFFEE (** Right hyper *)
+
+
+(*
+ * ISO 9995 Function and Modifier Keys
+ * Byte 3 = = 0xFE
+ *)
+
+
+let xk_ISO_Lock = 0xFE01
+let xk_ISO_Level2_Latch = 0xFE02
+let xk_ISO_Level3_Shift = 0xFE03
+let xk_ISO_Level3_Latch = 0xFE04
+let xk_ISO_Level3_Lock = 0xFE05
+let xk_ISO_Group_Shift = 0xFF7E (** Alias for mode_switch *)
+let xk_ISO_Group_Latch = 0xFE06
+let xk_ISO_Group_Lock = 0xFE07
+let xk_ISO_Next_Group = 0xFE08
+let xk_ISO_Next_Group_Lock = 0xFE09
+let xk_ISO_Prev_Group = 0xFE0A
+let xk_ISO_Prev_Group_Lock = 0xFE0B
+let xk_ISO_First_Group = 0xFE0C
+let xk_ISO_First_Group_Lock = 0xFE0D
+let xk_ISO_Last_Group = 0xFE0E
+let xk_ISO_Last_Group_Lock = 0xFE0F
+
+let xk_ISO_Left_Tab = 0xFE20
+let xk_ISO_Move_Line_Up = 0xFE21
+let xk_ISO_Move_Line_Down = 0xFE22
+let xk_ISO_Partial_Line_Up = 0xFE23
+let xk_ISO_Partial_Line_Down = 0xFE24
+let xk_ISO_Partial_Space_Left = 0xFE25
+let xk_ISO_Partial_Space_Right = 0xFE26
+let xk_ISO_Set_Margin_Left = 0xFE27
+let xk_ISO_Set_Margin_Right = 0xFE28
+let xk_ISO_Release_Margin_Left = 0xFE29
+let xk_ISO_Release_Margin_Right = 0xFE2A
+let xk_ISO_Release_Both_Margins = 0xFE2B
+let xk_ISO_Fast_Cursor_Left = 0xFE2C
+let xk_ISO_Fast_Cursor_Right = 0xFE2D
+let xk_ISO_Fast_Cursor_Up = 0xFE2E
+let xk_ISO_Fast_Cursor_Down = 0xFE2F
+let xk_ISO_Continuous_Underline = 0xFE30
+let xk_ISO_Discontinuous_Underline = 0xFE31
+let xk_ISO_Emphasize = 0xFE32
+let xk_ISO_Center_Object = 0xFE33
+let xk_ISO_Enter = 0xFE34
+
+let xk_dead_grave = 0xFE50
+let xk_dead_acute = 0xFE51
+let xk_dead_circumflex = 0xFE52
+let xk_dead_tilde = 0xFE53
+let xk_dead_macron = 0xFE54
+let xk_dead_breve = 0xFE55
+let xk_dead_abovedot = 0xFE56
+let xk_dead_diaeresis = 0xFE57
+let xk_dead_abovering = 0xFE58
+let xk_dead_doubleacute = 0xFE59
+let xk_dead_caron = 0xFE5A
+let xk_dead_cedilla = 0xFE5B
+let xk_dead_ogonek = 0xFE5C
+let xk_dead_iota = 0xFE5D
+let xk_dead_voiced_sound = 0xFE5E
+let xk_dead_semivoiced_sound = 0xFE5F
+let xk_dead_belowdot = 0xFE60
+
+let xk_First_Virtual_Screen = 0xFED0
+let xk_Prev_Virtual_Screen = 0xFED1
+let xk_Next_Virtual_Screen = 0xFED2
+let xk_Last_Virtual_Screen = 0xFED4
+let xk_Terminate_Server = 0xFED5
+
+let xk_AccessX_Enable = 0xFE70
+let xk_AccessX_Feedback_Enable = 0xFE71
+let xk_RepeatKeys_Enable = 0xFE72
+let xk_SlowKeys_Enable = 0xFE73
+let xk_BounceKeys_Enable = 0xFE74
+let xk_StickyKeys_Enable = 0xFE75
+let xk_MouseKeys_Enable = 0xFE76
+let xk_MouseKeys_Accel_Enable = 0xFE77
+let xk_Overlay1_Enable = 0xFE78
+let xk_Overlay2_Enable = 0xFE79
+let xk_AudibleBell_Enable = 0xFE7A
+
+let xk_Pointer_Left = 0xFEE0
+let xk_Pointer_Right = 0xFEE1
+let xk_Pointer_Up = 0xFEE2
+let xk_Pointer_Down = 0xFEE3
+let xk_Pointer_UpLeft = 0xFEE4
+let xk_Pointer_UpRight = 0xFEE5
+let xk_Pointer_DownLeft = 0xFEE6
+let xk_Pointer_DownRight = 0xFEE7
+let xk_Pointer_Button_Dflt = 0xFEE8
+let xk_Pointer_Button1 = 0xFEE9
+let xk_Pointer_Button2 = 0xFEEA
+let xk_Pointer_Button3 = 0xFEEB
+let xk_Pointer_Button4 = 0xFEEC
+let xk_Pointer_Button5 = 0xFEED
+let xk_Pointer_DblClick_Dflt = 0xFEEE
+let xk_Pointer_DblClick1 = 0xFEEF
+let xk_Pointer_DblClick2 = 0xFEF0
+let xk_Pointer_DblClick3 = 0xFEF1
+let xk_Pointer_DblClick4 = 0xFEF2
+let xk_Pointer_DblClick5 = 0xFEF3
+let xk_Pointer_Drag_Dflt = 0xFEF4
+let xk_Pointer_Drag1 = 0xFEF5
+let xk_Pointer_Drag2 = 0xFEF6
+let xk_Pointer_Drag3 = 0xFEF7
+let xk_Pointer_Drag4 = 0xFEF8
+let xk_Pointer_Drag5 = 0xFEFD
+
+let xk_Pointer_EnableKeys = 0xFEF9
+let xk_Pointer_Accelerate = 0xFEFA
+let xk_Pointer_DfltBtnNext = 0xFEFB
+let xk_Pointer_DfltBtnPrev = 0xFEFC
+
+
+
+(*
+ * 3270 Terminal Keys
+ * Byte 3 = = 0xFD
+ *)
+
+
+let xk_3270_Duplicate = 0xFD01
+let xk_3270_FieldMark = 0xFD02
+let xk_3270_Right2 = 0xFD03
+let xk_3270_Left2 = 0xFD04
+let xk_3270_BackTab = 0xFD05
+let xk_3270_EraseEOF = 0xFD06
+let xk_3270_EraseInput = 0xFD07
+let xk_3270_Reset = 0xFD08
+let xk_3270_Quit = 0xFD09
+let xk_3270_PA1 = 0xFD0A
+let xk_3270_PA2 = 0xFD0B
+let xk_3270_PA3 = 0xFD0C
+let xk_3270_Test = 0xFD0D
+let xk_3270_Attn = 0xFD0E
+let xk_3270_CursorBlink = 0xFD0F
+let xk_3270_AltCursor = 0xFD10
+let xk_3270_KeyClick = 0xFD11
+let xk_3270_Jump = 0xFD12
+let xk_3270_Ident = 0xFD13
+let xk_3270_Rule = 0xFD14
+let xk_3270_Copy = 0xFD15
+let xk_3270_Play = 0xFD16
+let xk_3270_Setup = 0xFD17
+let xk_3270_Record = 0xFD18
+let xk_3270_ChangeScreen = 0xFD19
+let xk_3270_DeleteWord = 0xFD1A
+let xk_3270_ExSelect = 0xFD1B
+let xk_3270_CursorSelect = 0xFD1C
+let xk_3270_PrintScreen = 0xFD1D
+let xk_3270_Enter = 0xFD1E
+
+
+(*
+ * Latin 1
+ * Byte 3 = 0
+ *)
+
+let xk_space = 0x020
+let xk_exclam = 0x021
+let xk_quotedbl = 0x022
+let xk_numbersign = 0x023
+let xk_dollar = 0x024
+let xk_percent = 0x025
+let xk_ampersand = 0x026
+let xk_apostrophe = 0x027
+let xk_quoteright = 0x027 (** deprecated *)
+let xk_parenleft = 0x028
+let xk_parenright = 0x029
+let xk_asterisk = 0x02a
+let xk_plus = 0x02b
+let xk_comma = 0x02c
+let xk_minus = 0x02d
+let xk_period = 0x02e
+let xk_slash = 0x02f
+let xk_0 = 0x030
+let xk_1 = 0x031
+let xk_2 = 0x032
+let xk_3 = 0x033
+let xk_4 = 0x034
+let xk_5 = 0x035
+let xk_6 = 0x036
+let xk_7 = 0x037
+let xk_8 = 0x038
+let xk_9 = 0x039
+let xk_colon = 0x03a
+let xk_semicolon = 0x03b
+let xk_less = 0x03c
+let xk_equal = 0x03d
+let xk_greater = 0x03e
+let xk_question = 0x03f
+let xk_at = 0x040
+let xk_A = 0x041
+let xk_B = 0x042
+let xk_C = 0x043
+let xk_D = 0x044
+let xk_E = 0x045
+let xk_F = 0x046
+let xk_G = 0x047
+let xk_H = 0x048
+let xk_I = 0x049
+let xk_J = 0x04a
+let xk_K = 0x04b
+let xk_L = 0x04c
+let xk_M = 0x04d
+let xk_N = 0x04e
+let xk_O = 0x04f
+let xk_P = 0x050
+let xk_Q = 0x051
+let xk_R = 0x052
+let xk_S = 0x053
+let xk_T = 0x054
+let xk_U = 0x055
+let xk_V = 0x056
+let xk_W = 0x057
+let xk_X = 0x058
+let xk_Y = 0x059
+let xk_Z = 0x05a
+let xk_bracketleft = 0x05b
+let xk_backslash = 0x05c
+let xk_bracketright = 0x05d
+let xk_asciicircum = 0x05e
+let xk_underscore = 0x05f
+let xk_grave = 0x060
+let xk_quoteleft = 0x060 (** deprecated *)
+let xk_a = 0x061
+let xk_b = 0x062
+let xk_c = 0x063
+let xk_d = 0x064
+let xk_e = 0x065
+let xk_f = 0x066
+let xk_g = 0x067
+let xk_h = 0x068
+let xk_i = 0x069
+let xk_j = 0x06a
+let xk_k = 0x06b
+let xk_l = 0x06c
+let xk_m = 0x06d
+let xk_n = 0x06e
+let xk_o = 0x06f
+let xk_p = 0x070
+let xk_q = 0x071
+let xk_r = 0x072
+let xk_s = 0x073
+let xk_t = 0x074
+let xk_u = 0x075
+let xk_v = 0x076
+let xk_w = 0x077
+let xk_x = 0x078
+let xk_y = 0x079
+let xk_z = 0x07a
+let xk_braceleft = 0x07b
+let xk_bar = 0x07c
+let xk_braceright = 0x07d
+let xk_asciitilde = 0x07e
+
+let xk_nobreakspace = 0x0a0
+let xk_exclamdown = 0x0a1
+let xk_cent = 0x0a2
+let xk_sterling = 0x0a3
+let xk_currency = 0x0a4
+let xk_yen = 0x0a5
+let xk_brokenbar = 0x0a6
+let xk_section = 0x0a7
+let xk_diaeresis = 0x0a8
+let xk_copyright = 0x0a9
+let xk_ordfeminine = 0x0aa
+let xk_guillemotleft = 0x0ab (** left angle quotation mark *)
+let xk_notsign = 0x0ac
+let xk_hyphen = 0x0ad
+let xk_registered = 0x0ae
+let xk_macron = 0x0af
+let xk_degree = 0x0b0
+let xk_plusminus = 0x0b1
+let xk_twosuperior = 0x0b2
+let xk_threesuperior = 0x0b3
+let xk_acute = 0x0b4
+let xk_mu = 0x0b5
+let xk_paragraph = 0x0b6
+let xk_periodcentered = 0x0b7
+let xk_cedilla = 0x0b8
+let xk_onesuperior = 0x0b9
+let xk_masculine = 0x0ba
+let xk_guillemotright = 0x0bb (** right angle quotation mark *)
+let xk_onequarter = 0x0bc
+let xk_onehalf = 0x0bd
+let xk_threequarters = 0x0be
+let xk_questiondown = 0x0bf
+let xk_Agrave = 0x0c0
+let xk_Aacute = 0x0c1
+let xk_Acircumflex = 0x0c2
+let xk_Atilde = 0x0c3
+let xk_Adiaeresis = 0x0c4
+let xk_Aring = 0x0c5
+let xk_AE = 0x0c6
+let xk_Ccedilla = 0x0c7
+let xk_Egrave = 0x0c8
+let xk_Eacute = 0x0c9
+let xk_Ecircumflex = 0x0ca
+let xk_Ediaeresis = 0x0cb
+let xk_Igrave = 0x0cc
+let xk_Iacute = 0x0cd
+let xk_Icircumflex = 0x0ce
+let xk_Idiaeresis = 0x0cf
+let xk_ETH = 0x0d0
+let xk_Eth = 0x0d0 (** deprecated *)
+let xk_Ntilde = 0x0d1
+let xk_Ograve = 0x0d2
+let xk_Oacute = 0x0d3
+let xk_Ocircumflex = 0x0d4
+let xk_Otilde = 0x0d5
+let xk_Odiaeresis = 0x0d6
+let xk_multiply = 0x0d7
+let xk_Ooblique = 0x0d8
+let xk_Ugrave = 0x0d9
+let xk_Uacute = 0x0da
+let xk_Ucircumflex = 0x0db
+let xk_Udiaeresis = 0x0dc
+let xk_Yacute = 0x0dd
+let xk_THORN = 0x0de
+let xk_Thorn = 0x0de (** deprecated *)
+let xk_ssharp = 0x0df
+let xk_agrave = 0x0e0
+let xk_aacute = 0x0e1
+let xk_acircumflex = 0x0e2
+let xk_atilde = 0x0e3
+let xk_adiaeresis = 0x0e4
+let xk_aring = 0x0e5
+let xk_ae = 0x0e6
+let xk_ccedilla = 0x0e7
+let xk_egrave = 0x0e8
+let xk_eacute = 0x0e9
+let xk_ecircumflex = 0x0ea
+let xk_ediaeresis = 0x0eb
+let xk_igrave = 0x0ec
+let xk_iacute = 0x0ed
+let xk_icircumflex = 0x0ee
+let xk_idiaeresis = 0x0ef
+let xk_eth = 0x0f0
+let xk_ntilde = 0x0f1
+let xk_ograve = 0x0f2
+let xk_oacute = 0x0f3
+let xk_ocircumflex = 0x0f4
+let xk_otilde = 0x0f5
+let xk_odiaeresis = 0x0f6
+let xk_division = 0x0f7
+let xk_oslash = 0x0f8
+let xk_ugrave = 0x0f9
+let xk_uacute = 0x0fa
+let xk_ucircumflex = 0x0fb
+let xk_udiaeresis = 0x0fc
+let xk_yacute = 0x0fd
+let xk_thorn = 0x0fe
+let xk_ydiaeresis = 0x0ff
+
+
+(*
+ * Latin 2
+ * Byte 3 = 1
+ *)
+
+
+let xk_Aogonek = 0x1a1
+let xk_breve = 0x1a2
+let xk_Lstroke = 0x1a3
+let xk_Lcaron = 0x1a5
+let xk_Sacute = 0x1a6
+let xk_Scaron = 0x1a9
+let xk_Scedilla = 0x1aa
+let xk_Tcaron = 0x1ab
+let xk_Zacute = 0x1ac
+let xk_Zcaron = 0x1ae
+let xk_Zabovedot = 0x1af
+let xk_aogonek = 0x1b1
+let xk_ogonek = 0x1b2
+let xk_lstroke = 0x1b3
+let xk_lcaron = 0x1b5
+let xk_sacute = 0x1b6
+let xk_caron = 0x1b7
+let xk_scaron = 0x1b9
+let xk_scedilla = 0x1ba
+let xk_tcaron = 0x1bb
+let xk_zacute = 0x1bc
+let xk_doubleacute = 0x1bd
+let xk_zcaron = 0x1be
+let xk_zabovedot = 0x1bf
+let xk_Racute = 0x1c0
+let xk_Abreve = 0x1c3
+let xk_Lacute = 0x1c5
+let xk_Cacute = 0x1c6
+let xk_Ccaron = 0x1c8
+let xk_Eogonek = 0x1ca
+let xk_Ecaron = 0x1cc
+let xk_Dcaron = 0x1cf
+let xk_Dstroke = 0x1d0
+let xk_Nacute = 0x1d1
+let xk_Ncaron = 0x1d2
+let xk_Odoubleacute = 0x1d5
+let xk_Rcaron = 0x1d8
+let xk_Uring = 0x1d9
+let xk_Udoubleacute = 0x1db
+let xk_Tcedilla = 0x1de
+let xk_racute = 0x1e0
+let xk_abreve = 0x1e3
+let xk_lacute = 0x1e5
+let xk_cacute = 0x1e6
+let xk_ccaron = 0x1e8
+let xk_eogonek = 0x1ea
+let xk_ecaron = 0x1ec
+let xk_dcaron = 0x1ef
+let xk_dstroke = 0x1f0
+let xk_nacute = 0x1f1
+let xk_ncaron = 0x1f2
+let xk_odoubleacute = 0x1f5
+let xk_udoubleacute = 0x1fb
+let xk_rcaron = 0x1f8
+let xk_uring = 0x1f9
+let xk_tcedilla = 0x1fe
+let xk_abovedot = 0x1ff
+
+
+(*
+ * Latin 3
+ * Byte 3 = 2
+ *)
+
+
+let xk_Hstroke = 0x2a1
+let xk_Hcircumflex = 0x2a6
+let xk_Iabovedot = 0x2a9
+let xk_Gbreve = 0x2ab
+let xk_Jcircumflex = 0x2ac
+let xk_hstroke = 0x2b1
+let xk_hcircumflex = 0x2b6
+let xk_idotless = 0x2b9
+let xk_gbreve = 0x2bb
+let xk_jcircumflex = 0x2bc
+let xk_Cabovedot = 0x2c5
+let xk_Ccircumflex = 0x2c6
+let xk_Gabovedot = 0x2d5
+let xk_Gcircumflex = 0x2d8
+let xk_Ubreve = 0x2dd
+let xk_Scircumflex = 0x2de
+let xk_cabovedot = 0x2e5
+let xk_ccircumflex = 0x2e6
+let xk_gabovedot = 0x2f5
+let xk_gcircumflex = 0x2f8
+let xk_ubreve = 0x2fd
+let xk_scircumflex = 0x2fe
+
+
+
+(*
+ * Latin 4
+ * Byte 3 = 3
+ *)
+
+
+let xk_kra = 0x3a2
+let xk_kappa = 0x3a2 (** deprecated *)
+let xk_Rcedilla = 0x3a3
+let xk_Itilde = 0x3a5
+let xk_Lcedilla = 0x3a6
+let xk_Emacron = 0x3aa
+let xk_Gcedilla = 0x3ab
+let xk_Tslash = 0x3ac
+let xk_rcedilla = 0x3b3
+let xk_itilde = 0x3b5
+let xk_lcedilla = 0x3b6
+let xk_emacron = 0x3ba
+let xk_gcedilla = 0x3bb
+let xk_tslash = 0x3bc
+let xk_ENG = 0x3bd
+let xk_eng = 0x3bf
+let xk_Amacron = 0x3c0
+let xk_Iogonek = 0x3c7
+let xk_Eabovedot = 0x3cc
+let xk_Imacron = 0x3cf
+let xk_Ncedilla = 0x3d1
+let xk_Omacron = 0x3d2
+let xk_Kcedilla = 0x3d3
+let xk_Uogonek = 0x3d9
+let xk_Utilde = 0x3dd
+let xk_Umacron = 0x3de
+let xk_amacron = 0x3e0
+let xk_iogonek = 0x3e7
+let xk_eabovedot = 0x3ec
+let xk_imacron = 0x3ef
+let xk_ncedilla = 0x3f1
+let xk_omacron = 0x3f2
+let xk_kcedilla = 0x3f3
+let xk_uogonek = 0x3f9
+let xk_utilde = 0x3fd
+let xk_umacron = 0x3fe
+
+
+(*
+ * Katakana
+ * Byte 3 = 4
+ *)
+
+
+let xk_overline = 0x47e
+let xk_kana_fullstop = 0x4a1
+let xk_kana_openingbracket = 0x4a2
+let xk_kana_closingbracket = 0x4a3
+let xk_kana_comma = 0x4a4
+let xk_kana_conjunctive = 0x4a5
+let xk_kana_middledot = 0x4a5 (** deprecated *)
+let xk_kana_WO = 0x4a6
+let xk_kana_a = 0x4a7
+let xk_kana_i = 0x4a8
+let xk_kana_u = 0x4a9
+let xk_kana_e = 0x4aa
+let xk_kana_o = 0x4ab
+let xk_kana_ya = 0x4ac
+let xk_kana_yu = 0x4ad
+let xk_kana_yo = 0x4ae
+let xk_kana_tsu = 0x4af
+let xk_kana_tu = 0x4af (** deprecated *)
+let xk_prolongedsound = 0x4b0
+let xk_kana_A = 0x4b1
+let xk_kana_I = 0x4b2
+let xk_kana_U = 0x4b3
+let xk_kana_E = 0x4b4
+let xk_kana_O = 0x4b5
+let xk_kana_KA = 0x4b6
+let xk_kana_KI = 0x4b7
+let xk_kana_KU = 0x4b8
+let xk_kana_KE = 0x4b9
+let xk_kana_KO = 0x4ba
+let xk_kana_SA = 0x4bb
+let xk_kana_SHI = 0x4bc
+let xk_kana_SU = 0x4bd
+let xk_kana_SE = 0x4be
+let xk_kana_SO = 0x4bf
+let xk_kana_TA = 0x4c0
+let xk_kana_CHI = 0x4c1
+let xk_kana_TI = 0x4c1 (** deprecated *)
+let xk_kana_TSU = 0x4c2
+let xk_kana_TU = 0x4c2 (** deprecated *)
+let xk_kana_TE = 0x4c3
+let xk_kana_TO = 0x4c4
+let xk_kana_NA = 0x4c5
+let xk_kana_NI = 0x4c6
+let xk_kana_NU = 0x4c7
+let xk_kana_NE = 0x4c8
+let xk_kana_NO = 0x4c9
+let xk_kana_HA = 0x4ca
+let xk_kana_HI = 0x4cb
+let xk_kana_FU = 0x4cc
+let xk_kana_HU = 0x4cc (** deprecated *)
+let xk_kana_HE = 0x4cd
+let xk_kana_HO = 0x4ce
+let xk_kana_MA = 0x4cf
+let xk_kana_MI = 0x4d0
+let xk_kana_MU = 0x4d1
+let xk_kana_ME = 0x4d2
+let xk_kana_MO = 0x4d3
+let xk_kana_YA = 0x4d4
+let xk_kana_YU = 0x4d5
+let xk_kana_YO = 0x4d6
+let xk_kana_RA = 0x4d7
+let xk_kana_RI = 0x4d8
+let xk_kana_RU = 0x4d9
+let xk_kana_RE = 0x4da
+let xk_kana_RO = 0x4db
+let xk_kana_WA = 0x4dc
+let xk_kana_N = 0x4dd
+let xk_voicedsound = 0x4de
+let xk_semivoicedsound = 0x4df
+let xk_kana_switch = 0xFF7E (** Alias for mode_switch *)
+
+
+(*
+ * Arabic
+ * Byte 3 = 5
+ *)
+
+
+let xk_Arabic_comma = 0x5ac
+let xk_Arabic_semicolon = 0x5bb
+let xk_Arabic_question_mark = 0x5bf
+let xk_Arabic_hamza = 0x5c1
+let xk_Arabic_maddaonalef = 0x5c2
+let xk_Arabic_hamzaonalef = 0x5c3
+let xk_Arabic_hamzaonwaw = 0x5c4
+let xk_Arabic_hamzaunderalef = 0x5c5
+let xk_Arabic_hamzaonyeh = 0x5c6
+let xk_Arabic_alef = 0x5c7
+let xk_Arabic_beh = 0x5c8
+let xk_Arabic_tehmarbuta = 0x5c9
+let xk_Arabic_teh = 0x5ca
+let xk_Arabic_theh = 0x5cb
+let xk_Arabic_jeem = 0x5cc
+let xk_Arabic_hah = 0x5cd
+let xk_Arabic_khah = 0x5ce
+let xk_Arabic_dal = 0x5cf
+let xk_Arabic_thal = 0x5d0
+let xk_Arabic_ra = 0x5d1
+let xk_Arabic_zain = 0x5d2
+let xk_Arabic_seen = 0x5d3
+let xk_Arabic_sheen = 0x5d4
+let xk_Arabic_sad = 0x5d5
+let xk_Arabic_dad = 0x5d6
+let xk_Arabic_tah = 0x5d7
+let xk_Arabic_zah = 0x5d8
+let xk_Arabic_ain = 0x5d9
+let xk_Arabic_ghain = 0x5da
+let xk_Arabic_tatweel = 0x5e0
+let xk_Arabic_feh = 0x5e1
+let xk_Arabic_qaf = 0x5e2
+let xk_Arabic_kaf = 0x5e3
+let xk_Arabic_lam = 0x5e4
+let xk_Arabic_meem = 0x5e5
+let xk_Arabic_noon = 0x5e6
+let xk_Arabic_ha = 0x5e7
+let xk_Arabic_heh = 0x5e7 (** deprecated *)
+let xk_Arabic_waw = 0x5e8
+let xk_Arabic_alefmaksura = 0x5e9
+let xk_Arabic_yeh = 0x5ea
+let xk_Arabic_fathatan = 0x5eb
+let xk_Arabic_dammatan = 0x5ec
+let xk_Arabic_kasratan = 0x5ed
+let xk_Arabic_fatha = 0x5ee
+let xk_Arabic_damma = 0x5ef
+let xk_Arabic_kasra = 0x5f0
+let xk_Arabic_shadda = 0x5f1
+let xk_Arabic_sukun = 0x5f2
+let xk_Arabic_switch = 0xFF7E (** Alias for mode_switch *)
+
+
+(*
+ * Cyrillic
+ * Byte 3 = 6
+ *)
+
+let xk_Serbian_dje = 0x6a1
+let xk_Macedonia_gje = 0x6a2
+let xk_Cyrillic_io = 0x6a3
+let xk_Ukrainian_ie = 0x6a4
+let xk_Ukranian_je = 0x6a4 (** deprecated *)
+let xk_Macedonia_dse = 0x6a5
+let xk_Ukrainian_i = 0x6a6
+let xk_Ukranian_i = 0x6a6 (** deprecated *)
+let xk_Ukrainian_yi = 0x6a7
+let xk_Ukranian_yi = 0x6a7 (** deprecated *)
+let xk_Cyrillic_je = 0x6a8
+let xk_Serbian_je = 0x6a8 (** deprecated *)
+let xk_Cyrillic_lje = 0x6a9
+let xk_Serbian_lje = 0x6a9 (** deprecated *)
+let xk_Cyrillic_nje = 0x6aa
+let xk_Serbian_nje = 0x6aa (** deprecated *)
+let xk_Serbian_tshe = 0x6ab
+let xk_Macedonia_kje = 0x6ac
+let xk_Byelorussian_shortu = 0x6ae
+let xk_Cyrillic_dzhe = 0x6af
+let xk_Serbian_dze = 0x6af (** deprecated *)
+let xk_numerosign = 0x6b0
+let xk_Serbian_DJE = 0x6b1
+let xk_Macedonia_GJE = 0x6b2
+let xk_Cyrillic_IO = 0x6b3
+let xk_Ukrainian_IE = 0x6b4
+let xk_Ukranian_JE = 0x6b4 (** deprecated *)
+let xk_Macedonia_DSE = 0x6b5
+let xk_Ukrainian_I = 0x6b6
+let xk_Ukranian_I = 0x6b6 (** deprecated *)
+let xk_Ukrainian_YI = 0x6b7
+let xk_Ukranian_YI = 0x6b7 (** deprecated *)
+let xk_Cyrillic_JE = 0x6b8
+let xk_Serbian_JE = 0x6b8 (** deprecated *)
+let xk_Cyrillic_LJE = 0x6b9
+let xk_Serbian_LJE = 0x6b9 (** deprecated *)
+let xk_Cyrillic_NJE = 0x6ba
+let xk_Serbian_NJE = 0x6ba (** deprecated *)
+let xk_Serbian_TSHE = 0x6bb
+let xk_Macedonia_KJE = 0x6bc
+let xk_Byelorussian_SHORTU = 0x6be
+let xk_Cyrillic_DZHE = 0x6bf
+let xk_Serbian_DZE = 0x6bf (** deprecated *)
+let xk_Cyrillic_yu = 0x6c0
+let xk_Cyrillic_a = 0x6c1
+let xk_Cyrillic_be = 0x6c2
+let xk_Cyrillic_tse = 0x6c3
+let xk_Cyrillic_de = 0x6c4
+let xk_Cyrillic_ie = 0x6c5
+let xk_Cyrillic_ef = 0x6c6
+let xk_Cyrillic_ghe = 0x6c7
+let xk_Cyrillic_ha = 0x6c8
+let xk_Cyrillic_i = 0x6c9
+let xk_Cyrillic_shorti = 0x6ca
+let xk_Cyrillic_ka = 0x6cb
+let xk_Cyrillic_el = 0x6cc
+let xk_Cyrillic_em = 0x6cd
+let xk_Cyrillic_en = 0x6ce
+let xk_Cyrillic_o = 0x6cf
+let xk_Cyrillic_pe = 0x6d0
+let xk_Cyrillic_ya = 0x6d1
+let xk_Cyrillic_er = 0x6d2
+let xk_Cyrillic_es = 0x6d3
+let xk_Cyrillic_te = 0x6d4
+let xk_Cyrillic_u = 0x6d5
+let xk_Cyrillic_zhe = 0x6d6
+let xk_Cyrillic_ve = 0x6d7
+let xk_Cyrillic_softsign = 0x6d8
+let xk_Cyrillic_yeru = 0x6d9
+let xk_Cyrillic_ze = 0x6da
+let xk_Cyrillic_sha = 0x6db
+let xk_Cyrillic_e = 0x6dc
+let xk_Cyrillic_shcha = 0x6dd
+let xk_Cyrillic_che = 0x6de
+let xk_Cyrillic_hardsign = 0x6df
+let xk_Cyrillic_YU = 0x6e0
+let xk_Cyrillic_A = 0x6e1
+let xk_Cyrillic_BE = 0x6e2
+let xk_Cyrillic_TSE = 0x6e3
+let xk_Cyrillic_DE = 0x6e4
+let xk_Cyrillic_IE = 0x6e5
+let xk_Cyrillic_EF = 0x6e6
+let xk_Cyrillic_GHE = 0x6e7
+let xk_Cyrillic_HA = 0x6e8
+let xk_Cyrillic_I = 0x6e9
+let xk_Cyrillic_SHORTI = 0x6ea
+let xk_Cyrillic_KA = 0x6eb
+let xk_Cyrillic_EL = 0x6ec
+let xk_Cyrillic_EM = 0x6ed
+let xk_Cyrillic_EN = 0x6ee
+let xk_Cyrillic_O = 0x6ef
+let xk_Cyrillic_PE = 0x6f0
+let xk_Cyrillic_YA = 0x6f1
+let xk_Cyrillic_ER = 0x6f2
+let xk_Cyrillic_ES = 0x6f3
+let xk_Cyrillic_TE = 0x6f4
+let xk_Cyrillic_U = 0x6f5
+let xk_Cyrillic_ZHE = 0x6f6
+let xk_Cyrillic_VE = 0x6f7
+let xk_Cyrillic_SOFTSIGN = 0x6f8
+let xk_Cyrillic_YERU = 0x6f9
+let xk_Cyrillic_ZE = 0x6fa
+let xk_Cyrillic_SHA = 0x6fb
+let xk_Cyrillic_E = 0x6fc
+let xk_Cyrillic_SHCHA = 0x6fd
+let xk_Cyrillic_CHE = 0x6fe
+let xk_Cyrillic_HARDSIGN = 0x6ff
+
+
+(*
+ * Greek
+ * Byte 3 = 7
+ *)
+
+
+let xk_Greek_ALPHAaccent = 0x7a1
+let xk_Greek_EPSILONaccent = 0x7a2
+let xk_Greek_ETAaccent = 0x7a3
+let xk_Greek_IOTAaccent = 0x7a4
+let xk_Greek_IOTAdiaeresis = 0x7a5
+let xk_Greek_OMICRONaccent = 0x7a7
+let xk_Greek_UPSILONaccent = 0x7a8
+let xk_Greek_UPSILONdieresis = 0x7a9
+let xk_Greek_OMEGAaccent = 0x7ab
+let xk_Greek_accentdieresis = 0x7ae
+let xk_Greek_horizbar = 0x7af
+let xk_Greek_alphaaccent = 0x7b1
+let xk_Greek_epsilonaccent = 0x7b2
+let xk_Greek_etaaccent = 0x7b3
+let xk_Greek_iotaaccent = 0x7b4
+let xk_Greek_iotadieresis = 0x7b5
+let xk_Greek_iotaaccentdieresis = 0x7b6
+let xk_Greek_omicronaccent = 0x7b7
+let xk_Greek_upsilonaccent = 0x7b8
+let xk_Greek_upsilondieresis = 0x7b9
+let xk_Greek_upsilonaccentdieresis = 0x7ba
+let xk_Greek_omegaaccent = 0x7bb
+let xk_Greek_ALPHA = 0x7c1
+let xk_Greek_BETA = 0x7c2
+let xk_Greek_GAMMA = 0x7c3
+let xk_Greek_DELTA = 0x7c4
+let xk_Greek_EPSILON = 0x7c5
+let xk_Greek_ZETA = 0x7c6
+let xk_Greek_ETA = 0x7c7
+let xk_Greek_THETA = 0x7c8
+let xk_Greek_IOTA = 0x7c9
+let xk_Greek_KAPPA = 0x7ca
+let xk_Greek_LAMDA = 0x7cb
+let xk_Greek_LAMBDA = 0x7cb
+let xk_Greek_MU = 0x7cc
+let xk_Greek_NU = 0x7cd
+let xk_Greek_XI = 0x7ce
+let xk_Greek_OMICRON = 0x7cf
+let xk_Greek_PI = 0x7d0
+let xk_Greek_RHO = 0x7d1
+let xk_Greek_SIGMA = 0x7d2
+let xk_Greek_TAU = 0x7d4
+let xk_Greek_UPSILON = 0x7d5
+let xk_Greek_PHI = 0x7d6
+let xk_Greek_CHI = 0x7d7
+let xk_Greek_PSI = 0x7d8
+let xk_Greek_OMEGA = 0x7d9
+let xk_Greek_alpha = 0x7e1
+let xk_Greek_beta = 0x7e2
+let xk_Greek_gamma = 0x7e3
+let xk_Greek_delta = 0x7e4
+let xk_Greek_epsilon = 0x7e5
+let xk_Greek_zeta = 0x7e6
+let xk_Greek_eta = 0x7e7
+let xk_Greek_theta = 0x7e8
+let xk_Greek_iota = 0x7e9
+let xk_Greek_kappa = 0x7ea
+let xk_Greek_lamda = 0x7eb
+let xk_Greek_lambda = 0x7eb
+let xk_Greek_mu = 0x7ec
+let xk_Greek_nu = 0x7ed
+let xk_Greek_xi = 0x7ee
+let xk_Greek_omicron = 0x7ef
+let xk_Greek_pi = 0x7f0
+let xk_Greek_rho = 0x7f1
+let xk_Greek_sigma = 0x7f2
+let xk_Greek_finalsmallsigma = 0x7f3
+let xk_Greek_tau = 0x7f4
+let xk_Greek_upsilon = 0x7f5
+let xk_Greek_phi = 0x7f6
+let xk_Greek_chi = 0x7f7
+let xk_Greek_psi = 0x7f8
+let xk_Greek_omega = 0x7f9
+let xk_Greek_switch = 0xFF7E (** Alias for mode_switch *)
+
+
+(*
+ * Technical
+ * Byte 3 = 8
+ *)
+
+
+let xk_leftradical = 0x8a1
+let xk_topleftradical = 0x8a2
+let xk_horizconnector = 0x8a3
+let xk_topintegral = 0x8a4
+let xk_botintegral = 0x8a5
+let xk_vertconnector = 0x8a6
+let xk_topleftsqbracket = 0x8a7
+let xk_botleftsqbracket = 0x8a8
+let xk_toprightsqbracket = 0x8a9
+let xk_botrightsqbracket = 0x8aa
+let xk_topleftparens = 0x8ab
+let xk_botleftparens = 0x8ac
+let xk_toprightparens = 0x8ad
+let xk_botrightparens = 0x8ae
+let xk_leftmiddlecurlybrace = 0x8af
+let xk_rightmiddlecurlybrace = 0x8b0
+let xk_topleftsummation = 0x8b1
+let xk_botleftsummation = 0x8b2
+let xk_topvertsummationconnector = 0x8b3
+let xk_botvertsummationconnector = 0x8b4
+let xk_toprightsummation = 0x8b5
+let xk_botrightsummation = 0x8b6
+let xk_rightmiddlesummation = 0x8b7
+let xk_lessthanequal = 0x8bc
+let xk_notequal = 0x8bd
+let xk_greaterthanequal = 0x8be
+let xk_integral = 0x8bf
+let xk_therefore = 0x8c0
+let xk_variation = 0x8c1
+let xk_infinity = 0x8c2
+let xk_nabla = 0x8c5
+let xk_approximate = 0x8c8
+let xk_similarequal = 0x8c9
+let xk_ifonlyif = 0x8cd
+let xk_implies = 0x8ce
+let xk_identical = 0x8cf
+let xk_radical = 0x8d6
+let xk_includedin = 0x8da
+let xk_includes = 0x8db
+let xk_intersection = 0x8dc
+let xk_union = 0x8dd
+let xk_logicaland = 0x8de
+let xk_logicalor = 0x8df
+let xk_partialderivative = 0x8ef
+let xk_function = 0x8f6
+let xk_leftarrow = 0x8fb
+let xk_uparrow = 0x8fc
+let xk_rightarrow = 0x8fd
+let xk_downarrow = 0x8fe
+
+
+(*
+ * Special
+ * Byte 3 = 9
+ *)
+
+
+let xk_blank = 0x9df
+let xk_soliddiamond = 0x9e0
+let xk_checkerboard = 0x9e1
+let xk_ht = 0x9e2
+let xk_ff = 0x9e3
+let xk_cr = 0x9e4
+let xk_lf = 0x9e5
+let xk_nl = 0x9e8
+let xk_vt = 0x9e9
+let xk_lowrightcorner = 0x9ea
+let xk_uprightcorner = 0x9eb
+let xk_upleftcorner = 0x9ec
+let xk_lowleftcorner = 0x9ed
+let xk_crossinglines = 0x9ee
+let xk_horizlinescan1 = 0x9ef
+let xk_horizlinescan3 = 0x9f0
+let xk_horizlinescan5 = 0x9f1
+let xk_horizlinescan7 = 0x9f2
+let xk_horizlinescan9 = 0x9f3
+let xk_leftt = 0x9f4
+let xk_rightt = 0x9f5
+let xk_bott = 0x9f6
+let xk_topt = 0x9f7
+let xk_vertbar = 0x9f8
+
+
+(*
+ * Publishing
+ * Byte 3 = a
+ *)
+
+
+let xk_emspace = 0xaa1
+let xk_enspace = 0xaa2
+let xk_em3space = 0xaa3
+let xk_em4space = 0xaa4
+let xk_digitspace = 0xaa5
+let xk_punctspace = 0xaa6
+let xk_thinspace = 0xaa7
+let xk_hairspace = 0xaa8
+let xk_emdash = 0xaa9
+let xk_endash = 0xaaa
+let xk_signifblank = 0xaac
+let xk_ellipsis = 0xaae
+let xk_doubbaselinedot = 0xaaf
+let xk_onethird = 0xab0
+let xk_twothirds = 0xab1
+let xk_onefifth = 0xab2
+let xk_twofifths = 0xab3
+let xk_threefifths = 0xab4
+let xk_fourfifths = 0xab5
+let xk_onesixth = 0xab6
+let xk_fivesixths = 0xab7
+let xk_careof = 0xab8
+let xk_figdash = 0xabb
+let xk_leftanglebracket = 0xabc
+let xk_decimalpoint = 0xabd
+let xk_rightanglebracket = 0xabe
+let xk_marker = 0xabf
+let xk_oneeighth = 0xac3
+let xk_threeeighths = 0xac4
+let xk_fiveeighths = 0xac5
+let xk_seveneighths = 0xac6
+let xk_trademark = 0xac9
+let xk_signaturemark = 0xaca
+let xk_trademarkincircle = 0xacb
+let xk_leftopentriangle = 0xacc
+let xk_rightopentriangle = 0xacd
+let xk_emopencircle = 0xace
+let xk_emopenrectangle = 0xacf
+let xk_leftsinglequotemark = 0xad0
+let xk_rightsinglequotemark = 0xad1
+let xk_leftdoublequotemark = 0xad2
+let xk_rightdoublequotemark = 0xad3
+let xk_prescription = 0xad4
+let xk_minutes = 0xad6
+let xk_seconds = 0xad7
+let xk_latincross = 0xad9
+let xk_hexagram = 0xada
+let xk_filledrectbullet = 0xadb
+let xk_filledlefttribullet = 0xadc
+let xk_filledrighttribullet = 0xadd
+let xk_emfilledcircle = 0xade
+let xk_emfilledrect = 0xadf
+let xk_enopencircbullet = 0xae0
+let xk_enopensquarebullet = 0xae1
+let xk_openrectbullet = 0xae2
+let xk_opentribulletup = 0xae3
+let xk_opentribulletdown = 0xae4
+let xk_openstar = 0xae5
+let xk_enfilledcircbullet = 0xae6
+let xk_enfilledsqbullet = 0xae7
+let xk_filledtribulletup = 0xae8
+let xk_filledtribulletdown = 0xae9
+let xk_leftpointer = 0xaea
+let xk_rightpointer = 0xaeb
+let xk_club = 0xaec
+let xk_diamond = 0xaed
+let xk_heart = 0xaee
+let xk_maltesecross = 0xaf0
+let xk_dagger = 0xaf1
+let xk_doubledagger = 0xaf2
+let xk_checkmark = 0xaf3
+let xk_ballotcross = 0xaf4
+let xk_musicalsharp = 0xaf5
+let xk_musicalflat = 0xaf6
+let xk_malesymbol = 0xaf7
+let xk_femalesymbol = 0xaf8
+let xk_telephone = 0xaf9
+let xk_telephonerecorder = 0xafa
+let xk_phonographcopyright = 0xafb
+let xk_caret = 0xafc
+let xk_singlelowquotemark = 0xafd
+let xk_doublelowquotemark = 0xafe
+let xk_cursor = 0xaff
+
+
+(*
+ * APL
+ * Byte 3 = b
+ *)
+
+
+let xk_leftcaret = 0xba3
+let xk_rightcaret = 0xba6
+let xk_downcaret = 0xba8
+let xk_upcaret = 0xba9
+let xk_overbar = 0xbc0
+let xk_downtack = 0xbc2
+let xk_upshoe = 0xbc3
+let xk_downstile = 0xbc4
+let xk_underbar = 0xbc6
+let xk_jot = 0xbca
+let xk_quad = 0xbcc
+let xk_uptack = 0xbce
+let xk_circle = 0xbcf
+let xk_upstile = 0xbd3
+let xk_downshoe = 0xbd6
+let xk_rightshoe = 0xbd8
+let xk_leftshoe = 0xbda
+let xk_lefttack = 0xbdc
+let xk_righttack = 0xbfc
+
+
+(*
+ * Hebrew
+ * Byte 3 = c
+ *)
+
+
+let xk_hebrew_doublelowline = 0xcdf
+let xk_hebrew_aleph = 0xce0
+let xk_hebrew_bet = 0xce1
+let xk_hebrew_beth = 0xce1 (** deprecated *)
+let xk_hebrew_gimel = 0xce2
+let xk_hebrew_gimmel = 0xce2 (** deprecated *)
+let xk_hebrew_dalet = 0xce3
+let xk_hebrew_daleth = 0xce3 (** deprecated *)
+let xk_hebrew_he = 0xce4
+let xk_hebrew_waw = 0xce5
+let xk_hebrew_zain = 0xce6
+let xk_hebrew_zayin = 0xce6 (** deprecated *)
+let xk_hebrew_chet = 0xce7
+let xk_hebrew_het = 0xce7 (** deprecated *)
+let xk_hebrew_tet = 0xce8
+let xk_hebrew_teth = 0xce8 (** deprecated *)
+let xk_hebrew_yod = 0xce9
+let xk_hebrew_finalkaph = 0xcea
+let xk_hebrew_kaph = 0xceb
+let xk_hebrew_lamed = 0xcec
+let xk_hebrew_finalmem = 0xced
+let xk_hebrew_mem = 0xcee
+let xk_hebrew_finalnun = 0xcef
+let xk_hebrew_nun = 0xcf0
+let xk_hebrew_samech = 0xcf1
+let xk_hebrew_samekh = 0xcf1 (** deprecated *)
+let xk_hebrew_ayin = 0xcf2
+let xk_hebrew_finalpe = 0xcf3
+let xk_hebrew_pe = 0xcf4
+let xk_hebrew_finalzade = 0xcf5
+let xk_hebrew_finalzadi = 0xcf5 (** deprecated *)
+let xk_hebrew_zade = 0xcf6
+let xk_hebrew_zadi = 0xcf6 (** deprecated *)
+let xk_hebrew_qoph = 0xcf7
+let xk_hebrew_kuf = 0xcf7 (** deprecated *)
+let xk_hebrew_resh = 0xcf8
+let xk_hebrew_shin = 0xcf9
+let xk_hebrew_taw = 0xcfa
+let xk_hebrew_taf = 0xcfa (** deprecated *)
+let xk_Hebrew_switch = 0xFF7E (** Alias for mode_switch *)
+
+
+(*
+ * Thai
+ * Byte 3 = d
+ *)
+
+
+let xk_Thai_kokai = 0xda1
+let xk_Thai_khokhai = 0xda2
+let xk_Thai_khokhuat = 0xda3
+let xk_Thai_khokhwai = 0xda4
+let xk_Thai_khokhon = 0xda5
+let xk_Thai_khorakhang = 0xda6
+let xk_Thai_ngongu = 0xda7
+let xk_Thai_chochan = 0xda8
+let xk_Thai_choching = 0xda9
+let xk_Thai_chochang = 0xdaa
+let xk_Thai_soso = 0xdab
+let xk_Thai_chochoe = 0xdac
+let xk_Thai_yoying = 0xdad
+let xk_Thai_dochada = 0xdae
+let xk_Thai_topatak = 0xdaf
+let xk_Thai_thothan = 0xdb0
+let xk_Thai_thonangmontho = 0xdb1
+let xk_Thai_thophuthao = 0xdb2
+let xk_Thai_nonen = 0xdb3
+let xk_Thai_dodek = 0xdb4
+let xk_Thai_totao = 0xdb5
+let xk_Thai_thothung = 0xdb6
+let xk_Thai_thothahan = 0xdb7
+let xk_Thai_thothong = 0xdb8
+let xk_Thai_nonu = 0xdb9
+let xk_Thai_bobaimai = 0xdba
+let xk_Thai_popla = 0xdbb
+let xk_Thai_phophung = 0xdbc
+let xk_Thai_fofa = 0xdbd
+let xk_Thai_phophan = 0xdbe
+let xk_Thai_fofan = 0xdbf
+let xk_Thai_phosamphao = 0xdc0
+let xk_Thai_moma = 0xdc1
+let xk_Thai_yoyak = 0xdc2
+let xk_Thai_rorua = 0xdc3
+let xk_Thai_ru = 0xdc4
+let xk_Thai_loling = 0xdc5
+let xk_Thai_lu = 0xdc6
+let xk_Thai_wowaen = 0xdc7
+let xk_Thai_sosala = 0xdc8
+let xk_Thai_sorusi = 0xdc9
+let xk_Thai_sosua = 0xdca
+let xk_Thai_hohip = 0xdcb
+let xk_Thai_lochula = 0xdcc
+let xk_Thai_oang = 0xdcd
+let xk_Thai_honokhuk = 0xdce
+let xk_Thai_paiyannoi = 0xdcf
+let xk_Thai_saraa = 0xdd0
+let xk_Thai_maihanakat = 0xdd1
+let xk_Thai_saraaa = 0xdd2
+let xk_Thai_saraam = 0xdd3
+let xk_Thai_sarai = 0xdd4
+let xk_Thai_saraii = 0xdd5
+let xk_Thai_saraue = 0xdd6
+let xk_Thai_sarauee = 0xdd7
+let xk_Thai_sarau = 0xdd8
+let xk_Thai_sarauu = 0xdd9
+let xk_Thai_phinthu = 0xdda
+let xk_Thai_maihanakat_maitho = 0xdde
+let xk_Thai_baht = 0xddf
+let xk_Thai_sarae = 0xde0
+let xk_Thai_saraae = 0xde1
+let xk_Thai_sarao = 0xde2
+let xk_Thai_saraaimaimuan = 0xde3
+let xk_Thai_saraaimaimalai = 0xde4
+let xk_Thai_lakkhangyao = 0xde5
+let xk_Thai_maiyamok = 0xde6
+let xk_Thai_maitaikhu = 0xde7
+let xk_Thai_maiek = 0xde8
+let xk_Thai_maitho = 0xde9
+let xk_Thai_maitri = 0xdea
+let xk_Thai_maichattawa = 0xdeb
+let xk_Thai_thanthakhat = 0xdec
+let xk_Thai_nikhahit = 0xded
+let xk_Thai_leksun = 0xdf0
+let xk_Thai_leknung = 0xdf1
+let xk_Thai_leksong = 0xdf2
+let xk_Thai_leksam = 0xdf3
+let xk_Thai_leksi = 0xdf4
+let xk_Thai_lekha = 0xdf5
+let xk_Thai_lekhok = 0xdf6
+let xk_Thai_lekchet = 0xdf7
+let xk_Thai_lekpaet = 0xdf8
+let xk_Thai_lekkao = 0xdf9
+
+
+(*
+ * Korean
+ * Byte 3 = e
+ *)
+
+
+
+let xk_Hangul = 0xff31 (** Hangul start/stop(toggle) *)
+let xk_Hangul_Start = 0xff32 (** Hangul start *)
+let xk_Hangul_End = 0xff33 (** Hangul end, English start *)
+let xk_Hangul_Hanja = 0xff34 (** Start Hangul->Hanja Conversion *)
+let xk_Hangul_Jamo = 0xff35 (** Hangul Jamo mode *)
+let xk_Hangul_Romaja = 0xff36 (** Hangul Romaja mode *)
+let xk_Hangul_Codeinput = 0xff37 (** Hangul code input mode *)
+let xk_Hangul_Jeonja = 0xff38 (** Jeonja mode *)
+let xk_Hangul_Banja = 0xff39 (** Banja mode *)
+let xk_Hangul_PreHanja = 0xff3a (** Pre Hanja conversion *)
+let xk_Hangul_PostHanja = 0xff3b (** Post Hanja conversion *)
+let xk_Hangul_SingleCandidate = 0xff3c (** Single candidate *)
+let xk_Hangul_MultipleCandidate = 0xff3d (** Multiple candidate *)
+let xk_Hangul_PreviousCandidate = 0xff3e (** Previous candidate *)
+let xk_Hangul_Special = 0xff3f (** Special symbols *)
+let xk_Hangul_switch = 0xFF7E (** Alias for mode_switch *)
+
+(** Hangul Consonant Characters *)
+let xk_Hangul_Kiyeog = 0xea1
+let xk_Hangul_SsangKiyeog = 0xea2
+let xk_Hangul_KiyeogSios = 0xea3
+let xk_Hangul_Nieun = 0xea4
+let xk_Hangul_NieunJieuj = 0xea5
+let xk_Hangul_NieunHieuh = 0xea6
+let xk_Hangul_Dikeud = 0xea7
+let xk_Hangul_SsangDikeud = 0xea8
+let xk_Hangul_Rieul = 0xea9
+let xk_Hangul_RieulKiyeog = 0xeaa
+let xk_Hangul_RieulMieum = 0xeab
+let xk_Hangul_RieulPieub = 0xeac
+let xk_Hangul_RieulSios = 0xead
+let xk_Hangul_RieulTieut = 0xeae
+let xk_Hangul_RieulPhieuf = 0xeaf
+let xk_Hangul_RieulHieuh = 0xeb0
+let xk_Hangul_Mieum = 0xeb1
+let xk_Hangul_Pieub = 0xeb2
+let xk_Hangul_SsangPieub = 0xeb3
+let xk_Hangul_PieubSios = 0xeb4
+let xk_Hangul_Sios = 0xeb5
+let xk_Hangul_SsangSios = 0xeb6
+let xk_Hangul_Ieung = 0xeb7
+let xk_Hangul_Jieuj = 0xeb8
+let xk_Hangul_SsangJieuj = 0xeb9
+let xk_Hangul_Cieuc = 0xeba
+let xk_Hangul_Khieuq = 0xebb
+let xk_Hangul_Tieut = 0xebc
+let xk_Hangul_Phieuf = 0xebd
+let xk_Hangul_Hieuh = 0xebe
+
+(** Hangul Vowel Characters *)
+let xk_Hangul_A = 0xebf
+let xk_Hangul_AE = 0xec0
+let xk_Hangul_YA = 0xec1
+let xk_Hangul_YAE = 0xec2
+let xk_Hangul_EO = 0xec3
+let xk_Hangul_E = 0xec4
+let xk_Hangul_YEO = 0xec5
+let xk_Hangul_YE = 0xec6
+let xk_Hangul_O = 0xec7
+let xk_Hangul_WA = 0xec8
+let xk_Hangul_WAE = 0xec9
+let xk_Hangul_OE = 0xeca
+let xk_Hangul_YO = 0xecb
+let xk_Hangul_U = 0xecc
+let xk_Hangul_WEO = 0xecd
+let xk_Hangul_WE = 0xece
+let xk_Hangul_WI = 0xecf
+let xk_Hangul_YU = 0xed0
+let xk_Hangul_EU = 0xed1
+let xk_Hangul_YI = 0xed2
+let xk_Hangul_I = 0xed3
+
+(** Hangul syllable-final (JongSeong) Characters *)
+let xk_Hangul_J_Kiyeog = 0xed4
+let xk_Hangul_J_SsangKiyeog = 0xed5
+let xk_Hangul_J_KiyeogSios = 0xed6
+let xk_Hangul_J_Nieun = 0xed7
+let xk_Hangul_J_NieunJieuj = 0xed8
+let xk_Hangul_J_NieunHieuh = 0xed9
+let xk_Hangul_J_Dikeud = 0xeda
+let xk_Hangul_J_Rieul = 0xedb
+let xk_Hangul_J_RieulKiyeog = 0xedc
+let xk_Hangul_J_RieulMieum = 0xedd
+let xk_Hangul_J_RieulPieub = 0xede
+let xk_Hangul_J_RieulSios = 0xedf
+let xk_Hangul_J_RieulTieut = 0xee0
+let xk_Hangul_J_RieulPhieuf = 0xee1
+let xk_Hangul_J_RieulHieuh = 0xee2
+let xk_Hangul_J_Mieum = 0xee3
+let xk_Hangul_J_Pieub = 0xee4
+let xk_Hangul_J_PieubSios = 0xee5
+let xk_Hangul_J_Sios = 0xee6
+let xk_Hangul_J_SsangSios = 0xee7
+let xk_Hangul_J_Ieung = 0xee8
+let xk_Hangul_J_Jieuj = 0xee9
+let xk_Hangul_J_Cieuc = 0xeea
+let xk_Hangul_J_Khieuq = 0xeeb
+let xk_Hangul_J_Tieut = 0xeec
+let xk_Hangul_J_Phieuf = 0xeed
+let xk_Hangul_J_Hieuh = 0xeee
+
+(** Ancient Hangul Consonant Characters *)
+let xk_Hangul_RieulYeorinHieuh = 0xeef
+let xk_Hangul_SunkyeongeumMieum = 0xef0
+let xk_Hangul_SunkyeongeumPieub = 0xef1
+let xk_Hangul_PanSios = 0xef2
+let xk_Hangul_KkogjiDalrinIeung = 0xef3
+let xk_Hangul_SunkyeongeumPhieuf = 0xef4
+let xk_Hangul_YeorinHieuh = 0xef5
+
+(** Ancient Hangul Vowel Characters *)
+let xk_Hangul_AraeA = 0xef6
+let xk_Hangul_AraeAE = 0xef7
+
+(** Ancient Hangul syllable-final (JongSeong) Characters *)
+let xk_Hangul_J_PanSios = 0xef8
+let xk_Hangul_J_KkogjiDalrinIeung = 0xef9
+let xk_Hangul_J_YeorinHieuh = 0xefa
+
+(** Korean currency symbol *)
+let xk_Korean_Won = 0xeff
+
+
+
+let name_to_keysym = [
+"VoidSymbol",0xFFFFFF;
+"BackSpace",0xFF08;
+"Tab",0xFF09;
+"Linefeed",0xFF0A;
+"Clear",0xFF0B;
+"Return",0xFF0D;
+"Pause",0xFF13;
+"Scroll_Lock",0xFF14;
+"Sys_Req",0xFF15;
+"Escape",0xFF1B;
+"Delete",0xFFFF;
+"Multi_key",0xFF20;
+"Kanji",0xFF21;
+"Muhenkan",0xFF22;
+"Henkan_Mode",0xFF23;
+"Henkan",0xFF23;
+"Romaji",0xFF24;
+"Hiragana",0xFF25;
+"Katakana",0xFF26;
+"Hiragana_Katakana",0xFF27;
+"Zenkaku",0xFF28;
+"Hankaku",0xFF29;
+"Zenkaku_Hankaku",0xFF2A;
+"Touroku",0xFF2B;
+"Massyo",0xFF2C;
+"Kana_Lock",0xFF2D;
+"Kana_Shift",0xFF2E;
+"Eisu_Shift",0xFF2F;
+"Eisu_toggle",0xFF30;
+"Home",0xFF50;
+"Left",0xFF51;
+"Up",0xFF52;
+"Right",0xFF53;
+"Down",0xFF54;
+"Prior",0xFF55;
+"Page_Up",0xFF55;
+"Next",0xFF56;
+"Page_Down",0xFF56;
+"End",0xFF57;
+"Begin",0xFF58;
+"Select",0xFF60;
+"Print",0xFF61;
+"Execute",0xFF62;
+"Insert",0xFF63;
+"Undo",0xFF65;
+"Redo",0xFF66;
+"Menu",0xFF67;
+"Find",0xFF68;
+"Cancel",0xFF69;
+"Help",0xFF6A;
+"Break",0xFF6B;
+"Mode_switch",0xFF7E;
+"script_switch",0xFF7E;
+"Num_Lock",0xFF7F;
+"KP_Space",0xFF80;
+"KP_Tab",0xFF89;
+"KP_Enter",0xFF8D;
+"KP_F1",0xFF91;
+"KP_F2",0xFF92;
+"KP_F3",0xFF93;
+"KP_F4",0xFF94;
+"KP_Home",0xFF95;
+"KP_Left",0xFF96;
+"KP_Up",0xFF97;
+"KP_Right",0xFF98;
+"KP_Down",0xFF99;
+"KP_Prior",0xFF9A;
+"KP_Page_Up",0xFF9A;
+"KP_Next",0xFF9B;
+"KP_Page_Down",0xFF9B;
+"KP_End",0xFF9C;
+"KP_Begin",0xFF9D;
+"KP_Insert",0xFF9E;
+"KP_Delete",0xFF9F;
+"KP_Equal",0xFFBD;
+"KP_Multiply",0xFFAA;
+"KP_Add",0xFFAB;
+"KP_Separator",0xFFAC;
+"KP_Subtract",0xFFAD;
+"KP_Decimal",0xFFAE;
+"KP_Divide",0xFFAF;
+"KP_0",0xFFB0;
+"KP_1",0xFFB1;
+"KP_2",0xFFB2;
+"KP_3",0xFFB3;
+"KP_4",0xFFB4;
+"KP_5",0xFFB5;
+"KP_6",0xFFB6;
+"KP_7",0xFFB7;
+"KP_8",0xFFB8;
+"KP_9",0xFFB9;
+"F1",0xFFBE;
+"F2",0xFFBF;
+"F3",0xFFC0;
+"F4",0xFFC1;
+"F5",0xFFC2;
+"F6",0xFFC3;
+"F7",0xFFC4;
+"F8",0xFFC5;
+"F9",0xFFC6;
+"F10",0xFFC7;
+"F11",0xFFC8;
+"L1",0xFFC8;
+"F12",0xFFC9;
+"L2",0xFFC9;
+"F13",0xFFCA;
+"L3",0xFFCA;
+"F14",0xFFCB;
+"L4",0xFFCB;
+"F15",0xFFCC;
+"L5",0xFFCC;
+"F16",0xFFCD;
+"L6",0xFFCD;
+"F17",0xFFCE;
+"L7",0xFFCE;
+"F18",0xFFCF;
+"L8",0xFFCF;
+"F19",0xFFD0;
+"L9",0xFFD0;
+"F20",0xFFD1;
+"L10",0xFFD1;
+"F21",0xFFD2;
+"R1",0xFFD2;
+"F22",0xFFD3;
+"R2",0xFFD3;
+"F23",0xFFD4;
+"R3",0xFFD4;
+"F24",0xFFD5;
+"R4",0xFFD5;
+"F25",0xFFD6;
+"R5",0xFFD6;
+"F26",0xFFD7;
+"R6",0xFFD7;
+"F27",0xFFD8;
+"R7",0xFFD8;
+"F28",0xFFD9;
+"R8",0xFFD9;
+"F29",0xFFDA;
+"R9",0xFFDA;
+"F30",0xFFDB;
+"R10",0xFFDB;
+"F31",0xFFDC;
+"R11",0xFFDC;
+"F32",0xFFDD;
+"R12",0xFFDD;
+"F33",0xFFDE;
+"R13",0xFFDE;
+"F34",0xFFDF;
+"R14",0xFFDF;
+"F35",0xFFE0;
+"R15",0xFFE0;
+"Shift_L",0xFFE1;
+"Shift_R",0xFFE2;
+"Control_L",0xFFE3;
+"Control_R",0xFFE4;
+"Caps_Lock",0xFFE5;
+"Shift_Lock",0xFFE6;
+"Meta_L",0xFFE7;
+"Meta_R",0xFFE8;
+"Alt_L",0xFFE9;
+"Alt_R",0xFFEA;
+"Super_L",0xFFEB;
+"Super_R",0xFFEC;
+"Hyper_L",0xFFED;
+"Hyper_R",0xFFEE;
+"ISO_Lock",0xFE01;
+"ISO_Level2_Latch",0xFE02;
+"ISO_Level3_Shift",0xFE03;
+"ISO_Level3_Latch",0xFE04;
+"ISO_Level3_Lock",0xFE05;
+"ISO_Group_Shift",0xFF7E;
+"ISO_Group_Latch",0xFE06;
+"ISO_Group_Lock",0xFE07;
+"ISO_Next_Group",0xFE08;
+"ISO_Next_Group_Lock",0xFE09;
+"ISO_Prev_Group",0xFE0A;
+"ISO_Prev_Group_Lock",0xFE0B;
+"ISO_First_Group",0xFE0C;
+"ISO_First_Group_Lock",0xFE0D;
+"ISO_Last_Group",0xFE0E;
+"ISO_Last_Group_Lock",0xFE0F;
+"ISO_Left_Tab",0xFE20;
+"ISO_Move_Line_Up",0xFE21;
+"ISO_Move_Line_Down",0xFE22;
+"ISO_Partial_Line_Up",0xFE23;
+"ISO_Partial_Line_Down",0xFE24;
+"ISO_Partial_Space_Left",0xFE25;
+"ISO_Partial_Space_Right",0xFE26;
+"ISO_Set_Margin_Left",0xFE27;
+"ISO_Set_Margin_Right",0xFE28;
+"ISO_Release_Margin_Left",0xFE29;
+"ISO_Release_Margin_Right",0xFE2A;
+"ISO_Release_Both_Margins",0xFE2B;
+"ISO_Fast_Cursor_Left",0xFE2C;
+"ISO_Fast_Cursor_Right",0xFE2D;
+"ISO_Fast_Cursor_Up",0xFE2E;
+"ISO_Fast_Cursor_Down",0xFE2F;
+"ISO_Continuous_Underline",0xFE30;
+"ISO_Discontinuous_Underline",0xFE31;
+"ISO_Emphasize",0xFE32;
+"ISO_Center_Object",0xFE33;
+"ISO_Enter",0xFE34;
+"dead_grave",0xFE50;
+"dead_acute",0xFE51;
+"dead_circumflex",0xFE52;
+"dead_tilde",0xFE53;
+"dead_macron",0xFE54;
+"dead_breve",0xFE55;
+"dead_abovedot",0xFE56;
+"dead_diaeresis",0xFE57;
+"dead_abovering",0xFE58;
+"dead_doubleacute",0xFE59;
+"dead_caron",0xFE5A;
+"dead_cedilla",0xFE5B;
+"dead_ogonek",0xFE5C;
+"dead_iota",0xFE5D;
+"dead_voiced_sound",0xFE5E;
+"dead_semivoiced_sound",0xFE5F;
+"dead_belowdot",0xFE60;
+"First_Virtual_Screen",0xFED0;
+"Prev_Virtual_Screen",0xFED1;
+"Next_Virtual_Screen",0xFED2;
+"Last_Virtual_Screen",0xFED4;
+"Terminate_Server",0xFED5;
+"AccessX_Enable",0xFE70;
+"AccessX_Feedback_Enable",0xFE71;
+"RepeatKeys_Enable",0xFE72;
+"SlowKeys_Enable",0xFE73;
+"BounceKeys_Enable",0xFE74;
+"StickyKeys_Enable",0xFE75;
+"MouseKeys_Enable",0xFE76;
+"MouseKeys_Accel_Enable",0xFE77;
+"Overlay1_Enable",0xFE78;
+"Overlay2_Enable",0xFE79;
+"AudibleBell_Enable",0xFE7A;
+"Pointer_Left",0xFEE0;
+"Pointer_Right",0xFEE1;
+"Pointer_Up",0xFEE2;
+"Pointer_Down",0xFEE3;
+"Pointer_UpLeft",0xFEE4;
+"Pointer_UpRight",0xFEE5;
+"Pointer_DownLeft",0xFEE6;
+"Pointer_DownRight",0xFEE7;
+"Pointer_Button_Dflt",0xFEE8;
+"Pointer_Button1",0xFEE9;
+"Pointer_Button2",0xFEEA;
+"Pointer_Button3",0xFEEB;
+"Pointer_Button4",0xFEEC;
+"Pointer_Button5",0xFEED;
+"Pointer_DblClick_Dflt",0xFEEE;
+"Pointer_DblClick1",0xFEEF;
+"Pointer_DblClick2",0xFEF0;
+"Pointer_DblClick3",0xFEF1;
+"Pointer_DblClick4",0xFEF2;
+"Pointer_DblClick5",0xFEF3;
+"Pointer_Drag_Dflt",0xFEF4;
+"Pointer_Drag1",0xFEF5;
+"Pointer_Drag2",0xFEF6;
+"Pointer_Drag3",0xFEF7;
+"Pointer_Drag4",0xFEF8;
+"Pointer_Drag5",0xFEFD;
+"Pointer_EnableKeys",0xFEF9;
+"Pointer_Accelerate",0xFEFA;
+"Pointer_DfltBtnNext",0xFEFB;
+"Pointer_DfltBtnPrev",0xFEFC;
+"3270_Duplicate",0xFD01;
+"3270_FieldMark",0xFD02;
+"3270_Right2",0xFD03;
+"3270_Left2",0xFD04;
+"3270_BackTab",0xFD05;
+"3270_EraseEOF",0xFD06;
+"3270_EraseInput",0xFD07;
+"3270_Reset",0xFD08;
+"3270_Quit",0xFD09;
+"3270_PA1",0xFD0A;
+"3270_PA2",0xFD0B;
+"3270_PA3",0xFD0C;
+"3270_Test",0xFD0D;
+"3270_Attn",0xFD0E;
+"3270_CursorBlink",0xFD0F;
+"3270_AltCursor",0xFD10;
+"3270_KeyClick",0xFD11;
+"3270_Jump",0xFD12;
+"3270_Ident",0xFD13;
+"3270_Rule",0xFD14;
+"3270_Copy",0xFD15;
+"3270_Play",0xFD16;
+"3270_Setup",0xFD17;
+"3270_Record",0xFD18;
+"3270_ChangeScreen",0xFD19;
+"3270_DeleteWord",0xFD1A;
+"3270_ExSelect",0xFD1B;
+"3270_CursorSelect",0xFD1C;
+"3270_PrintScreen",0xFD1D;
+"3270_Enter",0xFD1E;
+"space",0x020;
+"exclam",0x021;
+"quotedbl",0x022;
+"numbersign",0x023;
+"dollar",0x024;
+"percent",0x025;
+"ampersand",0x026;
+"apostrophe",0x027;
+"quoteright",0x027;
+"parenleft",0x028;
+"parenright",0x029;
+"asterisk",0x02a;
+"plus",0x02b;
+"comma",0x02c;
+"minus",0x02d;
+"period",0x02e;
+"slash",0x02f;
+"0",0x030;
+"1",0x031;
+"2",0x032;
+"3",0x033;
+"4",0x034;
+"5",0x035;
+"6",0x036;
+"7",0x037;
+"8",0x038;
+"9",0x039;
+"colon",0x03a;
+"semicolon",0x03b;
+"less",0x03c;
+"equal",0x03d;
+"greater",0x03e;
+"question",0x03f;
+"at",0x040;
+"A",0x041;
+"B",0x042;
+"C",0x043;
+"D",0x044;
+"E",0x045;
+"F",0x046;
+"G",0x047;
+"H",0x048;
+"I",0x049;
+"J",0x04a;
+"K",0x04b;
+"L",0x04c;
+"M",0x04d;
+"N",0x04e;
+"O",0x04f;
+"P",0x050;
+"Q",0x051;
+"R",0x052;
+"S",0x053;
+"T",0x054;
+"U",0x055;
+"V",0x056;
+"W",0x057;
+"X",0x058;
+"Y",0x059;
+"Z",0x05a;
+"bracketleft",0x05b;
+"backslash",0x05c;
+"bracketright",0x05d;
+"asciicircum",0x05e;
+"underscore",0x05f;
+"grave",0x060;
+"quoteleft",0x060;
+"a",0x061;
+"b",0x062;
+"c",0x063;
+"d",0x064;
+"e",0x065;
+"f",0x066;
+"g",0x067;
+"h",0x068;
+"i",0x069;
+"j",0x06a;
+"k",0x06b;
+"l",0x06c;
+"m",0x06d;
+"n",0x06e;
+"o",0x06f;
+"p",0x070;
+"q",0x071;
+"r",0x072;
+"s",0x073;
+"t",0x074;
+"u",0x075;
+"v",0x076;
+"w",0x077;
+"x",0x078;
+"y",0x079;
+"z",0x07a;
+"braceleft",0x07b;
+"bar",0x07c;
+"braceright",0x07d;
+"asciitilde",0x07e;
+"nobreakspace",0x0a0;
+"exclamdown",0x0a1;
+"cent",0x0a2;
+"sterling",0x0a3;
+"currency",0x0a4;
+"yen",0x0a5;
+"brokenbar",0x0a6;
+"section",0x0a7;
+"diaeresis",0x0a8;
+"copyright",0x0a9;
+"ordfeminine",0x0aa;
+"guillemotleft",0x0ab;
+"notsign",0x0ac;
+"hyphen",0x0ad;
+"registered",0x0ae;
+"macron",0x0af;
+"degree",0x0b0;
+"plusminus",0x0b1;
+"twosuperior",0x0b2;
+"threesuperior",0x0b3;
+"acute",0x0b4;
+"mu",0x0b5;
+"paragraph",0x0b6;
+"periodcentered",0x0b7;
+"cedilla",0x0b8;
+"onesuperior",0x0b9;
+"masculine",0x0ba;
+"guillemotright",0x0bb;
+"onequarter",0x0bc;
+"onehalf",0x0bd;
+"threequarters",0x0be;
+"questiondown",0x0bf;
+"Agrave",0x0c0;
+"Aacute",0x0c1;
+"Acircumflex",0x0c2;
+"Atilde",0x0c3;
+"Adiaeresis",0x0c4;
+"Aring",0x0c5;
+"AE",0x0c6;
+"Ccedilla",0x0c7;
+"Egrave",0x0c8;
+"Eacute",0x0c9;
+"Ecircumflex",0x0ca;
+"Ediaeresis",0x0cb;
+"Igrave",0x0cc;
+"Iacute",0x0cd;
+"Icircumflex",0x0ce;
+"Idiaeresis",0x0cf;
+"ETH",0x0d0;
+"Eth",0x0d0;
+"Ntilde",0x0d1;
+"Ograve",0x0d2;
+"Oacute",0x0d3;
+"Ocircumflex",0x0d4;
+"Otilde",0x0d5;
+"Odiaeresis",0x0d6;
+"multiply",0x0d7;
+"Ooblique",0x0d8;
+"Ugrave",0x0d9;
+"Uacute",0x0da;
+"Ucircumflex",0x0db;
+"Udiaeresis",0x0dc;
+"Yacute",0x0dd;
+"THORN",0x0de;
+"Thorn",0x0de;
+"ssharp",0x0df;
+"agrave",0x0e0;
+"aacute",0x0e1;
+"acircumflex",0x0e2;
+"atilde",0x0e3;
+"adiaeresis",0x0e4;
+"aring",0x0e5;
+"ae",0x0e6;
+"ccedilla",0x0e7;
+"egrave",0x0e8;
+"eacute",0x0e9;
+"ecircumflex",0x0ea;
+"ediaeresis",0x0eb;
+"igrave",0x0ec;
+"iacute",0x0ed;
+"icircumflex",0x0ee;
+"idiaeresis",0x0ef;
+"eth",0x0f0;
+"ntilde",0x0f1;
+"ograve",0x0f2;
+"oacute",0x0f3;
+"ocircumflex",0x0f4;
+"otilde",0x0f5;
+"odiaeresis",0x0f6;
+"division",0x0f7;
+"oslash",0x0f8;
+"ugrave",0x0f9;
+"uacute",0x0fa;
+"ucircumflex",0x0fb;
+"udiaeresis",0x0fc;
+"yacute",0x0fd;
+"thorn",0x0fe;
+"ydiaeresis",0x0ff;
+"Aogonek",0x1a1;
+"breve",0x1a2;
+"Lstroke",0x1a3;
+"Lcaron",0x1a5;
+"Sacute",0x1a6;
+"Scaron",0x1a9;
+"Scedilla",0x1aa;
+"Tcaron",0x1ab;
+"Zacute",0x1ac;
+"Zcaron",0x1ae;
+"Zabovedot",0x1af;
+"aogonek",0x1b1;
+"ogonek",0x1b2;
+"lstroke",0x1b3;
+"lcaron",0x1b5;
+"sacute",0x1b6;
+"caron",0x1b7;
+"scaron",0x1b9;
+"scedilla",0x1ba;
+"tcaron",0x1bb;
+"zacute",0x1bc;
+"doubleacute",0x1bd;
+"zcaron",0x1be;
+"zabovedot",0x1bf;
+"Racute",0x1c0;
+"Abreve",0x1c3;
+"Lacute",0x1c5;
+"Cacute",0x1c6;
+"Ccaron",0x1c8;
+"Eogonek",0x1ca;
+"Ecaron",0x1cc;
+"Dcaron",0x1cf;
+"Dstroke",0x1d0;
+"Nacute",0x1d1;
+"Ncaron",0x1d2;
+"Odoubleacute",0x1d5;
+"Rcaron",0x1d8;
+"Uring",0x1d9;
+"Udoubleacute",0x1db;
+"Tcedilla",0x1de;
+"racute",0x1e0;
+"abreve",0x1e3;
+"lacute",0x1e5;
+"cacute",0x1e6;
+"ccaron",0x1e8;
+"eogonek",0x1ea;
+"ecaron",0x1ec;
+"dcaron",0x1ef;
+"dstroke",0x1f0;
+"nacute",0x1f1;
+"ncaron",0x1f2;
+"odoubleacute",0x1f5;
+"udoubleacute",0x1fb;
+"rcaron",0x1f8;
+"uring",0x1f9;
+"tcedilla",0x1fe;
+"abovedot",0x1ff;
+"Hstroke",0x2a1;
+"Hcircumflex",0x2a6;
+"Iabovedot",0x2a9;
+"Gbreve",0x2ab;
+"Jcircumflex",0x2ac;
+"hstroke",0x2b1;
+"hcircumflex",0x2b6;
+"idotless",0x2b9;
+"gbreve",0x2bb;
+"jcircumflex",0x2bc;
+"Cabovedot",0x2c5;
+"Ccircumflex",0x2c6;
+"Gabovedot",0x2d5;
+"Gcircumflex",0x2d8;
+"Ubreve",0x2dd;
+"Scircumflex",0x2de;
+"cabovedot",0x2e5;
+"ccircumflex",0x2e6;
+"gabovedot",0x2f5;
+"gcircumflex",0x2f8;
+"ubreve",0x2fd;
+"scircumflex",0x2fe;
+"kra",0x3a2;
+"kappa",0x3a2;
+"Rcedilla",0x3a3;
+"Itilde",0x3a5;
+"Lcedilla",0x3a6;
+"Emacron",0x3aa;
+"Gcedilla",0x3ab;
+"Tslash",0x3ac;
+"rcedilla",0x3b3;
+"itilde",0x3b5;
+"lcedilla",0x3b6;
+"emacron",0x3ba;
+"gcedilla",0x3bb;
+"tslash",0x3bc;
+"ENG",0x3bd;
+"eng",0x3bf;
+"Amacron",0x3c0;
+"Iogonek",0x3c7;
+"Eabovedot",0x3cc;
+"Imacron",0x3cf;
+"Ncedilla",0x3d1;
+"Omacron",0x3d2;
+"Kcedilla",0x3d3;
+"Uogonek",0x3d9;
+"Utilde",0x3dd;
+"Umacron",0x3de;
+"amacron",0x3e0;
+"iogonek",0x3e7;
+"eabovedot",0x3ec;
+"imacron",0x3ef;
+"ncedilla",0x3f1;
+"omacron",0x3f2;
+"kcedilla",0x3f3;
+"uogonek",0x3f9;
+"utilde",0x3fd;
+"umacron",0x3fe;
+"overline",0x47e;
+"kana_fullstop",0x4a1;
+"kana_openingbracket",0x4a2;
+"kana_closingbracket",0x4a3;
+"kana_comma",0x4a4;
+"kana_conjunctive",0x4a5;
+"kana_middledot",0x4a5;
+"kana_WO",0x4a6;
+"kana_a",0x4a7;
+"kana_i",0x4a8;
+"kana_u",0x4a9;
+"kana_e",0x4aa;
+"kana_o",0x4ab;
+"kana_ya",0x4ac;
+"kana_yu",0x4ad;
+"kana_yo",0x4ae;
+"kana_tsu",0x4af;
+"kana_tu",0x4af;
+"prolongedsound",0x4b0;
+"kana_A",0x4b1;
+"kana_I",0x4b2;
+"kana_U",0x4b3;
+"kana_E",0x4b4;
+"kana_O",0x4b5;
+"kana_KA",0x4b6;
+"kana_KI",0x4b7;
+"kana_KU",0x4b8;
+"kana_KE",0x4b9;
+"kana_KO",0x4ba;
+"kana_SA",0x4bb;
+"kana_SHI",0x4bc;
+"kana_SU",0x4bd;
+"kana_SE",0x4be;
+"kana_SO",0x4bf;
+"kana_TA",0x4c0;
+"kana_CHI",0x4c1;
+"kana_TI",0x4c1;
+"kana_TSU",0x4c2;
+"kana_TU",0x4c2;
+"kana_TE",0x4c3;
+"kana_TO",0x4c4;
+"kana_NA",0x4c5;
+"kana_NI",0x4c6;
+"kana_NU",0x4c7;
+"kana_NE",0x4c8;
+"kana_NO",0x4c9;
+"kana_HA",0x4ca;
+"kana_HI",0x4cb;
+"kana_FU",0x4cc;
+"kana_HU",0x4cc;
+"kana_HE",0x4cd;
+"kana_HO",0x4ce;
+"kana_MA",0x4cf;
+"kana_MI",0x4d0;
+"kana_MU",0x4d1;
+"kana_ME",0x4d2;
+"kana_MO",0x4d3;
+"kana_YA",0x4d4;
+"kana_YU",0x4d5;
+"kana_YO",0x4d6;
+"kana_RA",0x4d7;
+"kana_RI",0x4d8;
+"kana_RU",0x4d9;
+"kana_RE",0x4da;
+"kana_RO",0x4db;
+"kana_WA",0x4dc;
+"kana_N",0x4dd;
+"voicedsound",0x4de;
+"semivoicedsound",0x4df;
+"kana_switch",0xFF7E;
+"Arabic_comma",0x5ac;
+"Arabic_semicolon",0x5bb;
+"Arabic_question_mark",0x5bf;
+"Arabic_hamza",0x5c1;
+"Arabic_maddaonalef",0x5c2;
+"Arabic_hamzaonalef",0x5c3;
+"Arabic_hamzaonwaw",0x5c4;
+"Arabic_hamzaunderalef",0x5c5;
+"Arabic_hamzaonyeh",0x5c6;
+"Arabic_alef",0x5c7;
+"Arabic_beh",0x5c8;
+"Arabic_tehmarbuta",0x5c9;
+"Arabic_teh",0x5ca;
+"Arabic_theh",0x5cb;
+"Arabic_jeem",0x5cc;
+"Arabic_hah",0x5cd;
+"Arabic_khah",0x5ce;
+"Arabic_dal",0x5cf;
+"Arabic_thal",0x5d0;
+"Arabic_ra",0x5d1;
+"Arabic_zain",0x5d2;
+"Arabic_seen",0x5d3;
+"Arabic_sheen",0x5d4;
+"Arabic_sad",0x5d5;
+"Arabic_dad",0x5d6;
+"Arabic_tah",0x5d7;
+"Arabic_zah",0x5d8;
+"Arabic_ain",0x5d9;
+"Arabic_ghain",0x5da;
+"Arabic_tatweel",0x5e0;
+"Arabic_feh",0x5e1;
+"Arabic_qaf",0x5e2;
+"Arabic_kaf",0x5e3;
+"Arabic_lam",0x5e4;
+"Arabic_meem",0x5e5;
+"Arabic_noon",0x5e6;
+"Arabic_ha",0x5e7;
+"Arabic_heh",0x5e7;
+"Arabic_waw",0x5e8;
+"Arabic_alefmaksura",0x5e9;
+"Arabic_yeh",0x5ea;
+"Arabic_fathatan",0x5eb;
+"Arabic_dammatan",0x5ec;
+"Arabic_kasratan",0x5ed;
+"Arabic_fatha",0x5ee;
+"Arabic_damma",0x5ef;
+"Arabic_kasra",0x5f0;
+"Arabic_shadda",0x5f1;
+"Arabic_sukun",0x5f2;
+"Arabic_switch",0xFF7E;
+"Serbian_dje",0x6a1;
+"Macedonia_gje",0x6a2;
+"Cyrillic_io",0x6a3;
+"Ukrainian_ie",0x6a4;
+"Ukranian_je",0x6a4;
+"Macedonia_dse",0x6a5;
+"Ukrainian_i",0x6a6;
+"Ukranian_i",0x6a6;
+"Ukrainian_yi",0x6a7;
+"Ukranian_yi",0x6a7;
+"Cyrillic_je",0x6a8;
+"Serbian_je",0x6a8;
+"Cyrillic_lje",0x6a9;
+"Serbian_lje",0x6a9;
+"Cyrillic_nje",0x6aa;
+"Serbian_nje",0x6aa;
+"Serbian_tshe",0x6ab;
+"Macedonia_kje",0x6ac;
+"Byelorussian_shortu",0x6ae;
+"Cyrillic_dzhe",0x6af;
+"Serbian_dze",0x6af;
+"numerosign",0x6b0;
+"Serbian_DJE",0x6b1;
+"Macedonia_GJE",0x6b2;
+"Cyrillic_IO",0x6b3;
+"Ukrainian_IE",0x6b4;
+"Ukranian_JE",0x6b4;
+"Macedonia_DSE",0x6b5;
+"Ukrainian_I",0x6b6;
+"Ukranian_I",0x6b6;
+"Ukrainian_YI",0x6b7;
+"Ukranian_YI",0x6b7;
+"Cyrillic_JE",0x6b8;
+"Serbian_JE",0x6b8;
+"Cyrillic_LJE",0x6b9;
+"Serbian_LJE",0x6b9;
+"Cyrillic_NJE",0x6ba;
+"Serbian_NJE",0x6ba;
+"Serbian_TSHE",0x6bb;
+"Macedonia_KJE",0x6bc;
+"Byelorussian_SHORTU",0x6be;
+"Cyrillic_DZHE",0x6bf;
+"Serbian_DZE",0x6bf;
+"Cyrillic_yu",0x6c0;
+"Cyrillic_a",0x6c1;
+"Cyrillic_be",0x6c2;
+"Cyrillic_tse",0x6c3;
+"Cyrillic_de",0x6c4;
+"Cyrillic_ie",0x6c5;
+"Cyrillic_ef",0x6c6;
+"Cyrillic_ghe",0x6c7;
+"Cyrillic_ha",0x6c8;
+"Cyrillic_i",0x6c9;
+"Cyrillic_shorti",0x6ca;
+"Cyrillic_ka",0x6cb;
+"Cyrillic_el",0x6cc;
+"Cyrillic_em",0x6cd;
+"Cyrillic_en",0x6ce;
+"Cyrillic_o",0x6cf;
+"Cyrillic_pe",0x6d0;
+"Cyrillic_ya",0x6d1;
+"Cyrillic_er",0x6d2;
+"Cyrillic_es",0x6d3;
+"Cyrillic_te",0x6d4;
+"Cyrillic_u",0x6d5;
+"Cyrillic_zhe",0x6d6;
+"Cyrillic_ve",0x6d7;
+"Cyrillic_softsign",0x6d8;
+"Cyrillic_yeru",0x6d9;
+"Cyrillic_ze",0x6da;
+"Cyrillic_sha",0x6db;
+"Cyrillic_e",0x6dc;
+"Cyrillic_shcha",0x6dd;
+"Cyrillic_che",0x6de;
+"Cyrillic_hardsign",0x6df;
+"Cyrillic_YU",0x6e0;
+"Cyrillic_A",0x6e1;
+"Cyrillic_BE",0x6e2;
+"Cyrillic_TSE",0x6e3;
+"Cyrillic_DE",0x6e4;
+"Cyrillic_IE",0x6e5;
+"Cyrillic_EF",0x6e6;
+"Cyrillic_GHE",0x6e7;
+"Cyrillic_HA",0x6e8;
+"Cyrillic_I",0x6e9;
+"Cyrillic_SHORTI",0x6ea;
+"Cyrillic_KA",0x6eb;
+"Cyrillic_EL",0x6ec;
+"Cyrillic_EM",0x6ed;
+"Cyrillic_EN",0x6ee;
+"Cyrillic_O",0x6ef;
+"Cyrillic_PE",0x6f0;
+"Cyrillic_YA",0x6f1;
+"Cyrillic_ER",0x6f2;
+"Cyrillic_ES",0x6f3;
+"Cyrillic_TE",0x6f4;
+"Cyrillic_U",0x6f5;
+"Cyrillic_ZHE",0x6f6;
+"Cyrillic_VE",0x6f7;
+"Cyrillic_SOFTSIGN",0x6f8;
+"Cyrillic_YERU",0x6f9;
+"Cyrillic_ZE",0x6fa;
+"Cyrillic_SHA",0x6fb;
+"Cyrillic_E",0x6fc;
+"Cyrillic_SHCHA",0x6fd;
+"Cyrillic_CHE",0x6fe;
+"Cyrillic_HARDSIGN",0x6ff;
+"Greek_ALPHAaccent",0x7a1;
+"Greek_EPSILONaccent",0x7a2;
+"Greek_ETAaccent",0x7a3;
+"Greek_IOTAaccent",0x7a4;
+"Greek_IOTAdiaeresis",0x7a5;
+"Greek_OMICRONaccent",0x7a7;
+"Greek_UPSILONaccent",0x7a8;
+"Greek_UPSILONdieresis",0x7a9;
+"Greek_OMEGAaccent",0x7ab;
+"Greek_accentdieresis",0x7ae;
+"Greek_horizbar",0x7af;
+"Greek_alphaaccent",0x7b1;
+"Greek_epsilonaccent",0x7b2;
+"Greek_etaaccent",0x7b3;
+"Greek_iotaaccent",0x7b4;
+"Greek_iotadieresis",0x7b5;
+"Greek_iotaaccentdieresis",0x7b6;
+"Greek_omicronaccent",0x7b7;
+"Greek_upsilonaccent",0x7b8;
+"Greek_upsilondieresis",0x7b9;
+"Greek_upsilonaccentdieresis",0x7ba;
+"Greek_omegaaccent",0x7bb;
+"Greek_ALPHA",0x7c1;
+"Greek_BETA",0x7c2;
+"Greek_GAMMA",0x7c3;
+"Greek_DELTA",0x7c4;
+"Greek_EPSILON",0x7c5;
+"Greek_ZETA",0x7c6;
+"Greek_ETA",0x7c7;
+"Greek_THETA",0x7c8;
+"Greek_IOTA",0x7c9;
+"Greek_KAPPA",0x7ca;
+"Greek_LAMDA",0x7cb;
+"Greek_LAMBDA",0x7cb;
+"Greek_MU",0x7cc;
+"Greek_NU",0x7cd;
+"Greek_XI",0x7ce;
+"Greek_OMICRON",0x7cf;
+"Greek_PI",0x7d0;
+"Greek_RHO",0x7d1;
+"Greek_SIGMA",0x7d2;
+"Greek_TAU",0x7d4;
+"Greek_UPSILON",0x7d5;
+"Greek_PHI",0x7d6;
+"Greek_CHI",0x7d7;
+"Greek_PSI",0x7d8;
+"Greek_OMEGA",0x7d9;
+"Greek_alpha",0x7e1;
+"Greek_beta",0x7e2;
+"Greek_gamma",0x7e3;
+"Greek_delta",0x7e4;
+"Greek_epsilon",0x7e5;
+"Greek_zeta",0x7e6;
+"Greek_eta",0x7e7;
+"Greek_theta",0x7e8;
+"Greek_iota",0x7e9;
+"Greek_kappa",0x7ea;
+"Greek_lamda",0x7eb;
+"Greek_lambda",0x7eb;
+"Greek_mu",0x7ec;
+"Greek_nu",0x7ed;
+"Greek_xi",0x7ee;
+"Greek_omicron",0x7ef;
+"Greek_pi",0x7f0;
+"Greek_rho",0x7f1;
+"Greek_sigma",0x7f2;
+"Greek_finalsmallsigma",0x7f3;
+"Greek_tau",0x7f4;
+"Greek_upsilon",0x7f5;
+"Greek_phi",0x7f6;
+"Greek_chi",0x7f7;
+"Greek_psi",0x7f8;
+"Greek_omega",0x7f9;
+"Greek_switch",0xFF7E;
+"leftradical",0x8a1;
+"topleftradical",0x8a2;
+"horizconnector",0x8a3;
+"topintegral",0x8a4;
+"botintegral",0x8a5;
+"vertconnector",0x8a6;
+"topleftsqbracket",0x8a7;
+"botleftsqbracket",0x8a8;
+"toprightsqbracket",0x8a9;
+"botrightsqbracket",0x8aa;
+"topleftparens",0x8ab;
+"botleftparens",0x8ac;
+"toprightparens",0x8ad;
+"botrightparens",0x8ae;
+"leftmiddlecurlybrace",0x8af;
+"rightmiddlecurlybrace",0x8b0;
+"topleftsummation",0x8b1;
+"botleftsummation",0x8b2;
+"topvertsummationconnector",0x8b3;
+"botvertsummationconnector",0x8b4;
+"toprightsummation",0x8b5;
+"botrightsummation",0x8b6;
+"rightmiddlesummation",0x8b7;
+"lessthanequal",0x8bc;
+"notequal",0x8bd;
+"greaterthanequal",0x8be;
+"integral",0x8bf;
+"therefore",0x8c0;
+"variation",0x8c1;
+"infinity",0x8c2;
+"nabla",0x8c5;
+"approximate",0x8c8;
+"similarequal",0x8c9;
+"ifonlyif",0x8cd;
+"implies",0x8ce;
+"identical",0x8cf;
+"radical",0x8d6;
+"includedin",0x8da;
+"includes",0x8db;
+"intersection",0x8dc;
+"union",0x8dd;
+"logicaland",0x8de;
+"logicalor",0x8df;
+"partialderivative",0x8ef;
+"function",0x8f6;
+"leftarrow",0x8fb;
+"uparrow",0x8fc;
+"rightarrow",0x8fd;
+"downarrow",0x8fe;
+"blank",0x9df;
+"soliddiamond",0x9e0;
+"checkerboard",0x9e1;
+"ht",0x9e2;
+"ff",0x9e3;
+"cr",0x9e4;
+"lf",0x9e5;
+"nl",0x9e8;
+"vt",0x9e9;
+"lowrightcorner",0x9ea;
+"uprightcorner",0x9eb;
+"upleftcorner",0x9ec;
+"lowleftcorner",0x9ed;
+"crossinglines",0x9ee;
+"horizlinescan1",0x9ef;
+"horizlinescan3",0x9f0;
+"horizlinescan5",0x9f1;
+"horizlinescan7",0x9f2;
+"horizlinescan9",0x9f3;
+"leftt",0x9f4;
+"rightt",0x9f5;
+"bott",0x9f6;
+"topt",0x9f7;
+"vertbar",0x9f8;
+"emspace",0xaa1;
+"enspace",0xaa2;
+"em3space",0xaa3;
+"em4space",0xaa4;
+"digitspace",0xaa5;
+"punctspace",0xaa6;
+"thinspace",0xaa7;
+"hairspace",0xaa8;
+"emdash",0xaa9;
+"endash",0xaaa;
+"signifblank",0xaac;
+"ellipsis",0xaae;
+"doubbaselinedot",0xaaf;
+"onethird",0xab0;
+"twothirds",0xab1;
+"onefifth",0xab2;
+"twofifths",0xab3;
+"threefifths",0xab4;
+"fourfifths",0xab5;
+"onesixth",0xab6;
+"fivesixths",0xab7;
+"careof",0xab8;
+"figdash",0xabb;
+"leftanglebracket",0xabc;
+"decimalpoint",0xabd;
+"rightanglebracket",0xabe;
+"marker",0xabf;
+"oneeighth",0xac3;
+"threeeighths",0xac4;
+"fiveeighths",0xac5;
+"seveneighths",0xac6;
+"trademark",0xac9;
+"signaturemark",0xaca;
+"trademarkincircle",0xacb;
+"leftopentriangle",0xacc;
+"rightopentriangle",0xacd;
+"emopencircle",0xace;
+"emopenrectangle",0xacf;
+"leftsinglequotemark",0xad0;
+"rightsinglequotemark",0xad1;
+"leftdoublequotemark",0xad2;
+"rightdoublequotemark",0xad3;
+"prescription",0xad4;
+"minutes",0xad6;
+"seconds",0xad7;
+"latincross",0xad9;
+"hexagram",0xada;
+"filledrectbullet",0xadb;
+"filledlefttribullet",0xadc;
+"filledrighttribullet",0xadd;
+"emfilledcircle",0xade;
+"emfilledrect",0xadf;
+"enopencircbullet",0xae0;
+"enopensquarebullet",0xae1;
+"openrectbullet",0xae2;
+"opentribulletup",0xae3;
+"opentribulletdown",0xae4;
+"openstar",0xae5;
+"enfilledcircbullet",0xae6;
+"enfilledsqbullet",0xae7;
+"filledtribulletup",0xae8;
+"filledtribulletdown",0xae9;
+"leftpointer",0xaea;
+"rightpointer",0xaeb;
+"club",0xaec;
+"diamond",0xaed;
+"heart",0xaee;
+"maltesecross",0xaf0;
+"dagger",0xaf1;
+"doubledagger",0xaf2;
+"checkmark",0xaf3;
+"ballotcross",0xaf4;
+"musicalsharp",0xaf5;
+"musicalflat",0xaf6;
+"malesymbol",0xaf7;
+"femalesymbol",0xaf8;
+"telephone",0xaf9;
+"telephonerecorder",0xafa;
+"phonographcopyright",0xafb;
+"caret",0xafc;
+"singlelowquotemark",0xafd;
+"doublelowquotemark",0xafe;
+"cursor",0xaff;
+"leftcaret",0xba3;
+"rightcaret",0xba6;
+"downcaret",0xba8;
+"upcaret",0xba9;
+"overbar",0xbc0;
+"downtack",0xbc2;
+"upshoe",0xbc3;
+"downstile",0xbc4;
+"underbar",0xbc6;
+"jot",0xbca;
+"quad",0xbcc;
+"uptack",0xbce;
+"circle",0xbcf;
+"upstile",0xbd3;
+"downshoe",0xbd6;
+"rightshoe",0xbd8;
+"leftshoe",0xbda;
+"lefttack",0xbdc;
+"righttack",0xbfc;
+"hebrew_doublelowline",0xcdf;
+"hebrew_aleph",0xce0;
+"hebrew_bet",0xce1;
+"hebrew_beth",0xce1;
+"hebrew_gimel",0xce2;
+"hebrew_gimmel",0xce2;
+"hebrew_dalet",0xce3;
+"hebrew_daleth",0xce3;
+"hebrew_he",0xce4;
+"hebrew_waw",0xce5;
+"hebrew_zain",0xce6;
+"hebrew_zayin",0xce6;
+"hebrew_chet",0xce7;
+"hebrew_het",0xce7;
+"hebrew_tet",0xce8;
+"hebrew_teth",0xce8;
+"hebrew_yod",0xce9;
+"hebrew_finalkaph",0xcea;
+"hebrew_kaph",0xceb;
+"hebrew_lamed",0xcec;
+"hebrew_finalmem",0xced;
+"hebrew_mem",0xcee;
+"hebrew_finalnun",0xcef;
+"hebrew_nun",0xcf0;
+"hebrew_samech",0xcf1;
+"hebrew_samekh",0xcf1;
+"hebrew_ayin",0xcf2;
+"hebrew_finalpe",0xcf3;
+"hebrew_pe",0xcf4;
+"hebrew_finalzade",0xcf5;
+"hebrew_finalzadi",0xcf5;
+"hebrew_zade",0xcf6;
+"hebrew_zadi",0xcf6;
+"hebrew_qoph",0xcf7;
+"hebrew_kuf",0xcf7;
+"hebrew_resh",0xcf8;
+"hebrew_shin",0xcf9;
+"hebrew_taw",0xcfa;
+"hebrew_taf",0xcfa;
+"Hebrew_switch",0xFF7E;
+"Thai_kokai",0xda1;
+"Thai_khokhai",0xda2;
+"Thai_khokhuat",0xda3;
+"Thai_khokhwai",0xda4;
+"Thai_khokhon",0xda5;
+"Thai_khorakhang",0xda6;
+"Thai_ngongu",0xda7;
+"Thai_chochan",0xda8;
+"Thai_choching",0xda9;
+"Thai_chochang",0xdaa;
+"Thai_soso",0xdab;
+"Thai_chochoe",0xdac;
+"Thai_yoying",0xdad;
+"Thai_dochada",0xdae;
+"Thai_topatak",0xdaf;
+"Thai_thothan",0xdb0;
+"Thai_thonangmontho",0xdb1;
+"Thai_thophuthao",0xdb2;
+"Thai_nonen",0xdb3;
+"Thai_dodek",0xdb4;
+"Thai_totao",0xdb5;
+"Thai_thothung",0xdb6;
+"Thai_thothahan",0xdb7;
+"Thai_thothong",0xdb8;
+"Thai_nonu",0xdb9;
+"Thai_bobaimai",0xdba;
+"Thai_popla",0xdbb;
+"Thai_phophung",0xdbc;
+"Thai_fofa",0xdbd;
+"Thai_phophan",0xdbe;
+"Thai_fofan",0xdbf;
+"Thai_phosamphao",0xdc0;
+"Thai_moma",0xdc1;
+"Thai_yoyak",0xdc2;
+"Thai_rorua",0xdc3;
+"Thai_ru",0xdc4;
+"Thai_loling",0xdc5;
+"Thai_lu",0xdc6;
+"Thai_wowaen",0xdc7;
+"Thai_sosala",0xdc8;
+"Thai_sorusi",0xdc9;
+"Thai_sosua",0xdca;
+"Thai_hohip",0xdcb;
+"Thai_lochula",0xdcc;
+"Thai_oang",0xdcd;
+"Thai_honokhuk",0xdce;
+"Thai_paiyannoi",0xdcf;
+"Thai_saraa",0xdd0;
+"Thai_maihanakat",0xdd1;
+"Thai_saraaa",0xdd2;
+"Thai_saraam",0xdd3;
+"Thai_sarai",0xdd4;
+"Thai_saraii",0xdd5;
+"Thai_saraue",0xdd6;
+"Thai_sarauee",0xdd7;
+"Thai_sarau",0xdd8;
+"Thai_sarauu",0xdd9;
+"Thai_phinthu",0xdda;
+"Thai_maihanakat_maitho",0xdde;
+"Thai_baht",0xddf;
+"Thai_sarae",0xde0;
+"Thai_saraae",0xde1;
+"Thai_sarao",0xde2;
+"Thai_saraaimaimuan",0xde3;
+"Thai_saraaimaimalai",0xde4;
+"Thai_lakkhangyao",0xde5;
+"Thai_maiyamok",0xde6;
+"Thai_maitaikhu",0xde7;
+"Thai_maiek",0xde8;
+"Thai_maitho",0xde9;
+"Thai_maitri",0xdea;
+"Thai_maichattawa",0xdeb;
+"Thai_thanthakhat",0xdec;
+"Thai_nikhahit",0xded;
+"Thai_leksun",0xdf0;
+"Thai_leknung",0xdf1;
+"Thai_leksong",0xdf2;
+"Thai_leksam",0xdf3;
+"Thai_leksi",0xdf4;
+"Thai_lekha",0xdf5;
+"Thai_lekhok",0xdf6;
+"Thai_lekchet",0xdf7;
+"Thai_lekpaet",0xdf8;
+"Thai_lekkao",0xdf9;
+"Hangul",0xff31;
+"Hangul_Start",0xff32;
+"Hangul_End",0xff33;
+"Hangul_Hanja",0xff34;
+"Hangul_Jamo",0xff35;
+"Hangul_Romaja",0xff36;
+"Hangul_Codeinput",0xff37;
+"Hangul_Jeonja",0xff38;
+"Hangul_Banja",0xff39;
+"Hangul_PreHanja",0xff3a;
+"Hangul_PostHanja",0xff3b;
+"Hangul_SingleCandidate",0xff3c;
+"Hangul_MultipleCandidate",0xff3d;
+"Hangul_PreviousCandidate",0xff3e;
+"Hangul_Special",0xff3f;
+"Hangul_switch",0xFF7E;
+"Hangul_Kiyeog",0xea1;
+"Hangul_SsangKiyeog",0xea2;
+"Hangul_KiyeogSios",0xea3;
+"Hangul_Nieun",0xea4;
+"Hangul_NieunJieuj",0xea5;
+"Hangul_NieunHieuh",0xea6;
+"Hangul_Dikeud",0xea7;
+"Hangul_SsangDikeud",0xea8;
+"Hangul_Rieul",0xea9;
+"Hangul_RieulKiyeog",0xeaa;
+"Hangul_RieulMieum",0xeab;
+"Hangul_RieulPieub",0xeac;
+"Hangul_RieulSios",0xead;
+"Hangul_RieulTieut",0xeae;
+"Hangul_RieulPhieuf",0xeaf;
+"Hangul_RieulHieuh",0xeb0;
+"Hangul_Mieum",0xeb1;
+"Hangul_Pieub",0xeb2;
+"Hangul_SsangPieub",0xeb3;
+"Hangul_PieubSios",0xeb4;
+"Hangul_Sios",0xeb5;
+"Hangul_SsangSios",0xeb6;
+"Hangul_Ieung",0xeb7;
+"Hangul_Jieuj",0xeb8;
+"Hangul_SsangJieuj",0xeb9;
+"Hangul_Cieuc",0xeba;
+"Hangul_Khieuq",0xebb;
+"Hangul_Tieut",0xebc;
+"Hangul_Phieuf",0xebd;
+"Hangul_Hieuh",0xebe;
+"Hangul_A",0xebf;
+"Hangul_AE",0xec0;
+"Hangul_YA",0xec1;
+"Hangul_YAE",0xec2;
+"Hangul_EO",0xec3;
+"Hangul_E",0xec4;
+"Hangul_YEO",0xec5;
+"Hangul_YE",0xec6;
+"Hangul_O",0xec7;
+"Hangul_WA",0xec8;
+"Hangul_WAE",0xec9;
+"Hangul_OE",0xeca;
+"Hangul_YO",0xecb;
+"Hangul_U",0xecc;
+"Hangul_WEO",0xecd;
+"Hangul_WE",0xece;
+"Hangul_WI",0xecf;
+"Hangul_YU",0xed0;
+"Hangul_EU",0xed1;
+"Hangul_YI",0xed2;
+"Hangul_I",0xed3;
+"Hangul_J_Kiyeog",0xed4;
+"Hangul_J_SsangKiyeog",0xed5;
+"Hangul_J_KiyeogSios",0xed6;
+"Hangul_J_Nieun",0xed7;
+"Hangul_J_NieunJieuj",0xed8;
+"Hangul_J_NieunHieuh",0xed9;
+"Hangul_J_Dikeud",0xeda;
+"Hangul_J_Rieul",0xedb;
+"Hangul_J_RieulKiyeog",0xedc;
+"Hangul_J_RieulMieum",0xedd;
+"Hangul_J_RieulPieub",0xede;
+"Hangul_J_RieulSios",0xedf;
+"Hangul_J_RieulTieut",0xee0;
+"Hangul_J_RieulPhieuf",0xee1;
+"Hangul_J_RieulHieuh",0xee2;
+"Hangul_J_Mieum",0xee3;
+"Hangul_J_Pieub",0xee4;
+"Hangul_J_PieubSios",0xee5;
+"Hangul_J_Sios",0xee6;
+"Hangul_J_SsangSios",0xee7;
+"Hangul_J_Ieung",0xee8;
+"Hangul_J_Jieuj",0xee9;
+"Hangul_J_Cieuc",0xeea;
+"Hangul_J_Khieuq",0xeeb;
+"Hangul_J_Tieut",0xeec;
+"Hangul_J_Phieuf",0xeed;
+"Hangul_J_Hieuh",0xeee;
+"Hangul_RieulYeorinHieuh",0xeef;
+"Hangul_SunkyeongeumMieum",0xef0;
+"Hangul_SunkyeongeumPieub",0xef1;
+"Hangul_PanSios",0xef2;
+"Hangul_KkogjiDalrinIeung",0xef3;
+"Hangul_SunkyeongeumPhieuf",0xef4;
+"Hangul_YeorinHieuh",0xef5;
+"Hangul_AraeA",0xef6;
+"Hangul_AraeAE",0xef7;
+"Hangul_J_PanSios",0xef8;
+"Hangul_J_KkogjiDalrinIeung",0xef9;
+"Hangul_J_YeorinHieuh",0xefa;
+"Korean_Won",0xeff;
+]
+let keysym_to_name = [
+0xFFFFFF,"VoidSymbol";
+0xFF08,"BackSpace";
+0xFF09,"Tab";
+0xFF0A,"Linefeed";
+0xFF0B,"Clear";
+0xFF0D,"Return";
+0xFF13,"Pause";
+0xFF14,"Scroll_Lock";
+0xFF15,"Sys_Req";
+0xFF1B,"Escape";
+0xFFFF,"Delete";
+0xFF20,"Multi_key";
+0xFF21,"Kanji";
+0xFF22,"Muhenkan";
+0xFF23,"Henkan_Mode";
+0xFF23,"Henkan";
+0xFF24,"Romaji";
+0xFF25,"Hiragana";
+0xFF26,"Katakana";
+0xFF27,"Hiragana_Katakana";
+0xFF28,"Zenkaku";
+0xFF29,"Hankaku";
+0xFF2A,"Zenkaku_Hankaku";
+0xFF2B,"Touroku";
+0xFF2C,"Massyo";
+0xFF2D,"Kana_Lock";
+0xFF2E,"Kana_Shift";
+0xFF2F,"Eisu_Shift";
+0xFF30,"Eisu_toggle";
+0xFF50,"Home";
+0xFF51,"Left";
+0xFF52,"Up";
+0xFF53,"Right";
+0xFF54,"Down";
+0xFF55,"Prior";
+0xFF55,"Page_Up";
+0xFF56,"Next";
+0xFF56,"Page_Down";
+0xFF57,"End";
+0xFF58,"Begin";
+0xFF60,"Select";
+0xFF61,"Print";
+0xFF62,"Execute";
+0xFF63,"Insert";
+0xFF65,"Undo";
+0xFF66,"Redo";
+0xFF67,"Menu";
+0xFF68,"Find";
+0xFF69,"Cancel";
+0xFF6A,"Help";
+0xFF6B,"Break";
+0xFF7E,"Mode_switch";
+0xFF7E,"script_switch";
+0xFF7F,"Num_Lock";
+0xFF80,"KP_Space";
+0xFF89,"KP_Tab";
+0xFF8D,"KP_Enter";
+0xFF91,"KP_F1";
+0xFF92,"KP_F2";
+0xFF93,"KP_F3";
+0xFF94,"KP_F4";
+0xFF95,"KP_Home";
+0xFF96,"KP_Left";
+0xFF97,"KP_Up";
+0xFF98,"KP_Right";
+0xFF99,"KP_Down";
+0xFF9A,"KP_Prior";
+0xFF9A,"KP_Page_Up";
+0xFF9B,"KP_Next";
+0xFF9B,"KP_Page_Down";
+0xFF9C,"KP_End";
+0xFF9D,"KP_Begin";
+0xFF9E,"KP_Insert";
+0xFF9F,"KP_Delete";
+0xFFBD,"KP_Equal";
+0xFFAA,"KP_Multiply";
+0xFFAB,"KP_Add";
+0xFFAC,"KP_Separator";
+0xFFAD,"KP_Subtract";
+0xFFAE,"KP_Decimal";
+0xFFAF,"KP_Divide";
+0xFFB0,"KP_0";
+0xFFB1,"KP_1";
+0xFFB2,"KP_2";
+0xFFB3,"KP_3";
+0xFFB4,"KP_4";
+0xFFB5,"KP_5";
+0xFFB6,"KP_6";
+0xFFB7,"KP_7";
+0xFFB8,"KP_8";
+0xFFB9,"KP_9";
+0xFFBE,"F1";
+0xFFBF,"F2";
+0xFFC0,"F3";
+0xFFC1,"F4";
+0xFFC2,"F5";
+0xFFC3,"F6";
+0xFFC4,"F7";
+0xFFC5,"F8";
+0xFFC6,"F9";
+0xFFC7,"F10";
+0xFFC8,"F11";
+0xFFC8,"L1";
+0xFFC9,"F12";
+0xFFC9,"L2";
+0xFFCA,"F13";
+0xFFCA,"L3";
+0xFFCB,"F14";
+0xFFCB,"L4";
+0xFFCC,"F15";
+0xFFCC,"L5";
+0xFFCD,"F16";
+0xFFCD,"L6";
+0xFFCE,"F17";
+0xFFCE,"L7";
+0xFFCF,"F18";
+0xFFCF,"L8";
+0xFFD0,"F19";
+0xFFD0,"L9";
+0xFFD1,"F20";
+0xFFD1,"L10";
+0xFFD2,"F21";
+0xFFD2,"R1";
+0xFFD3,"F22";
+0xFFD3,"R2";
+0xFFD4,"F23";
+0xFFD4,"R3";
+0xFFD5,"F24";
+0xFFD5,"R4";
+0xFFD6,"F25";
+0xFFD6,"R5";
+0xFFD7,"F26";
+0xFFD7,"R6";
+0xFFD8,"F27";
+0xFFD8,"R7";
+0xFFD9,"F28";
+0xFFD9,"R8";
+0xFFDA,"F29";
+0xFFDA,"R9";
+0xFFDB,"F30";
+0xFFDB,"R10";
+0xFFDC,"F31";
+0xFFDC,"R11";
+0xFFDD,"F32";
+0xFFDD,"R12";
+0xFFDE,"F33";
+0xFFDE,"R13";
+0xFFDF,"F34";
+0xFFDF,"R14";
+0xFFE0,"F35";
+0xFFE0,"R15";
+0xFFE1,"Shift_L";
+0xFFE2,"Shift_R";
+0xFFE3,"Control_L";
+0xFFE4,"Control_R";
+0xFFE5,"Caps_Lock";
+0xFFE6,"Shift_Lock";
+0xFFE7,"Meta_L";
+0xFFE8,"Meta_R";
+0xFFE9,"Alt_L";
+0xFFEA,"Alt_R";
+0xFFEB,"Super_L";
+0xFFEC,"Super_R";
+0xFFED,"Hyper_L";
+0xFFEE,"Hyper_R";
+0xFE01,"ISO_Lock";
+0xFE02,"ISO_Level2_Latch";
+0xFE03,"ISO_Level3_Shift";
+0xFE04,"ISO_Level3_Latch";
+0xFE05,"ISO_Level3_Lock";
+0xFF7E,"ISO_Group_Shift";
+0xFE06,"ISO_Group_Latch";
+0xFE07,"ISO_Group_Lock";
+0xFE08,"ISO_Next_Group";
+0xFE09,"ISO_Next_Group_Lock";
+0xFE0A,"ISO_Prev_Group";
+0xFE0B,"ISO_Prev_Group_Lock";
+0xFE0C,"ISO_First_Group";
+0xFE0D,"ISO_First_Group_Lock";
+0xFE0E,"ISO_Last_Group";
+0xFE0F,"ISO_Last_Group_Lock";
+0xFE20,"ISO_Left_Tab";
+0xFE21,"ISO_Move_Line_Up";
+0xFE22,"ISO_Move_Line_Down";
+0xFE23,"ISO_Partial_Line_Up";
+0xFE24,"ISO_Partial_Line_Down";
+0xFE25,"ISO_Partial_Space_Left";
+0xFE26,"ISO_Partial_Space_Right";
+0xFE27,"ISO_Set_Margin_Left";
+0xFE28,"ISO_Set_Margin_Right";
+0xFE29,"ISO_Release_Margin_Left";
+0xFE2A,"ISO_Release_Margin_Right";
+0xFE2B,"ISO_Release_Both_Margins";
+0xFE2C,"ISO_Fast_Cursor_Left";
+0xFE2D,"ISO_Fast_Cursor_Right";
+0xFE2E,"ISO_Fast_Cursor_Up";
+0xFE2F,"ISO_Fast_Cursor_Down";
+0xFE30,"ISO_Continuous_Underline";
+0xFE31,"ISO_Discontinuous_Underline";
+0xFE32,"ISO_Emphasize";
+0xFE33,"ISO_Center_Object";
+0xFE34,"ISO_Enter";
+0xFE50,"dead_grave";
+0xFE51,"dead_acute";
+0xFE52,"dead_circumflex";
+0xFE53,"dead_tilde";
+0xFE54,"dead_macron";
+0xFE55,"dead_breve";
+0xFE56,"dead_abovedot";
+0xFE57,"dead_diaeresis";
+0xFE58,"dead_abovering";
+0xFE59,"dead_doubleacute";
+0xFE5A,"dead_caron";
+0xFE5B,"dead_cedilla";
+0xFE5C,"dead_ogonek";
+0xFE5D,"dead_iota";
+0xFE5E,"dead_voiced_sound";
+0xFE5F,"dead_semivoiced_sound";
+0xFE60,"dead_belowdot";
+0xFED0,"First_Virtual_Screen";
+0xFED1,"Prev_Virtual_Screen";
+0xFED2,"Next_Virtual_Screen";
+0xFED4,"Last_Virtual_Screen";
+0xFED5,"Terminate_Server";
+0xFE70,"AccessX_Enable";
+0xFE71,"AccessX_Feedback_Enable";
+0xFE72,"RepeatKeys_Enable";
+0xFE73,"SlowKeys_Enable";
+0xFE74,"BounceKeys_Enable";
+0xFE75,"StickyKeys_Enable";
+0xFE76,"MouseKeys_Enable";
+0xFE77,"MouseKeys_Accel_Enable";
+0xFE78,"Overlay1_Enable";
+0xFE79,"Overlay2_Enable";
+0xFE7A,"AudibleBell_Enable";
+0xFEE0,"Pointer_Left";
+0xFEE1,"Pointer_Right";
+0xFEE2,"Pointer_Up";
+0xFEE3,"Pointer_Down";
+0xFEE4,"Pointer_UpLeft";
+0xFEE5,"Pointer_UpRight";
+0xFEE6,"Pointer_DownLeft";
+0xFEE7,"Pointer_DownRight";
+0xFEE8,"Pointer_Button_Dflt";
+0xFEE9,"Pointer_Button1";
+0xFEEA,"Pointer_Button2";
+0xFEEB,"Pointer_Button3";
+0xFEEC,"Pointer_Button4";
+0xFEED,"Pointer_Button5";
+0xFEEE,"Pointer_DblClick_Dflt";
+0xFEEF,"Pointer_DblClick1";
+0xFEF0,"Pointer_DblClick2";
+0xFEF1,"Pointer_DblClick3";
+0xFEF2,"Pointer_DblClick4";
+0xFEF3,"Pointer_DblClick5";
+0xFEF4,"Pointer_Drag_Dflt";
+0xFEF5,"Pointer_Drag1";
+0xFEF6,"Pointer_Drag2";
+0xFEF7,"Pointer_Drag3";
+0xFEF8,"Pointer_Drag4";
+0xFEFD,"Pointer_Drag5";
+0xFEF9,"Pointer_EnableKeys";
+0xFEFA,"Pointer_Accelerate";
+0xFEFB,"Pointer_DfltBtnNext";
+0xFEFC,"Pointer_DfltBtnPrev";
+0xFD01,"3270_Duplicate";
+0xFD02,"3270_FieldMark";
+0xFD03,"3270_Right2";
+0xFD04,"3270_Left2";
+0xFD05,"3270_BackTab";
+0xFD06,"3270_EraseEOF";
+0xFD07,"3270_EraseInput";
+0xFD08,"3270_Reset";
+0xFD09,"3270_Quit";
+0xFD0A,"3270_PA1";
+0xFD0B,"3270_PA2";
+0xFD0C,"3270_PA3";
+0xFD0D,"3270_Test";
+0xFD0E,"3270_Attn";
+0xFD0F,"3270_CursorBlink";
+0xFD10,"3270_AltCursor";
+0xFD11,"3270_KeyClick";
+0xFD12,"3270_Jump";
+0xFD13,"3270_Ident";
+0xFD14,"3270_Rule";
+0xFD15,"3270_Copy";
+0xFD16,"3270_Play";
+0xFD17,"3270_Setup";
+0xFD18,"3270_Record";
+0xFD19,"3270_ChangeScreen";
+0xFD1A,"3270_DeleteWord";
+0xFD1B,"3270_ExSelect";
+0xFD1C,"3270_CursorSelect";
+0xFD1D,"3270_PrintScreen";
+0xFD1E,"3270_Enter";
+0x020,"space";
+0x021,"exclam";
+0x022,"quotedbl";
+0x023,"numbersign";
+0x024,"dollar";
+0x025,"percent";
+0x026,"ampersand";
+0x027,"apostrophe";
+0x027,"quoteright";
+0x028,"parenleft";
+0x029,"parenright";
+0x02a,"asterisk";
+0x02b,"plus";
+0x02c,"comma";
+0x02d,"minus";
+0x02e,"period";
+0x02f,"slash";
+0x030,"0";
+0x031,"1";
+0x032,"2";
+0x033,"3";
+0x034,"4";
+0x035,"5";
+0x036,"6";
+0x037,"7";
+0x038,"8";
+0x039,"9";
+0x03a,"colon";
+0x03b,"semicolon";
+0x03c,"less";
+0x03d,"equal";
+0x03e,"greater";
+0x03f,"question";
+0x040,"at";
+0x041,"A";
+0x042,"B";
+0x043,"C";
+0x044,"D";
+0x045,"E";
+0x046,"F";
+0x047,"G";
+0x048,"H";
+0x049,"I";
+0x04a,"J";
+0x04b,"K";
+0x04c,"L";
+0x04d,"M";
+0x04e,"N";
+0x04f,"O";
+0x050,"P";
+0x051,"Q";
+0x052,"R";
+0x053,"S";
+0x054,"T";
+0x055,"U";
+0x056,"V";
+0x057,"W";
+0x058,"X";
+0x059,"Y";
+0x05a,"Z";
+0x05b,"bracketleft";
+0x05c,"backslash";
+0x05d,"bracketright";
+0x05e,"asciicircum";
+0x05f,"underscore";
+0x060,"grave";
+0x060,"quoteleft";
+0x061,"a";
+0x062,"b";
+0x063,"c";
+0x064,"d";
+0x065,"e";
+0x066,"f";
+0x067,"g";
+0x068,"h";
+0x069,"i";
+0x06a,"j";
+0x06b,"k";
+0x06c,"l";
+0x06d,"m";
+0x06e,"n";
+0x06f,"o";
+0x070,"p";
+0x071,"q";
+0x072,"r";
+0x073,"s";
+0x074,"t";
+0x075,"u";
+0x076,"v";
+0x077,"w";
+0x078,"x";
+0x079,"y";
+0x07a,"z";
+0x07b,"braceleft";
+0x07c,"bar";
+0x07d,"braceright";
+0x07e,"asciitilde";
+0x0a0,"nobreakspace";
+0x0a1,"exclamdown";
+0x0a2,"cent";
+0x0a3,"sterling";
+0x0a4,"currency";
+0x0a5,"yen";
+0x0a6,"brokenbar";
+0x0a7,"section";
+0x0a8,"diaeresis";
+0x0a9,"copyright";
+0x0aa,"ordfeminine";
+0x0ab,"guillemotleft";
+0x0ac,"notsign";
+0x0ad,"hyphen";
+0x0ae,"registered";
+0x0af,"macron";
+0x0b0,"degree";
+0x0b1,"plusminus";
+0x0b2,"twosuperior";
+0x0b3,"threesuperior";
+0x0b4,"acute";
+0x0b5,"mu";
+0x0b6,"paragraph";
+0x0b7,"periodcentered";
+0x0b8,"cedilla";
+0x0b9,"onesuperior";
+0x0ba,"masculine";
+0x0bb,"guillemotright";
+0x0bc,"onequarter";
+0x0bd,"onehalf";
+0x0be,"threequarters";
+0x0bf,"questiondown";
+0x0c0,"Agrave";
+0x0c1,"Aacute";
+0x0c2,"Acircumflex";
+0x0c3,"Atilde";
+0x0c4,"Adiaeresis";
+0x0c5,"Aring";
+0x0c6,"AE";
+0x0c7,"Ccedilla";
+0x0c8,"Egrave";
+0x0c9,"Eacute";
+0x0ca,"Ecircumflex";
+0x0cb,"Ediaeresis";
+0x0cc,"Igrave";
+0x0cd,"Iacute";
+0x0ce,"Icircumflex";
+0x0cf,"Idiaeresis";
+0x0d0,"ETH";
+0x0d0,"Eth";
+0x0d1,"Ntilde";
+0x0d2,"Ograve";
+0x0d3,"Oacute";
+0x0d4,"Ocircumflex";
+0x0d5,"Otilde";
+0x0d6,"Odiaeresis";
+0x0d7,"multiply";
+0x0d8,"Ooblique";
+0x0d9,"Ugrave";
+0x0da,"Uacute";
+0x0db,"Ucircumflex";
+0x0dc,"Udiaeresis";
+0x0dd,"Yacute";
+0x0de,"THORN";
+0x0de,"Thorn";
+0x0df,"ssharp";
+0x0e0,"agrave";
+0x0e1,"aacute";
+0x0e2,"acircumflex";
+0x0e3,"atilde";
+0x0e4,"adiaeresis";
+0x0e5,"aring";
+0x0e6,"ae";
+0x0e7,"ccedilla";
+0x0e8,"egrave";
+0x0e9,"eacute";
+0x0ea,"ecircumflex";
+0x0eb,"ediaeresis";
+0x0ec,"igrave";
+0x0ed,"iacute";
+0x0ee,"icircumflex";
+0x0ef,"idiaeresis";
+0x0f0,"eth";
+0x0f1,"ntilde";
+0x0f2,"ograve";
+0x0f3,"oacute";
+0x0f4,"ocircumflex";
+0x0f5,"otilde";
+0x0f6,"odiaeresis";
+0x0f7,"division";
+0x0f8,"oslash";
+0x0f9,"ugrave";
+0x0fa,"uacute";
+0x0fb,"ucircumflex";
+0x0fc,"udiaeresis";
+0x0fd,"yacute";
+0x0fe,"thorn";
+0x0ff,"ydiaeresis";
+0x1a1,"Aogonek";
+0x1a2,"breve";
+0x1a3,"Lstroke";
+0x1a5,"Lcaron";
+0x1a6,"Sacute";
+0x1a9,"Scaron";
+0x1aa,"Scedilla";
+0x1ab,"Tcaron";
+0x1ac,"Zacute";
+0x1ae,"Zcaron";
+0x1af,"Zabovedot";
+0x1b1,"aogonek";
+0x1b2,"ogonek";
+0x1b3,"lstroke";
+0x1b5,"lcaron";
+0x1b6,"sacute";
+0x1b7,"caron";
+0x1b9,"scaron";
+0x1ba,"scedilla";
+0x1bb,"tcaron";
+0x1bc,"zacute";
+0x1bd,"doubleacute";
+0x1be,"zcaron";
+0x1bf,"zabovedot";
+0x1c0,"Racute";
+0x1c3,"Abreve";
+0x1c5,"Lacute";
+0x1c6,"Cacute";
+0x1c8,"Ccaron";
+0x1ca,"Eogonek";
+0x1cc,"Ecaron";
+0x1cf,"Dcaron";
+0x1d0,"Dstroke";
+0x1d1,"Nacute";
+0x1d2,"Ncaron";
+0x1d5,"Odoubleacute";
+0x1d8,"Rcaron";
+0x1d9,"Uring";
+0x1db,"Udoubleacute";
+0x1de,"Tcedilla";
+0x1e0,"racute";
+0x1e3,"abreve";
+0x1e5,"lacute";
+0x1e6,"cacute";
+0x1e8,"ccaron";
+0x1ea,"eogonek";
+0x1ec,"ecaron";
+0x1ef,"dcaron";
+0x1f0,"dstroke";
+0x1f1,"nacute";
+0x1f2,"ncaron";
+0x1f5,"odoubleacute";
+0x1fb,"udoubleacute";
+0x1f8,"rcaron";
+0x1f9,"uring";
+0x1fe,"tcedilla";
+0x1ff,"abovedot";
+0x2a1,"Hstroke";
+0x2a6,"Hcircumflex";
+0x2a9,"Iabovedot";
+0x2ab,"Gbreve";
+0x2ac,"Jcircumflex";
+0x2b1,"hstroke";
+0x2b6,"hcircumflex";
+0x2b9,"idotless";
+0x2bb,"gbreve";
+0x2bc,"jcircumflex";
+0x2c5,"Cabovedot";
+0x2c6,"Ccircumflex";
+0x2d5,"Gabovedot";
+0x2d8,"Gcircumflex";
+0x2dd,"Ubreve";
+0x2de,"Scircumflex";
+0x2e5,"cabovedot";
+0x2e6,"ccircumflex";
+0x2f5,"gabovedot";
+0x2f8,"gcircumflex";
+0x2fd,"ubreve";
+0x2fe,"scircumflex";
+0x3a2,"kra";
+0x3a2,"kappa";
+0x3a3,"Rcedilla";
+0x3a5,"Itilde";
+0x3a6,"Lcedilla";
+0x3aa,"Emacron";
+0x3ab,"Gcedilla";
+0x3ac,"Tslash";
+0x3b3,"rcedilla";
+0x3b5,"itilde";
+0x3b6,"lcedilla";
+0x3ba,"emacron";
+0x3bb,"gcedilla";
+0x3bc,"tslash";
+0x3bd,"ENG";
+0x3bf,"eng";
+0x3c0,"Amacron";
+0x3c7,"Iogonek";
+0x3cc,"Eabovedot";
+0x3cf,"Imacron";
+0x3d1,"Ncedilla";
+0x3d2,"Omacron";
+0x3d3,"Kcedilla";
+0x3d9,"Uogonek";
+0x3dd,"Utilde";
+0x3de,"Umacron";
+0x3e0,"amacron";
+0x3e7,"iogonek";
+0x3ec,"eabovedot";
+0x3ef,"imacron";
+0x3f1,"ncedilla";
+0x3f2,"omacron";
+0x3f3,"kcedilla";
+0x3f9,"uogonek";
+0x3fd,"utilde";
+0x3fe,"umacron";
+0x47e,"overline";
+0x4a1,"kana_fullstop";
+0x4a2,"kana_openingbracket";
+0x4a3,"kana_closingbracket";
+0x4a4,"kana_comma";
+0x4a5,"kana_conjunctive";
+0x4a5,"kana_middledot";
+0x4a6,"kana_WO";
+0x4a7,"kana_a";
+0x4a8,"kana_i";
+0x4a9,"kana_u";
+0x4aa,"kana_e";
+0x4ab,"kana_o";
+0x4ac,"kana_ya";
+0x4ad,"kana_yu";
+0x4ae,"kana_yo";
+0x4af,"kana_tsu";
+0x4af,"kana_tu";
+0x4b0,"prolongedsound";
+0x4b1,"kana_A";
+0x4b2,"kana_I";
+0x4b3,"kana_U";
+0x4b4,"kana_E";
+0x4b5,"kana_O";
+0x4b6,"kana_KA";
+0x4b7,"kana_KI";
+0x4b8,"kana_KU";
+0x4b9,"kana_KE";
+0x4ba,"kana_KO";
+0x4bb,"kana_SA";
+0x4bc,"kana_SHI";
+0x4bd,"kana_SU";
+0x4be,"kana_SE";
+0x4bf,"kana_SO";
+0x4c0,"kana_TA";
+0x4c1,"kana_CHI";
+0x4c1,"kana_TI";
+0x4c2,"kana_TSU";
+0x4c2,"kana_TU";
+0x4c3,"kana_TE";
+0x4c4,"kana_TO";
+0x4c5,"kana_NA";
+0x4c6,"kana_NI";
+0x4c7,"kana_NU";
+0x4c8,"kana_NE";
+0x4c9,"kana_NO";
+0x4ca,"kana_HA";
+0x4cb,"kana_HI";
+0x4cc,"kana_FU";
+0x4cc,"kana_HU";
+0x4cd,"kana_HE";
+0x4ce,"kana_HO";
+0x4cf,"kana_MA";
+0x4d0,"kana_MI";
+0x4d1,"kana_MU";
+0x4d2,"kana_ME";
+0x4d3,"kana_MO";
+0x4d4,"kana_YA";
+0x4d5,"kana_YU";
+0x4d6,"kana_YO";
+0x4d7,"kana_RA";
+0x4d8,"kana_RI";
+0x4d9,"kana_RU";
+0x4da,"kana_RE";
+0x4db,"kana_RO";
+0x4dc,"kana_WA";
+0x4dd,"kana_N";
+0x4de,"voicedsound";
+0x4df,"semivoicedsound";
+0xFF7E,"kana_switch";
+0x5ac,"Arabic_comma";
+0x5bb,"Arabic_semicolon";
+0x5bf,"Arabic_question_mark";
+0x5c1,"Arabic_hamza";
+0x5c2,"Arabic_maddaonalef";
+0x5c3,"Arabic_hamzaonalef";
+0x5c4,"Arabic_hamzaonwaw";
+0x5c5,"Arabic_hamzaunderalef";
+0x5c6,"Arabic_hamzaonyeh";
+0x5c7,"Arabic_alef";
+0x5c8,"Arabic_beh";
+0x5c9,"Arabic_tehmarbuta";
+0x5ca,"Arabic_teh";
+0x5cb,"Arabic_theh";
+0x5cc,"Arabic_jeem";
+0x5cd,"Arabic_hah";
+0x5ce,"Arabic_khah";
+0x5cf,"Arabic_dal";
+0x5d0,"Arabic_thal";
+0x5d1,"Arabic_ra";
+0x5d2,"Arabic_zain";
+0x5d3,"Arabic_seen";
+0x5d4,"Arabic_sheen";
+0x5d5,"Arabic_sad";
+0x5d6,"Arabic_dad";
+0x5d7,"Arabic_tah";
+0x5d8,"Arabic_zah";
+0x5d9,"Arabic_ain";
+0x5da,"Arabic_ghain";
+0x5e0,"Arabic_tatweel";
+0x5e1,"Arabic_feh";
+0x5e2,"Arabic_qaf";
+0x5e3,"Arabic_kaf";
+0x5e4,"Arabic_lam";
+0x5e5,"Arabic_meem";
+0x5e6,"Arabic_noon";
+0x5e7,"Arabic_ha";
+0x5e7,"Arabic_heh";
+0x5e8,"Arabic_waw";
+0x5e9,"Arabic_alefmaksura";
+0x5ea,"Arabic_yeh";
+0x5eb,"Arabic_fathatan";
+0x5ec,"Arabic_dammatan";
+0x5ed,"Arabic_kasratan";
+0x5ee,"Arabic_fatha";
+0x5ef,"Arabic_damma";
+0x5f0,"Arabic_kasra";
+0x5f1,"Arabic_shadda";
+0x5f2,"Arabic_sukun";
+0xFF7E,"Arabic_switch";
+0x6a1,"Serbian_dje";
+0x6a2,"Macedonia_gje";
+0x6a3,"Cyrillic_io";
+0x6a4,"Ukrainian_ie";
+0x6a4,"Ukranian_je";
+0x6a5,"Macedonia_dse";
+0x6a6,"Ukrainian_i";
+0x6a6,"Ukranian_i";
+0x6a7,"Ukrainian_yi";
+0x6a7,"Ukranian_yi";
+0x6a8,"Cyrillic_je";
+0x6a8,"Serbian_je";
+0x6a9,"Cyrillic_lje";
+0x6a9,"Serbian_lje";
+0x6aa,"Cyrillic_nje";
+0x6aa,"Serbian_nje";
+0x6ab,"Serbian_tshe";
+0x6ac,"Macedonia_kje";
+0x6ae,"Byelorussian_shortu";
+0x6af,"Cyrillic_dzhe";
+0x6af,"Serbian_dze";
+0x6b0,"numerosign";
+0x6b1,"Serbian_DJE";
+0x6b2,"Macedonia_GJE";
+0x6b3,"Cyrillic_IO";
+0x6b4,"Ukrainian_IE";
+0x6b4,"Ukranian_JE";
+0x6b5,"Macedonia_DSE";
+0x6b6,"Ukrainian_I";
+0x6b6,"Ukranian_I";
+0x6b7,"Ukrainian_YI";
+0x6b7,"Ukranian_YI";
+0x6b8,"Cyrillic_JE";
+0x6b8,"Serbian_JE";
+0x6b9,"Cyrillic_LJE";
+0x6b9,"Serbian_LJE";
+0x6ba,"Cyrillic_NJE";
+0x6ba,"Serbian_NJE";
+0x6bb,"Serbian_TSHE";
+0x6bc,"Macedonia_KJE";
+0x6be,"Byelorussian_SHORTU";
+0x6bf,"Cyrillic_DZHE";
+0x6bf,"Serbian_DZE";
+0x6c0,"Cyrillic_yu";
+0x6c1,"Cyrillic_a";
+0x6c2,"Cyrillic_be";
+0x6c3,"Cyrillic_tse";
+0x6c4,"Cyrillic_de";
+0x6c5,"Cyrillic_ie";
+0x6c6,"Cyrillic_ef";
+0x6c7,"Cyrillic_ghe";
+0x6c8,"Cyrillic_ha";
+0x6c9,"Cyrillic_i";
+0x6ca,"Cyrillic_shorti";
+0x6cb,"Cyrillic_ka";
+0x6cc,"Cyrillic_el";
+0x6cd,"Cyrillic_em";
+0x6ce,"Cyrillic_en";
+0x6cf,"Cyrillic_o";
+0x6d0,"Cyrillic_pe";
+0x6d1,"Cyrillic_ya";
+0x6d2,"Cyrillic_er";
+0x6d3,"Cyrillic_es";
+0x6d4,"Cyrillic_te";
+0x6d5,"Cyrillic_u";
+0x6d6,"Cyrillic_zhe";
+0x6d7,"Cyrillic_ve";
+0x6d8,"Cyrillic_softsign";
+0x6d9,"Cyrillic_yeru";
+0x6da,"Cyrillic_ze";
+0x6db,"Cyrillic_sha";
+0x6dc,"Cyrillic_e";
+0x6dd,"Cyrillic_shcha";
+0x6de,"Cyrillic_che";
+0x6df,"Cyrillic_hardsign";
+0x6e0,"Cyrillic_YU";
+0x6e1,"Cyrillic_A";
+0x6e2,"Cyrillic_BE";
+0x6e3,"Cyrillic_TSE";
+0x6e4,"Cyrillic_DE";
+0x6e5,"Cyrillic_IE";
+0x6e6,"Cyrillic_EF";
+0x6e7,"Cyrillic_GHE";
+0x6e8,"Cyrillic_HA";
+0x6e9,"Cyrillic_I";
+0x6ea,"Cyrillic_SHORTI";
+0x6eb,"Cyrillic_KA";
+0x6ec,"Cyrillic_EL";
+0x6ed,"Cyrillic_EM";
+0x6ee,"Cyrillic_EN";
+0x6ef,"Cyrillic_O";
+0x6f0,"Cyrillic_PE";
+0x6f1,"Cyrillic_YA";
+0x6f2,"Cyrillic_ER";
+0x6f3,"Cyrillic_ES";
+0x6f4,"Cyrillic_TE";
+0x6f5,"Cyrillic_U";
+0x6f6,"Cyrillic_ZHE";
+0x6f7,"Cyrillic_VE";
+0x6f8,"Cyrillic_SOFTSIGN";
+0x6f9,"Cyrillic_YERU";
+0x6fa,"Cyrillic_ZE";
+0x6fb,"Cyrillic_SHA";
+0x6fc,"Cyrillic_E";
+0x6fd,"Cyrillic_SHCHA";
+0x6fe,"Cyrillic_CHE";
+0x6ff,"Cyrillic_HARDSIGN";
+0x7a1,"Greek_ALPHAaccent";
+0x7a2,"Greek_EPSILONaccent";
+0x7a3,"Greek_ETAaccent";
+0x7a4,"Greek_IOTAaccent";
+0x7a5,"Greek_IOTAdiaeresis";
+0x7a7,"Greek_OMICRONaccent";
+0x7a8,"Greek_UPSILONaccent";
+0x7a9,"Greek_UPSILONdieresis";
+0x7ab,"Greek_OMEGAaccent";
+0x7ae,"Greek_accentdieresis";
+0x7af,"Greek_horizbar";
+0x7b1,"Greek_alphaaccent";
+0x7b2,"Greek_epsilonaccent";
+0x7b3,"Greek_etaaccent";
+0x7b4,"Greek_iotaaccent";
+0x7b5,"Greek_iotadieresis";
+0x7b6,"Greek_iotaaccentdieresis";
+0x7b7,"Greek_omicronaccent";
+0x7b8,"Greek_upsilonaccent";
+0x7b9,"Greek_upsilondieresis";
+0x7ba,"Greek_upsilonaccentdieresis";
+0x7bb,"Greek_omegaaccent";
+0x7c1,"Greek_ALPHA";
+0x7c2,"Greek_BETA";
+0x7c3,"Greek_GAMMA";
+0x7c4,"Greek_DELTA";
+0x7c5,"Greek_EPSILON";
+0x7c6,"Greek_ZETA";
+0x7c7,"Greek_ETA";
+0x7c8,"Greek_THETA";
+0x7c9,"Greek_IOTA";
+0x7ca,"Greek_KAPPA";
+0x7cb,"Greek_LAMDA";
+0x7cb,"Greek_LAMBDA";
+0x7cc,"Greek_MU";
+0x7cd,"Greek_NU";
+0x7ce,"Greek_XI";
+0x7cf,"Greek_OMICRON";
+0x7d0,"Greek_PI";
+0x7d1,"Greek_RHO";
+0x7d2,"Greek_SIGMA";
+0x7d4,"Greek_TAU";
+0x7d5,"Greek_UPSILON";
+0x7d6,"Greek_PHI";
+0x7d7,"Greek_CHI";
+0x7d8,"Greek_PSI";
+0x7d9,"Greek_OMEGA";
+0x7e1,"Greek_alpha";
+0x7e2,"Greek_beta";
+0x7e3,"Greek_gamma";
+0x7e4,"Greek_delta";
+0x7e5,"Greek_epsilon";
+0x7e6,"Greek_zeta";
+0x7e7,"Greek_eta";
+0x7e8,"Greek_theta";
+0x7e9,"Greek_iota";
+0x7ea,"Greek_kappa";
+0x7eb,"Greek_lamda";
+0x7eb,"Greek_lambda";
+0x7ec,"Greek_mu";
+0x7ed,"Greek_nu";
+0x7ee,"Greek_xi";
+0x7ef,"Greek_omicron";
+0x7f0,"Greek_pi";
+0x7f1,"Greek_rho";
+0x7f2,"Greek_sigma";
+0x7f3,"Greek_finalsmallsigma";
+0x7f4,"Greek_tau";
+0x7f5,"Greek_upsilon";
+0x7f6,"Greek_phi";
+0x7f7,"Greek_chi";
+0x7f8,"Greek_psi";
+0x7f9,"Greek_omega";
+0xFF7E,"Greek_switch";
+0x8a1,"leftradical";
+0x8a2,"topleftradical";
+0x8a3,"horizconnector";
+0x8a4,"topintegral";
+0x8a5,"botintegral";
+0x8a6,"vertconnector";
+0x8a7,"topleftsqbracket";
+0x8a8,"botleftsqbracket";
+0x8a9,"toprightsqbracket";
+0x8aa,"botrightsqbracket";
+0x8ab,"topleftparens";
+0x8ac,"botleftparens";
+0x8ad,"toprightparens";
+0x8ae,"botrightparens";
+0x8af,"leftmiddlecurlybrace";
+0x8b0,"rightmiddlecurlybrace";
+0x8b1,"topleftsummation";
+0x8b2,"botleftsummation";
+0x8b3,"topvertsummationconnector";
+0x8b4,"botvertsummationconnector";
+0x8b5,"toprightsummation";
+0x8b6,"botrightsummation";
+0x8b7,"rightmiddlesummation";
+0x8bc,"lessthanequal";
+0x8bd,"notequal";
+0x8be,"greaterthanequal";
+0x8bf,"integral";
+0x8c0,"therefore";
+0x8c1,"variation";
+0x8c2,"infinity";
+0x8c5,"nabla";
+0x8c8,"approximate";
+0x8c9,"similarequal";
+0x8cd,"ifonlyif";
+0x8ce,"implies";
+0x8cf,"identical";
+0x8d6,"radical";
+0x8da,"includedin";
+0x8db,"includes";
+0x8dc,"intersection";
+0x8dd,"union";
+0x8de,"logicaland";
+0x8df,"logicalor";
+0x8ef,"partialderivative";
+0x8f6,"function";
+0x8fb,"leftarrow";
+0x8fc,"uparrow";
+0x8fd,"rightarrow";
+0x8fe,"downarrow";
+0x9df,"blank";
+0x9e0,"soliddiamond";
+0x9e1,"checkerboard";
+0x9e2,"ht";
+0x9e3,"ff";
+0x9e4,"cr";
+0x9e5,"lf";
+0x9e8,"nl";
+0x9e9,"vt";
+0x9ea,"lowrightcorner";
+0x9eb,"uprightcorner";
+0x9ec,"upleftcorner";
+0x9ed,"lowleftcorner";
+0x9ee,"crossinglines";
+0x9ef,"horizlinescan1";
+0x9f0,"horizlinescan3";
+0x9f1,"horizlinescan5";
+0x9f2,"horizlinescan7";
+0x9f3,"horizlinescan9";
+0x9f4,"leftt";
+0x9f5,"rightt";
+0x9f6,"bott";
+0x9f7,"topt";
+0x9f8,"vertbar";
+0xaa1,"emspace";
+0xaa2,"enspace";
+0xaa3,"em3space";
+0xaa4,"em4space";
+0xaa5,"digitspace";
+0xaa6,"punctspace";
+0xaa7,"thinspace";
+0xaa8,"hairspace";
+0xaa9,"emdash";
+0xaaa,"endash";
+0xaac,"signifblank";
+0xaae,"ellipsis";
+0xaaf,"doubbaselinedot";
+0xab0,"onethird";
+0xab1,"twothirds";
+0xab2,"onefifth";
+0xab3,"twofifths";
+0xab4,"threefifths";
+0xab5,"fourfifths";
+0xab6,"onesixth";
+0xab7,"fivesixths";
+0xab8,"careof";
+0xabb,"figdash";
+0xabc,"leftanglebracket";
+0xabd,"decimalpoint";
+0xabe,"rightanglebracket";
+0xabf,"marker";
+0xac3,"oneeighth";
+0xac4,"threeeighths";
+0xac5,"fiveeighths";
+0xac6,"seveneighths";
+0xac9,"trademark";
+0xaca,"signaturemark";
+0xacb,"trademarkincircle";
+0xacc,"leftopentriangle";
+0xacd,"rightopentriangle";
+0xace,"emopencircle";
+0xacf,"emopenrectangle";
+0xad0,"leftsinglequotemark";
+0xad1,"rightsinglequotemark";
+0xad2,"leftdoublequotemark";
+0xad3,"rightdoublequotemark";
+0xad4,"prescription";
+0xad6,"minutes";
+0xad7,"seconds";
+0xad9,"latincross";
+0xada,"hexagram";
+0xadb,"filledrectbullet";
+0xadc,"filledlefttribullet";
+0xadd,"filledrighttribullet";
+0xade,"emfilledcircle";
+0xadf,"emfilledrect";
+0xae0,"enopencircbullet";
+0xae1,"enopensquarebullet";
+0xae2,"openrectbullet";
+0xae3,"opentribulletup";
+0xae4,"opentribulletdown";
+0xae5,"openstar";
+0xae6,"enfilledcircbullet";
+0xae7,"enfilledsqbullet";
+0xae8,"filledtribulletup";
+0xae9,"filledtribulletdown";
+0xaea,"leftpointer";
+0xaeb,"rightpointer";
+0xaec,"club";
+0xaed,"diamond";
+0xaee,"heart";
+0xaf0,"maltesecross";
+0xaf1,"dagger";
+0xaf2,"doubledagger";
+0xaf3,"checkmark";
+0xaf4,"ballotcross";
+0xaf5,"musicalsharp";
+0xaf6,"musicalflat";
+0xaf7,"malesymbol";
+0xaf8,"femalesymbol";
+0xaf9,"telephone";
+0xafa,"telephonerecorder";
+0xafb,"phonographcopyright";
+0xafc,"caret";
+0xafd,"singlelowquotemark";
+0xafe,"doublelowquotemark";
+0xaff,"cursor";
+0xba3,"leftcaret";
+0xba6,"rightcaret";
+0xba8,"downcaret";
+0xba9,"upcaret";
+0xbc0,"overbar";
+0xbc2,"downtack";
+0xbc3,"upshoe";
+0xbc4,"downstile";
+0xbc6,"underbar";
+0xbca,"jot";
+0xbcc,"quad";
+0xbce,"uptack";
+0xbcf,"circle";
+0xbd3,"upstile";
+0xbd6,"downshoe";
+0xbd8,"rightshoe";
+0xbda,"leftshoe";
+0xbdc,"lefttack";
+0xbfc,"righttack";
+0xcdf,"hebrew_doublelowline";
+0xce0,"hebrew_aleph";
+0xce1,"hebrew_bet";
+0xce1,"hebrew_beth";
+0xce2,"hebrew_gimel";
+0xce2,"hebrew_gimmel";
+0xce3,"hebrew_dalet";
+0xce3,"hebrew_daleth";
+0xce4,"hebrew_he";
+0xce5,"hebrew_waw";
+0xce6,"hebrew_zain";
+0xce6,"hebrew_zayin";
+0xce7,"hebrew_chet";
+0xce7,"hebrew_het";
+0xce8,"hebrew_tet";
+0xce8,"hebrew_teth";
+0xce9,"hebrew_yod";
+0xcea,"hebrew_finalkaph";
+0xceb,"hebrew_kaph";
+0xcec,"hebrew_lamed";
+0xced,"hebrew_finalmem";
+0xcee,"hebrew_mem";
+0xcef,"hebrew_finalnun";
+0xcf0,"hebrew_nun";
+0xcf1,"hebrew_samech";
+0xcf1,"hebrew_samekh";
+0xcf2,"hebrew_ayin";
+0xcf3,"hebrew_finalpe";
+0xcf4,"hebrew_pe";
+0xcf5,"hebrew_finalzade";
+0xcf5,"hebrew_finalzadi";
+0xcf6,"hebrew_zade";
+0xcf6,"hebrew_zadi";
+0xcf7,"hebrew_qoph";
+0xcf7,"hebrew_kuf";
+0xcf8,"hebrew_resh";
+0xcf9,"hebrew_shin";
+0xcfa,"hebrew_taw";
+0xcfa,"hebrew_taf";
+0xFF7E,"Hebrew_switch";
+0xda1,"Thai_kokai";
+0xda2,"Thai_khokhai";
+0xda3,"Thai_khokhuat";
+0xda4,"Thai_khokhwai";
+0xda5,"Thai_khokhon";
+0xda6,"Thai_khorakhang";
+0xda7,"Thai_ngongu";
+0xda8,"Thai_chochan";
+0xda9,"Thai_choching";
+0xdaa,"Thai_chochang";
+0xdab,"Thai_soso";
+0xdac,"Thai_chochoe";
+0xdad,"Thai_yoying";
+0xdae,"Thai_dochada";
+0xdaf,"Thai_topatak";
+0xdb0,"Thai_thothan";
+0xdb1,"Thai_thonangmontho";
+0xdb2,"Thai_thophuthao";
+0xdb3,"Thai_nonen";
+0xdb4,"Thai_dodek";
+0xdb5,"Thai_totao";
+0xdb6,"Thai_thothung";
+0xdb7,"Thai_thothahan";
+0xdb8,"Thai_thothong";
+0xdb9,"Thai_nonu";
+0xdba,"Thai_bobaimai";
+0xdbb,"Thai_popla";
+0xdbc,"Thai_phophung";
+0xdbd,"Thai_fofa";
+0xdbe,"Thai_phophan";
+0xdbf,"Thai_fofan";
+0xdc0,"Thai_phosamphao";
+0xdc1,"Thai_moma";
+0xdc2,"Thai_yoyak";
+0xdc3,"Thai_rorua";
+0xdc4,"Thai_ru";
+0xdc5,"Thai_loling";
+0xdc6,"Thai_lu";
+0xdc7,"Thai_wowaen";
+0xdc8,"Thai_sosala";
+0xdc9,"Thai_sorusi";
+0xdca,"Thai_sosua";
+0xdcb,"Thai_hohip";
+0xdcc,"Thai_lochula";
+0xdcd,"Thai_oang";
+0xdce,"Thai_honokhuk";
+0xdcf,"Thai_paiyannoi";
+0xdd0,"Thai_saraa";
+0xdd1,"Thai_maihanakat";
+0xdd2,"Thai_saraaa";
+0xdd3,"Thai_saraam";
+0xdd4,"Thai_sarai";
+0xdd5,"Thai_saraii";
+0xdd6,"Thai_saraue";
+0xdd7,"Thai_sarauee";
+0xdd8,"Thai_sarau";
+0xdd9,"Thai_sarauu";
+0xdda,"Thai_phinthu";
+0xdde,"Thai_maihanakat_maitho";
+0xddf,"Thai_baht";
+0xde0,"Thai_sarae";
+0xde1,"Thai_saraae";
+0xde2,"Thai_sarao";
+0xde3,"Thai_saraaimaimuan";
+0xde4,"Thai_saraaimaimalai";
+0xde5,"Thai_lakkhangyao";
+0xde6,"Thai_maiyamok";
+0xde7,"Thai_maitaikhu";
+0xde8,"Thai_maiek";
+0xde9,"Thai_maitho";
+0xdea,"Thai_maitri";
+0xdeb,"Thai_maichattawa";
+0xdec,"Thai_thanthakhat";
+0xded,"Thai_nikhahit";
+0xdf0,"Thai_leksun";
+0xdf1,"Thai_leknung";
+0xdf2,"Thai_leksong";
+0xdf3,"Thai_leksam";
+0xdf4,"Thai_leksi";
+0xdf5,"Thai_lekha";
+0xdf6,"Thai_lekhok";
+0xdf7,"Thai_lekchet";
+0xdf8,"Thai_lekpaet";
+0xdf9,"Thai_lekkao";
+0xff31,"Hangul";
+0xff32,"Hangul_Start";
+0xff33,"Hangul_End";
+0xff34,"Hangul_Hanja";
+0xff35,"Hangul_Jamo";
+0xff36,"Hangul_Romaja";
+0xff37,"Hangul_Codeinput";
+0xff38,"Hangul_Jeonja";
+0xff39,"Hangul_Banja";
+0xff3a,"Hangul_PreHanja";
+0xff3b,"Hangul_PostHanja";
+0xff3c,"Hangul_SingleCandidate";
+0xff3d,"Hangul_MultipleCandidate";
+0xff3e,"Hangul_PreviousCandidate";
+0xff3f,"Hangul_Special";
+0xFF7E,"Hangul_switch";
+0xea1,"Hangul_Kiyeog";
+0xea2,"Hangul_SsangKiyeog";
+0xea3,"Hangul_KiyeogSios";
+0xea4,"Hangul_Nieun";
+0xea5,"Hangul_NieunJieuj";
+0xea6,"Hangul_NieunHieuh";
+0xea7,"Hangul_Dikeud";
+0xea8,"Hangul_SsangDikeud";
+0xea9,"Hangul_Rieul";
+0xeaa,"Hangul_RieulKiyeog";
+0xeab,"Hangul_RieulMieum";
+0xeac,"Hangul_RieulPieub";
+0xead,"Hangul_RieulSios";
+0xeae,"Hangul_RieulTieut";
+0xeaf,"Hangul_RieulPhieuf";
+0xeb0,"Hangul_RieulHieuh";
+0xeb1,"Hangul_Mieum";
+0xeb2,"Hangul_Pieub";
+0xeb3,"Hangul_SsangPieub";
+0xeb4,"Hangul_PieubSios";
+0xeb5,"Hangul_Sios";
+0xeb6,"Hangul_SsangSios";
+0xeb7,"Hangul_Ieung";
+0xeb8,"Hangul_Jieuj";
+0xeb9,"Hangul_SsangJieuj";
+0xeba,"Hangul_Cieuc";
+0xebb,"Hangul_Khieuq";
+0xebc,"Hangul_Tieut";
+0xebd,"Hangul_Phieuf";
+0xebe,"Hangul_Hieuh";
+0xebf,"Hangul_A";
+0xec0,"Hangul_AE";
+0xec1,"Hangul_YA";
+0xec2,"Hangul_YAE";
+0xec3,"Hangul_EO";
+0xec4,"Hangul_E";
+0xec5,"Hangul_YEO";
+0xec6,"Hangul_YE";
+0xec7,"Hangul_O";
+0xec8,"Hangul_WA";
+0xec9,"Hangul_WAE";
+0xeca,"Hangul_OE";
+0xecb,"Hangul_YO";
+0xecc,"Hangul_U";
+0xecd,"Hangul_WEO";
+0xece,"Hangul_WE";
+0xecf,"Hangul_WI";
+0xed0,"Hangul_YU";
+0xed1,"Hangul_EU";
+0xed2,"Hangul_YI";
+0xed3,"Hangul_I";
+0xed4,"Hangul_J_Kiyeog";
+0xed5,"Hangul_J_SsangKiyeog";
+0xed6,"Hangul_J_KiyeogSios";
+0xed7,"Hangul_J_Nieun";
+0xed8,"Hangul_J_NieunJieuj";
+0xed9,"Hangul_J_NieunHieuh";
+0xeda,"Hangul_J_Dikeud";
+0xedb,"Hangul_J_Rieul";
+0xedc,"Hangul_J_RieulKiyeog";
+0xedd,"Hangul_J_RieulMieum";
+0xede,"Hangul_J_RieulPieub";
+0xedf,"Hangul_J_RieulSios";
+0xee0,"Hangul_J_RieulTieut";
+0xee1,"Hangul_J_RieulPhieuf";
+0xee2,"Hangul_J_RieulHieuh";
+0xee3,"Hangul_J_Mieum";
+0xee4,"Hangul_J_Pieub";
+0xee5,"Hangul_J_PieubSios";
+0xee6,"Hangul_J_Sios";
+0xee7,"Hangul_J_SsangSios";
+0xee8,"Hangul_J_Ieung";
+0xee9,"Hangul_J_Jieuj";
+0xeea,"Hangul_J_Cieuc";
+0xeeb,"Hangul_J_Khieuq";
+0xeec,"Hangul_J_Tieut";
+0xeed,"Hangul_J_Phieuf";
+0xeee,"Hangul_J_Hieuh";
+0xeef,"Hangul_RieulYeorinHieuh";
+0xef0,"Hangul_SunkyeongeumMieum";
+0xef1,"Hangul_SunkyeongeumPieub";
+0xef2,"Hangul_PanSios";
+0xef3,"Hangul_KkogjiDalrinIeung";
+0xef4,"Hangul_SunkyeongeumPhieuf";
+0xef5,"Hangul_YeorinHieuh";
+0xef6,"Hangul_AraeA";
+0xef7,"Hangul_AraeAE";
+0xef8,"Hangul_J_PanSios";
+0xef9,"Hangul_J_KkogjiDalrinIeung";
+0xefa,"Hangul_J_YeorinHieuh";
+0xeff,"Korean_Won";
+]
diff --git a/ide/utils/configwin_messages.ml b/ide/utils/configwin_messages.ml
new file mode 100644
index 00000000..a6085138
--- /dev/null
+++ b/ide/utils/configwin_messages.ml
@@ -0,0 +1,51 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(** Module containing the messages of Configwin.*)
+
+let software = "Configwin";;
+let version = "1.3";;
+
+let html_config = "Configwin bindings configurator for html parameters"
+
+let home =
+ try Sys.getenv "HOME"
+ with Not_found -> ""
+
+let mCapture = "Capture";;
+let mType_key = "Type key" ;;
+let mAdd = "Add";;
+let mRemove = "Remove";;
+let mUp = "Up";;
+let mEdit = "Edit";;
+let mOk = "Ok";;
+let mCancel = "Cancel";;
+let mApply = "Apply";;
+let mValue = "Value"
+let mKey = "Key"
+
+let shortcuts = "Shortcuts"
+let html_end = "End with"
+let html_begin = "Begin with"
+
diff --git a/ide/utils/configwin_types.ml b/ide/utils/configwin_types.ml
new file mode 100644
index 00000000..ee8ec70c
--- /dev/null
+++ b/ide/utils/configwin_types.ml
@@ -0,0 +1,299 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(** This module contains the types used in Configwin. *)
+
+open Uoptions
+
+(** A module to define key options, with the {!Uoptions} module. *)
+module KeyOption = struct
+ let name_to_keysym =
+ ("Button1", Configwin_keys.xk_Pointer_Button1) ::
+ ("Button2", Configwin_keys.xk_Pointer_Button2) ::
+ ("Button3", Configwin_keys.xk_Pointer_Button3) ::
+ ("Button4", Configwin_keys.xk_Pointer_Button4) ::
+ ("Button5", Configwin_keys.xk_Pointer_Button5) ::
+ Configwin_keys.name_to_keysym
+
+ let string_to_key s =
+ let mask = ref [] in
+ let key = try
+ let pos = String.rindex s '-' in
+ for i = 0 to pos - 1 do
+ let m = match s.[i] with
+ 'C' -> `CONTROL
+ | 'S' -> `SHIFT
+ | 'L' -> `LOCK
+ | 'M' -> `MOD1
+ | 'A' -> `MOD1
+ | '1' -> `MOD1
+ | '2' -> `MOD2
+ | '3' -> `MOD3
+ | '4' -> `MOD4
+ | '5' -> `MOD5
+ | _ ->
+ prerr_endline s;
+ raise Not_found
+ in
+ mask := m :: !mask
+ done;
+ String.sub s (pos+1) (String.length s - pos - 1)
+ with _ ->
+ s
+ in
+ try
+ !mask, List.assoc key name_to_keysym
+ with
+ e ->
+ prerr_endline s;
+ raise e
+
+ let key_to_string (m, k) =
+ let s = List.assoc k Configwin_keys.keysym_to_name in
+ match m with
+ [] -> s
+ | _ ->
+ let rec iter m s =
+ match m with
+ [] -> s
+ | c :: m ->
+ iter m ((
+ match c with
+ `CONTROL -> "C"
+ | `SHIFT -> "S"
+ | `LOCK -> "L"
+ | `MOD1 -> "A"
+ | `MOD2 -> "2"
+ | `MOD3 -> "3"
+ | `MOD4 -> "4"
+ | `MOD5 -> "5"
+ | _ -> raise Not_found
+ ) ^ s)
+ in
+ iter m ("-" ^ s)
+
+ let modifiers_to_string m =
+ let rec iter m s =
+ match m with
+ [] -> s
+ | c :: m ->
+ iter m ((
+ match c with
+ `CONTROL -> "<ctrl>"
+ | `SHIFT -> "<shft>"
+ | `LOCK -> "<lock>"
+ | `MOD1 -> "<alt>"
+ | `MOD2 -> "<mod2>"
+ | `MOD3 -> "<mod3>"
+ | `MOD4 -> "<mod4>"
+ | `MOD5 -> "<mod5>"
+ | _ -> raise Not_found
+ ) ^ s)
+ in
+ iter m ""
+
+ let value_to_key v =
+ match v with
+ StringValue s -> string_to_key s
+ | _ ->
+ prerr_endline "value_to_key";
+ raise Not_found
+
+ let key_to_value k =
+ StringValue (key_to_string k)
+
+ let (t : (Gdk.Tags.modifier list * int) option_class) =
+ define_option_class "Key" value_to_key key_to_value
+end
+
+(** This type represents a string or filename parameter. *)
+type string_param = {
+ string_label : string; (** the label of the parameter *)
+ mutable string_value : string; (** the current value of the parameter *)
+ string_editable : bool ; (** indicates if the value can be changed *)
+ string_f_apply : (string -> unit) ; (** the function to call to apply the new value of the parameter *)
+ string_help : string option ; (** optional help string *)
+ string_expand : bool ; (** expand or not *)
+ } ;;
+
+(** This type represents a boolean parameter. *)
+type bool_param = {
+ bool_label : string; (** the label of the parameter *)
+ mutable bool_value : bool; (** the current value of the parameter *)
+ bool_editable : bool ; (** indicates if the value can be changed *)
+ bool_f_apply : (bool -> unit) ; (** the function to call to apply the new value of the parameter *)
+ bool_help : string option ; (** optional help string *)
+ } ;;
+
+(** This type represents a parameter whose value is a list of ['a]. *)
+type 'a list_param = {
+ list_label : string; (** the label of the parameter *)
+ mutable list_value : 'a list; (** the current value of the parameter *)
+ list_titles : string list option; (** the titles of columns, if they must be displayed *)
+ list_f_edit : ('a -> 'a) option; (** optional edition function *)
+ list_eq : ('a -> 'a -> bool) ; (** the comparison function used to get list without doubles *)
+ list_strings : ('a -> string list); (** the function to get a string list from a ['a]. *)
+ list_color : ('a -> string option) ; (** a function to get the optional color of an element *)
+ list_editable : bool ; (** indicates if the value can be changed *)
+ list_f_add : unit -> 'a list ; (** the function to call to add list *)
+ list_f_apply : ('a list -> unit) ; (** the function to call to apply the new value of the parameter *)
+ list_help : string option ; (** optional help string *)
+ } ;;
+
+type combo_param = {
+ combo_label : string ;
+ mutable combo_value : string ;
+ combo_choices : string list ;
+ combo_editable : bool ;
+ combo_blank_allowed : bool ;
+ combo_new_allowed : bool ;
+ combo_f_apply : (string -> unit);
+ combo_help : string option ; (** optional help string *)
+ combo_expand : bool ; (** expand the entry widget or not *)
+ } ;;
+
+type custom_param = {
+ custom_box : GPack.box ;
+ custom_f_apply : (unit -> unit) ;
+ custom_expand : bool ;
+ custom_framed : string option ; (** optional label for an optional frame *)
+ } ;;
+
+type color_param = {
+ color_label : string; (** the label of the parameter *)
+ mutable color_value : string; (** the current value of the parameter *)
+ color_editable : bool ; (** indicates if the value can be changed *)
+ color_f_apply : (string -> unit) ; (** the function to call to apply the new value of the parameter *)
+ color_help : string option ; (** optional help string *)
+ color_expand : bool ; (** expand the entry widget or not *)
+ } ;;
+
+type date_param = {
+ date_label : string ; (** the label of the parameter *)
+ mutable date_value : int * int * int ; (** day, month, year *)
+ date_editable : bool ; (** indicates if the value can be changed *)
+ date_f_string : (int * int * int) -> string ;
+ (** the function used to display the current value (day, month, year) *)
+ date_f_apply : ((int * int * int) -> unit) ;
+ (** the function to call to apply the new value (day, month, year) of the parameter *)
+ date_help : string option ; (** optional help string *)
+ date_expand : bool ; (** expand the entry widget or not *)
+ } ;;
+
+type font_param = {
+ font_label : string ; (** the label of the parameter *)
+ mutable font_value : string ; (** the font name *)
+ font_editable : bool ; (** indicates if the value can be changed *)
+ font_f_apply : (string -> unit) ;
+ (** the function to call to apply the new value of the parameter *)
+ font_help : string option ; (** optional help string *)
+ font_expand : bool ; (** expand the entry widget or not *)
+ } ;;
+
+
+type hotkey_param = {
+ hk_label : string ; (** the label of the parameter *)
+ mutable hk_value : (Gdk.Tags.modifier list * int) ;
+ (** The value, as a list of modifiers and a key code *)
+ hk_editable : bool ; (** indicates if the value can be changed *)
+ hk_f_apply : ((Gdk.Tags.modifier list * int) -> unit) ;
+ (** the function to call to apply the new value of the paramter *)
+ hk_help : string option ; (** optional help string *)
+ hk_expand : bool ; (** expand or not *)
+ }
+
+type modifiers_param = {
+ md_label : string ; (** the label of the parameter *)
+ mutable md_value : Gdk.Tags.modifier list ;
+ (** The value, as a list of modifiers and a key code *)
+ md_editable : bool ; (** indicates if the value can be changed *)
+ md_f_apply : Gdk.Tags.modifier list -> unit ;
+ (** the function to call to apply the new value of the paramter *)
+ md_help : string option ; (** optional help string *)
+ md_expand : bool ; (** expand or not *)
+ md_allow : Gdk.Tags.modifier list
+ }
+
+(** This type represents the different kinds of parameters. *)
+type parameter_kind =
+ String_param of string_param
+ | List_param of (unit -> <box: GObj.widget ; apply : unit>)
+ | Filename_param of string_param
+ | Bool_param of bool_param
+ | Text_param of string_param
+ | Combo_param of combo_param
+ | Custom_param of custom_param
+ | Color_param of color_param
+ | Date_param of date_param
+ | Font_param of font_param
+ | Hotkey_param of hotkey_param
+ | Modifiers_param of modifiers_param
+ | Html_param of string_param
+;;
+
+(** This type represents the structure of the configuration window. *)
+type configuration_structure =
+ | Section of string * parameter_kind list (** label of the section, parameters *)
+ | Section_list of string * configuration_structure list (** label of the section, list of the sub sections *)
+;;
+
+(** To indicate what button was pushed by the user when the window is closed. *)
+type return_button =
+ Return_apply (** The user clicked on Apply at least once before
+ closing the window with Cancel or the window manager. *)
+ | Return_ok (** The user closed the window with the ok button. *)
+ | Return_cancel (** The user closed the window with the cancel
+ button or the window manager but never clicked
+ on the apply button.*)
+
+(** {2 Bindings in the html editor} *)
+
+type html_binding = {
+ mutable html_key : (Gdk.Tags.modifier list * int) ;
+ mutable html_begin : string ;
+ mutable html_end : string ;
+ }
+
+module Html_binding = struct
+ let value_to_hb v =
+ match v with
+ List [StringValue hk ; StringValue debut; StringValue fin ]
+ | SmallList [StringValue hk ; StringValue debut; StringValue fin ] ->
+ { html_key = KeyOption.string_to_key hk ;
+ html_begin = debut ;
+ html_end = fin ;
+ }
+ | _ ->
+ prerr_endline "Html_binding.value_to_hb";
+ raise Not_found
+
+ let hb_to_value hb =
+ SmallList [ StringValue (KeyOption.key_to_string hb.html_key) ;
+ StringValue hb.html_begin ;
+ StringValue hb.html_end ;
+ ]
+
+ let (t : html_binding option_class) =
+ define_option_class "html_binding" value_to_hb hb_to_value
+end
diff --git a/ide/utils/editable_cells.ml b/ide/utils/editable_cells.ml
new file mode 100644
index 00000000..e6d2f4d4
--- /dev/null
+++ b/ide/utils/editable_cells.ml
@@ -0,0 +1,114 @@
+open GTree
+open Gobject
+
+let create l =
+ let hbox = GPack.hbox () in
+ let scw = GBin.scrolled_window
+ ~hpolicy:`AUTOMATIC
+ ~vpolicy:`AUTOMATIC
+ ~packing:(hbox#pack ~expand:true) () in
+
+ let columns = new GTree.column_list in
+ let command_col = columns#add Data.string in
+ let coq_col = columns#add Data.string in
+ let store = GTree.list_store columns
+ in
+
+(* populate the store *)
+ let _ = List.iter (fun (x,y) ->
+ let row = store#append () in
+ store#set ~row ~column:command_col x;
+ store#set ~row ~column:coq_col y)
+ l
+ in
+ let view = GTree.view ~model:store ~packing:scw#add_with_viewport () in
+
+ (* Alternate colors for the rows *)
+ view#set_rules_hint true;
+
+ let renderer_comm = GTree.cell_renderer_text [`EDITABLE true] in
+ ignore (renderer_comm#connect#edited
+ ~callback:(fun (path:Gtk.tree_path) (s:string) ->
+ store#set
+ ~row:(store#get_iter path)
+ ~column:command_col s));
+ let first =
+ GTree.view_column ~title:"Coq Command to try"
+ ~renderer:(renderer_comm,["text",command_col])
+ ()
+ in ignore (view#append_column first);
+
+ let renderer_coq = GTree.cell_renderer_text [`EDITABLE true] in
+ ignore(renderer_coq#connect#edited
+ ~callback:(fun (path:Gtk.tree_path) (s:string) ->
+ store#set
+ ~row:(store#get_iter path)
+ ~column:coq_col s));
+ let second =
+ GTree.view_column ~title:"Coq Command to insert"
+ ~renderer:(renderer_coq,["text",coq_col])
+ ()
+ in ignore (view#append_column second);
+
+ let vbox = GPack.button_box `VERTICAL ~packing:hbox#pack ~layout:`SPREAD ()
+ in
+ let up = GButton.button ~stock:`GO_UP ~label:"Up" ~packing:(vbox#pack ~expand:true ~fill:false) () in
+ let down = GButton.button
+ ~stock:`GO_DOWN
+ ~label:"Down"
+ ~packing:(vbox#pack ~expand:true ~fill:false) ()
+ in
+ let add = GButton.button ~stock:`ADD
+ ~label:"Add"
+ ~packing:(vbox#pack ~expand:true ~fill:false)
+ ()
+ in
+ let remove = GButton.button ~stock:`REMOVE
+ ~label:"Remove"
+ ~packing:(vbox#pack ~expand:true ~fill:false) ()
+ in
+
+ ignore (add#connect#clicked
+ ~callback:(fun b ->
+ let n = store#append () in
+ view#selection#select_iter n));
+ ignore (remove#connect#clicked
+ ~callback:(fun b -> match view#selection#get_selected_rows with
+ | [] -> ()
+ | path::_ ->
+ let iter = store#get_iter path in
+ ignore (store#remove iter);
+ ));
+ ignore (up#connect#clicked
+ ~callback:(fun b ->
+ match view#selection#get_selected_rows with
+ | [] -> ()
+ | path::_ ->
+ let iter = store#get_iter path in
+ GtkTree.TreePath.prev path;
+ let upiter = store#get_iter path in
+ ignore (store#swap iter upiter);
+ ));
+ ignore (down#connect#clicked
+ ~callback:(fun b ->
+ match view#selection#get_selected_rows with
+ | [] -> ()
+ | path::_ ->
+ let iter = store#get_iter path in
+ GtkTree.TreePath.next path;
+ try let upiter = store#get_iter path in
+ ignore (store#swap iter upiter)
+ with _ -> ()
+ ));
+ let get_data () =
+ let start_path = GtkTree.TreePath.from_string "0" in
+ let start_iter = store#get_iter start_path in
+ let rec all acc =
+ let new_acc = (store#get ~row:start_iter ~column:command_col,
+ store#get ~row:start_iter ~column:coq_col)::acc
+ in
+ if store#iter_next start_iter then all new_acc else List.rev new_acc
+ in all []
+ in
+ (hbox,get_data)
+
diff --git a/ide/utils/okey.ml b/ide/utils/okey.ml
new file mode 100644
index 00000000..17e371f5
--- /dev/null
+++ b/ide/utils/okey.ml
@@ -0,0 +1,185 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+type modifier = Gdk.Tags.modifier
+
+type handler = {
+ cond : (unit -> bool) ;
+ cback : (unit -> unit) ;
+ }
+
+type handler_spec = int * int * Gdk.keysym
+ (** mods * mask * key *)
+
+let int_of_modifier = function
+ `SHIFT -> 1
+ | `LOCK -> 2
+ | `CONTROL -> 4
+ | `MOD1 -> 8
+ | `MOD2 -> 16
+ | `MOD3 -> 32
+ | `MOD4 -> 64
+ | `MOD5 -> 128
+ | `BUTTON1 -> 256
+ | `BUTTON2 -> 512
+ | `BUTTON3 -> 1024
+ | `BUTTON4 -> 2048
+ | `BUTTON5 -> 4096
+
+let print_modifier l =
+ List.iter
+ (fun m ->
+ print_string
+ (((function
+ `SHIFT -> "SHIFT"
+ | `LOCK -> "LOCK"
+ | `CONTROL -> "CONTROL"
+ | `MOD1 -> "MOD1"
+ | `MOD2 -> "MOD2"
+ | `MOD3 -> "MOD3"
+ | `MOD4 -> "MOD4"
+ | `MOD5 -> "MOD5"
+ | `BUTTON1 -> "B1"
+ | `BUTTON2 -> "B2"
+ | `BUTTON3 -> "B3"
+ | `BUTTON4 -> "B4"
+ | `BUTTON5 -> "B5")
+ m)^" ")
+ )
+ l;
+ print_newline ()
+
+let int_of_modifiers l =
+ List.fold_left (fun acc -> fun m -> acc + (int_of_modifier m)) 0 l
+
+module H =
+ struct
+ type t = handler_spec * handler
+ let equal (m,k) (mods, mask, key) =
+ (k = key) && ((m land mask) = mods)
+
+ let filter_with_mask mods mask key l =
+ List.filter (fun a -> (fst a) <> (mods, mask, key)) l
+
+ let find_handlers mods key l =
+ List.map snd
+ (List.filter
+ (fun ((m,ma,k),_) -> equal (mods,key) (m,ma,k))
+ l
+ )
+
+ end
+
+let (table : (int, H.t list ref) Hashtbl.t) = Hashtbl.create 13
+
+let key_press w ev =
+ let key = GdkEvent.Key.keyval ev in
+ let modifiers = GdkEvent.Key.state ev in
+ try
+ let (r : H.t list ref) = Hashtbl.find table w#get_oid in
+ let l = H.find_handlers (int_of_modifiers modifiers) key !r in
+ let b = ref true in
+ List.iter
+ (fun h ->
+ if h.cond () then
+ (h.cback () ; b := false)
+ else
+ ()
+ )
+ l;
+ !b
+ with
+ Not_found ->
+ true
+
+let associate_key_press w =
+ ignore ((w#event#connect#key_press ~callback: (key_press w)) : GtkSignal.id)
+
+let default_modifiers = ref ([] : modifier list)
+let default_mask = ref ([`MOD2 ; `MOD3 ; `MOD4 ; `MOD5 ; `LOCK] : modifier list)
+
+let set_default_modifiers l = default_modifiers := l
+let set_default_mask l = default_mask := l
+
+let remove_widget (w : < event : GObj.event_ops ; get_oid : int ; ..>) () =
+ try
+ let r = Hashtbl.find table w#get_oid in
+ r := []
+ with
+ Not_found ->
+ ()
+
+let add1 ?(remove=false) w
+ ?(cond=(fun () -> true))
+ ?(mods= !default_modifiers)
+ ?(mask= !default_mask)
+ k callback =
+ let r =
+ try Hashtbl.find table w#get_oid
+ with Not_found ->
+ let r = ref [] in
+ Hashtbl.add table w#get_oid r;
+ ignore (w#connect#destroy ~callback: (remove_widget w));
+ associate_key_press w;
+ r
+ in
+ let n_mods = int_of_modifiers mods in
+ let n_mask = lnot (int_of_modifiers mask) in
+ let new_h = { cond = cond ; cback = callback } in
+ if remove then
+ (
+ let l = H.filter_with_mask n_mods n_mask k !r in
+ r := ((n_mods, n_mask, k), new_h) :: l
+ )
+ else
+ r := ((n_mods, n_mask, k), new_h) :: !r
+
+let add w
+ ?(cond=(fun () -> true))
+ ?(mods= !default_modifiers)
+ ?(mask= !default_mask)
+ k callback =
+ add1 w ~cond ~mods ~mask k callback
+
+let add_list w
+ ?(cond=(fun () -> true))
+ ?(mods= !default_modifiers)
+ ?(mask= !default_mask)
+ k_list callback =
+ List.iter (fun k -> add w ~cond ~mods ~mask k callback) k_list
+
+let set w
+ ?(cond=(fun () -> true))
+ ?(mods= !default_modifiers)
+ ?(mask= !default_mask)
+ k callback =
+ add1 ~remove: true w ~cond ~mods ~mask k callback
+
+let set_list w
+ ?(cond=(fun () -> true))
+ ?(mods= !default_modifiers)
+ ?(mask= !default_mask)
+ k_list callback =
+ List.iter (fun k -> set w ~cond ~mods ~mask k callback) k_list
+
diff --git a/ide/utils/okey.mli b/ide/utils/okey.mli
new file mode 100644
index 00000000..a0effe72
--- /dev/null
+++ b/ide/utils/okey.mli
@@ -0,0 +1,114 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(** Okey interface.
+
+ Once the lib is compiled and installed, you can use it by referencing
+ it with the [Okey] module. You must add [okey.cmo] or [okey.cmx]
+ on the commande line when you link.
+*)
+
+type modifier = Gdk.Tags.modifier
+
+(** Set the default modifier list. The first default value is [[]].*)
+val set_default_modifiers : modifier list -> unit
+
+(** Set the default modifier mask. The first default value is
+ [[`MOD2 ; `MOD3 ; `MOD4 ; `MOD5 ; `LOCK]].
+ The mask defines the modifiers not taken into account
+ when looking for the handler of a key press event.
+*)
+val set_default_mask : modifier list -> unit
+
+(** [add widget key callback] associates the [callback] function to the event
+ "key_press" with the given [key] for the given [widget].
+
+ @param remove when true, the previous handlers for the given key and modifier
+ list are not kept.
+ @param cond this function is a guard: the [callback] function is not called
+ if the [cond] function returns [false].
+ The default [cond] function always returns [true].
+
+ @param mods the list of modifiers. If not given, the default modifiers
+ are used.
+ You can set the default modifiers with function {!Okey.set_default_modifiers}.
+
+ @param mask the list of modifiers which must not be taken
+ into account to trigger the given handler. [mods]
+ and [mask] must not have common modifiers. If not given, the default mask
+ is used.
+ You can set the default modifiers mask with function {!Okey.set_default_mask}.
+*)
+val add :
+ < connect : < destroy : callback: (unit -> unit) -> GtkSignal.id; .. >;
+ event : GObj.event_ops; get_oid : int; .. > ->
+ ?cond: (unit -> bool) ->
+ ?mods: modifier list ->
+ ?mask: modifier list ->
+ Gdk.keysym ->
+ (unit -> unit) ->
+ unit
+
+(** It calls {!Okey.add} for each given key.*)
+val add_list :
+ < connect : < destroy : callback: (unit -> unit) -> GtkSignal.id; .. >;
+ event : GObj.event_ops; get_oid : int; .. > ->
+ ?cond: (unit -> bool) ->
+ ?mods: modifier list ->
+ ?mask: modifier list ->
+ Gdk.keysym list ->
+ (unit -> unit) ->
+ unit
+
+(** Like {!Okey.add} but the previous handlers for the
+ given modifiers and key are not kept.*)
+val set :
+ < connect : < destroy : callback: (unit -> unit) -> GtkSignal.id; .. >;
+ event : GObj.event_ops; get_oid : int; .. > ->
+ ?cond: (unit -> bool) ->
+ ?mods: modifier list ->
+ ?mask: modifier list ->
+ Gdk.keysym ->
+ (unit -> unit) ->
+ unit
+
+(** It calls {!Okey.set} for each given key.*)
+val set_list :
+ < connect : < destroy : callback: (unit -> unit) -> GtkSignal.id; .. >;
+ event : GObj.event_ops; get_oid : int; .. > ->
+ ?cond: (unit -> bool) ->
+ ?mods: modifier list ->
+ ?mask: modifier list ->
+ Gdk.keysym list ->
+ (unit -> unit) ->
+ unit
+
+(** Remove the handlers associated to the given widget.
+ This is automatically done when a widget is destroyed but
+ you can do it yourself. *)
+val remove_widget :
+ < connect : < destroy : callback: (unit -> unit) -> GtkSignal.id; .. >;
+ event : GObj.event_ops; get_oid : int; .. > ->
+ unit ->
+ unit
diff --git a/ide/utils/uoptions.ml b/ide/utils/uoptions.ml
new file mode 100644
index 00000000..416f5769
--- /dev/null
+++ b/ide/utils/uoptions.ml
@@ -0,0 +1,772 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(** Simple options:
+ This will enable very simple configuration, by a mouse-based configurator.
+ Options will be defined by a special function, which will also check
+ if a value has been provided by the user in its .gwmlrc file.
+ The .gwmlrc will be created by a dedicated tool, which could be used
+ to generate both .gwmlrc and .efunsrc files.
+
+Note: this is redundant, since such options could also be better set
+in the .Xdefaults file (using Xrm to load them). Maybe we should merge
+both approaches in a latter release.
+
+ Code from Fabrice Le Fessant.
+
+ *)
+
+type option_value =
+ Module of option_module
+ | StringValue of string
+ | IntValue of int
+ | FloatValue of float
+ | List of option_value list
+ | SmallList of option_value list
+and option_module = (string * option_value) list
+;;
+
+
+
+type 'a option_class =
+ { class_name : string;
+ from_value : option_value -> 'a;
+ to_value : 'a -> option_value;
+ mutable class_hooks : ('a option_record -> unit) list }
+
+and 'a option_record =
+ { option_name : string list;
+ option_class : 'a option_class;
+ mutable option_value : 'a;
+ option_help : string;
+ mutable option_hooks : (unit -> unit) list;
+ mutable string_wrappers : (('a -> string) * (string -> 'a)) option;
+ option_file : options_file;
+ }
+
+and options_file = {
+ mutable file_name : string;
+ mutable file_options : Obj.t option_record list;
+ mutable file_rc : option_module;
+ mutable file_pruned : bool;
+ }
+;;
+
+let create_options_file name =
+ ignore
+ (
+ if not (Sys.file_exists name) then
+ let oc = open_out name in
+ close_out oc
+ );
+ {
+ file_name = name;
+ file_options =[];
+ file_rc = [];
+ file_pruned = false;
+ }
+
+let set_options_file opfile name = opfile.file_name <- name
+
+let
+ define_option_class
+ (class_name : string)
+ (from_value : option_value -> 'a)
+ (to_value : 'a -> option_value) =
+ let c =
+ {class_name = class_name;
+ from_value = from_value;
+ to_value = to_value;
+ class_hooks = []}
+ in
+ c
+;;
+
+(*
+let filename =
+ ref
+ (Filename.concat Sysenv.home
+ ("." ^ Filename.basename Sys.argv.(0) ^ "rc"))
+;;
+let gwmlrc = ref [];;
+
+let options = ref [];;
+*)
+
+let rec find_value list m =
+ match list with
+ [] -> raise Not_found
+ | name :: tail ->
+ let m = List.assoc name m in
+ match m, tail with
+ _, [] -> m
+ | Module m, _ :: _ -> find_value tail m
+ | _ -> raise Not_found
+;;
+
+let prune_file file =
+ file.file_pruned <- true
+
+let
+ define_option
+ (opfile : options_file)
+ (option_name : string list)
+ (option_help : string)
+ (option_class : 'a option_class)
+ (default_value : 'a) =
+ let o =
+ {option_name = option_name;
+ option_help = option_help;
+ option_class = option_class;
+ option_value = default_value;
+ string_wrappers = None;
+ option_hooks = [];
+ option_file = opfile; }
+ in
+ opfile.file_options <- (Obj.magic o : Obj.t option_record) ::
+ opfile.file_options;
+ o.option_value <-
+ begin try o.option_class.from_value (find_value option_name
+ opfile.file_rc) with
+ Not_found -> default_value
+ | e ->
+ Printf.printf "Options.define_option, for option %s: "
+ (match option_name with
+ [] -> "???"
+ | name :: _ -> name);
+ Printf.printf "%s" (Printexc.to_string e);
+ print_newline ();
+ default_value
+ end;
+ o
+;;
+
+
+open Genlex;;
+
+let lexer = make_lexer ["="; "{"; "}"; "["; "]"; ";"; "("; ")"; ","; "."];;
+
+let rec parse_gwmlrc (strm__ : _ Stream.t) =
+ match
+ try Some (parse_id strm__) with
+ Stream.Failure -> None
+ with
+ Some id ->
+ begin match Stream.peek strm__ with
+ Some (Kwd "=") ->
+ Stream.junk strm__;
+ let v =
+ try parse_option strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ in
+ let eof =
+ try parse_gwmlrc strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ in
+ (id, v) :: eof
+ | _ -> raise (Stream.Error "")
+ end
+ | _ -> []
+and parse_option (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some (Kwd "{") ->
+ Stream.junk strm__;
+ let v =
+ try parse_gwmlrc strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ in
+ begin match Stream.peek strm__ with
+ Some (Kwd "}") -> Stream.junk strm__; Module v
+ | _ -> raise (Stream.Error "")
+ end
+ | Some (Ident s) -> Stream.junk strm__; StringValue s
+ | Some (String s) -> Stream.junk strm__; StringValue s
+ | Some (Int i) -> Stream.junk strm__; IntValue i
+ | Some (Float f) -> Stream.junk strm__; FloatValue f
+ | Some (Char c) ->
+ Stream.junk strm__;
+ StringValue (let s = String.create 1 in s.[0] <- c; s)
+ | Some (Kwd "[") ->
+ Stream.junk strm__;
+ let v =
+ try parse_list strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ in
+ List v
+ | Some (Kwd "(") ->
+ Stream.junk strm__;
+ let v =
+ try parse_list strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ in
+ List v
+ | _ -> raise Stream.Failure
+and parse_id (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some (Ident s) -> Stream.junk strm__; s
+ | Some (String s) -> Stream.junk strm__; s
+ | _ -> raise Stream.Failure
+and parse_list (strm__ : _ Stream.t) =
+ match Stream.peek strm__ with
+ Some (Kwd ";") ->
+ Stream.junk strm__;
+ begin try parse_list strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ end
+ | Some (Kwd ",") ->
+ Stream.junk strm__;
+ begin try parse_list strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ end
+ | Some (Kwd ".") ->
+ Stream.junk strm__;
+ begin try parse_list strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ end
+ | _ ->
+ match
+ try Some (parse_option strm__) with
+ Stream.Failure -> None
+ with
+ Some v ->
+ let t =
+ try parse_list strm__ with
+ Stream.Failure -> raise (Stream.Error "")
+ in
+ v :: t
+ | _ ->
+ match Stream.peek strm__ with
+ Some (Kwd "]") -> Stream.junk strm__; []
+ | Some (Kwd ")") -> Stream.junk strm__; []
+ | _ -> raise Stream.Failure
+;;
+
+let exec_hooks o =
+ List.iter
+ (fun f ->
+ try f () with
+ _ -> ())
+ o.option_hooks
+;;
+
+let exec_chooks o =
+ List.iter
+ (fun f ->
+ try f o with
+ _ -> ())
+ o.option_class.class_hooks
+;;
+
+let really_load filename options =
+ let temp_file = filename ^ ".tmp" in
+ if Sys.file_exists temp_file then begin
+ Printf.printf
+ "File %s exists\n" temp_file;
+ Printf.printf
+ "An error may have occurred during previous configuration save.\n";
+ Printf.printf
+ "Please, check your configurations files, and rename/remove this file\n";
+ Printf.printf "before restarting";
+ print_newline ();
+ exit 1
+ end
+ else
+ let ic = open_in filename in
+ let s = Stream.of_channel ic in
+ try
+ let stream = lexer s in
+ let list =
+ try parse_gwmlrc stream with
+ e ->
+ Printf.printf "At pos %d/%d" (Stream.count s) (Stream.count stream);
+ print_newline ();
+ raise e
+ in
+ List.iter
+ (fun o ->
+ try
+ o.option_value <-
+ o.option_class.from_value (find_value o.option_name list);
+ exec_chooks o;
+ exec_hooks o
+ with
+ e ->
+ ()
+ )
+ options;
+ list
+ with
+ e ->
+ Printf.printf "Error %s in %s" (Printexc.to_string e) filename;
+ print_newline ();
+ []
+;;
+
+let load opfile =
+ try opfile.file_rc <- really_load opfile.file_name opfile.file_options with
+ Not_found ->
+ Printf.printf "No %s found" opfile.file_name; print_newline ()
+;;
+
+let append opfile filename =
+ try opfile.file_rc <-
+ really_load filename opfile.file_options @ opfile.file_rc with
+ Not_found ->
+ Printf.printf "No %s found" filename; print_newline ()
+;;
+
+let ( !! ) o = o.option_value;;
+let ( =:= ) o v = o.option_value <- v; exec_chooks o; exec_hooks o;;
+
+let value_to_string v =
+ match v with
+ StringValue s -> s
+ | IntValue i -> string_of_int i
+ | FloatValue f -> string_of_float f
+ | _ -> failwith "Options: not a string option"
+;;
+
+let string_to_value s = StringValue s;;
+
+let value_to_int v =
+ match v with
+ StringValue s -> int_of_string s
+ | IntValue i -> i
+ | _ -> failwith "Options: not an int option"
+;;
+
+let int_to_value i = IntValue i;;
+
+(* The Pervasives version is too restrictive *)
+let bool_of_string s =
+ match String.lowercase s with
+ "true" -> true
+ | "false" -> false
+ | "yes" -> true
+ | "no" -> false
+ | "y" -> true
+ | "n" -> false
+ | _ -> invalid_arg "bool_of_string"
+;;
+
+let value_to_bool v =
+ match v with
+ StringValue s -> bool_of_string s
+ | IntValue v when v = 0 -> false
+ | IntValue v when v = 1 -> true
+ | _ -> failwith "Options: not a bool option"
+;;
+let bool_to_value i = StringValue (string_of_bool i);;
+
+let value_to_float v =
+ match v with
+ StringValue s -> float_of_string s
+ | FloatValue f -> f
+ | _ -> failwith "Options: not a float option"
+;;
+
+let float_to_value i = FloatValue i;;
+
+let value_to_string2 v =
+ match v with
+ List [s1; s2] | SmallList [s1;s2] ->
+ value_to_string s1, value_to_string s2
+ | _ -> failwith "Options: not a string2 option"
+;;
+
+let string2_to_value (s1, s2) = SmallList [StringValue s1; StringValue s2];;
+
+let value_to_list v2c v =
+ match v with
+ List l | SmallList l -> List.rev (List.rev_map v2c l)
+ | StringValue s -> failwith (Printf.sprintf
+ "Options: not a list option (StringValue [%s])" s)
+ | FloatValue _ -> failwith "Options: not a list option (FloatValue)"
+ | IntValue _ -> failwith "Options: not a list option (IntValue)"
+ | Module _ -> failwith "Options: not a list option (Module)"
+;;
+
+let list_to_value c2v l =
+ List
+ (List.fold_right
+ (fun v list ->
+ try c2v v :: list with
+ _ -> list)
+ l [])
+;;
+
+let smalllist_to_value c2v l =
+ SmallList
+ (List.fold_right
+ (fun v list ->
+ try c2v v :: list with
+ _ -> list)
+ l [])
+;;
+
+let string_option =
+ define_option_class "String" value_to_string string_to_value
+;;
+let color_option =
+ define_option_class "Color" value_to_string string_to_value
+;;
+let font_option = define_option_class "Font" value_to_string string_to_value;;
+
+let int_option = define_option_class "Int" value_to_int int_to_value;;
+
+let bool_option = define_option_class "Bool" value_to_bool bool_to_value;;
+let float_option = define_option_class "Float" value_to_float float_to_value;;
+
+let string2_option =
+ define_option_class "String2" value_to_string2 string2_to_value
+;;
+
+let list_option cl =
+ define_option_class (cl.class_name ^ " List") (value_to_list cl.from_value)
+ (list_to_value cl.to_value)
+;;
+
+let smalllist_option cl =
+ define_option_class (cl.class_name ^ " List") (value_to_list cl.from_value)
+ (smalllist_to_value cl.to_value)
+;;
+
+let to_value cl = cl.to_value;;
+let from_value cl = cl.from_value;;
+
+let value_to_sum l v =
+ match v with
+ StringValue s -> List.assoc s l
+ | _ -> failwith "Options: not a sum option"
+;;
+
+let sum_to_value l v = StringValue (List.assq v l);;
+
+let sum_option l =
+ let ll = List.map (fun (a1, a2) -> a2, a1) l in
+ define_option_class "Sum" (value_to_sum l) (sum_to_value ll)
+;;
+
+let exit_exn = Exit;;
+let safe_string s =
+ if s = "" then "\"\""
+ else
+ try
+ match s.[0] with
+ 'a'..'z' | 'A'..'Z' ->
+ for i = 1 to String.length s - 1 do
+ match s.[i] with
+ 'a'..'z' | 'A'..'Z' | '_' | '0'..'9' -> ()
+ | _ -> raise exit_exn
+ done;
+ s
+ | _ ->
+ if string_of_int (int_of_string s) = s ||
+ string_of_float (float_of_string s) = s then
+ s
+ else raise exit_exn
+ with
+ _ -> Printf.sprintf "\"%s\"" (String.escaped s)
+;;
+
+let with_help = ref false;;
+
+let rec save_module indent oc list =
+ let subm = ref [] in
+ List.iter
+ (fun (name, help, value) ->
+ match name with
+ [] -> assert false
+ | [name] ->
+ if !with_help && help <> "" then
+ Printf.fprintf oc "(* %s *)\n" help;
+ Printf.fprintf oc "%s %s = " indent (safe_string name);
+ save_value indent oc value;
+ Printf.fprintf oc "\n"
+ | m :: tail ->
+ let p =
+ try List.assoc m !subm with
+ _ -> let p = ref [] in subm := (m, p) :: !subm; p
+ in
+ p := (tail, help, value) :: !p)
+ list;
+ List.iter
+ (fun (m, p) ->
+ Printf.fprintf oc "%s %s = {\n" indent (safe_string m);
+ save_module (indent ^ " ") oc !p;
+ Printf.fprintf oc "%s}\n" indent)
+ !subm
+and save_list indent oc list =
+ match list with
+ [] -> ()
+ | [v] -> save_value indent oc v
+ | v :: tail ->
+ save_value indent oc v; Printf.fprintf oc ", "; save_list indent oc tail
+and save_list_nl indent oc list =
+ match list with
+ [] -> ()
+ | [v] -> Printf.fprintf oc "\n%s" indent; save_value indent oc v
+ | v :: tail ->
+ Printf.fprintf oc "\n%s" indent;
+ save_value indent oc v;
+ Printf.fprintf oc ";";
+ save_list_nl indent oc tail
+and save_value indent oc v =
+ match v with
+ StringValue s -> Printf.fprintf oc "%s" (safe_string s)
+ | IntValue i -> Printf.fprintf oc "%d" i
+ | FloatValue f -> Printf.fprintf oc "%f" f
+ | List l ->
+ Printf.fprintf oc "[";
+ save_list_nl (indent ^ " ") oc l;
+ Printf.fprintf oc "]"
+ | SmallList l ->
+ Printf.fprintf oc "(";
+ save_list (indent ^ " ") oc l;
+ Printf.fprintf oc ")"
+ | Module m ->
+ Printf.fprintf oc "{";
+ save_module_fields (indent ^ " ") oc m;
+ Printf.fprintf oc "}"
+
+and save_module_fields indent oc m =
+ match m with
+ [] -> ()
+ | (name, v) :: tail ->
+ Printf.fprintf oc "%s %s = " indent (safe_string name);
+ save_value indent oc v;
+ Printf.fprintf oc "\n";
+ save_module_fields indent oc tail
+;;
+
+let save opfile =
+ let filename = opfile.file_name in
+ let temp_file = filename ^ ".tmp" in
+ let old_file = filename ^ ".old" in
+ let oc = open_out temp_file in
+ save_module "" oc
+ (List.map
+ (fun o ->
+ o.option_name, o.option_help,
+ (try
+ o.option_class.to_value o.option_value
+ with
+ e ->
+ Printf.printf "Error while saving option \"%s\": %s"
+ (try List.hd o.option_name with
+ _ -> "???")
+ (Printexc.to_string e);
+ print_newline ();
+ StringValue ""))
+ (List.rev opfile.file_options));
+ if not opfile.file_pruned then begin
+ Printf.fprintf oc
+ "\n(*\n The following options are not used (errors, obsolete, ...) \n*)\n";
+ List.iter
+ (fun (name, value) ->
+ try
+ List.iter
+ (fun o ->
+ match o.option_name with
+ n :: _ -> if n = name then raise Exit
+ | _ -> ())
+ opfile.file_options;
+ Printf.fprintf oc "%s = " (safe_string name);
+ save_value " " oc value;
+ Printf.fprintf oc "\n"
+ with
+ _ -> ())
+ opfile.file_rc;
+ end;
+ close_out oc;
+ (try Sys.rename filename old_file with _ -> ());
+ (try Sys.rename temp_file filename with _ -> ())
+;;
+
+let save_with_help opfile =
+ with_help := true;
+ begin try save opfile with
+ _ -> ()
+ end;
+ with_help := false
+;;
+
+let option_hook option f = option.option_hooks <- f :: option.option_hooks;;
+
+let class_hook option_class f =
+ option_class.class_hooks <- f :: option_class.class_hooks
+;;
+
+let rec iter_order f list =
+ match list with
+ [] -> ()
+ | v :: tail -> f v; iter_order f tail
+;;
+
+let help oc opfile =
+ List.iter
+ (fun o ->
+ Printf.fprintf oc "OPTION \"";
+ begin match o.option_name with
+ [] -> Printf.fprintf oc "???"
+ | [name] -> Printf.fprintf oc "%s" name
+ | name :: tail ->
+ Printf.fprintf oc "%s" name;
+ iter_order (fun name -> Printf.fprintf oc ":%s" name) o.option_name
+ end;
+ Printf.fprintf oc "\" (TYPE \"%s\"): %s\n CURRENT: \n"
+ o.option_class.class_name o.option_help;
+ begin try
+ save_value "" oc (o.option_class.to_value o.option_value)
+ with
+ _ -> ()
+ end;
+ Printf.fprintf oc "\n")
+ opfile.file_options;
+ flush oc
+;;
+
+
+let tuple2_to_value (c1, c2) (a1, a2) =
+ SmallList [to_value c1 a1; to_value c2 a2]
+;;
+
+let value_to_tuple2 (c1, c2) v =
+ match v with
+ List [v1; v2] -> from_value c1 v1, from_value c2 v2
+ | SmallList [v1; v2] -> from_value c1 v1, from_value c2 v2
+ | List l | SmallList l ->
+ Printf.printf "list of %d" (List.length l);
+ print_newline ();
+ failwith "Options: not a tuple2 list option"
+ | _ -> failwith "Options: not a tuple2 option"
+;;
+
+let tuple2_option p =
+ define_option_class "tuple2_option" (value_to_tuple2 p) (tuple2_to_value p)
+;;
+
+let tuple3_to_value (c1, c2, c3) (a1, a2, a3) =
+ SmallList [to_value c1 a1; to_value c2 a2; to_value c3 a3]
+;;
+let value_to_tuple3 (c1, c2, c3) v =
+ match v with
+ List [v1; v2; v3] -> from_value c1 v1, from_value c2 v2, from_value c3 v3
+ | SmallList [v1; v2; v3] ->
+ from_value c1 v1, from_value c2 v2, from_value c3 v3
+ | _ -> failwith "Options: not a tuple3 option"
+;;
+
+let tuple3_option p =
+ define_option_class "tuple3_option" (value_to_tuple3 p) (tuple3_to_value p)
+;;
+
+let tuple4_to_value (c1, c2, c3, c4) (a1, a2, a3, a4) =
+ SmallList [to_value c1 a1; to_value c2 a2; to_value c3 a3; to_value c4 a4]
+;;
+let value_to_tuple4 (c1, c2, c3, c4) v =
+ match v with
+ List [v1; v2; v3; v4] ->
+ (from_value c1 v1, from_value c2 v2, from_value c3 v3, from_value c4 v4)
+ | SmallList [v1; v2; v3; v4] ->
+ (from_value c1 v1, from_value c2 v2, from_value c3 v3, from_value c4 v4)
+ | _ -> failwith "Options: not a tuple4 option"
+;;
+
+let tuple4_option p =
+ define_option_class "tuple4_option" (value_to_tuple4 p) (tuple4_to_value p)
+;;
+
+
+let shortname o = String.concat ":" o.option_name;;
+let get_class o = o.option_class;;
+let get_help o =
+ let help = o.option_help in if help = "" then "No Help Available" else help
+;;
+
+
+let simple_options opfile =
+ let list = ref [] in
+ List.iter (fun o ->
+ match o.option_name with
+ [] | _ :: _ :: _ -> ()
+ | [name] ->
+ match o.option_class.to_value o.option_value with
+ Module _ | SmallList _ | List _ ->
+ begin
+ match o.string_wrappers with
+ None -> ()
+ | Some (to_string, from_string) ->
+ list := (name, to_string o.option_value) :: !list
+ end
+ | v ->
+ list := (name, value_to_string v) :: !list
+ ) opfile.file_options;
+ !list
+
+let get_option opfile name =
+ let rec iter name list =
+ match list with
+ [] -> raise Not_found
+ | o :: list ->
+ if o.option_name = name then o
+ else iter name list
+ in
+ iter [name] opfile.file_options
+
+
+let set_simple_option opfile name v =
+ let o = get_option opfile name in
+ begin
+ match o.string_wrappers with
+ None ->
+ o.option_value <- o.option_class.from_value (string_to_value v);
+ | Some (_, from_string) ->
+ o.option_value <- from_string v
+ end;
+ exec_chooks o; exec_hooks o;;
+
+let get_simple_option opfile name =
+ let o = get_option opfile name in
+ match o.string_wrappers with
+ None ->
+ value_to_string (o.option_class.to_value o.option_value)
+ | Some (to_string, _) ->
+ to_string o.option_value
+
+let set_option_hook opfile name hook =
+ let o = get_option opfile name in
+ o.option_hooks <- hook :: o.option_hooks
+
+let set_string_wrappers o to_string from_string =
+ o.string_wrappers <- Some (to_string, from_string)
+
+let simple_args opfile =
+ List.map (fun (name, v) ->
+ ("-" ^ name),
+ Arg.String (set_simple_option opfile name),
+ (Printf.sprintf "<string> : \t%s (current: %s)"
+ (get_option opfile name).option_help
+ v)
+ ) (simple_options opfile)
diff --git a/ide/utils/uoptions.mli b/ide/utils/uoptions.mli
new file mode 100644
index 00000000..a323ac60
--- /dev/null
+++ b/ide/utils/uoptions.mli
@@ -0,0 +1,148 @@
+(**************************************************************************)
+(* Cameleon *)
+(* *)
+(* Copyright (C) 2002 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. *)
+(* *)
+(* This program is free software; you can redistribute it and/or modify *)
+(* it under the terms of the GNU General Public License as published by *)
+(* the Free Software Foundation; either version 2 of the License, or *)
+(* any later version. *)
+(* *)
+(* This program is distributed in the hope that it will be useful, *)
+(* but WITHOUT ANY WARRANTY; without even the implied warranty of *)
+(* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *)
+(* GNU General Public License for more details. *)
+(* *)
+(* You should have received a copy of the GNU General Public License *)
+(* along with this program; if not, write to the Free Software *)
+(* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA *)
+(* 02111-1307 USA *)
+(* *)
+(* Contact: Maxence.Guesdon@inria.fr *)
+(**************************************************************************)
+
+(**
+ This module implements a simple mechanism to handle program options files.
+ An options file is defined as a set of [variable = value] lines,
+ where value can be a simple string, a list of values (between brackets
+or parentheses) or a set of [variable = value] lines between braces.
+The option file is automatically loaded and saved, and options are
+manipulated inside the program as easily as references.
+
+ Code from Fabrice Le Fessant.
+*)
+
+type 'a option_class
+(** The abstract type for a class of options. A class is a set of options
+which use the same conversion functions from loading and saving.*)
+
+type 'a option_record
+(** The abstract type for an option *)
+
+type options_file
+
+val create_options_file : string -> options_file
+val set_options_file : options_file -> string -> unit
+val prune_file : options_file -> unit
+
+(** {2 Operations on option files} *)
+
+val load : options_file -> unit
+(** [load file] loads the option file. All options whose value is specified
+ in the option file are updated. *)
+
+val append : options_file -> string -> unit
+(** [append filename] loads the specified option file. All options whose
+value is specified in this file are updated. *)
+
+val save : options_file -> unit
+(** [save file] saves all the options values to the option file. *)
+
+val save_with_help : options_file -> unit
+(** [save_with_help ()] saves all the options values to the option file,
+ with the help provided for each option. *)
+
+(** {2 Creating options} *)
+
+val define_option : options_file ->
+ string list -> string -> 'a option_class -> 'a -> 'a option_record
+val option_hook : 'a option_record -> (unit -> unit) -> unit
+
+val string_option : string option_class
+val color_option : string option_class
+val font_option : string option_class
+val int_option : int option_class
+val bool_option : bool option_class
+val float_option : float option_class
+val string2_option : (string * string) option_class
+
+ (* parameterized options *)
+val list_option : 'a option_class -> 'a list option_class
+val smalllist_option : 'a option_class -> 'a list option_class
+val sum_option : (string * 'a) list -> 'a option_class
+val tuple2_option :
+ 'a option_class * 'b option_class -> ('a * 'b) option_class
+val tuple3_option : 'a option_class * 'b option_class * 'c option_class ->
+ ('a * 'b * 'c) option_class
+val tuple4_option :
+ 'a option_class * 'b option_class * 'c option_class * 'd option_class ->
+ ('a * 'b * 'c * 'd) option_class
+
+(** {2 Using options} *)
+
+val ( !! ) : 'a option_record -> 'a
+val ( =:= ) : 'a option_record -> 'a -> unit
+
+val shortname : 'a option_record -> string
+val get_help : 'a option_record -> string
+
+(** {2 Creating new option classes} *)
+
+val get_class : 'a option_record -> 'a option_class
+
+val class_hook : 'a option_class -> ('a option_record -> unit) -> unit
+
+type option_value =
+ Module of option_module
+| StringValue of string
+| IntValue of int
+| FloatValue of float
+| List of option_value list
+| SmallList of option_value list
+
+and option_module =
+ (string * option_value) list
+
+val define_option_class :
+ string -> (option_value -> 'a) -> ('a -> option_value) -> 'a option_class
+
+val to_value : 'a option_class -> 'a -> option_value
+val from_value : 'a option_class -> option_value -> 'a
+
+val value_to_string : option_value -> string
+val string_to_value : string -> option_value
+val value_to_int : option_value -> int
+val int_to_value : int -> option_value
+val bool_of_string : string -> bool
+val value_to_bool : option_value -> bool
+val bool_to_value : bool -> option_value
+val value_to_float : option_value -> float
+val float_to_value : float -> option_value
+val value_to_string2 : option_value -> string * string
+val string2_to_value : string * string -> option_value
+val value_to_list : (option_value -> 'a) -> option_value -> 'a list
+val list_to_value : ('a -> option_value) -> 'a list -> option_value
+val smalllist_to_value : ('a -> option_value) -> 'a list -> option_value
+
+val set_simple_option : options_file -> string -> string -> unit
+val simple_options : options_file -> (string * string) list
+val get_simple_option : options_file -> string -> string
+val set_option_hook : options_file -> string -> (unit -> unit) -> unit
+
+val set_string_wrappers : 'a option_record ->
+ ('a -> string) -> (string -> 'a) -> unit
+
+(** {2 Other functions} *)
+
+val simple_args : options_file -> (string * Arg.spec * string) list