]> matita.cs.unibo.it Git - helm.git/blob - helm/gTopLevel/texTermEditor.ml
Interface change: the get_as_string and set_term methods of the term-editors
[helm.git] / helm / gTopLevel / texTermEditor.ml
1 (* Copyright (C) 2000-2002, HELM Team.
2  * 
3  * This file is part of HELM, an Hypertextual, Electronic
4  * Library of Mathematics, developed at the Computer Science
5  * Department, University of Bologna, Italy.
6  * 
7  * HELM is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * 
12  * HELM is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with HELM; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20  * MA  02111-1307, USA.
21  * 
22  * For details, see the HELM World-Wide-Web page,
23  * http://cs.unibo.it/helm/.
24  *)
25
26 (******************************************************************************)
27 (*                                                                            *)
28 (*                               PROJECT HELM                                 *)
29 (*                                                                            *)
30 (*                Claudio Sacerdoti Coen <sacerdot@cs.unibo.it>               *)
31 (*                                 06/01/2002                                 *)
32 (*                                                                            *)
33 (*                                                                            *)
34 (******************************************************************************)
35
36 (* A WIDGET TO ENTER CIC TERMS *)
37
38 class type term_editor =
39  object
40    method coerce : GObj.widget
41    (* get_as_string returns the unquoted string *)
42    method get_as_string : string
43    method get_metasenv_and_term :
44      context:Cic.context ->
45      metasenv:Cic.metasenv -> Cic.metasenv * Cic.term
46    method reset : unit
47    (* The input of set_term is unquoted *)
48    method set_term : string -> unit
49    method id_to_uris : Disambiguate.domain_and_interpretation ref
50  end
51 ;;
52
53 let empty_id_to_uris = ([],function _ -> None);;
54
55 module Make(C:Disambiguate.Callbacks) =
56   struct
57
58    module Disambiguate' = Disambiguate.Make(C);;
59
60    class term_editor_impl
61     mqi_handle
62     ?packing ?width ?height
63     ?isnotempty_callback ?share_id_to_uris_with () : term_editor
64    =
65     let mmlwidget =
66      GMathViewAux.single_selection_math_view
67       ?packing ?width ?height () in
68     let drawing_area = mmlwidget#get_drawing_area in
69     let _ = drawing_area#misc#set_can_focus true in
70     let _ = drawing_area#misc#grab_focus () in
71     let logger =
72      fun l s -> prerr_endline ("TERM_EDITOR (" ^ string_of_int l ^ "): " ^ s) in
73     let tex_editor =
74      Mathml_editor.create
75       Mathml_editor.default_dictionary_path
76       Mathml_editor.default_mathml_stylesheet_path
77       Mathml_editor.default_tex_stylesheet_path
78       logger
79     in
80     let _ =
81      (new GObj.event_ops mmlwidget#coerce#as_widget)#connect#button_press
82       ~callback:(fun _ -> drawing_area#misc#grab_focus () ; true) in
83     let _ =
84      (new GObj.event_ops drawing_area#coerce#as_widget)#connect#focus_in
85        ~callback:
86          (fun _ ->
87            mmlwidget#freeze ;
88            Mathml_editor.cursor_show ~editor:tex_editor ;
89            mmlwidget#thaw ;
90            true) in
91     let _ =
92      (new GObj.event_ops drawing_area#coerce#as_widget)#connect#focus_out
93        ~callback:
94          (fun _ ->
95            mmlwidget#freeze ;
96            Mathml_editor.cursor_hide ~editor:tex_editor ;
97            mmlwidget#thaw ;
98            true) in
99     let _ = Mathml_editor.push tex_editor '$' in
100     let dom_tree = Mathml_editor.get_mml tex_editor in
101     let _ = mmlwidget#load_doc dom_tree in
102     let _ = 
103      drawing_area#event#connect#key_press
104       (function e ->
105         let key = GdkEvent.Key.keyval e in
106          mmlwidget#freeze ;
107 (*CSC: pre-lexer *)
108          if key = GdkKeysyms._space && GdkEvent.Key.state e = [] then
109           begin
110            ignore (Mathml_editor.freeze tex_editor) ;
111            Mathml_editor.push tex_editor '\\' ;
112            Mathml_editor.push tex_editor ';' ;
113            ignore (Mathml_editor.thaw tex_editor)
114           end
115 (*CSC: end of pre-lexer *)
116          else if
117           key >= 32 && key < 256 &&
118            (GdkEvent.Key.state e = [] || GdkEvent.Key.state e = [`SHIFT])
119          then
120           Mathml_editor.push tex_editor (Char.chr key)
121          else if key = GdkKeysyms._u then
122           begin
123            mmlwidget#freeze ;
124            ignore (Mathml_editor.freeze tex_editor) ;
125            Mathml_editor.reset tex_editor ;
126            Mathml_editor.push tex_editor '$' ;
127            ignore (Mathml_editor.thaw tex_editor) ;
128            mmlwidget#thaw
129           end
130          else if key = GdkKeysyms._BackSpace then
131           Mathml_editor.drop tex_editor false ;
132          mmlwidget#thaw ;
133          false) in
134     let id_to_uris =
135      match share_id_to_uris_with with
136         None -> ref empty_id_to_uris
137       | Some obj -> obj#id_to_uris
138     in
139     let _ =
140      match isnotempty_callback with
141         None -> ()
142       | Some callback ->
143          (* This approximation of the test that checks if the tree is empty *)
144          (* is utterly unprecise. We assume a tree to look as an empty tree *)
145          (* iff it is made of just one node m:mtext (which should be the    *)
146          (* cursor).                                                        *)
147          let is_empty_tree () =
148           let root = dom_tree#get_documentElement in
149            match root#get_firstChild with
150               None -> true
151             | Some n -> n#get_nodeName#to_string = "m:mtext"
152          in
153           dom_tree#addEventListener
154            ~typ:(Gdome.domString "DOMSubtreeModified")
155            ~listener:
156              (Gdome.eventListener
157                (function _ -> callback (not (is_empty_tree ()))))
158            ~useCapture:false
159     in
160      object(self)
161       method coerce = mmlwidget#coerce
162       method reset =
163        mmlwidget#freeze ;
164        ignore (Mathml_editor.freeze tex_editor) ;
165        Mathml_editor.reset tex_editor ;
166        Mathml_editor.push tex_editor '$' ;
167        ignore (Mathml_editor.thaw tex_editor) ;
168        mmlwidget#thaw
169
170       (* The input of set_term is unquoted *)
171       method set_term txt =
172        mmlwidget#freeze ;
173        ignore (Mathml_editor.freeze tex_editor) ;
174        self#reset ;
175        let txt' = Str.global_replace (Str.regexp "_") "\\_" txt in
176         String.iter (fun ch -> Mathml_editor.push tex_editor ch) txt' ;
177         ignore (Mathml_editor.thaw tex_editor) ;
178         mmlwidget#thaw
179
180       (* get_as_string returns the unquoted string *)
181       method get_as_string =
182        let term = Mathml_editor.get_tex tex_editor in
183         Str.global_replace (Str.regexp "^\\$\\$?") ""
184          (Str.global_replace (Str.regexp "\\$\\$?$") ""
185            (Str.global_replace (Str.regexp "\\\\_") "_" term))
186
187       method get_metasenv_and_term ~context ~metasenv =
188        let name_context =
189         List.map
190          (function
191              Some (n,_) -> Some n
192            | None -> None
193          ) context
194        in
195         let lexbuf = Lexing.from_string (Mathml_editor.get_tex tex_editor) in
196          let dom,mk_metasenv_and_expr =
197           TexCicTextualParserContext.main
198            ~context:name_context ~metasenv TexCicTextualLexer.token lexbuf
199          in
200           let id_to_uris',metasenv,expr =
201            Disambiguate'.disambiguate_input mqi_handle 
202             context metasenv dom mk_metasenv_and_expr ~id_to_uris:!id_to_uris
203           in
204            id_to_uris := id_to_uris' ;
205            metasenv,expr
206       method id_to_uris = id_to_uris
207    end
208
209    let term_editor = new term_editor_impl
210
211 end
212 ;;