~ubuntu-branches/ubuntu/wily/coq-doc/wily

« back to all changes in this revision

Viewing changes to ide/coqide.ml

  • Committer: Bazaar Package Importer
  • Author(s): Stéphane Glondu, Stéphane Glondu, Samuel Mimram
  • Date: 2010-01-07 22:50:39 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20100107225039-n3cq82589u0qt0s2
Tags: 8.2pl1-1
[ Stéphane Glondu ]
* New upstream release (Closes: #563669)
  - remove patches
* Packaging overhaul:
  - use git, advertise it in Vcs-* fields of debian/control
  - use debhelper 7 and dh with override
  - use source format 3.0 (quilt)
* debian/control:
  - set Maintainer to d-o-m, set Uploaders to Sam and myself
  - add Homepage field
  - bump Standards-Version to 3.8.3
* Register PDF documentation into doc-base
* Add debian/watch
* Update debian/copyright

[ Samuel Mimram ]
* Change coq-doc's description to mention that it provides documentation in
  pdf format, not postscript, closes: #543545.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
(************************************************************************)
 
3
(*  v      *   The Coq Proof Assistant  /  The Coq Development Team     *)
 
4
(* <O___,, * CNRS-Ecole Polytechnique-INRIA Futurs-Universite Paris Sud *)
 
5
(*   \VV/  **************************************************************)
 
6
(*    //   *      This file is distributed under the terms of the       *)
 
7
(*         *       GNU Lesser General Public License Version 2.1        *)
 
8
(************************************************************************)
 
9
 
 
10
(* $Id: coqide.ml 12104 2009-04-24 18:10:10Z notin $ *)
 
11
 
 
12
open Preferences
 
13
open Vernacexpr
 
14
open Coq
 
15
open Ideutils
 
16
  
 
17
let cb_ = ref None
 
18
let cb () = ((Option.get !cb_):GData.clipboard)
 
19
let last_cb_content = ref ""
 
20
 
 
21
let (message_view:GText.view option ref) = ref None
 
22
let (proof_view:GText.view option ref) = ref None
 
23
  
 
24
let (_notebook:GPack.notebook option ref) = ref None
 
25
let notebook () = Option.get !_notebook
 
26
 
 
27
let update_notebook_pos () =
 
28
  let pos =
 
29
    match !current.vertical_tabs, !current.opposite_tabs with
 
30
      | false, false -> `TOP
 
31
      | false, true  -> `BOTTOM
 
32
      | true , false -> `LEFT
 
33
      | true , true  -> `RIGHT
 
34
  in
 
35
  (notebook ())#set_tab_pos pos
 
36
  
 
37
(* Tabs contain the name of the edited file and 2 status informations: 
 
38
   Saved state + Focused proof buffer *)
 
39
let decompose_tab w = 
 
40
  let vbox = new GPack.box ((Gobject.try_cast w "GtkBox"):Gtk.box Gtk.obj) in
 
41
  let l = vbox#children in
 
42
    match l with 
 
43
      | [img;lbl] -> 
 
44
          let img = new GMisc.image 
 
45
            ((Gobject.try_cast img#as_widget "GtkImage"):
 
46
               Gtk.image Gtk.obj) 
 
47
          in
 
48
          let lbl = GMisc.label_cast lbl in
 
49
            vbox,img,lbl
 
50
      | _ -> assert false
 
51
          
 
52
let set_tab_label i n =
 
53
  let nb = notebook () in
 
54
  let _,_,lbl = decompose_tab (nb#get_tab_label(nb#get_nth_page i))#as_widget 
 
55
  in
 
56
    lbl#set_use_markup true;
 
57
    (* lbl#set_text n *) lbl#set_label n
 
58
    
 
59
    
 
60
let set_tab_image ~icon i = 
 
61
  let nb = notebook () in
 
62
  let _,img,_ = decompose_tab (nb#get_tab_label(nb#get_nth_page i))#as_widget
 
63
  in
 
64
    img#set_icon_size `SMALL_TOOLBAR;
 
65
    img#set_stock icon
 
66
      
 
67
let set_current_tab_image ~icon = set_tab_image ~icon (notebook())#current_page
 
68
  
 
69
let set_current_tab_label n = set_tab_label (notebook())#current_page n 
 
70
  
 
71
let get_tab_label i =
 
72
  let nb = notebook () in
 
73
  let _,_,lbl = decompose_tab (nb#get_tab_label(nb#get_nth_page i))#as_widget 
 
74
  in
 
75
    lbl#text
 
76
      
 
77
let get_full_tab_label i = 
 
78
  let nb = notebook () in
 
79
  let _,_,lbl = decompose_tab (nb#get_tab_label(nb#get_nth_page i))#as_widget 
 
80
  in
 
81
    lbl
 
82
      
 
83
let get_current_tab_label () = get_tab_label (notebook())#current_page
 
84
  
 
85
let get_current_page () = 
 
86
  let i = (notebook())#current_page in
 
87
    (notebook())#get_nth_page i
 
88
      
 
89
(* This function must remove "focused proof" decoration *)                                    
 
90
let reset_tab_label i = 
 
91
  set_tab_label i (get_tab_label i)
 
92
    
 
93
let to_do_on_page_switch = ref []
 
94
  
 
95
module Vector = struct 
 
96
  exception Found of int
 
97
  type 'a t = ('a option) array ref
 
98
  let create () = ref [||]
 
99
  let length t = Array.length !t
 
100
  let get t i = Option.get (Array.get !t i)
 
101
  let set t i v = Array.set !t i (Some v)
 
102
  let remove t i = Array.set !t i None
 
103
  let append t e = t := Array.append !t [|Some e|]; (Array.length !t)-1
 
104
  let iter f t =  Array.iter (function | None -> () | Some x -> f x) !t
 
105
  let find_or_fail f t = 
 
106
    let test i = function | None -> () | Some e -> if f e then raise (Found i) in 
 
107
      Array.iteri test t
 
108
        
 
109
  let exists f t =
 
110
    let l = Array.length !t in
 
111
    let rec test i = 
 
112
      (i < l) && (((!t.(i) <> None) && f (Option.get !t.(i))) || test (i+1)) 
 
113
    in 
 
114
      test 0
 
115
end
 
116
 
 
117
type 'a viewable_script =
 
118
    {view : Undo.undoable_view;
 
119
     mutable analyzed_view : 'a option;
 
120
    }
 
121
 
 
122
 
 
123
class type analyzed_views= 
 
124
object('self)
 
125
  val mutable act_id : GtkSignal.id option
 
126
  val current_all : 'self viewable_script
 
127
  val mutable deact_id : GtkSignal.id option
 
128
  val input_buffer : GText.buffer
 
129
  val input_view : Undo.undoable_view
 
130
  val last_array : string array
 
131
  val mutable last_index : bool
 
132
  val message_buffer : GText.buffer
 
133
  val message_view : GText.view
 
134
  val proof_buffer : GText.buffer
 
135
  val proof_view : GText.view
 
136
  val mutable is_active : bool
 
137
  val mutable read_only : bool
 
138
  val mutable filename : string option
 
139
  val mutable stats : Unix.stats option
 
140
  val mutable detached_views : GWindow.window list
 
141
  method without_auto_complete : 'a 'b. ('a -> 'b) -> 'a -> 'b
 
142
  method set_auto_complete : bool -> unit
 
143
 
 
144
  method kill_detached_views : unit -> unit
 
145
  method add_detached_view : GWindow.window -> unit
 
146
  method remove_detached_view : GWindow.window -> unit
 
147
 
 
148
  method view : Undo.undoable_view
 
149
  method filename : string option
 
150
  method stats :  Unix.stats option
 
151
  method set_filename : string option -> unit
 
152
  method update_stats : unit
 
153
  method revert : unit
 
154
  method auto_save : unit
 
155
  method save : string -> bool
 
156
  method save_as : string -> bool
 
157
  method read_only : bool
 
158
  method set_read_only : bool -> unit
 
159
  method is_active : bool
 
160
  method activate : unit -> unit
 
161
  method active_keypress_handler : GdkEvent.Key.t -> bool
 
162
  method backtrack_to : GText.iter -> unit
 
163
  method backtrack_to_no_lock : GText.iter -> unit
 
164
  method clear_message : unit
 
165
  method deactivate : unit -> unit
 
166
  method disconnected_keypress_handler : GdkEvent.Key.t -> bool
 
167
  method electric_handler : GtkSignal.id
 
168
  method find_phrase_starting_at :
 
169
    GText.iter -> (GText.iter * GText.iter) option
 
170
  method get_insert : GText.iter
 
171
  method get_start_of_input : GText.iter
 
172
  method go_to_insert : unit
 
173
  method indent_current_line : unit
 
174
  method insert_command : string -> string -> unit
 
175
  method tactic_wizard : string list -> unit
 
176
  method insert_message : string -> unit
 
177
  method insert_this_phrase_on_success :
 
178
    bool -> bool -> bool -> string -> string -> bool
 
179
  method process_next_phrase : bool -> bool -> bool -> bool
 
180
  method process_until_iter_or_error : GText.iter -> unit
 
181
  method process_until_end_or_error : unit
 
182
  method recenter_insert : unit
 
183
  method reset_initial : unit
 
184
  method send_to_coq :
 
185
    bool -> bool -> string ->
 
186
    bool -> bool -> bool ->
 
187
    (bool*(reset_info*(Util.loc * Vernacexpr.vernac_expr))) option
 
188
  method set_message : string -> unit
 
189
  method show_pm_goal : unit
 
190
  method show_goals : unit
 
191
  method show_goals_full : unit
 
192
  method undo_last_step : unit
 
193
  method help_for_keyword : unit -> unit
 
194
  method complete_at_offset : int -> bool
 
195
 
 
196
  method blaster : unit -> unit
 
197
end
 
198
 
 
199
let (input_views:analyzed_views viewable_script Vector.t) = Vector.create ()
 
200
 
 
201
 
 
202
let signals_to_crash = [Sys.sigabrt; Sys.sigalrm; Sys.sigfpe; Sys.sighup; 
 
203
                        Sys.sigill; Sys.sigpipe; Sys.sigquit; 
 
204
                        (* Sys.sigsegv; Sys.sigterm;*) Sys.sigusr2]
 
205
 
 
206
let crash_save i =
 
207
  (*  ignore (Unix.sigprocmask Unix.SIG_BLOCK signals_to_crash);*)
 
208
  Pervasives.prerr_endline "Trying to save all buffers in .crashcoqide files";
 
209
  let count = ref 0 in 
 
210
    Vector.iter 
 
211
      (function {view=view; analyzed_view = Some av } -> 
 
212
         (let filename = match av#filename with 
 
213
            | None -> 
 
214
                incr count; 
 
215
                "Unnamed_coqscript_"^(string_of_int !count)^".crashcoqide"
 
216
            | Some f -> f^".crashcoqide"
 
217
          in
 
218
            try 
 
219
              if try_export filename (view#buffer#get_text ()) then
 
220
                Pervasives.prerr_endline ("Saved "^filename)
 
221
              else Pervasives.prerr_endline ("Could not save "^filename)
 
222
            with _ -> Pervasives.prerr_endline ("Could not save "^filename))
 
223
         | _ -> Pervasives.prerr_endline "Unanalyzed view found. Please report."
 
224
      )
 
225
      input_views;
 
226
    Pervasives.prerr_endline "Done. Please report.";
 
227
    if i <> 127 then exit i
 
228
 
 
229
let ignore_break () =
 
230
  List.iter
 
231
    (fun i ->
 
232
       try Sys.set_signal i (Sys.Signal_handle crash_save)
 
233
       with _ -> prerr_endline "Signal ignored (normal if Win32)")
 
234
    signals_to_crash;
 
235
  Sys.set_signal Sys.sigint Sys.Signal_ignore
 
236
 
 
237
(* Locking machinery for Coq kernel *)
 
238
let coq_computing = Mutex.create ()
 
239
 
 
240
(* To prevent Coq from interrupting during undoing...*)
 
241
let coq_may_stop = Mutex.create ()
 
242
 
 
243
let break () = 
 
244
  prerr_endline "User break received:";
 
245
  if not (Mutex.try_lock coq_computing) then 
 
246
    begin
 
247
      prerr_endline " trying to stop computation:";
 
248
      if Mutex.try_lock coq_may_stop then begin
 
249
          Util.interrupt := true;
 
250
          prerr_endline " interrupt flag set. Computation should stop soon...";
 
251
          Mutex.unlock coq_may_stop
 
252
        end else prerr_endline " interruption refused (may not stop now)";
 
253
    end
 
254
  else begin
 
255
      Mutex.unlock coq_computing;
 
256
      prerr_endline " ignored (not computing)"
 
257
    end
 
258
 
 
259
let do_if_not_computing text f x = 
 
260
  let threaded_task () =
 
261
    if Mutex.try_lock coq_computing 
 
262
    then 
 
263
      begin
 
264
        let w = Blaster_window.blaster_window () in
 
265
          if not (Mutex.try_lock w#lock) then 
 
266
            begin 
 
267
              break ();
 
268
              let lck = Mutex.create () in
 
269
                Mutex.lock lck;
 
270
                prerr_endline "Waiting on blaster...";
 
271
                Condition.wait w#blaster_killed lck;
 
272
                prerr_endline "Waiting on blaster ok";
 
273
                Mutex.unlock lck
 
274
            end 
 
275
          else 
 
276
            Mutex.unlock w#lock;
 
277
          let idle = 
 
278
            Glib.Timeout.add ~ms:300
 
279
              ~callback:(fun () -> async !pulse ();true) in
 
280
            begin
 
281
              prerr_endline "Getting lock";
 
282
              try
 
283
                f x;
 
284
                Glib.Timeout.remove idle;
 
285
                prerr_endline "Releasing lock";
 
286
                Mutex.unlock coq_computing;
 
287
              with e ->
 
288
                Glib.Timeout.remove idle;
 
289
                prerr_endline "Releasing lock (on error)";
 
290
                Mutex.unlock coq_computing;
 
291
                raise e
 
292
            end
 
293
      end 
 
294
    else 
 
295
      prerr_endline 
 
296
        "Discarded order (computations are ongoing)" 
 
297
  in
 
298
    prerr_endline ("Launching thread " ^ text);
 
299
    ignore (Thread.create threaded_task ())
 
300
 
 
301
let add_input_view tv = 
 
302
  Vector.append input_views tv
 
303
 
 
304
let get_input_view i = 
 
305
  if 0 <= i && i < Vector.length input_views
 
306
  then
 
307
    Vector.get input_views i
 
308
  else raise Not_found 
 
309
 
 
310
let active_view = ref None
 
311
 
 
312
let get_active_view () = Vector.get input_views (Option.get !active_view)
 
313
 
 
314
let set_active_view i = 
 
315
  (match !active_view with  None -> () | Some i -> 
 
316
     reset_tab_label i);
 
317
  (notebook ())#goto_page i; 
 
318
  let txt = get_current_tab_label () in
 
319
    set_current_tab_label ("<span background=\"light green\">"^txt^"</span>");
 
320
    active_view := Some i
 
321
 
 
322
let set_current_view i = (notebook ())#goto_page i
 
323
 
 
324
let kill_input_view i = 
 
325
  let v = Vector.get input_views i in
 
326
    (match v.analyzed_view with 
 
327
       | Some v -> v#kill_detached_views ()
 
328
       | None -> ());
 
329
    v.view#destroy ();
 
330
    v.analyzed_view <- None;
 
331
    Vector.remove input_views i
 
332
 
 
333
let get_current_view_page () = (notebook ())#current_page
 
334
let get_current_view () = Vector.get input_views (notebook ())#current_page
 
335
let remove_current_view_page () = 
 
336
  let c =  (notebook ())#current_page in
 
337
    kill_input_view c;
 
338
    ((notebook ())#get_nth_page c)#misc#hide ()
 
339
 
 
340
let is_word_char c =
 
341
  (* TODO: avoid num and prime at the head of a word *)
 
342
  Glib.Unichar.isalnum c || c = underscore || c = prime
 
343
 
 
344
let starts_word it = 
 
345
  prerr_endline ("Starts word ? '"^(Glib.Utf8.from_unichar it#char)^"'");
 
346
  (not it#copy#nocopy#backward_char ||
 
347
     (let c = it#backward_char#char in
 
348
        not (is_word_char c)))
 
349
 
 
350
let ends_word it = 
 
351
  (not it#copy#nocopy#forward_char ||
 
352
     let c = it#forward_char#char in
 
353
       not (is_word_char c)
 
354
  )
 
355
 
 
356
let inside_word it = 
 
357
  let c = it#char in
 
358
    not (starts_word it) &&
 
359
      not (ends_word it) &&
 
360
      is_word_char c
 
361
 
 
362
let is_on_word_limit it = inside_word it || ends_word it 
 
363
 
 
364
let rec find_word_start it =
 
365
  prerr_endline "Find word start";
 
366
  if not it#nocopy#backward_char then 
 
367
    (prerr_endline "find_word_start: cannot backward"; it)
 
368
  else if is_word_char it#char
 
369
  then find_word_start it
 
370
  else (it#nocopy#forward_char; 
 
371
        prerr_endline ("Word start at: "^(string_of_int it#offset));it)
 
372
let find_word_start (it:GText.iter) = find_word_start it#copy
 
373
 
 
374
let rec find_word_end it =
 
375
  prerr_endline "Find word end";
 
376
  if let c = it#char in c<>0 && is_word_char c
 
377
  then begin 
 
378
      ignore (it#nocopy#forward_char);
 
379
      find_word_end it
 
380
    end else (prerr_endline ("Word end at: "^(string_of_int it#offset));it)
 
381
let find_word_end it = find_word_end it#copy
 
382
 
 
383
 
 
384
let get_word_around it = 
 
385
  let start = find_word_start it in
 
386
  let stop =  find_word_end it in
 
387
    start,stop
 
388
 
 
389
 
 
390
let rec complete_backward w (it:GText.iter) = 
 
391
  prerr_endline "Complete backward...";
 
392
  match it#backward_search w with 
 
393
    | None -> (prerr_endline "backward_search failed";None)
 
394
    | Some (start,stop) -> 
 
395
        prerr_endline ("complete_backward got a match:"^(string_of_int start#offset)^(string_of_int stop#offset));
 
396
        if starts_word start then 
 
397
          let ne = find_word_end stop in
 
398
            if ne#compare stop = 0
 
399
            then complete_backward w start
 
400
            else Some (start,stop,ne)
 
401
        else complete_backward w start
 
402
          
 
403
let rec complete_forward w (it:GText.iter) = 
 
404
  prerr_endline "Complete forward...";
 
405
  match it#forward_search w with 
 
406
    | None -> None
 
407
    | Some (start,stop) -> 
 
408
        if starts_word start then       
 
409
          let ne = find_word_end stop in
 
410
            if ne#compare stop = 0 then 
 
411
              complete_forward w stop
 
412
            else Some (stop,stop,ne)
 
413
        else complete_forward w stop
 
414
 
 
415
(* Reset this to None on page change ! *)
 
416
let (last_completion:(string*int*int*bool) option ref) = ref None
 
417
 
 
418
let () = to_do_on_page_switch := 
 
419
  (fun i -> last_completion := None)::!to_do_on_page_switch
 
420
 
 
421
let rec complete input_buffer w (offset:int) =
 
422
  match !last_completion with 
 
423
    | Some (lw,loffset,lpos,backward)
 
424
        when lw=w && loffset=offset ->
 
425
        begin
 
426
          let iter = input_buffer#get_iter (`OFFSET lpos) in
 
427
            if backward then 
 
428
              match complete_backward w iter with
 
429
                | None -> 
 
430
                    last_completion := 
 
431
                      Some (lw,loffset,
 
432
                            (find_word_end 
 
433
                               (input_buffer#get_iter (`OFFSET loffset)))#offset ,
 
434
                            false); 
 
435
                    None
 
436
                | Some (ss,start,stop) as result -> 
 
437
                    last_completion := 
 
438
                      Some (w,offset,ss#offset,true);
 
439
                    result
 
440
            else
 
441
              match complete_forward w iter with
 
442
                | None -> 
 
443
                    last_completion := None;
 
444
                    None
 
445
                | Some (ss,start,stop) as result -> 
 
446
                    last_completion := 
 
447
                      Some (w,offset,ss#offset,false);
 
448
                    result
 
449
        end
 
450
    | _ -> begin
 
451
          match complete_backward w (input_buffer#get_iter (`OFFSET offset)) with
 
452
            | None -> 
 
453
                last_completion := 
 
454
                  Some (w,offset,(find_word_end (input_buffer#get_iter
 
455
                                                   (`OFFSET offset)))#offset,false);
 
456
                complete input_buffer w offset
 
457
            | Some (ss,start,stop) as result -> 
 
458
                last_completion := Some (w,offset,ss#offset,true);
 
459
                result
 
460
      end
 
461
        
 
462
let get_current_word () =
 
463
  let av = Option.get ((get_current_view ()).analyzed_view) in 
 
464
    match (cb ())#text with
 
465
      | None -> 
 
466
          prerr_endline "None selected";
 
467
          let it = av#get_insert in
 
468
          let start = find_word_start it in
 
469
          let stop = find_word_end start in
 
470
            av#view#buffer#move_mark `SEL_BOUND start;
 
471
            av#view#buffer#move_mark `INSERT stop;
 
472
            av#view#buffer#get_text ~slice:true ~start ~stop ()
 
473
      | Some t ->
 
474
          prerr_endline "Some selected";
 
475
          prerr_endline t;
 
476
          t
 
477
            
 
478
 
 
479
let input_channel b ic =
 
480
  let buf = String.create 1024 and len = ref 0 in
 
481
    while len := input ic buf 0 1024; !len > 0 do
 
482
      Buffer.add_substring b buf 0 !len
 
483
    done
 
484
 
 
485
let with_file handler name ~f =
 
486
  try
 
487
    let ic = open_in_gen [Open_rdonly;Open_creat] 0o644 name in
 
488
    try f ic; close_in ic with e -> close_in ic; raise e
 
489
  with Sys_error s -> handler s
 
490
 
 
491
type info =  {start:GText.mark;
 
492
              stop:GText.mark;
 
493
              ast:Util.loc * Vernacexpr.vernac_expr;
 
494
              reset_info:Coq.reset_info
 
495
             }
 
496
 
 
497
exception Size of int
 
498
let (processed_stack:info Stack.t) = Stack.create ()
 
499
let push x = Stack.push x processed_stack
 
500
let pop () = try Stack.pop processed_stack with Stack.Empty -> raise (Size 0)
 
501
let top () = try Stack.top processed_stack with Stack.Empty -> raise (Size 0)
 
502
let is_empty () = Stack.is_empty processed_stack
 
503
 
 
504
(* push a new Coq phrase *)
 
505
 
 
506
let update_on_end_of_segment id =
 
507
  let lookup_section = function 
 
508
    | { reset_info = ResetAtSegmentStart id',_,_ } when id = id' -> raise Exit
 
509
    | { reset_info = _,_,r } -> r := false
 
510
  in
 
511
    try Stack.iter lookup_section processed_stack with Exit -> ()
 
512
 
 
513
let push_phrase reset_info start_of_phrase_mark end_of_phrase_mark ast = 
 
514
  let x = {start = start_of_phrase_mark;
 
515
           stop = end_of_phrase_mark;
 
516
           ast = ast;
 
517
           reset_info = reset_info
 
518
          } in
 
519
  begin
 
520
    match snd ast with
 
521
    | VernacEndSegment (_,id) -> 
 
522
        prerr_endline "Updating on end of segment 1";
 
523
        update_on_end_of_segment id
 
524
    | _ -> ()
 
525
  end;
 
526
  push x
 
527
 
 
528
 
 
529
let repush_phrase reset_info x =
 
530
  let x = { x with reset_info = reset_info } in
 
531
  begin
 
532
    match snd x.ast with
 
533
      | VernacEndSegment (_,id) ->
 
534
          prerr_endline "Updating on end of segment 2";
 
535
          update_on_end_of_segment id
 
536
      | _ -> ()
 
537
  end;
 
538
  push x
 
539
 
 
540
type backtrack =
 
541
| BacktrackToNextActiveMark
 
542
| BacktrackToMark of reset_mark
 
543
| BacktrackToModSec of Names.identifier
 
544
| NoBacktrack
 
545
 
 
546
let add_undo = function (n,a,b,p,l as x) -> if p = 0 then (n+1,a,b,p,l) else x
 
547
let add_abort = function
 
548
  | (n,a,b,0,l) -> (0,a+1,b,0,l)
 
549
  | (n,a,b,p,l) -> (n,a,b,p-1,l)
 
550
let add_qed q (n,a,b,p,l as x) =
 
551
  if q = 0 then x else (n,a,BacktrackToNextActiveMark,p+q,l)
 
552
let add_backtrack (n,a,b,p,l) b' = (n,a,b',p,l)
 
553
 
 
554
let update_proofs (n,a,b,p,cur_lems) prev_lems =
 
555
  let ncommon = List.length (Util.list_intersect cur_lems prev_lems) in
 
556
  let openproofs = List.length cur_lems - ncommon in
 
557
  let closedproofs = List.length prev_lems - ncommon in
 
558
  let undos = (n,a,b,p,prev_lems) in
 
559
  add_qed closedproofs (Util.iterate add_abort openproofs undos)
 
560
 
 
561
let pop_command undos t =
 
562
  let (state_info,undo_info,section_info) = t.reset_info in
 
563
  let undos =
 
564
    if !section_info then
 
565
      let undos = update_proofs undos undo_info in
 
566
      match state_info with
 
567
      | _ when is_vernac_tactic_command (snd t.ast) ->
 
568
          (* A tactic, active if not below a Qed *)
 
569
          add_undo undos
 
570
      | ResetAtRegisteredObject mark ->
 
571
          add_backtrack undos (BacktrackToMark mark)
 
572
      | ResetAtSegmentStart id ->
 
573
          add_backtrack undos (BacktrackToModSec id)
 
574
      | _ when is_vernac_state_preserving_command (snd t.ast) ->
 
575
          undos
 
576
      | _ ->
 
577
          add_backtrack undos BacktrackToNextActiveMark
 
578
    else
 
579
      begin 
 
580
        prerr_endline "In section";
 
581
      (* An object inside a closed section *)
 
582
      add_backtrack undos BacktrackToNextActiveMark
 
583
      end in
 
584
  ignore (pop ());
 
585
  undos
 
586
 
 
587
let apply_aborts a =
 
588
  if a <> 0 then prerr_endline ("Applying "^string_of_int a^" aborts");
 
589
  try Util.repeat a Pfedit.delete_current_proof ()
 
590
  with e -> prerr_endline "WARNING : found a closed environment"; raise e
 
591
 
 
592
exception UndoStackExhausted
 
593
 
 
594
let apply_tactic_undo n =
 
595
  if n<>0 then
 
596
    (prerr_endline ("Applying "^string_of_int n^" undos");
 
597
     try Pfedit.undo n with _ -> raise UndoStackExhausted)
 
598
 
 
599
let apply_reset = function
 
600
  | BacktrackToMark mark -> reset_to mark
 
601
  | BacktrackToModSec id -> reset_to_mod id
 
602
  | NoBacktrack -> ()
 
603
  | BacktrackToNextActiveMark -> assert false
 
604
 
 
605
let rec apply_undos (n,a,b,p,l as undos) =
 
606
  if p = 0 & b <> BacktrackToNextActiveMark then
 
607
    begin
 
608
      apply_aborts a;
 
609
      try
 
610
        apply_tactic_undo n;
 
611
        apply_reset b
 
612
      with UndoStackExhausted ->
 
613
        apply_undos (n,0,BacktrackToNextActiveMark,p,l)
 
614
    end
 
615
  else
 
616
    (* re-synchronize Coq to the current state of the stack *)
 
617
    if is_empty () then
 
618
      Coq.reset_initial ()
 
619
    else
 
620
      begin
 
621
        let t = top () in
 
622
        apply_undos (pop_command undos t);
 
623
        let reset_info = Coq.compute_reset_info (snd t.ast) in
 
624
        interp_last t.ast;
 
625
        repush_phrase reset_info t
 
626
      end
 
627
 
 
628
(* For electric handlers *)
 
629
exception Found
 
630
 
 
631
(* For find_phrase_starting_at *)
 
632
exception Stop of int
 
633
 
 
634
let activate_input i = 
 
635
  (match !active_view with
 
636
     | None -> () 
 
637
     | Some n ->
 
638
         let a_v = Option.get (Vector.get input_views n).analyzed_view in
 
639
           a_v#deactivate ();
 
640
           a_v#reset_initial
 
641
  );
 
642
  let activate_function = (Option.get (Vector.get input_views i).analyzed_view)#activate in
 
643
    activate_function ();
 
644
    set_active_view i
 
645
 
 
646
let warning msg = 
 
647
  GToolbox.message_box ~title:"Warning"
 
648
    ~icon:(let img = GMisc.image () in
 
649
             img#set_stock `DIALOG_WARNING;
 
650
             img#set_icon_size `DIALOG;
 
651
             img#coerce)
 
652
    msg
 
653
 
 
654
 
 
655
class analyzed_view index =
 
656
  let {view = input_view_} as current_all_ =  get_input_view index in
 
657
  let proof_view_ = Option.get !proof_view in
 
658
  let message_view_ = Option.get !message_view in
 
659
object(self)
 
660
  val current_all =  current_all_
 
661
  val input_view = current_all_.view
 
662
  val proof_view = Option.get !proof_view
 
663
  val message_view = Option.get !message_view
 
664
  val input_buffer = input_view_#buffer
 
665
  val proof_buffer = proof_view_#buffer
 
666
  val message_buffer = message_view_#buffer 
 
667
  val mutable is_active = false
 
668
  val mutable read_only = false
 
669
  val mutable filename = None 
 
670
  val mutable stats = None
 
671
  val mutable last_modification_time = 0.
 
672
  val mutable last_auto_save_time = 0.
 
673
  val mutable detached_views = []
 
674
 
 
675
  val mutable auto_complete_on = !current.auto_complete
 
676
 
 
677
  method private toggle_auto_complete = 
 
678
    auto_complete_on <- not auto_complete_on
 
679
  method set_auto_complete t = auto_complete_on <- t
 
680
  method without_auto_complete : 'a 'b. ('a -> 'b) -> 'a -> 'b = fun f x ->
 
681
    let old = auto_complete_on in
 
682
      self#set_auto_complete false;
 
683
      let y = f x in
 
684
        self#set_auto_complete old;
 
685
        y
 
686
  method add_detached_view (w:GWindow.window) = 
 
687
    detached_views <- w::detached_views
 
688
  method remove_detached_view (w:GWindow.window) = 
 
689
    detached_views <- List.filter (fun e -> w#misc#get_oid<>e#misc#get_oid) detached_views
 
690
 
 
691
  method kill_detached_views () = 
 
692
    List.iter (fun w -> w#destroy ()) detached_views;
 
693
    detached_views <- []
 
694
 
 
695
  method view = input_view
 
696
  method filename = filename
 
697
  method stats = stats
 
698
  method set_filename f = 
 
699
    filename <- f;
 
700
    match f with 
 
701
      | Some f -> stats <- my_stat f
 
702
      | None -> ()
 
703
 
 
704
  method update_stats = 
 
705
    match filename with 
 
706
      | Some f -> stats <- my_stat f 
 
707
      | _ -> ()
 
708
 
 
709
  method revert = 
 
710
    match filename with 
 
711
      | Some f -> begin
 
712
            let do_revert () = begin
 
713
                !push_info "Reverting buffer";
 
714
                try
 
715
                  if is_active then self#reset_initial;
 
716
                  let b = Buffer.create 1024 in
 
717
                    with_file !flash_info f ~f:(input_channel b);
 
718
                    let s = try_convert (Buffer.contents b) in
 
719
                      input_buffer#set_text s;
 
720
                      self#update_stats;
 
721
                      input_buffer#place_cursor input_buffer#start_iter;
 
722
                      input_buffer#set_modified false;
 
723
                      !pop_info ();
 
724
                      !flash_info "Buffer reverted";
 
725
                      Highlight.highlight_all input_buffer;
 
726
                with _  -> 
 
727
                  !pop_info ();
 
728
                  !flash_info "Warning: could not revert buffer";
 
729
              end
 
730
            in
 
731
              if input_buffer#modified then 
 
732
                match (GToolbox.question_box 
 
733
                         ~title:"Modified buffer changed on disk"
 
734
                         ~buttons:["Revert from File";
 
735
                                   "Overwrite File";
 
736
                                   "Disable Auto Revert"] 
 
737
                         ~default:0
 
738
                         ~icon:(stock_to_widget `DIALOG_WARNING)
 
739
                         "Some unsaved buffers changed on disk"
 
740
                      )
 
741
                with 1 -> do_revert ()
 
742
                  | 2 -> if self#save f then !flash_info "Overwritten" else
 
743
                        !flash_info "Could not overwrite file"
 
744
                  | _ -> 
 
745
                      prerr_endline "Auto revert set to false";
 
746
                      !current.global_auto_revert <- false;
 
747
                      disconnect_revert_timer ()
 
748
              else do_revert () 
 
749
        end
 
750
      | None -> ()
 
751
          
 
752
  method save f = 
 
753
    if try_export f (input_buffer#get_text ()) then begin
 
754
        filename <- Some f;
 
755
        input_buffer#set_modified false;
 
756
        stats <- my_stat f;
 
757
        (match self#auto_save_name with 
 
758
           | None -> ()
 
759
           | Some fn -> try Sys.remove fn with _ -> ());
 
760
        true
 
761
      end
 
762
    else false
 
763
 
 
764
  method private auto_save_name = 
 
765
    match filename with 
 
766
      | None -> None
 
767
      | Some f -> 
 
768
          let dir = Filename.dirname f in
 
769
          let base = (fst !current.auto_save_name) ^ 
 
770
            (Filename.basename f) ^ 
 
771
            (snd !current.auto_save_name) 
 
772
          in Some (Filename.concat dir base)
 
773
            
 
774
  method private need_auto_save = 
 
775
    input_buffer#modified &&
 
776
      last_modification_time > last_auto_save_time
 
777
      
 
778
  method auto_save =
 
779
    if self#need_auto_save then begin
 
780
        match self#auto_save_name with 
 
781
          | None -> () 
 
782
          | Some fn -> 
 
783
              try 
 
784
                last_auto_save_time <- Unix.time();
 
785
                prerr_endline ("Autosave time : "^(string_of_float (Unix.time())));
 
786
                if try_export fn (input_buffer#get_text ()) then begin
 
787
                    !flash_info ~delay:1000 "Autosaved"
 
788
                  end
 
789
                else warning 
 
790
                  ("Autosave failed (check if " ^ fn ^ " is writable)")
 
791
              with _ -> 
 
792
                warning ("Autosave: unexpected error while writing "^fn)
 
793
      end             
 
794
      
 
795
  method save_as f =
 
796
    if Sys.file_exists f then 
 
797
      match (GToolbox.question_box ~title:"File exists on disk"
 
798
               ~buttons:["Overwrite";
 
799
                         "Cancel";] 
 
800
               ~default:1
 
801
               ~icon:
 
802
               (let img = GMisc.image () in
 
803
                  img#set_stock `DIALOG_WARNING;
 
804
                  img#set_icon_size `DIALOG;
 
805
                  img#coerce)
 
806
               ("File "^f^"already exists")
 
807
            )
 
808
      with 1 -> self#save f
 
809
        | _ -> false
 
810
    else self#save f
 
811
 
 
812
  method set_read_only b = read_only<-b
 
813
  method read_only = read_only
 
814
  method is_active = is_active
 
815
  method insert_message s =
 
816
    message_buffer#insert s;
 
817
    message_view#misc#draw None
 
818
 
 
819
  method set_message s =
 
820
    message_buffer#set_text s;
 
821
    message_view#misc#draw None
 
822
 
 
823
  method clear_message = message_buffer#set_text ""
 
824
  val mutable last_index = true
 
825
  val last_array = [|"";""|]
 
826
  method get_start_of_input =  input_buffer#get_iter_at_mark (`NAME "start_of_input") 
 
827
 
 
828
  method get_insert = get_insert input_buffer
 
829
 
 
830
  method recenter_insert = 
 
831
    (* BUG : to investigate further: 
 
832
       FIXED : Never call  GMain.* in thread !
 
833
       PLUS : GTK BUG ??? Cannot be called from a thread...
 
834
       ADDITION: using sync instead of async causes deadlock...*)
 
835
    ignore (GtkThread.async (
 
836
                              input_view#scroll_to_mark 
 
837
                                ~use_align:false
 
838
                                ~yalign:0.75
 
839
                                ~within_margin:0.25)
 
840
              `INSERT)
 
841
 
 
842
 
 
843
  method indent_current_line = 
 
844
    let get_nb_space it =
 
845
      let it = it#copy in
 
846
      let nb_sep = ref 0 in
 
847
      let continue = ref true in
 
848
        while !continue do 
 
849
          if it#char = space then begin 
 
850
              incr nb_sep;
 
851
              if not it#nocopy#forward_char then continue := false;
 
852
            end else continue := false
 
853
        done;
 
854
        !nb_sep
 
855
    in
 
856
    let previous_line = self#get_insert in
 
857
      if previous_line#nocopy#backward_line then begin
 
858
          let previous_line_spaces = get_nb_space previous_line in
 
859
          let current_line_start = self#get_insert#set_line_offset 0 in
 
860
          let current_line_spaces = get_nb_space current_line_start in
 
861
            if input_buffer#delete_interactive 
 
862
              ~start:current_line_start 
 
863
              ~stop:(current_line_start#forward_chars current_line_spaces)
 
864
              ()
 
865
            then 
 
866
              let current_line_start = self#get_insert#set_line_offset 0 in
 
867
                input_buffer#insert 
 
868
                  ~iter:current_line_start
 
869
                  (String.make previous_line_spaces ' ')
 
870
        end
 
871
 
 
872
  method show_pm_goal = 
 
873
      proof_buffer#insert 
 
874
        (Printf.sprintf "    *** Declarative Mode ***\n");
 
875
      try 
 
876
        let (hyps,concl) = get_current_pm_goal () in
 
877
        List.iter
 
878
          (fun ((_,_,_,(s,_)) as _hyp) -> 
 
879
             proof_buffer#insert (s^"\n"))
 
880
          hyps;
 
881
        proof_buffer#insert 
 
882
          (String.make 38 '_' ^ "\n");
 
883
        let (_,_,_,s) = concl in 
 
884
          proof_buffer#insert ("thesis := \n "^s^"\n");
 
885
        let my_mark = `NAME "end_of_conclusion" in
 
886
          proof_buffer#move_mark
 
887
            ~where:((proof_buffer#get_iter_at_mark `INSERT)) 
 
888
            my_mark;
 
889
          ignore (proof_view#scroll_to_mark my_mark) 
 
890
    with Not_found ->  
 
891
      match Decl_mode.get_end_command (Pfedit.get_pftreestate ()) with
 
892
          Some endc ->
 
893
            proof_buffer#insert 
 
894
              ("Subproof completed, now type "^endc^".") 
 
895
        | None ->
 
896
            proof_buffer#insert "Proof completed."
 
897
 
 
898
  method show_goals = 
 
899
    try
 
900
      proof_view#buffer#set_text "";
 
901
      match Decl_mode.get_current_mode () with
 
902
          Decl_mode.Mode_none ->  proof_buffer#insert (Coq.print_no_goal ())
 
903
        | Decl_mode.Mode_tactic ->   
 
904
            begin
 
905
              let s = Coq.get_current_goals () in
 
906
                match s with 
 
907
                  | [] -> proof_buffer#insert (Coq.print_no_goal ())
 
908
                  | (hyps,concl)::r -> 
 
909
                      let goal_nb = List.length s in
 
910
                        proof_buffer#insert 
 
911
                          (Printf.sprintf "%d subgoal%s\n" 
 
912
                             goal_nb
 
913
                             (if goal_nb<=1 then "" else "s"));
 
914
                        List.iter
 
915
                          (fun ((_,_,_,(s,_)) as _hyp) -> 
 
916
                             proof_buffer#insert (s^"\n"))
 
917
                          hyps;
 
918
                        proof_buffer#insert 
 
919
                          (String.make 38 '_' ^ "(1/"^
 
920
                             (string_of_int goal_nb)^
 
921
                             ")\n") ;
 
922
                        let _,_,_,sconcl = concl in
 
923
                          proof_buffer#insert sconcl;
 
924
                          proof_buffer#insert "\n";
 
925
                          let my_mark = `NAME "end_of_conclusion" in
 
926
                            proof_buffer#move_mark
 
927
                              ~where:((proof_buffer#get_iter_at_mark `INSERT)) 
 
928
                              my_mark;
 
929
                            proof_buffer#insert "\n\n";
 
930
                            let i = ref 1 in
 
931
                              List.iter 
 
932
                                (function (_,(_,_,_,concl)) -> 
 
933
                                   incr i;
 
934
                                   proof_buffer#insert 
 
935
                                     (String.make 38 '_' ^"("^
 
936
                                        (string_of_int !i)^
 
937
                                        "/"^
 
938
                                        (string_of_int goal_nb)^
 
939
                                        ")\n");
 
940
                                   proof_buffer#insert concl;
 
941
                                   proof_buffer#insert "\n\n";
 
942
                                )
 
943
                                r;
 
944
                              ignore (proof_view#scroll_to_mark my_mark) 
 
945
            end
 
946
        | Decl_mode.Mode_proof -> 
 
947
            self#show_pm_goal
 
948
    with e -> 
 
949
      prerr_endline ("Don't worry be happy despite: "^Printexc.to_string e)
 
950
        
 
951
              
 
952
  val mutable full_goal_done = true
 
953
 
 
954
  method show_goals_full = 
 
955
    if not full_goal_done then
 
956
      begin
 
957
        try
 
958
          proof_view#buffer#set_text "";
 
959
          match Decl_mode.get_current_mode () with
 
960
              Decl_mode.Mode_none ->  
 
961
                proof_buffer#insert (Coq.print_no_goal ())
 
962
            | Decl_mode.Mode_tactic ->   
 
963
                begin
 
964
                  match Coq.get_current_goals () with 
 
965
                      [] -> Util.anomaly "show_goals_full"
 
966
                  | ((hyps,concl)::r) as s ->
 
967
                      let last_shown_area = 
 
968
                        proof_buffer#create_tag [`BACKGROUND "light green"]
 
969
                      in
 
970
                      let goal_nb = List.length s in
 
971
                        proof_buffer#insert (Printf.sprintf "%d subgoal%s\n" 
 
972
                                         goal_nb
 
973
                                         (if goal_nb<=1 then "" else "s"));
 
974
                  let coq_menu commands = 
 
975
                    let tag = proof_buffer#create_tag []
 
976
                    in 
 
977
                      ignore
 
978
                        (tag#connect#event ~callback:
 
979
                           (fun ~origin ev it ->
 
980
                              begin match GdkEvent.get_type ev with 
 
981
                                | `BUTTON_PRESS -> 
 
982
                                    let ev = (GdkEvent.Button.cast ev) in
 
983
                                      if (GdkEvent.Button.button ev) = 3
 
984
                                      then begin 
 
985
                                        let loc_menu = GMenu.menu () in
 
986
                                        let factory = 
 
987
                                          new GMenu.factory loc_menu in
 
988
                                        let add_coq_command (cp,ip) = 
 
989
                                          ignore 
 
990
                                            (factory#add_item cp 
 
991
                                               ~callback:
 
992
                                     (fun () -> ignore
 
993
                                        (self#insert_this_phrase_on_success 
 
994
                                           true
 
995
                                           true 
 
996
                                           false 
 
997
                                           ("progress "^ip^"\n") 
 
998
                                           (ip^"\n"))
 
999
                                     )
 
1000
                                  )
 
1001
                              in
 
1002
                              List.iter add_coq_command commands;
 
1003
                              loc_menu#popup 
 
1004
                                ~button:3
 
1005
                                ~time:(GdkEvent.Button.time ev);
 
1006
                            end
 
1007
                        | `MOTION_NOTIFY -> 
 
1008
                            proof_buffer#remove_tag
 
1009
                            ~start:proof_buffer#start_iter
 
1010
                            ~stop:proof_buffer#end_iter
 
1011
                            last_shown_area;
 
1012
                            prerr_endline "Before find_tag_limits";
 
1013
                            
 
1014
                            let s,e = find_tag_limits tag 
 
1015
                                        (new GText.iter it) 
 
1016
                            in
 
1017
                            prerr_endline "After find_tag_limits";
 
1018
                            proof_buffer#apply_tag 
 
1019
                              ~start:s 
 
1020
                              ~stop:e 
 
1021
                              last_shown_area;
 
1022
                            
 
1023
                            prerr_endline "Applied tag";
 
1024
                            ()
 
1025
                        | _ -> ()
 
1026
                        end;false
 
1027
                     )
 
1028
                  );
 
1029
                tag
 
1030
              in
 
1031
              List.iter
 
1032
                (fun ((_,_,_,(s,_)) as hyp) -> 
 
1033
                   let tag = coq_menu (hyp_menu hyp) in
 
1034
                   proof_buffer#insert ~tags:[tag] (s^"\n"))
 
1035
                hyps;
 
1036
              proof_buffer#insert 
 
1037
                (String.make 38 '_' ^"(1/"^
 
1038
                 (string_of_int goal_nb)^
 
1039
                 ")\n") 
 
1040
              ;
 
1041
              let tag = coq_menu (concl_menu concl) in
 
1042
              let _,_,_,sconcl = concl in
 
1043
              proof_buffer#insert ~tags:[tag] sconcl;
 
1044
              proof_buffer#insert "\n";
 
1045
              let my_mark = `NAME "end_of_conclusion" in
 
1046
              proof_buffer#move_mark
 
1047
                ~where:((proof_buffer#get_iter_at_mark `INSERT)) my_mark;
 
1048
              proof_buffer#insert "\n\n";
 
1049
              let i = ref 1 in
 
1050
              List.iter 
 
1051
                (function (_,(_,_,_,concl)) -> 
 
1052
                   incr i;
 
1053
                   proof_buffer#insert 
 
1054
                     (String.make 38 '_' ^"("^
 
1055
                      (string_of_int !i)^
 
1056
                      "/"^
 
1057
                      (string_of_int goal_nb)^
 
1058
                      ")\n");
 
1059
                   proof_buffer#insert concl;
 
1060
                   proof_buffer#insert "\n\n";
 
1061
                )
 
1062
                r;
 
1063
                ignore (proof_view#scroll_to_mark my_mark) ;
 
1064
                full_goal_done <- true
 
1065
                end
 
1066
            | Decl_mode.Mode_proof ->
 
1067
                self#show_pm_goal
 
1068
          with e -> prerr_endline (Printexc.to_string e)
 
1069
      end
 
1070
      
 
1071
  method send_to_coq verbosely replace phrase show_output show_error localize =
 
1072
    let display_output msg =
 
1073
      self#insert_message (if show_output then msg else "") in
 
1074
    let display_error e =
 
1075
      let (s,loc) = Coq.process_exn e in
 
1076
      assert (Glib.Utf8.validate s);
 
1077
      self#insert_message s;
 
1078
      message_view#misc#draw None;
 
1079
      if localize then 
 
1080
        (match Option.map Util.unloc loc with 
 
1081
          | None -> ()
 
1082
          | Some (start,stop) ->
 
1083
              let convert_pos = byte_offset_to_char_offset phrase in
 
1084
              let start = convert_pos start in
 
1085
              let stop = convert_pos stop in
 
1086
              let i = self#get_start_of_input in 
 
1087
              let starti = i#forward_chars start in
 
1088
              let stopi = i#forward_chars stop in
 
1089
              input_buffer#apply_tag_by_name "error"
 
1090
                ~start:starti
 
1091
                ~stop:stopi;
 
1092
              input_buffer#place_cursor starti) in
 
1093
    try 
 
1094
      full_goal_done <- false;
 
1095
      prerr_endline "Send_to_coq starting now";
 
1096
      Decl_mode.clear_daimon_flag ();
 
1097
      if replace then begin
 
1098
        let r,info = Coq.interp_and_replace ("info " ^ phrase) in
 
1099
        let complete = not (Decl_mode.get_daimon_flag ()) in 
 
1100
        let msg = read_stdout () in
 
1101
        sync display_output msg;
 
1102
        Some (complete,r)       
 
1103
      end else begin
 
1104
        let r = Coq.interp verbosely phrase in
 
1105
        let complete = not (Decl_mode.get_daimon_flag ()) in 
 
1106
        let msg = read_stdout () in
 
1107
        sync display_output msg;
 
1108
        Some (complete,r)
 
1109
      end
 
1110
    with e ->
 
1111
      if show_error then sync display_error e;
 
1112
      None
 
1113
 
 
1114
  method find_phrase_starting_at (start:GText.iter) = 
 
1115
    prerr_endline "find_phrase_starting_at starting now";
 
1116
    let trash_bytes = ref "" in
 
1117
    let end_iter = start#copy in
 
1118
    let lexbuf_function s count =
 
1119
      let i = ref 0 in
 
1120
      let n_trash = String.length !trash_bytes in
 
1121
        String.blit !trash_bytes 0 s 0 n_trash;
 
1122
        i := n_trash;
 
1123
        try
 
1124
          while !i <= count - 1 do
 
1125
            let c = end_iter#char in
 
1126
              if c = 0 then raise (Stop !i);
 
1127
              let c' = Glib.Utf8.from_unichar c in
 
1128
              let n = String.length c' in
 
1129
                if (n<=0) then exit (-2);
 
1130
                if n > count - !i  then 
 
1131
                  begin
 
1132
                    let ri = count - !i in
 
1133
                      String.blit c' 0 s !i ri;
 
1134
                      trash_bytes := String.sub c' ri (n-ri);
 
1135
                      i := count ;
 
1136
                  end else begin
 
1137
                      String.blit c' 0 s !i n;
 
1138
                      i:= !i + n
 
1139
                    end;
 
1140
                if not end_iter#nocopy#forward_char then 
 
1141
                  raise (Stop !i)
 
1142
          done;
 
1143
          count
 
1144
        with Stop x ->
 
1145
          x
 
1146
    in
 
1147
      try
 
1148
        trash_bytes := "";
 
1149
        let _ = Find_phrase.get (Lexing.from_function lexbuf_function) 
 
1150
        in
 
1151
          end_iter#nocopy#set_offset (start#offset + !Find_phrase.length);
 
1152
          Some (start,end_iter)
 
1153
      with
 
1154
          (*
 
1155
            | Find_phrase.EOF s -> 
 
1156
          (* Phrase is at the end of the buffer*)
 
1157
            let si = start#offset in
 
1158
            let ei = si + !Find_phrase.length in
 
1159
            end_iter#nocopy#set_offset (ei - 1);
 
1160
            input_buffer#insert ~iter:end_iter "\n";
 
1161
            Some (input_buffer#get_iter (`OFFSET si),
 
1162
            input_buffer#get_iter (`OFFSET ei))
 
1163
          *)
 
1164
        | _ -> None
 
1165
 
 
1166
  method complete_at_offset (offset:int) = 
 
1167
    prerr_endline ("Completion at offset : " ^ string_of_int offset);
 
1168
    let it () = input_buffer#get_iter (`OFFSET offset) in
 
1169
    let iit = it () in
 
1170
    let start = find_word_start iit in
 
1171
      if ends_word iit then 
 
1172
        let w = input_buffer#get_text 
 
1173
          ~start
 
1174
          ~stop:iit
 
1175
          ()
 
1176
        in
 
1177
          if String.length w <> 0 then begin
 
1178
              prerr_endline ("Completion of prefix : '" ^ w^"'");
 
1179
              match complete input_buffer w start#offset with 
 
1180
                | None -> false
 
1181
                | Some (ss,start,stop) -> 
 
1182
                    let completion = input_buffer#get_text ~start ~stop () in
 
1183
                      ignore (input_buffer#delete_selection ());
 
1184
                      ignore (input_buffer#insert_interactive completion);
 
1185
                      input_buffer#move_mark `SEL_BOUND (it())#backward_char;
 
1186
                      true
 
1187
            end else false
 
1188
      else false
 
1189
 
 
1190
        
 
1191
  method process_next_phrase verbosely display_goals do_highlight = 
 
1192
    let get_next_phrase () =
 
1193
      self#clear_message;
 
1194
      prerr_endline "process_next_phrase starting now";
 
1195
      if do_highlight then begin
 
1196
          !push_info "Coq is computing";
 
1197
          input_view#set_editable false;
 
1198
        end;
 
1199
      match self#find_phrase_starting_at self#get_start_of_input with 
 
1200
        | None ->
 
1201
            if do_highlight then begin
 
1202
                input_view#set_editable true;
 
1203
                !pop_info ();
 
1204
              end;
 
1205
            None
 
1206
        | Some(start,stop) ->
 
1207
            prerr_endline "process_next_phrase : to_process highlight";
 
1208
            if do_highlight then begin
 
1209
                input_buffer#apply_tag_by_name ~start ~stop "to_process";
 
1210
                prerr_endline "process_next_phrase : to_process applied";
 
1211
              end;
 
1212
            prerr_endline "process_next_phrase : getting phrase";
 
1213
            Some((start,stop),start#get_slice ~stop) in
 
1214
    let remove_tag (start,stop) =
 
1215
      if do_highlight then begin
 
1216
          input_buffer#remove_tag_by_name ~start ~stop "to_process" ;
 
1217
          input_view#set_editable true;
 
1218
          !pop_info ();
 
1219
        end in
 
1220
      let mark_processed reset_info complete (start,stop) ast =
 
1221
        let b = input_buffer in
 
1222
        b#move_mark ~where:stop (`NAME "start_of_input");
 
1223
        b#apply_tag_by_name 
 
1224
          (if complete then "processed" else "unjustified") ~start ~stop;
 
1225
        if (self#get_insert#compare) stop <= 0 then 
 
1226
          begin
 
1227
            b#place_cursor stop;
 
1228
            self#recenter_insert
 
1229
          end;
 
1230
        let start_of_phrase_mark = `MARK (b#create_mark start) in
 
1231
        let end_of_phrase_mark = `MARK (b#create_mark stop) in
 
1232
        push_phrase
 
1233
          reset_info 
 
1234
          start_of_phrase_mark 
 
1235
          end_of_phrase_mark ast;
 
1236
        if display_goals then self#show_goals;
 
1237
        remove_tag (start,stop) in
 
1238
      begin
 
1239
        match sync get_next_phrase () with
 
1240
            None -> false
 
1241
          | Some (loc,phrase) ->
 
1242
            (match self#send_to_coq verbosely false phrase true true true with
 
1243
              | Some (complete,(reset_info,ast)) -> 
 
1244
                  sync (mark_processed reset_info complete) loc ast; true
 
1245
              | None -> sync remove_tag loc; false)
 
1246
      end
 
1247
    
 
1248
  method insert_this_phrase_on_success 
 
1249
    show_output show_msg localize coqphrase insertphrase = 
 
1250
    let mark_processed reset_info complete ast =
 
1251
      let stop = self#get_start_of_input in
 
1252
      if stop#starts_line then
 
1253
        input_buffer#insert ~iter:stop insertphrase
 
1254
      else input_buffer#insert ~iter:stop ("\n"^insertphrase); 
 
1255
      let start = self#get_start_of_input in
 
1256
      input_buffer#move_mark ~where:stop (`NAME "start_of_input");
 
1257
      input_buffer#apply_tag_by_name 
 
1258
        (if complete then "processed" else "unjustified") ~start ~stop;
 
1259
      if (self#get_insert#compare) stop <= 0 then 
 
1260
        input_buffer#place_cursor stop;
 
1261
      let start_of_phrase_mark = `MARK (input_buffer#create_mark start) in
 
1262
      let end_of_phrase_mark = `MARK (input_buffer#create_mark stop) in
 
1263
      push_phrase reset_info start_of_phrase_mark end_of_phrase_mark ast;
 
1264
      self#show_goals;
 
1265
      (*Auto insert save on success... 
 
1266
      try (match Coq.get_current_goals () with 
 
1267
        | [] ->  
 
1268
            (match self#send_to_coq "Save.\n" true true true with
 
1269
              | Some ast -> 
 
1270
                  begin
 
1271
                    let stop = self#get_start_of_input in
 
1272
                    if stop#starts_line then
 
1273
                      input_buffer#insert ~iter:stop "Save.\n"
 
1274
                    else input_buffer#insert ~iter:stop "\nSave.\n"; 
 
1275
                    let start = self#get_start_of_input in
 
1276
                    input_buffer#move_mark ~where:stop (`NAME"start_of_input");
 
1277
                    input_buffer#apply_tag_by_name "processed" ~start ~stop;
 
1278
                    if (self#get_insert#compare) stop <= 0 then 
 
1279
                      input_buffer#place_cursor stop;
 
1280
                    let start_of_phrase_mark =
 
1281
                      `MARK (input_buffer#create_mark start) in
 
1282
                    let end_of_phrase_mark =
 
1283
                      `MARK (input_buffer#create_mark stop) in
 
1284
                    push_phrase
 
1285
                      reset_info start_of_phrase_mark end_of_phrase_mark ast
 
1286
                  end
 
1287
              | None -> ())
 
1288
        | _ -> ())
 
1289
      with _ -> ()*) in
 
1290
    match self#send_to_coq false false coqphrase show_output show_msg localize with
 
1291
      | Some (complete,(reset_info,ast)) ->
 
1292
          sync (mark_processed reset_info complete) ast; true
 
1293
      | None ->
 
1294
          sync
 
1295
            (fun _ -> self#insert_message ("Unsuccessfully tried: "^coqphrase))
 
1296
            ();
 
1297
          false
 
1298
 
 
1299
  method process_until_iter_or_error stop =
 
1300
    let stop' = `OFFSET stop#offset in
 
1301
    let start = self#get_start_of_input#copy in
 
1302
    let start' = `OFFSET start#offset in
 
1303
      sync (fun _ ->
 
1304
              input_buffer#apply_tag_by_name ~start ~stop "to_process";
 
1305
              input_view#set_editable false) ();
 
1306
      !push_info "Coq is computing";
 
1307
      let get_current () =
 
1308
        if !current.stop_before then
 
1309
          match self#find_phrase_starting_at self#get_start_of_input with
 
1310
            | None -> self#get_start_of_input
 
1311
            | Some (_, stop2) -> stop2
 
1312
        else begin
 
1313
            self#get_start_of_input
 
1314
          end
 
1315
      in   
 
1316
        (try 
 
1317
            while ((stop#compare (get_current())>=0) 
 
1318
                    && (self#process_next_phrase false false false))
 
1319
            do Util.check_for_interrupt () done
 
1320
          with Sys.Break -> 
 
1321
            prerr_endline "Interrupted during process_until_iter_or_error");
 
1322
        sync (fun _ ->
 
1323
          self#show_goals;
 
1324
          (* Start and stop might be invalid if an eol was added at eof *)
 
1325
          let start = input_buffer#get_iter start' in
 
1326
          let stop =  input_buffer#get_iter stop' in
 
1327
            input_buffer#remove_tag_by_name ~start ~stop "to_process" ;
 
1328
            input_view#set_editable true) ();
 
1329
        !pop_info()
 
1330
 
 
1331
  method process_until_end_or_error = 
 
1332
    self#process_until_iter_or_error input_buffer#end_iter
 
1333
 
 
1334
  method reset_initial =
 
1335
    sync (fun _ ->
 
1336
            Stack.iter 
 
1337
              (function inf -> 
 
1338
                 let start = input_buffer#get_iter_at_mark inf.start in
 
1339
                 let stop = input_buffer#get_iter_at_mark inf.stop in
 
1340
                   input_buffer#move_mark ~where:start (`NAME "start_of_input");
 
1341
                   input_buffer#remove_tag_by_name "processed" ~start ~stop;
 
1342
                   input_buffer#remove_tag_by_name "unjustified" ~start ~stop;
 
1343
                   input_buffer#delete_mark inf.start;
 
1344
                   input_buffer#delete_mark inf.stop;
 
1345
              ) 
 
1346
              processed_stack;
 
1347
            Stack.clear processed_stack;
 
1348
            self#clear_message)();
 
1349
    Coq.reset_initial ()
 
1350
 
 
1351
  (* backtrack Coq to the phrase preceding iterator [i] *)
 
1352
  method backtrack_to_no_lock i =
 
1353
    prerr_endline "Backtracking_to iter starts now.";
 
1354
    (* pop Coq commands until we reach iterator [i] *)
 
1355
    let  rec pop_commands done_smthg undos =
 
1356
      if is_empty () then 
 
1357
        done_smthg, undos
 
1358
      else
 
1359
        let t = top () in 
 
1360
        if i#compare (input_buffer#get_iter_at_mark t.stop) < 0 then
 
1361
          begin
 
1362
            prerr_endline "Popped top command";
 
1363
            pop_commands true (pop_command undos t)
 
1364
          end
 
1365
        else
 
1366
          done_smthg, undos
 
1367
    in
 
1368
    let undos = (0,0,NoBacktrack,0,undo_info()) in
 
1369
    let done_smthg, undos = pop_commands false undos in
 
1370
      prerr_endline "Popped commands";
 
1371
      if done_smthg then
 
1372
        begin 
 
1373
          try 
 
1374
            apply_undos undos;
 
1375
            sync (fun _ ->
 
1376
                    let start =
 
1377
                      if is_empty () then input_buffer#start_iter 
 
1378
                      else input_buffer#get_iter_at_mark (top ()).stop in
 
1379
                      prerr_endline "Removing (long) processed tag...";
 
1380
                      input_buffer#remove_tag_by_name 
 
1381
                        ~start 
 
1382
                        ~stop:self#get_start_of_input
 
1383
                        "processed";
 
1384
                      input_buffer#remove_tag_by_name 
 
1385
                        ~start 
 
1386
                        ~stop:self#get_start_of_input
 
1387
                        "unjustified";
 
1388
                      prerr_endline "Moving (long) start_of_input...";
 
1389
                      input_buffer#move_mark ~where:start (`NAME "start_of_input");
 
1390
                      self#show_goals;
 
1391
                      clear_stdout ();
 
1392
                      self#clear_message)
 
1393
              ();
 
1394
          with _ -> 
 
1395
            !push_info "WARNING: undo failed badly -> Coq might be in an inconsistent state.
 
1396
Please restart and report NOW.";
 
1397
      end
 
1398
    else prerr_endline "backtrack_to : discarded (...)"
 
1399
      
 
1400
  method backtrack_to i = 
 
1401
    if Mutex.try_lock coq_may_stop then 
 
1402
      (!push_info "Undoing...";
 
1403
       self#backtrack_to_no_lock i; Mutex.unlock coq_may_stop;
 
1404
       !pop_info ())
 
1405
    else prerr_endline "backtrack_to : discarded (lock is busy)"
 
1406
 
 
1407
  method go_to_insert =
 
1408
    let point = self#get_insert in
 
1409
      if point#compare self#get_start_of_input>=0
 
1410
      then self#process_until_iter_or_error point
 
1411
      else self#backtrack_to point
 
1412
 
 
1413
  method undo_last_step =
 
1414
    if Mutex.try_lock coq_may_stop then  
 
1415
      (!push_info "Undoing last step...";
 
1416
       (try
 
1417
            let last_command = top () in
 
1418
            let start = input_buffer#get_iter_at_mark last_command.start in
 
1419
            let update_input () =
 
1420
              prerr_endline "Removing processed tag...";
 
1421
              input_buffer#remove_tag_by_name 
 
1422
                ~start
 
1423
                ~stop:(input_buffer#get_iter_at_mark last_command.stop) 
 
1424
                "processed";
 
1425
              input_buffer#remove_tag_by_name 
 
1426
                ~start
 
1427
                ~stop:(input_buffer#get_iter_at_mark last_command.stop) 
 
1428
              "unjustified";
 
1429
              prerr_endline "Moving start_of_input";
 
1430
              input_buffer#move_mark
 
1431
                ~where:start
 
1432
                (`NAME "start_of_input");
 
1433
              input_buffer#place_cursor start;
 
1434
              self#recenter_insert;
 
1435
              self#show_goals;
 
1436
              self#clear_message
 
1437
            in
 
1438
              let undo = pop_command (0,0,NoBacktrack,0,undo_info()) last_command in
 
1439
              apply_undos undo;
 
1440
              sync update_input ()
 
1441
        with
 
1442
          | Size 0 -> (* !flash_info "Nothing to Undo"*)()
 
1443
       );
 
1444
       !pop_info ();
 
1445
       Mutex.unlock coq_may_stop)
 
1446
    else prerr_endline "undo_last_step discarded"
 
1447
 
 
1448
      
 
1449
  method blaster () = 
 
1450
    
 
1451
    ignore (Thread.create 
 
1452
              (fun () ->  
 
1453
                 prerr_endline "Blaster called";
 
1454
                 let c = Blaster_window.present_blaster_window () in
 
1455
                   if Mutex.try_lock c#lock then begin
 
1456
                       c#clear ();
 
1457
                      Decl_mode.check_not_proof_mode "No blaster in Proof mode";
 
1458
                       let current_gls = try get_current_goals () with _ -> [] in
 
1459
                         
 
1460
                       let set_goal i (s,t) = 
 
1461
                         let gnb = string_of_int i in
 
1462
                         let s = gnb ^":"^s in
 
1463
                         let t' = gnb ^": progress "^t in
 
1464
                         let t'' = gnb ^": "^t in
 
1465
                           c#set
 
1466
                             ("Goal "^gnb)
 
1467
                             s 
 
1468
                             (fun () -> try_interptac t')
 
1469
                             (sync(fun () -> self#insert_command t'' t''))
 
1470
                       in
 
1471
                       let set_current_goal (s,t) = 
 
1472
                         c#set
 
1473
                           "Goal 1"
 
1474
                           s 
 
1475
                           (fun () -> try_interptac ("progress "^t))
 
1476
                           (sync(fun () -> self#insert_command t t))
 
1477
                       in
 
1478
                         begin match current_gls with 
 
1479
                           | [] -> ()
 
1480
                           | (hyp_l,current_gl)::r ->
 
1481
                               List.iter set_current_goal (concl_menu current_gl);
 
1482
                               List.iter 
 
1483
                                 (fun hyp -> 
 
1484
                                    List.iter set_current_goal (hyp_menu hyp))
 
1485
                                 hyp_l;
 
1486
                               let i = ref 2 in
 
1487
                                 List.iter 
 
1488
                                   (fun (hyp_l,gl) -> 
 
1489
                                      List.iter (set_goal !i) (concl_menu gl);
 
1490
                                      incr i)
 
1491
                                   r
 
1492
                         end;
 
1493
                         let _ =  c#blaster () in
 
1494
                           Mutex.unlock c#lock
 
1495
                     end else prerr_endline "Blaster discarded")
 
1496
              ())
 
1497
      
 
1498
  method insert_command cp ip = 
 
1499
    async(fun _ -> self#clear_message)();
 
1500
    ignore (self#insert_this_phrase_on_success true false false cp ip)
 
1501
 
 
1502
  method tactic_wizard l =
 
1503
    async(fun _ -> self#clear_message)();
 
1504
    ignore 
 
1505
      (List.exists 
 
1506
         (fun p -> 
 
1507
            self#insert_this_phrase_on_success true false false 
 
1508
              ("progress "^p^".\n") (p^".\n")) l)
 
1509
      
 
1510
  method active_keypress_handler k = 
 
1511
    let state = GdkEvent.Key.state k in
 
1512
      begin
 
1513
        match  state with
 
1514
          | l when List.mem `MOD1 l ->
 
1515
              let k = GdkEvent.Key.keyval k in
 
1516
                if GdkKeysyms._Return=k
 
1517
                then ignore(
 
1518
                             if (input_buffer#insert_interactive "\n") then
 
1519
                               begin
 
1520
                                 let i= self#get_insert#backward_word_start in
 
1521
                                   prerr_endline "active_kp_hf: Placing cursor";
 
1522
                                   self#process_until_iter_or_error i
 
1523
                               end);
 
1524
                true
 
1525
          | l when List.mem `CONTROL l -> 
 
1526
              let k = GdkEvent.Key.keyval k in
 
1527
                if GdkKeysyms._Break=k
 
1528
                then break ();
 
1529
                false
 
1530
          | l -> 
 
1531
              if GdkEvent.Key.keyval k = GdkKeysyms._Tab then begin
 
1532
                  prerr_endline "active_kp_handler for Tab";
 
1533
                  self#indent_current_line;
 
1534
                  true
 
1535
                end else false
 
1536
      end
 
1537
  method disconnected_keypress_handler k = 
 
1538
    match GdkEvent.Key.state k with
 
1539
      | l when List.mem `CONTROL l -> 
 
1540
          let k = GdkEvent.Key.keyval k in
 
1541
            if GdkKeysyms._c=k
 
1542
            then break ();
 
1543
            false
 
1544
      | l -> false
 
1545
          
 
1546
 
 
1547
  val mutable deact_id = None
 
1548
  val mutable act_id = None
 
1549
 
 
1550
  method deactivate () = 
 
1551
    is_active <- false;
 
1552
    (match act_id with None -> () 
 
1553
       | Some id ->
 
1554
           reset_initial ();
 
1555
           input_view#misc#disconnect id;
 
1556
           prerr_endline "DISCONNECTED old active : ";
 
1557
           print_id id;
 
1558
    );
 
1559
    deact_id <- Some 
 
1560
      (input_view#event#connect#key_press self#disconnected_keypress_handler);
 
1561
    prerr_endline "CONNECTED  inactive : ";
 
1562
    print_id (Option.get deact_id)
 
1563
 
 
1564
  method activate () =
 
1565
    is_active <- true;
 
1566
    (match deact_id with None -> () 
 
1567
       | Some id -> input_view#misc#disconnect id;
 
1568
           prerr_endline "DISCONNECTED old inactive : ";
 
1569
           print_id id
 
1570
    );
 
1571
    act_id <- Some 
 
1572
      (input_view#event#connect#key_press self#active_keypress_handler);
 
1573
    prerr_endline "CONNECTED active : ";
 
1574
    print_id (Option.get act_id);
 
1575
    match 
 
1576
      (Option.get ((Vector.get input_views index).analyzed_view)) #filename 
 
1577
    with
 
1578
      | None -> ()
 
1579
      | Some f -> let dir = Filename.dirname f in
 
1580
                    if not (is_in_loadpath dir) then
 
1581
                      begin
 
1582
                        ignore (Coq.interp false
 
1583
                                  (Printf.sprintf "Add LoadPath \"%s\". "  dir))
 
1584
                      end
 
1585
                        
 
1586
  method electric_handler = 
 
1587
    input_buffer#connect#insert_text ~callback:
 
1588
      (fun it x -> 
 
1589
         begin try
 
1590
             if last_index then begin
 
1591
                 last_array.(0)<-x;
 
1592
                 if (last_array.(1) ^ last_array.(0) = ".\n") then raise Found
 
1593
               end else begin
 
1594
                   last_array.(1)<-x;
 
1595
                   if (last_array.(0) ^ last_array.(1) = ".\n") then raise Found
 
1596
                 end
 
1597
           with Found -> 
 
1598
             begin
 
1599
               ignore (self#process_next_phrase false true true)
 
1600
             end;
 
1601
         end;
 
1602
         last_index <- not last_index;)
 
1603
 
 
1604
  method private electric_paren tag =
 
1605
    let oparen_code = Glib.Utf8.to_unichar "("  (ref 0) in
 
1606
    let cparen_code = Glib.Utf8.to_unichar ")"  (ref 0) in
 
1607
      ignore (input_buffer#connect#insert_text ~callback:
 
1608
                (fun it x ->
 
1609
                   input_buffer#remove_tag
 
1610
                     ~start:input_buffer#start_iter
 
1611
                     ~stop:input_buffer#end_iter
 
1612
                     tag;
 
1613
                   if x = "" then () else
 
1614
                     match x.[String.length x - 1] with 
 
1615
                       | ')' -> 
 
1616
                           let hit = self#get_insert in
 
1617
                           let count = ref 0 in
 
1618
                             if hit#nocopy#backward_find_char 
 
1619
                               (fun c -> 
 
1620
                                  if c = oparen_code && !count = 0 then true 
 
1621
                                  else if c = cparen_code then 
 
1622
                                    (incr count;false)
 
1623
                                  else if c = oparen_code then 
 
1624
                                    (decr count;false)
 
1625
                                  else false
 
1626
                               )
 
1627
                             then
 
1628
                               begin
 
1629
                                 prerr_endline "Found matching parenthesis";
 
1630
                                 input_buffer#apply_tag tag ~start:hit ~stop:hit#forward_char
 
1631
                               end
 
1632
                             else ()
 
1633
                       | _ -> ())
 
1634
             )
 
1635
 
 
1636
  method help_for_keyword () = 
 
1637
    
 
1638
    browse_keyword (self#insert_message) (get_current_word ())
 
1639
 
 
1640
  initializer 
 
1641
    ignore (message_buffer#connect#insert_text
 
1642
              ~callback:(fun it s -> ignore 
 
1643
                           (message_view#scroll_to_mark
 
1644
                              ~use_align:false
 
1645
                              ~within_margin:0.49
 
1646
                              `INSERT)));
 
1647
    ignore (input_buffer#connect#insert_text
 
1648
              ~callback:(fun it s ->
 
1649
                           if (it#compare self#get_start_of_input)<0
 
1650
                           then GtkSignal.stop_emit ();
 
1651
                           if String.length s > 1 then 
 
1652
                             (prerr_endline "insert_text: Placing cursor";input_buffer#place_cursor it)));
 
1653
    ignore (input_buffer#connect#after#apply_tag
 
1654
              ~callback:(fun tag ~start ~stop ->
 
1655
                           if (start#compare self#get_start_of_input)>=0
 
1656
                           then 
 
1657
                             begin
 
1658
                               input_buffer#remove_tag_by_name 
 
1659
                                 ~start
 
1660
                                 ~stop
 
1661
                                 "processed";
 
1662
                               input_buffer#remove_tag_by_name 
 
1663
                                 ~start
 
1664
                                 ~stop
 
1665
                                 "unjustified"
 
1666
                             end
 
1667
                        )
 
1668
           );
 
1669
    ignore (input_buffer#connect#after#insert_text
 
1670
              ~callback:(fun it s ->
 
1671
                           if auto_complete_on && 
 
1672
                             String.length s = 1 && s <> " " && s <> "\n" 
 
1673
                           then 
 
1674
                             let v = Option.get (get_current_view ()).analyzed_view 
 
1675
                             in 
 
1676
                             let has_completed = 
 
1677
                               v#complete_at_offset 
 
1678
                                 ((v#view#buffer#get_iter `SEL_BOUND)#offset)
 
1679
                             in
 
1680
                               if has_completed then 
 
1681
                                 input_buffer#move_mark `SEL_BOUND (input_buffer#get_iter `SEL_BOUND)#forward_char;
 
1682
                               
 
1683
                               
 
1684
                        )
 
1685
           );
 
1686
    ignore (input_buffer#connect#modified_changed
 
1687
              ~callback:
 
1688
              (fun () ->
 
1689
                 if input_buffer#modified then 
 
1690
                   set_tab_image index 
 
1691
                     ~icon:(match (Option.get (current_all.analyzed_view))#filename with 
 
1692
                              | None -> `SAVE_AS
 
1693
                              | Some _ -> `SAVE
 
1694
                           )
 
1695
                 else set_tab_image index ~icon:`YES;
 
1696
              ));
 
1697
    ignore (input_buffer#connect#changed
 
1698
              ~callback:(fun () -> 
 
1699
                           last_modification_time <- Unix.time ();
 
1700
                           let r = input_view#visible_rect in
 
1701
                           let stop = 
 
1702
                             input_view#get_iter_at_location 
 
1703
                               ~x:(Gdk.Rectangle.x r + Gdk.Rectangle.width r)
 
1704
                               ~y:(Gdk.Rectangle.y r + Gdk.Rectangle.height r)
 
1705
                           in
 
1706
                             input_buffer#remove_tag_by_name 
 
1707
                               ~start:self#get_start_of_input
 
1708
                               ~stop
 
1709
                               "error";
 
1710
                             Highlight.highlight_around_current_line
 
1711
                               input_buffer 
 
1712
                        )
 
1713
           );
 
1714
    ignore (input_buffer#add_selection_clipboard (cb()));
 
1715
    let paren_highlight_tag = input_buffer#create_tag ~name:"paren" [`BACKGROUND "purple"]  in
 
1716
      self#electric_paren paren_highlight_tag;
 
1717
      ignore (input_buffer#connect#after#mark_set 
 
1718
                ~callback:(fun it (m:Gtk.text_mark) ->
 
1719
                             !set_location 
 
1720
                               (Printf.sprintf 
 
1721
                                  "Line: %5d Char: %3d" (self#get_insert#line + 1)
 
1722
                                  (self#get_insert#line_offset + 1));
 
1723
                             match GtkText.Mark.get_name m  with
 
1724
                               | Some "insert" ->                
 
1725
                                   input_buffer#remove_tag
 
1726
                                     ~start:input_buffer#start_iter
 
1727
                                     ~stop:input_buffer#end_iter
 
1728
                                     paren_highlight_tag;
 
1729
                               | Some s -> 
 
1730
                                   prerr_endline (s^" moved")
 
1731
                               | None -> () )
 
1732
             );
 
1733
      ignore (input_buffer#connect#insert_text
 
1734
                (fun it s -> 
 
1735
                   prerr_endline "Should recenter ?";
 
1736
                   if String.contains s '\n' then begin
 
1737
                       prerr_endline "Should recenter : yes";
 
1738
                       self#recenter_insert
 
1739
                     end))
 
1740
end
 
1741
 
 
1742
let create_input_tab filename =
 
1743
  let b = GText.buffer () in 
 
1744
  let _ = GMisc.label () in 
 
1745
  let v_box = GPack.hbox ~homogeneous:false () in
 
1746
  let _ = GMisc.image ~packing:v_box#pack () in
 
1747
  let _ = GMisc.label ~text:filename ~packing:v_box#pack () in
 
1748
  let appendp x = ignore ((notebook ())#append_page
 
1749
                ~tab_label:v_box#coerce x) in  
 
1750
  let fr1 = GBin.frame ~shadow_type:`ETCHED_OUT
 
1751
    ~packing:appendp () 
 
1752
  in 
 
1753
  let sw1 = GBin.scrolled_window
 
1754
    ~vpolicy:`AUTOMATIC 
 
1755
    ~hpolicy:`AUTOMATIC
 
1756
    ~packing:fr1#add () 
 
1757
  in
 
1758
  let tv1 = Undo.undoable_view ~buffer:b ~packing:(sw1#add) () in
 
1759
    prerr_endline ("Language: "^ b#start_iter#language);
 
1760
    tv1#misc#set_name "ScriptWindow";
 
1761
    let _ = tv1#set_editable true in
 
1762
    let _ = tv1#set_wrap_mode `NONE in
 
1763
      b#place_cursor ~where:(b#start_iter);
 
1764
      ignore (tv1#event#connect#button_press ~callback:
 
1765
                (fun ev -> GdkEvent.Button.button ev = 3));
 
1766
      (*  ignore (tv1#event#connect#button_press ~callback:
 
1767
          (fun ev -> 
 
1768
          if (GdkEvent.Button.button ev=2) then
 
1769
          (try 
 
1770
          prerr_endline "Paste invoked";
 
1771
          GtkSignal.emit_unit 
 
1772
          (get_current_view()).view#as_view 
 
1773
          GtkText.View.Signals.paste_clipboard;
 
1774
          true
 
1775
          with _ -> false)
 
1776
          else false
 
1777
          ));*)
 
1778
      tv1#misc#grab_focus ();
 
1779
      ignore (tv1#buffer#create_mark 
 
1780
                ~name:"start_of_input" 
 
1781
                tv1#buffer#start_iter);
 
1782
      ignore (tv1#buffer#create_tag 
 
1783
                ~name:"kwd" 
 
1784
                [`FOREGROUND "blue"]);
 
1785
      ignore (tv1#buffer#create_tag 
 
1786
                ~name:"decl" 
 
1787
                [`FOREGROUND "orange red"]);
 
1788
      ignore (tv1#buffer#create_tag 
 
1789
                ~name:"comment" 
 
1790
                [`FOREGROUND "brown"]);
 
1791
      ignore (tv1#buffer#create_tag 
 
1792
                ~name:"reserved" 
 
1793
                [`FOREGROUND "dark red"]);
 
1794
      ignore (tv1#buffer#create_tag 
 
1795
                ~name:"error" 
 
1796
                [`UNDERLINE `DOUBLE ; `FOREGROUND "red"]);
 
1797
      ignore (tv1#buffer#create_tag 
 
1798
                ~name:"to_process" 
 
1799
                [`BACKGROUND "light blue" ;`EDITABLE false]);
 
1800
      ignore (tv1#buffer#create_tag 
 
1801
                ~name:"processed" 
 
1802
                [`BACKGROUND "light green" ;`EDITABLE false]);
 
1803
      ignore (tv1#buffer#create_tag (* Proof mode *)
 
1804
                ~name:"unjustified" 
 
1805
               [`UNDERLINE `SINGLE ; `FOREGROUND "red";
 
1806
                 `BACKGROUND "gold" ;`EDITABLE false]);
 
1807
      ignore (tv1#buffer#create_tag 
 
1808
                ~name:"found" 
 
1809
                [`BACKGROUND "blue"; `FOREGROUND "white"]);
 
1810
      tv1
 
1811
 
 
1812
 
 
1813
let last_make = ref "";;
 
1814
let last_make_index = ref 0;;
 
1815
let search_compile_error_regexp =
 
1816
  Str.regexp
 
1817
    "File \"\\([^\"]+\\)\", line \\([0-9]+\\), characters \\([0-9]+\\)-\\([0-9]+\\)";;
 
1818
 
 
1819
let search_next_error () =
 
1820
  let _ = Str.search_forward search_compile_error_regexp !last_make !last_make_index in
 
1821
  let f = Str.matched_group 1 !last_make
 
1822
  and l = int_of_string (Str.matched_group 2 !last_make)
 
1823
  and b = int_of_string (Str.matched_group 3 !last_make)
 
1824
  and e = int_of_string (Str.matched_group 4 !last_make)
 
1825
  and msg_index = Str.match_beginning ()
 
1826
  in 
 
1827
    last_make_index := Str.group_end 4; 
 
1828
    (f,l,b,e,
 
1829
     String.sub !last_make msg_index (String.length !last_make - msg_index))
 
1830
 
 
1831
let main files = 
 
1832
  (* Statup preferences *)
 
1833
  load_pref ();
 
1834
 
 
1835
  (* Main window *)
 
1836
  let w = GWindow.window 
 
1837
    ~wm_class:"CoqIde" ~wm_name:"CoqIde"
 
1838
    ~allow_grow:true ~allow_shrink:true 
 
1839
    ~width:!current.window_width ~height:!current.window_height 
 
1840
    ~title:"CoqIde" ()
 
1841
  in
 
1842
    (try
 
1843
         let icon_image = lib_ide_file "coq.png" in
 
1844
         let icon = GdkPixbuf.from_file icon_image in
 
1845
           w#set_icon (Some icon)
 
1846
     with _ -> ());
 
1847
 
 
1848
    let vbox = GPack.vbox ~homogeneous:false ~packing:w#add () in
 
1849
 
 
1850
 
 
1851
    (* Menu bar *)
 
1852
    let menubar = GMenu.menu_bar ~packing:vbox#pack () in
 
1853
 
 
1854
    (* Toolbar *)
 
1855
    let toolbar = GButton.toolbar 
 
1856
      ~orientation:`HORIZONTAL 
 
1857
      ~style:`ICONS
 
1858
      ~tooltips:true 
 
1859
      ~packing:(* handle#add *)
 
1860
      (vbox#pack ~expand:false ~fill:false)
 
1861
      ()
 
1862
    in
 
1863
      show_toolbar := 
 
1864
        (fun b -> if b then toolbar#misc#show () else toolbar#misc#hide ());
 
1865
 
 
1866
      let factory = new GMenu.factory ~accel_path:"<CoqIde MenuBar>/" menubar in
 
1867
      let accel_group = factory#accel_group in
 
1868
 
 
1869
      (* File Menu *)
 
1870
      let file_menu = factory#add_submenu "_File" in
 
1871
 
 
1872
      let file_factory = new GMenu.factory ~accel_path:"<CoqIde MenuBar>/File/" file_menu ~accel_group in
 
1873
 
 
1874
      (* File/Load Menu *)
 
1875
      let load_file handler f =
 
1876
        let f = absolute_filename f in          
 
1877
          try
 
1878
            prerr_endline "Loading file starts";
 
1879
            Vector.find_or_fail 
 
1880
              (function 
 
1881
                 | {analyzed_view=Some av} -> 
 
1882
                     (match av#filename with 
 
1883
                        | None -> false 
 
1884
                        | Some fn -> same_file f fn)
 
1885
                 | _ -> false) 
 
1886
              !input_views;
 
1887
            prerr_endline "Loading: must open";
 
1888
            let b = Buffer.create 1024 in
 
1889
              prerr_endline "Loading: get raw content";
 
1890
              with_file handler f ~f:(input_channel b);
 
1891
              prerr_endline "Loading: convert content";
 
1892
              let s = do_convert (Buffer.contents b) in
 
1893
                prerr_endline "Loading: create view";
 
1894
                let view = create_input_tab (Glib.Convert.filename_to_utf8 
 
1895
                                               (Filename.basename f)) 
 
1896
                in
 
1897
                  prerr_endline "Loading: change font";
 
1898
                  view#misc#modify_font !current.text_font;
 
1899
                  prerr_endline "Loading: adding view";
 
1900
                  let index = add_input_view {view = view;
 
1901
                                              analyzed_view = None;
 
1902
                                             }
 
1903
                  in
 
1904
                  let av = (new analyzed_view index) in 
 
1905
                    prerr_endline "Loading: register view";
 
1906
                    (get_input_view index).analyzed_view <- Some av;
 
1907
                    prerr_endline "Loading: set filename";
 
1908
                    av#set_filename (Some f);
 
1909
                    prerr_endline "Loading: stats";
 
1910
                    av#update_stats;
 
1911
                    let input_buffer = view#buffer in
 
1912
                      prerr_endline "Loading: fill buffer";
 
1913
                      input_buffer#set_text s;
 
1914
                      input_buffer#place_cursor input_buffer#start_iter;
 
1915
                      prerr_endline ("Loading: switch to view "^ string_of_int index);
 
1916
                      set_current_view index;
 
1917
                      set_tab_image index ~icon:`YES;
 
1918
                      prerr_endline "Loading: highlight";
 
1919
                      Highlight.highlight_all input_buffer;
 
1920
                      input_buffer#set_modified false;
 
1921
                      prerr_endline "Loading: clear undo";
 
1922
                      av#view#clear_undo;
 
1923
                      prerr_endline "Loading: success"
 
1924
          with       
 
1925
            | Vector.Found i -> set_current_view i
 
1926
            | e -> handler ("Load failed: "^(Printexc.to_string e))
 
1927
      in
 
1928
      let load f = load_file !flash_info f in
 
1929
      let load_m = file_factory#add_item "_New" 
 
1930
        ~key:GdkKeysyms._N in
 
1931
      let load_f () =     
 
1932
        match select_file_for_save ~title:"Create file" () with 
 
1933
          | None -> ()
 
1934
          | Some f -> load f
 
1935
      in
 
1936
        ignore (load_m#connect#activate (load_f));
 
1937
 
 
1938
      let load_m = file_factory#add_item "_Open" 
 
1939
        ~key:GdkKeysyms._O in
 
1940
      let load_f () =     
 
1941
        match select_file_for_open ~title:"Load file" () with 
 
1942
          | None -> ()
 
1943
          | Some f -> load f
 
1944
      in
 
1945
        ignore (load_m#connect#activate (load_f));
 
1946
 
 
1947
        (* File/Save Menu *)
 
1948
        let save_m = file_factory#add_item "_Save" 
 
1949
          ~key:GdkKeysyms._S in
 
1950
 
 
1951
          
 
1952
        let save_f () = 
 
1953
          let current = get_current_view () in
 
1954
            try
 
1955
              (match (Option.get current.analyzed_view)#filename with 
 
1956
                 | None ->
 
1957
                     begin match select_file_for_save ~title:"Save file" ()
 
1958
                       with
 
1959
                         | None -> ()
 
1960
                         | Some f -> 
 
1961
                             if (Option.get current.analyzed_view)#save_as f then begin
 
1962
                                 set_current_tab_label (Filename.basename f);
 
1963
                                 !flash_info ("File " ^ f ^ " saved")
 
1964
                               end
 
1965
                             else warning ("Save Failed (check if " ^ f ^ " is writable)")
 
1966
                     end
 
1967
                 | Some f -> 
 
1968
                     if (Option.get current.analyzed_view)#save f then 
 
1969
                       !flash_info ("File " ^ f ^ " saved")
 
1970
                     else warning  ("Save Failed (check if " ^ f ^ " is writable)")
 
1971
                       
 
1972
              )
 
1973
            with 
 
1974
              | e -> warning "Save: unexpected error"
 
1975
        in   
 
1976
          ignore (save_m#connect#activate save_f);
 
1977
 
 
1978
          (* File/Save As Menu *)
 
1979
          let saveas_m = file_factory#add_item "S_ave as" 
 
1980
          in
 
1981
          let saveas_f () = 
 
1982
            let current = get_current_view () in
 
1983
              try (match (Option.get current.analyzed_view)#filename with 
 
1984
                     | None -> 
 
1985
                         begin match select_file_for_save ~title:"Save file as" ()
 
1986
                           with
 
1987
                             | None -> ()
 
1988
                             | Some f -> 
 
1989
                                 if (Option.get current.analyzed_view)#save_as f then begin
 
1990
                                     set_current_tab_label (Filename.basename f);
 
1991
                                     !flash_info "Saved"
 
1992
                                   end
 
1993
                                 else !flash_info "Save Failed"
 
1994
                         end
 
1995
                     | Some f -> 
 
1996
                         begin match select_file_for_save 
 
1997
                             ~dir:(ref (Filename.dirname f)) 
 
1998
                             ~filename:(Filename.basename f)
 
1999
                             ~title:"Save file as" ()
 
2000
                           with
 
2001
                             | None -> ()
 
2002
                             | Some f -> 
 
2003
                                 if (Option.get current.analyzed_view)#save_as f then begin
 
2004
                                     set_current_tab_label (Filename.basename f);
 
2005
                                     !flash_info "Saved"
 
2006
                                   end else !flash_info "Save Failed"
 
2007
                         end);
 
2008
              with e -> !flash_info "Save Failed"
 
2009
          in   
 
2010
            ignore (saveas_m#connect#activate saveas_f);
 
2011
            
 
2012
            (* File/Save All Menu *)
 
2013
            let saveall_m = file_factory#add_item "Sa_ve all" in
 
2014
            let saveall_f () = 
 
2015
              Vector.iter
 
2016
                (function 
 
2017
                   | {view = view ; analyzed_view = Some av} -> 
 
2018
                       begin match av#filename with 
 
2019
                         | None -> ()
 
2020
                         | Some f ->
 
2021
                             ignore (av#save f)
 
2022
                       end
 
2023
                   | _ -> ()
 
2024
                )  input_views
 
2025
            in
 
2026
            let has_something_to_save () = 
 
2027
              Vector.exists
 
2028
                (function 
 
2029
                   | {view=view} -> view#buffer#modified        
 
2030
                )
 
2031
                input_views
 
2032
            in
 
2033
              ignore (saveall_m#connect#activate saveall_f);
 
2034
              
 
2035
              (* File/Revert Menu *)
 
2036
              let revert_m = file_factory#add_item "_Revert all buffers" in
 
2037
              let revert_f () = 
 
2038
                Vector.iter 
 
2039
                  (function 
 
2040
                       {view = view ; analyzed_view = Some av} -> 
 
2041
                         (try 
 
2042
                              match av#filename,av#stats with 
 
2043
                                | Some f,Some stats -> 
 
2044
                                    let new_stats = Unix.stat f in
 
2045
                                      if new_stats.Unix.st_mtime > stats.Unix.st_mtime 
 
2046
                                      then av#revert
 
2047
                                | Some _, None -> av#revert
 
2048
                                | _ -> ()
 
2049
                          with _ -> av#revert)
 
2050
                     | _ -> ()
 
2051
                  )  input_views
 
2052
              in
 
2053
                ignore (revert_m#connect#activate revert_f);
 
2054
                
 
2055
                (* File/Close Menu *)
 
2056
                let close_m =
 
2057
                  file_factory#add_item "_Close buffer" ~key:GdkKeysyms._W in
 
2058
                let close_f () = 
 
2059
                  let v = Option.get !active_view in
 
2060
                  let act = get_current_view_page () in
 
2061
                    if v = act then !flash_info "Cannot close an active view"
 
2062
                    else remove_current_view_page ()
 
2063
                in
 
2064
                  ignore (close_m#connect#activate close_f);
 
2065
                  
 
2066
                  (* File/Print Menu *)
 
2067
                  let print_f () =
 
2068
                    let v = get_current_view () in
 
2069
                    let av = Option.get v.analyzed_view in
 
2070
                      match av#filename with
 
2071
                        | None -> 
 
2072
                            !flash_info "Cannot print: this buffer has no name"
 
2073
                        | Some f ->
 
2074
                            let cmd = 
 
2075
                              "cd " ^ Filename.quote (Filename.dirname f) ^ "; " ^
 
2076
                                !current.cmd_coqdoc ^ " -ps " ^ Filename.quote (Filename.basename f) ^ 
 
2077
                                " | " ^ !current.cmd_print
 
2078
                            in
 
2079
                            let print_window = GWindow.window
 
2080
                              ~title:"Print" 
 
2081
                              ~modal:true 
 
2082
                              ~position:`CENTER
 
2083
                              ~wm_class:"CodIDE" 
 
2084
                              ~wm_name: "CodIDE"  () in
 
2085
                            let vbox_print = GPack.vbox  
 
2086
                              ~spacing:10 
 
2087
                              ~border_width:10 
 
2088
                              ~packing:print_window#add () in
 
2089
                            let _ = GMisc.label 
 
2090
                              ~justify:`LEFT
 
2091
                              ~text:"Print using the following command:" 
 
2092
                              ~packing:vbox_print#add () in
 
2093
                            let print_entry = GEdit.entry 
 
2094
                              ~text:cmd
 
2095
                              ~editable:true
 
2096
                              ~width_chars:80
 
2097
                              ~packing:vbox_print#add () in 
 
2098
                            let hbox_print = GPack.hbox 
 
2099
                              ~spacing:10 
 
2100
                              ~packing:vbox_print#add () in 
 
2101
                            let print_cancel_button = GButton.button ~stock:`CANCEL ~label:"Cancel" ~packing:hbox_print#add () in
 
2102
                            let print_button  = GButton.button ~stock:`PRINT  ~label:"Print"  ~packing:hbox_print#add () in
 
2103
                            let callback_print () = 
 
2104
                              let cmd = print_entry#text in
 
2105
                              let s,_ = run_command av#insert_message cmd in
 
2106
                                !flash_info (cmd ^ if s = Unix.WEXITED 0 then " succeeded" else " failed");
 
2107
                                print_window#destroy ()
 
2108
                            in
 
2109
                              ignore (print_cancel_button#connect#clicked ~callback:print_window#destroy) ;
 
2110
                              ignore (print_button#connect#clicked ~callback:callback_print);
 
2111
                              print_window#misc#show();
 
2112
                  in
 
2113
                  let _ = file_factory#add_item "_Print..."
 
2114
                    ~key:GdkKeysyms._P
 
2115
                    ~callback:print_f in
 
2116
 
 
2117
                  (* File/Export to Menu *)
 
2118
                  let export_f kind () =
 
2119
                    let v = get_current_view () in
 
2120
                    let av = Option.get v.analyzed_view in
 
2121
                      match av#filename with
 
2122
                        | None -> 
 
2123
                            !flash_info "Cannot print: this buffer has no name"
 
2124
                        | Some f ->
 
2125
                            let basef = Filename.basename f in
 
2126
                            let output = 
 
2127
                              let basef_we = try Filename.chop_extension basef with _ -> basef in
 
2128
                                match kind with
 
2129
                                  | "latex" -> basef_we ^ ".tex"
 
2130
                                  | "dvi" | "ps" | "pdf" | "html" -> basef_we ^ "." ^ kind
 
2131
                                  | _ -> assert false
 
2132
                            in
 
2133
                            let cmd = 
 
2134
                              "cd " ^ Filename.quote (Filename.dirname f) ^ "; " ^
 
2135
                                !current.cmd_coqdoc ^ " --" ^ kind ^ " -o " ^ (Filename.quote output) ^ " " ^ (Filename.quote basef)
 
2136
                            in
 
2137
                            let s,_ = run_command av#insert_message cmd in
 
2138
                              !flash_info (cmd ^ 
 
2139
                                             if s = Unix.WEXITED 0 
 
2140
                                             then " succeeded" 
 
2141
                                             else " failed")
 
2142
                  in
 
2143
                  let file_export_m =  file_factory#add_submenu "E_xport to" in
 
2144
 
 
2145
                  let file_export_factory = new GMenu.factory ~accel_path:"<CoqIde MenuBar>/Export/" file_export_m ~accel_group in
 
2146
                  let _ = 
 
2147
                    file_export_factory#add_item "_Html" ~callback:(export_f "html") 
 
2148
                  in
 
2149
                  let _ = 
 
2150
                    file_export_factory#add_item "_LaTeX" ~callback:(export_f "latex")
 
2151
                  in
 
2152
                  let _ = 
 
2153
                    file_export_factory#add_item "_Dvi" ~callback:(export_f "dvi") 
 
2154
                  in
 
2155
                  let _ = 
 
2156
                    file_export_factory#add_item "_Pdf" ~callback:(export_f "pdf") 
 
2157
                  in
 
2158
                  let _ = 
 
2159
                    file_export_factory#add_item "_Ps" ~callback:(export_f "ps") 
 
2160
                  in
 
2161
 
 
2162
                  (* File/Rehighlight Menu *)
 
2163
                  let rehighlight_m = file_factory#add_item "Reh_ighlight" ~key:GdkKeysyms._L in
 
2164
                    ignore (rehighlight_m#connect#activate 
 
2165
                              (fun () -> 
 
2166
                                 Highlight.highlight_all 
 
2167
                                   (get_current_view()).view#buffer;
 
2168
                                 (Option.get (get_current_view()).analyzed_view)#recenter_insert));
 
2169
 
 
2170
                    (* File/Quit Menu *)
 
2171
                    let quit_f () =
 
2172
                      save_pref();
 
2173
                      if has_something_to_save () then 
 
2174
                        match (GToolbox.question_box ~title:"Quit"
 
2175
                                 ~buttons:["Save Named Buffers and Quit";
 
2176
                                           "Quit without Saving";
 
2177
                                           "Don't Quit"] 
 
2178
                                 ~default:0
 
2179
                                 ~icon:
 
2180
                                 (let img = GMisc.image () in
 
2181
                                    img#set_stock `DIALOG_WARNING;
 
2182
                                    img#set_icon_size `DIALOG;
 
2183
                                    img#coerce)
 
2184
                                 "There are unsaved buffers"
 
2185
                              )
 
2186
                        with 1 -> saveall_f () ; exit 0
 
2187
                          | 2 -> exit 0
 
2188
                          | _ -> ()
 
2189
                      else exit 0
 
2190
                    in
 
2191
                    let _ = file_factory#add_item "_Quit" ~key:GdkKeysyms._Q 
 
2192
                      ~callback:quit_f
 
2193
                    in
 
2194
                      ignore (w#event#connect#delete (fun _ -> quit_f (); true));
 
2195
 
 
2196
                      (* Edit Menu *)
 
2197
                      let edit_menu = factory#add_submenu "_Edit" in
 
2198
                      let edit_f = new GMenu.factory ~accel_path:"<CoqIde MenuBar>/Edit/" edit_menu ~accel_group in
 
2199
                        ignore(edit_f#add_item "_Undo" ~key:GdkKeysyms._u ~callback:
 
2200
                                 (do_if_not_computing "undo"
 
2201
                                    (fun () -> 
 
2202
                                       ignore ((Option.get ((get_current_view()).analyzed_view))#
 
2203
                                                 without_auto_complete 
 
2204
                                                 (fun () -> (get_current_view()).view#undo) ()))));
 
2205
                        ignore(edit_f#add_item "_Clear Undo Stack" 
 
2206
                                 (* ~key:GdkKeysyms._exclam *)
 
2207
                                 ~callback:
 
2208
                                 (fun () -> 
 
2209
                                    ignore (get_current_view()).view#clear_undo));
 
2210
                        ignore(edit_f#add_separator ());
 
2211
                        ignore(edit_f#add_item "Cut" ~key:GdkKeysyms._X ~callback:
 
2212
                                 (fun () -> GtkSignal.emit_unit
 
2213
                                    (get_current_view()).view#as_view 
 
2214
                                    GtkText.View.S.cut_clipboard));
 
2215
                        ignore(edit_f#add_item "Copy" ~key:GdkKeysyms._C ~callback:
 
2216
                                 (fun () -> GtkSignal.emit_unit
 
2217
                                    (get_current_view()).view#as_view 
 
2218
                                    GtkText.View.S.copy_clipboard));
 
2219
                        ignore(edit_f#add_item "Paste" ~key:GdkKeysyms._V ~callback:
 
2220
                                 (fun () -> 
 
2221
                                    try GtkSignal.emit_unit
 
2222
                                      (get_current_view()).view#as_view 
 
2223
                                      GtkText.View.S.paste_clipboard
 
2224
                                    with _ -> prerr_endline "EMIT PASTE FAILED"));
 
2225
                        ignore (edit_f#add_separator ());
 
2226
 
 
2227
 
 
2228
                        (*
 
2229
                          let toggle_auto_complete_i = 
 
2230
                          edit_f#add_check_item "_Auto Completion" 
 
2231
                          ~active:!current.auto_complete
 
2232
                          ~callback:
 
2233
                          in
 
2234
                        *)
 
2235
                        (*
 
2236
                          auto_complete := 
 
2237
                          (fun b -> match (get_current_view()).analyzed_view with
 
2238
                          | Some av -> av#set_auto_complete b
 
2239
                          | None -> ());
 
2240
                        *)
 
2241
 
 
2242
                        let last_found = ref None in
 
2243
                        let search_backward = ref false in
 
2244
                        let find_w = GWindow.window 
 
2245
                          (* ~wm_class:"CoqIde" ~wm_name:"CoqIde" *)
 
2246
                          (* ~allow_grow:true ~allow_shrink:true *)
 
2247
                          (* ~width:!current.window_width ~height:!current.window_height *)
 
2248
                          ~position:`CENTER
 
2249
                          ~title:"CoqIde search/replace" ()
 
2250
                        in
 
2251
                        let find_box = GPack.table
 
2252
                          ~columns:3 ~rows:5
 
2253
                          ~col_spacings:10 ~row_spacings:10 ~border_width:10
 
2254
                          ~homogeneous:false ~packing:find_w#add () in
 
2255
                          
 
2256
                        let _ = 
 
2257
                          GMisc.label ~text:"Find:"
 
2258
                            ~xalign:1.0
 
2259
                            ~packing:(find_box#attach ~left:0 ~top:0 ~fill:`X) () 
 
2260
                        in
 
2261
                        let find_entry = GEdit.entry
 
2262
                          ~editable: true
 
2263
                          ~packing: (find_box#attach ~left:1 ~top:0 ~expand:`X)
 
2264
                          ()
 
2265
                        in
 
2266
                        let _ = 
 
2267
                          GMisc.label ~text:"Replace with:"
 
2268
                            ~xalign:1.0
 
2269
                            ~packing:(find_box#attach ~left:0 ~top:1 ~fill:`X) () 
 
2270
                        in
 
2271
                        let replace_entry = GEdit.entry
 
2272
                          ~editable: true
 
2273
                          ~packing: (find_box#attach ~left:1 ~top:1 ~expand:`X)
 
2274
                          ()
 
2275
                        in
 
2276
                        (* let _ = 
 
2277
                          GButton.check_button
 
2278
                            ~label:"case sensitive"
 
2279
                            ~active:true
 
2280
                            ~packing: (find_box#attach ~left:1 ~top:2)
 
2281
                            ()
 
2282
                        
 
2283
                        in
 
2284
                        *)
 
2285
                          (*
 
2286
                            let find_backwards_check = 
 
2287
                            GButton.check_button
 
2288
                            ~label:"search backwards"
 
2289
                            ~active:false
 
2290
                            ~packing: (find_box#attach ~left:1 ~top:3)
 
2291
                            ()
 
2292
                            in
 
2293
                          *)
 
2294
                        let close_find_button =
 
2295
                          GButton.button
 
2296
                            ~label:"Close"
 
2297
                            ~packing: (find_box#attach ~left:2 ~top:0)
 
2298
                            ()
 
2299
                        in
 
2300
                        let replace_button =
 
2301
                          GButton.button
 
2302
                            ~label:"Replace"
 
2303
                            ~packing: (find_box#attach ~left:2 ~top:1)
 
2304
                            ()
 
2305
                        in
 
2306
                        let replace_find_button =
 
2307
                          GButton.button
 
2308
                            ~label:"Replace and find"
 
2309
                            ~packing: (find_box#attach ~left:2 ~top:2)
 
2310
                            ()
 
2311
                        in
 
2312
                        let find_again_button =
 
2313
                          GButton.button
 
2314
                            ~label:"_Find again"
 
2315
                            ~packing: (find_box#attach ~left:2 ~top:3)
 
2316
                            ()
 
2317
                        in
 
2318
                        let find_again_backward_button =
 
2319
                          GButton.button
 
2320
                            ~label:"Find _backward"
 
2321
                            ~packing: (find_box#attach ~left:2 ~top:4)
 
2322
                            ()
 
2323
                        in
 
2324
                        let last_find () =
 
2325
                          let v = (get_current_view()).view in
 
2326
                          let b = v#buffer in
 
2327
                          let start,stop =
 
2328
                            match !last_found with 
 
2329
                              | None -> let i = b#get_iter_at_mark `INSERT in (i,i)
 
2330
                              | Some(start,stop) ->
 
2331
                                  let start = b#get_iter_at_mark start
 
2332
                                  and stop = b#get_iter_at_mark stop
 
2333
                                  in
 
2334
                                    b#remove_tag_by_name ~start ~stop "found";
 
2335
                                    last_found:=None;
 
2336
                                    start,stop
 
2337
                          in
 
2338
                            (v,b,start,stop)
 
2339
                        in
 
2340
                        let do_replace () =
 
2341
                          let v = (get_current_view()).view in
 
2342
                          let b = v#buffer in
 
2343
                            match !last_found with 
 
2344
                              | None -> ()
 
2345
                              | Some(start,stop) ->
 
2346
                                  let start = b#get_iter_at_mark start
 
2347
                                  and stop = b#get_iter_at_mark stop
 
2348
                                  in
 
2349
                                    b#delete ~start ~stop;
 
2350
                                    b#insert ~iter:start replace_entry#text;
 
2351
                                    last_found:=None
 
2352
                        in
 
2353
                        let find_from (v : Undo.undoable_view)
 
2354
                            (b : GText.buffer) (starti : GText.iter) text =
 
2355
                          prerr_endline ("Searching for " ^ text);
 
2356
                          match (if !search_backward then starti#backward_search text
 
2357
                                 else starti#forward_search text)
 
2358
                          with
 
2359
                            | None -> ()
 
2360
                            | Some(start,stop) ->
 
2361
                                b#apply_tag_by_name "found" ~start ~stop;
 
2362
                                let start = `MARK (b#create_mark start)
 
2363
                                and stop = `MARK (b#create_mark stop)
 
2364
                                in
 
2365
                                  v#scroll_to_mark ~use_align:false ~yalign:0.75 ~within_margin:0.25
 
2366
                                    stop;
 
2367
                                  last_found := Some(start,stop)
 
2368
                        in
 
2369
                        let do_find () =
 
2370
                          let (v,b,starti,_) = last_find () in
 
2371
                            find_from v b starti find_entry#text 
 
2372
                        in
 
2373
                        let do_replace_find () =
 
2374
                          do_replace();
 
2375
                          do_find()
 
2376
                        in
 
2377
                        let close_find () =
 
2378
                          let (v,b,_,stop) = last_find () in
 
2379
                            b#place_cursor stop;
 
2380
                            find_w#misc#hide();
 
2381
                            v#coerce#misc#grab_focus()
 
2382
                        in
 
2383
                          to_do_on_page_switch := 
 
2384
                            (fun i -> if find_w#misc#visible then close_find()):: 
 
2385
                              !to_do_on_page_switch;
 
2386
                          let find_again_forward () =
 
2387
                            search_backward := false;
 
2388
                            let (v,b,start,_) = last_find () in
 
2389
                            let start = start#forward_chars 1 in
 
2390
                              find_from v b start find_entry#text
 
2391
                          in
 
2392
                          let find_again_backward () =
 
2393
                            search_backward := true;
 
2394
                            let (v,b,start,_) = last_find () in
 
2395
                            let start = start#backward_chars 1 in
 
2396
                              find_from v b start find_entry#text
 
2397
                          in
 
2398
                          let key_find ev =
 
2399
                            let s = GdkEvent.Key.state ev and k = GdkEvent.Key.keyval ev in
 
2400
                              if k = GdkKeysyms._Escape then
 
2401
                                begin
 
2402
                                  let (v,b,_,stop) = last_find () in
 
2403
                                    find_w#misc#hide();
 
2404
                                    v#coerce#misc#grab_focus();
 
2405
                                    true
 
2406
                                end 
 
2407
                              else if k = GdkKeysyms._Return then
 
2408
                                begin
 
2409
                                  close_find();
 
2410
                                  true
 
2411
                                end 
 
2412
                              else if List.mem `CONTROL s && k = GdkKeysyms._f then
 
2413
                                begin
 
2414
                                  find_again_forward ();
 
2415
                                  true
 
2416
                                end
 
2417
                              else if List.mem `CONTROL s && k = GdkKeysyms._b then
 
2418
                                begin
 
2419
                                  find_again_backward ();
 
2420
                                  true
 
2421
                                end
 
2422
                              else false (* to let default callback execute *)
 
2423
                          in
 
2424
                          let find_f ~backward () = 
 
2425
                            search_backward := backward;
 
2426
                            find_w#show ();
 
2427
                            find_w#present ();
 
2428
                            find_entry#misc#grab_focus ()
 
2429
                          in
 
2430
                          let _ = edit_f#add_item "_Find in buffer"
 
2431
                            ~key:GdkKeysyms._F
 
2432
                            ~callback:(find_f ~backward:false)
 
2433
                          in
 
2434
                          let _ = edit_f#add_item "Find _backwards"
 
2435
                            ~key:GdkKeysyms._B
 
2436
                            ~callback:(find_f ~backward:true)
 
2437
                          in
 
2438
                          let _ = close_find_button#connect#clicked close_find in
 
2439
                          let _ = replace_button#connect#clicked do_replace in
 
2440
                          let _ = replace_find_button#connect#clicked do_replace_find in
 
2441
                          let _ = find_again_button#connect#clicked find_again_forward in
 
2442
                          let _ = find_again_backward_button#connect#clicked find_again_backward in
 
2443
                          let _ = find_entry#connect#changed do_find in
 
2444
                          let _ = find_entry#event#connect#key_press ~callback:key_find in
 
2445
                          let _ = find_w#event#connect#delete (fun _ -> find_w#misc#hide(); true) in
 
2446
                            (*
 
2447
                              let search_if = edit_f#add_item "Search _forward"
 
2448
                              ~key:GdkKeysyms._greater
 
2449
                              in
 
2450
                              let search_ib = edit_f#add_item "Search _backward"
 
2451
                              ~key:GdkKeysyms._less
 
2452
                              in
 
2453
                            *)
 
2454
                            (*
 
2455
                              let complete_i = edit_f#add_item "_Complete"
 
2456
                              ~key:GdkKeysyms._comma
 
2457
                              ~callback:
 
2458
                              (do_if_not_computing 
 
2459
                              (fun b -> 
 
2460
                              let v = Option.get (get_current_view ()).analyzed_view 
 
2461
                              
 
2462
                              in v#complete_at_offset 
 
2463
                              ((v#view#buffer#get_iter `SEL_BOUND)#offset)
 
2464
                              ))
 
2465
                              in
 
2466
                              complete_i#misc#set_state `INSENSITIVE;
 
2467
                            *)
 
2468
                            
 
2469
                            ignore(edit_f#add_item "Complete Word" ~key:GdkKeysyms._slash ~callback:
 
2470
                                     (fun () -> 
 
2471
                                        ignore (
 
2472
                                                 let av = Option.get ((get_current_view()).analyzed_view) in 
 
2473
                                                   av#complete_at_offset (av#get_insert)#offset
 
2474
                                               )));
 
2475
 
 
2476
                            ignore(edit_f#add_separator ());
 
2477
                            (* external editor *)
 
2478
                            let _ = 
 
2479
                              edit_f#add_item "External editor" ~callback:
 
2480
                                (fun () ->       
 
2481
                                   let av = Option.get ((get_current_view()).analyzed_view) in 
 
2482
                                     match av#filename with
 
2483
                                       | None -> warning "Call to external editor available only on named files"
 
2484
                                       | Some f ->
 
2485
                                           save_f ();
 
2486
                                           let com = Flags.subst_command_placeholder !current.cmd_editor (Filename.quote f) in
 
2487
                                           let _ = run_command av#insert_message com in
 
2488
                                             av#revert)
 
2489
                            in
 
2490
                            let _ = edit_f#add_separator () in
 
2491
                              (* Preferences *)
 
2492
                            let reset_revert_timer () =
 
2493
                              disconnect_revert_timer ();
 
2494
                              if !current.global_auto_revert then 
 
2495
                                revert_timer := Some
 
2496
                                  (GMain.Timeout.add ~ms:!current.global_auto_revert_delay 
 
2497
                                     ~callback:
 
2498
                                     (fun () -> 
 
2499
                                        do_if_not_computing "revert" (sync revert_f) ();
 
2500
                                        true))
 
2501
                            in reset_revert_timer (); (* to enable statup preferences timer *)
 
2502
 
 
2503
                              let auto_save_f () = 
 
2504
                                Vector.iter 
 
2505
                                  (function 
 
2506
                                       {view = view ; analyzed_view = Some av} -> 
 
2507
                                         (try 
 
2508
                                              av#auto_save
 
2509
                                          with _ -> ())
 
2510
                                     | _ -> ()
 
2511
                                  )  
 
2512
                                  input_views
 
2513
                              in
 
2514
 
 
2515
                              let reset_auto_save_timer () =
 
2516
                                disconnect_auto_save_timer ();
 
2517
                                if !current.auto_save then 
 
2518
                                  auto_save_timer := Some
 
2519
                                    (GMain.Timeout.add ~ms:!current.auto_save_delay 
 
2520
                                       ~callback:
 
2521
                                       (fun () -> 
 
2522
                                          do_if_not_computing "autosave" (sync auto_save_f) ();
 
2523
                                          true))
 
2524
                              in reset_auto_save_timer (); (* to enable statup preferences timer *)
 
2525
 
 
2526
 
 
2527
                                let _ =
 
2528
                                  edit_f#add_item "_Preferences"
 
2529
                                    ~callback:(fun () -> configure ~apply:update_notebook_pos (); reset_revert_timer ())
 
2530
                                in
 
2531
                                  (*
 
2532
                                    let save_prefs_m =
 
2533
                                    configuration_factory#add_item "_Save preferences"
 
2534
                                    ~callback:(fun () -> save_pref ())
 
2535
                                    in
 
2536
                                  *)
 
2537
                                  (* Navigation Menu *)
 
2538
                                let navigation_menu =  factory#add_submenu "_Navigation" in
 
2539
                                let navigation_factory = 
 
2540
                                  new GMenu.factory navigation_menu 
 
2541
                                    ~accel_path:"<CoqIde MenuBar>/Navigation/"
 
2542
                                    ~accel_group 
 
2543
                                    ~accel_modi:!current.modifier_for_navigation 
 
2544
                                in
 
2545
                                let do_or_activate f () = 
 
2546
                                  let current = get_current_view () in
 
2547
                                  let analyzed_view = Option.get current.analyzed_view in
 
2548
                                    if analyzed_view#is_active then 
 
2549
                                      ignore (f analyzed_view)
 
2550
                                    else
 
2551
                                      begin
 
2552
                                        !flash_info "New proof started";
 
2553
                                        activate_input (notebook ())#current_page;
 
2554
                                        ignore (f analyzed_view)
 
2555
                                      end
 
2556
                                in
 
2557
 
 
2558
                                let do_or_activate f = 
 
2559
                                  do_if_not_computing "do_or_activate"
 
2560
                                    (do_or_activate
 
2561
                                       (fun av -> f av ; !pop_info();!push_info (Coq.current_status())))
 
2562
                                in
 
2563
 
 
2564
                                let add_to_menu_toolbar text ~tooltip ?key ~callback icon = 
 
2565
                                  begin
 
2566
                                    match key with None -> () 
 
2567
                                      | Some key -> ignore (navigation_factory#add_item text ~key ~callback)
 
2568
                                  end;
 
2569
                                  ignore (toolbar#insert_button
 
2570
                                            ~tooltip
 
2571
(*                                          ~text:tooltip*)
 
2572
                                            ~icon:(stock_to_widget ~size:`LARGE_TOOLBAR icon)
 
2573
                                            ~callback
 
2574
                                            ())
 
2575
                                in
 
2576
                                  add_to_menu_toolbar 
 
2577
                                    "_Save" 
 
2578
                                    ~tooltip:"Save current buffer" 
 
2579
                                    ~callback:save_f
 
2580
                                    `SAVE;
 
2581
                                  add_to_menu_toolbar 
 
2582
                                    "_Close" 
 
2583
                                    ~tooltip:"Close current buffer" 
 
2584
                                    ~callback:close_f
 
2585
                                    `CLOSE;
 
2586
                                  add_to_menu_toolbar 
 
2587
                                    "_Forward" 
 
2588
                                    ~tooltip:"Forward one command" 
 
2589
                                    ~key:GdkKeysyms._Down 
 
2590
                                    ~callback:(do_or_activate (fun a -> a#process_next_phrase true true true))
 
2591
                                    `GO_DOWN;
 
2592
                                  add_to_menu_toolbar "_Backward"
 
2593
                                    ~tooltip:"Backward one command" 
 
2594
                                    ~key:GdkKeysyms._Up
 
2595
                                    ~callback:(do_or_activate (fun a -> a#undo_last_step))
 
2596
                                    `GO_UP;
 
2597
                                  add_to_menu_toolbar 
 
2598
                                    "_Go to" 
 
2599
                                    ~tooltip:"Go to cursor" 
 
2600
                                    ~key:GdkKeysyms._Right
 
2601
                                    ~callback:(do_or_activate (fun a-> a#go_to_insert))
 
2602
                                    `JUMP_TO;
 
2603
                                  add_to_menu_toolbar 
 
2604
                                    "_Start" 
 
2605
                                    ~tooltip:"Go to start" 
 
2606
                                    ~key:GdkKeysyms._Home
 
2607
                                    ~callback:(do_or_activate (fun a -> a#reset_initial))
 
2608
                                    `GOTO_TOP;
 
2609
                                  add_to_menu_toolbar 
 
2610
                                    "_End" 
 
2611
                                    ~tooltip:"Go to end" 
 
2612
                                    ~key:GdkKeysyms._End
 
2613
                                    ~callback:(do_or_activate (fun a -> a#process_until_end_or_error))
 
2614
                                    `GOTO_BOTTOM;
 
2615
                                  add_to_menu_toolbar "_Interrupt"
 
2616
                                    ~tooltip:"Interrupt computations"    
 
2617
                                    ~key:GdkKeysyms._Break 
 
2618
                                    ~callback:break
 
2619
                                    `STOP;
 
2620
 
 
2621
                                  (* Tactics Menu *)
 
2622
                                  let tactics_menu =  factory#add_submenu "_Try Tactics" in
 
2623
                                  let tactics_factory = 
 
2624
                                    new GMenu.factory tactics_menu 
 
2625
                                      ~accel_path:"<CoqIde MenuBar>/Tactics/"
 
2626
                                      ~accel_group 
 
2627
                                      ~accel_modi:!current.modifier_for_tactics
 
2628
                                  in
 
2629
                                  let do_if_active_raw f () = 
 
2630
                                    let current = get_current_view () in
 
2631
                                    let analyzed_view = Option.get current.analyzed_view in
 
2632
                                      if analyzed_view#is_active then ignore (f analyzed_view)
 
2633
                                  in
 
2634
                                  let do_if_active f =
 
2635
                                    do_if_not_computing "do_if_active" (do_if_active_raw f) in
 
2636
 
 
2637
                                    (*
 
2638
                                      let blaster_i = 
 
2639
                                      tactics_factory#add_item "_Blaster"
 
2640
                                      ~key:GdkKeysyms._b
 
2641
                                      ~callback: (do_if_active_raw (fun a -> a#blaster ()))
 
2642
                                    (* Custom locking mechanism! *)
 
2643
                                      in
 
2644
                                      blaster_i#misc#set_state `INSENSITIVE;
 
2645
                                    *)
 
2646
                                    
 
2647
                                    ignore (tactics_factory#add_item "_auto" 
 
2648
                                              ~key:GdkKeysyms._a
 
2649
                                              ~callback:(do_if_active (fun a -> a#insert_command "progress auto.\n" "auto.\n"))
 
2650
                                           );
 
2651
                                    ignore (tactics_factory#add_item "_auto with *"
 
2652
                                              ~key:GdkKeysyms._asterisk
 
2653
                                              ~callback:(do_if_active (fun a -> a#insert_command 
 
2654
                                                                         "progress auto with *.\n"
 
2655
                                                                         "auto with *.\n")));
 
2656
                                    ignore (tactics_factory#add_item "_eauto"
 
2657
                                              ~key:GdkKeysyms._e
 
2658
                                              ~callback:(do_if_active (fun a -> a#insert_command 
 
2659
                                                                         "progress eauto.\n"
 
2660
                                                                         "eauto.\n"))
 
2661
                                           );
 
2662
                                    ignore (tactics_factory#add_item "_eauto with *"
 
2663
                                              ~key:GdkKeysyms._ampersand
 
2664
                                              ~callback:(do_if_active (fun a -> a#insert_command 
 
2665
                                                                         "progress eauto with *.\n" 
 
2666
                                                                         "eauto with *.\n"))
 
2667
                                           );
 
2668
                                    ignore (tactics_factory#add_item "_intuition"
 
2669
                                              ~key:GdkKeysyms._i
 
2670
                                              ~callback:(do_if_active (fun a -> a#insert_command 
 
2671
                                                                         "progress intuition.\n" 
 
2672
                                                                         "intuition.\n"))
 
2673
                                           );
 
2674
                                    ignore (tactics_factory#add_item "_omega"
 
2675
                                              ~key:GdkKeysyms._o
 
2676
                                              ~callback:(do_if_active (fun a -> a#insert_command 
 
2677
                                                                         "omega.\n" "omega.\n"))
 
2678
                                           );
 
2679
                                    ignore (tactics_factory#add_item "_simpl"
 
2680
                                              ~key:GdkKeysyms._s
 
2681
                                              ~callback:(do_if_active (fun a -> a#insert_command "progress simpl.\n" "simpl.\n" ))
 
2682
                                           );
 
2683
                                    ignore (tactics_factory#add_item "_tauto"
 
2684
                                              ~key:GdkKeysyms._p
 
2685
                                              ~callback:(do_if_active (fun a -> a#insert_command "tauto.\n" "tauto.\n" ))
 
2686
                                           );
 
2687
                                    ignore (tactics_factory#add_item "_trivial"
 
2688
                                              ~key:GdkKeysyms._v
 
2689
                                              ~callback:(do_if_active( fun a -> a#insert_command "progress trivial.\n"  "trivial.\n" ))
 
2690
                                           );
 
2691
 
 
2692
 
 
2693
                                    ignore (toolbar#insert_button
 
2694
                                              ~tooltip:"Proof Wizard"
 
2695
                                              ~text:"Wizard"
 
2696
                                              ~icon:(stock_to_widget ~size:`LARGE_TOOLBAR `DIALOG_INFO)
 
2697
                                              ~callback:(do_if_active (fun a -> a#tactic_wizard
 
2698
                                                                         !current.automatic_tactics
 
2699
                                                                      ))
 
2700
                                              ());
 
2701
 
 
2702
 
 
2703
 
 
2704
                                    ignore (tactics_factory#add_item "<Proof _Wizard>"
 
2705
                                              ~key:GdkKeysyms._dollar
 
2706
                                              ~callback:(do_if_active (fun a -> a#tactic_wizard 
 
2707
                                                                         !current.automatic_tactics
 
2708
                                                                      ))
 
2709
                                           );
 
2710
                                    
 
2711
                                    ignore (tactics_factory#add_separator ());
 
2712
                                    let add_simple_template (factory: GMenu.menu GMenu.factory) 
 
2713
                                        (menu_text, text) =
 
2714
                                      let text = 
 
2715
                                        let l = String.length text - 1 in
 
2716
                                          if String.get text l = '.'
 
2717
                                          then text ^"\n"
 
2718
                                          else text ^" "
 
2719
                                      in
 
2720
                                        ignore (factory#add_item menu_text
 
2721
                                                  ~callback:
 
2722
                                                  (fun () -> let {view = view } = get_current_view () in
 
2723
                                                               ignore (view#buffer#insert_interactive text)))
 
2724
                                    in
 
2725
                                      List.iter 
 
2726
                                        (fun l -> 
 
2727
                                           match l with 
 
2728
                                             | [] -> ()
 
2729
                                             | [s] -> add_simple_template tactics_factory ("_"^s, s) 
 
2730
                                             | s::_ -> 
 
2731
                                                 let a = "_@..." in
 
2732
                                                   a.[1] <- s.[0];
 
2733
                                                   let f = tactics_factory#add_submenu a in 
 
2734
                                                   let ff = new GMenu.factory f ~accel_group in
 
2735
                                                     List.iter 
 
2736
                                                       (fun x -> 
 
2737
                                                          add_simple_template
 
2738
                                                            ff 
 
2739
                                                            ((String.sub x 0 1)^
 
2740
                                                               "_"^
 
2741
                                                               (String.sub x 1 (String.length x - 1)),
 
2742
                                                             x))
 
2743
                                                       l
 
2744
                                        ) 
 
2745
                                        Coq_commands.tactics;
 
2746
                                      
 
2747
                                      (* Templates Menu *)
 
2748
                                      let templates_menu =  factory#add_submenu "Te_mplates" in
 
2749
                                      let templates_factory = new GMenu.factory templates_menu 
 
2750
                                        ~accel_path:"<CoqIde MenuBar>/Templates/"
 
2751
                                        ~accel_group 
 
2752
                                        ~accel_modi:!current.modifier_for_templates
 
2753
                                      in
 
2754
                                      let add_complex_template (menu_text, text, offset, len, key) =
 
2755
                                        (* Templates/Lemma *)
 
2756
                                        let callback () =
 
2757
                                          let {view = view } = get_current_view () in
 
2758
                                            if view#buffer#insert_interactive text then begin
 
2759
                                                let iter = view#buffer#get_iter_at_mark `INSERT in
 
2760
                                                  ignore (iter#nocopy#backward_chars offset);
 
2761
                                                  view#buffer#move_mark `INSERT iter;
 
2762
                                                  ignore (iter#nocopy#backward_chars len);
 
2763
                                                  view#buffer#move_mark `SEL_BOUND iter;
 
2764
                                              end in
 
2765
                                          ignore (templates_factory#add_item menu_text ~callback ?key)
 
2766
                                      in
 
2767
                                        add_complex_template 
 
2768
                                          ("_Lemma __", "Lemma new_lemma : .\nProof.\n\nSave.\n", 
 
2769
                                           19, 9, Some GdkKeysyms._L);
 
2770
                                        add_complex_template 
 
2771
                                          ("_Theorem __", "Theorem new_theorem : .\nProof.\n\nSave.\n", 
 
2772
                                           19, 11, Some GdkKeysyms._T);
 
2773
                                        add_complex_template 
 
2774
                                          ("_Definition __", "Definition ident := .\n",
 
2775
                                           6, 5, Some GdkKeysyms._D);
 
2776
                                        add_complex_template 
 
2777
                                          ("_Inductive __", "Inductive ident : :=\n  | : .\n",
 
2778
                                           14, 5, Some GdkKeysyms._I);
 
2779
                                        add_complex_template 
 
2780
                                          ("_Fixpoint __", "Fixpoint ident (_ : _) {struct _} : _ :=\n.\n",
 
2781
                                           29, 5, Some GdkKeysyms._F);
 
2782
                                        add_complex_template("_Scheme __",
 
2783
                                                             "Scheme new_scheme := Induction for _ Sort _
 
2784
with _ := Induction for _ Sort _.\n",61,10, Some GdkKeysyms._S);
 
2785
 
 
2786
                                        (* Template for match *)
 
2787
                                        let callback () = 
 
2788
                                          let w = get_current_word () in
 
2789
                                            try 
 
2790
                                              let cases = Coq.make_cases w
 
2791
                                              in
 
2792
                                              let print c = function
 
2793
                                                | [x] -> Format.fprintf c "  | %s => _@\n" x
 
2794
                                                | x::l -> Format.fprintf c "  | (%s%a) => _@\n" x 
 
2795
                                                    (print_list (fun c s -> Format.fprintf c " %s" s)) l
 
2796
                                                | [] -> assert false
 
2797
                                              in
 
2798
                                              let b = Buffer.create 1024 in
 
2799
                                              let fmt = Format.formatter_of_buffer b in
 
2800
                                                Format.fprintf fmt "@[match var with@\n%aend@]@."
 
2801
                                                  (print_list print) cases;
 
2802
                                                let s = Buffer.contents b in
 
2803
                                                  prerr_endline s;
 
2804
                                                  let {view = view } = get_current_view () in
 
2805
                                                    ignore (view#buffer#delete_selection ());
 
2806
                                                    let m = view#buffer#create_mark 
 
2807
                                                      (view#buffer#get_iter `INSERT)
 
2808
                                                    in
 
2809
                                                      if view#buffer#insert_interactive s then 
 
2810
                                                        let i = view#buffer#get_iter (`MARK m) in
 
2811
                                                        let _ = i#nocopy#forward_chars 9 in
 
2812
                                                          view#buffer#place_cursor i;
 
2813
                                                          view#buffer#move_mark ~where:(i#backward_chars 3)
 
2814
                                                            `SEL_BOUND 
 
2815
                                            with Not_found -> !flash_info "Not an inductive type"
 
2816
                                        in
 
2817
                                          ignore (templates_factory#add_item "match ..."
 
2818
                                                    ~key:GdkKeysyms._C
 
2819
                                                    ~callback
 
2820
                                                 );
 
2821
                                          
 
2822
                                          (*
 
2823
                                            let add_simple_template (factory: GMenu.menu GMenu.factory) 
 
2824
                                            (menu_text, text) =
 
2825
                                            let text = 
 
2826
                                            let l = String.length text - 1 in
 
2827
                                            if String.get text l = '.'
 
2828
                                            then text ^"\n"
 
2829
                                            else text ^" "
 
2830
                                            in
 
2831
                                            ignore (factory#add_item menu_text
 
2832
                                            ~callback:
 
2833
                                            (fun () -> let {view = view } = get_current_view () in
 
2834
                                            ignore (view#buffer#insert_interactive text)))
 
2835
                                            in
 
2836
                                          *)
 
2837
                                          ignore (templates_factory#add_separator ());
 
2838
                                          (*
 
2839
                                            List.iter (add_simple_template templates_factory)
 
2840
                                            [ "_auto", "auto ";
 
2841
                                            "_auto with *", "auto with * ";
 
2842
                                            "_eauto", "eauto ";
 
2843
                                            "_eauto with *", "eauto with * ";
 
2844
                                            "_intuition", "intuition ";
 
2845
                                            "_omega", "omega ";
 
2846
                                            "_simpl", "simpl ";
 
2847
                                            "_tauto", "tauto ";
 
2848
                                            "tri_vial", "trivial ";
 
2849
                                            ];
 
2850
                                            ignore (templates_factory#add_separator ());
 
2851
                                          *)
 
2852
                                          List.iter 
 
2853
                                            (fun l -> 
 
2854
                                               match l with 
 
2855
                                                 | [] -> ()
 
2856
                                                 | [s] -> add_simple_template templates_factory ("_"^s, s) 
 
2857
                                                 | s::_ -> 
 
2858
                                                     let a = "_@..." in
 
2859
                                                       a.[1] <- s.[0];
 
2860
                                                       let f = templates_factory#add_submenu a in 
 
2861
                                                       let ff = new GMenu.factory f ~accel_group in
 
2862
                                                         List.iter 
 
2863
                                                           (fun x -> 
 
2864
                                                              add_simple_template 
 
2865
                                                                ff 
 
2866
                                                                ((String.sub x 0 1)^
 
2867
                                                                   "_"^
 
2868
                                                                   (String.sub x 1 (String.length x - 1)),
 
2869
                                                                 x))
 
2870
                                                           l
 
2871
                                            ) 
 
2872
                                            Coq_commands.commands;
 
2873
                                          
 
2874
                                          (* Queries Menu *)
 
2875
                                          let queries_menu =  factory#add_submenu "_Queries" in
 
2876
                                          let queries_factory = new GMenu.factory queries_menu ~accel_group
 
2877
                                            ~accel_path:"<CoqIde MenuBar>/Queries"
 
2878
                                            ~accel_modi:[]
 
2879
                                          in
 
2880
                                            
 
2881
                                          (* Command/Show commands *)
 
2882
                                          let _ = 
 
2883
                                            queries_factory#add_item "_SearchAbout " ~key:GdkKeysyms._F2
 
2884
                                              ~callback:(fun () -> let term = get_current_word () in
 
2885
                                                                     (Command_windows.command_window ())#new_command
 
2886
                                                                       ~command:"SearchAbout"
 
2887
                                                                       ~term 
 
2888
                                                                       ())
 
2889
                                          in
 
2890
                                          let _ = 
 
2891
                                            queries_factory#add_item "_Check " ~key:GdkKeysyms._F3
 
2892
                                              ~callback:(fun () -> let term = get_current_word () in
 
2893
                                                                     (Command_windows.command_window ())#new_command
 
2894
                                                                       ~command:"Check"
 
2895
                                                                       ~term 
 
2896
                                                                       ())
 
2897
                                          in
 
2898
                                          let _ = 
 
2899
                                            queries_factory#add_item "_Print " ~key:GdkKeysyms._F4
 
2900
                                              ~callback:(fun () -> let term = get_current_word () in
 
2901
                                                                     (Command_windows.command_window ())#new_command
 
2902
                                                                       ~command:"Print"
 
2903
                                                                       ~term 
 
2904
                                                                       ())
 
2905
                                          in
 
2906
                                          let _ = 
 
2907
                                            queries_factory#add_item "_Locate" 
 
2908
                                              ~callback:(fun () -> let term = get_current_word () in
 
2909
                                                                     (Command_windows.command_window ())#new_command
 
2910
                                                                       ~command:"Locate"
 
2911
                                                                       ~term 
 
2912
                                                                       ())
 
2913
                                          in
 
2914
                                          let _ = 
 
2915
                                            queries_factory#add_item "_Whelp Locate" 
 
2916
                                              ~callback:(fun () -> let term = get_current_word () in
 
2917
                                                                     (Command_windows.command_window ())#new_command
 
2918
                                                                       ~command:"Whelp Locate"
 
2919
                                                                       ~term 
 
2920
                                                                       ())
 
2921
                                          in
 
2922
 
 
2923
                                          (* Display menu *)
 
2924
                                            
 
2925
                                          let display_menu =  factory#add_submenu "_Display" in
 
2926
                                          let view_factory =  new GMenu.factory display_menu
 
2927
                                            ~accel_path:"<CoqIde MenuBar>/Display/"
 
2928
                                            ~accel_group 
 
2929
                                            ~accel_modi:!current.modifier_for_display
 
2930
                                          in
 
2931
 
 
2932
                                          let _ = ignore (view_factory#add_check_item 
 
2933
                                                            "Display _implicit arguments" 
 
2934
                                                            ~key:GdkKeysyms._i
 
2935
                                                            ~callback:(fun _ -> printing_state.printing_implicit <- not printing_state.printing_implicit; do_or_activate (fun a -> a#show_goals) ())) in
 
2936
 
 
2937
                                          let _ = ignore (view_factory#add_check_item 
 
2938
                                                            "Display _coercions"
 
2939
                                                            ~key:GdkKeysyms._c
 
2940
                                                            ~callback:(fun _ -> printing_state.printing_coercions <- not printing_state.printing_coercions; do_or_activate (fun a -> a#show_goals) ())) in
 
2941
 
 
2942
                                          let _ = ignore (view_factory#add_check_item
 
2943
                                                            "Display raw _matching expressions"
 
2944
                                                            ~key:GdkKeysyms._m
 
2945
                                                            ~callback:(fun _ -> printing_state.printing_raw_matching <- not printing_state.printing_raw_matching; do_or_activate (fun a -> a#show_goals) ())) in
 
2946
 
 
2947
                                          let _ = ignore (view_factory#add_check_item  
 
2948
                                                            "Deactivate _notations display"
 
2949
                                                            ~key:GdkKeysyms._n
 
2950
                                                            ~callback:(fun _ -> printing_state.printing_no_notation <- not printing_state.printing_no_notation; do_or_activate (fun a -> a#show_goals) ())) in
 
2951
 
 
2952
                                          let _ = ignore (view_factory#add_check_item  
 
2953
                                                            "Display _all basic low-level contents"
 
2954
                                                            ~key:GdkKeysyms._a
 
2955
                                                            ~callback:(fun _ -> printing_state.printing_all <- not printing_state.printing_all; do_or_activate (fun a -> a#show_goals) ())) in 
 
2956
 
 
2957
                                          let _ = ignore (view_factory#add_check_item     
 
2958
                                                            "Display _existential variable instances"
 
2959
                                                            ~key:GdkKeysyms._e
 
2960
                                                            ~callback:(fun _ -> printing_state.printing_evar_instances <- not printing_state.printing_evar_instances; do_or_activate (fun a -> a#show_goals) ())) in
 
2961
 
 
2962
                                          let _ = ignore (view_factory#add_check_item  
 
2963
                                                            "Display _universe levels"
 
2964
                                                            ~key:GdkKeysyms._u
 
2965
                                                            ~callback:(fun _ -> printing_state.printing_universes <- not printing_state.printing_universes; do_or_activate (fun a -> a#show_goals) ())) in
 
2966
 
 
2967
                                          let _ = ignore (view_factory#add_check_item  
 
2968
                                                            "Display all _low-level contents"
 
2969
                                                            ~key:GdkKeysyms._l
 
2970
                                                            ~callback:(fun _ -> printing_state.printing_full_all <- not printing_state.printing_full_all; do_or_activate (fun a -> a#show_goals) ())) in 
 
2971
 
 
2972
                                          (* Unicode *)
 
2973
(*
 
2974
                                          let unicode_menu =  factory#add_submenu "_Unicode" in
 
2975
                                          let unicode_factory =  new GMenu.factory unicode_menu
 
2976
                                            ~accel_path:"<CoqIde MenuBar>/Unicode/"
 
2977
                                            ~accel_group 
 
2978
                                            ~accel_modi:[]
 
2979
                                          in
 
2980
                                          let logic_symbols_menu = unicode_factory#add_submenu "Math operators" in
 
2981
                                          let logic_factory = new GMenu.factory logic_symbols_menu
 
2982
                                            ~accel_path:"<CoqIde MenuBar>/Unicode/Math operators"
 
2983
                                            ~accel_group 
 
2984
                                            ~accel_modi:[]
 
2985
                                          in
 
2986
                                          let new_unicode_item s = ignore (
 
2987
                                            logic_factory#add_item s 
 
2988
                                              ~callback:(fun () ->  
 
2989
                                                           let v = get_current_view () in
 
2990
                                                             ignore (v.view#buffer#insert_interactive s)))
 
2991
                                          in
 
2992
                                          
 
2993
                                          for i = 0x2200 to 0x22FF do
 
2994
                                                List.iter new_unicode_item [Glib.Utf8.from_unichar i];
 
2995
                                                 
 
2996
                                          done;                 
 
2997
                                                                                
 
2998
*)                                
 
2999
                                        
 
3000
                                        
 
3001
                                          (* Externals *)
 
3002
                                          let externals_menu =  factory#add_submenu "_Compile" in
 
3003
                                          let externals_factory = new GMenu.factory externals_menu 
 
3004
                                            ~accel_path:"<CoqIde MenuBar>/Compile/"
 
3005
                                            ~accel_group 
 
3006
                                            ~accel_modi:[]
 
3007
                                          in
 
3008
                                            
 
3009
                                          (* Command/Compile Menu *)
 
3010
                                          let compile_f () =
 
3011
                                            let v = get_current_view () in
 
3012
                                            let av = Option.get v.analyzed_view in
 
3013
                                              save_f ();
 
3014
                                              match av#filename with
 
3015
                                                | None -> 
 
3016
                                                    !flash_info "Active buffer has no name"
 
3017
                                                | Some f ->
 
3018
                                                    let cmd = !current.cmd_coqc ^ " -I " 
 
3019
                                                      ^ (Filename.quote (Filename.dirname f))
 
3020
                                                      ^ " " ^ (Filename.quote f) in
 
3021
                                                    let s,res = run_command av#insert_message cmd in
 
3022
                                                      if s = Unix.WEXITED 0 then
 
3023
                                                        !flash_info (f ^ " successfully compiled")
 
3024
                                                      else begin
 
3025
                                                          !flash_info (f ^ " failed to compile");
 
3026
                                                          activate_input (notebook ())#current_page;
 
3027
                                                          av#process_until_end_or_error;
 
3028
                                                          av#insert_message "Compilation output:\n";
 
3029
                                                          av#insert_message res
 
3030
                                                        end
 
3031
                                          in
 
3032
                                          let _ = 
 
3033
                                            externals_factory#add_item "_Compile Buffer" ~callback:compile_f 
 
3034
                                          in
 
3035
 
 
3036
                                          (* Command/Make Menu *)
 
3037
                                          let make_f () =
 
3038
                                            let v = get_current_view () in
 
3039
                                            let av = Option.get v.analyzed_view in
 
3040
                                              match av#filename with
 
3041
                                                | None -> 
 
3042
                                                    !flash_info "Cannot make: this buffer has no name"
 
3043
                                                | Some f ->
 
3044
                                                    let cmd = 
 
3045
                                                      "cd " ^ Filename.quote (Filename.dirname f) ^ "; " ^ !current.cmd_make in
 
3046
 
 
3047
                                                      (*
 
3048
                                                        save_f ();
 
3049
                                                      *)
 
3050
                                                      av#insert_message "Command output:\n";
 
3051
                                                      let s,res = run_command av#insert_message cmd in
 
3052
                                                        last_make := res;
 
3053
                                                        last_make_index := 0;
 
3054
                                                        !flash_info (!current.cmd_make ^ if s = Unix.WEXITED 0 then " succeeded" else " failed")
 
3055
                                          in
 
3056
                                          let _ = externals_factory#add_item "_Make" 
 
3057
                                            ~key:GdkKeysyms._F6
 
3058
                                            ~callback:make_f 
 
3059
                                          in
 
3060
                                            
 
3061
 
 
3062
                                          (* Compile/Next Error *)
 
3063
                                          let next_error () = 
 
3064
                                            try
 
3065
                                              let file,line,start,stop,error_msg = search_next_error () in
 
3066
                                                load file;
 
3067
                                                let v = get_current_view () in
 
3068
                                                let av = Option.get v.analyzed_view in
 
3069
                                                let input_buffer = v.view#buffer in
 
3070
                                                  (*
 
3071
                                                    let init = input_buffer#start_iter in
 
3072
                                                    let i = init#forward_lines (line-1) in
 
3073
                                                  *)
 
3074
                                                  (*
 
3075
                                                    let convert_pos = byte_offset_to_char_offset phrase in
 
3076
                                                    let start = convert_pos start in
 
3077
                                                    let stop = convert_pos stop in
 
3078
                                                  *)
 
3079
                                                  (*
 
3080
                                                    let starti = i#forward_chars start in
 
3081
                                                    let stopi = i#forward_chars stop in
 
3082
                                                  *)
 
3083
                                                let starti = input_buffer#get_iter_at_byte ~line:(line-1) start in
 
3084
                                                let stopi = input_buffer#get_iter_at_byte ~line:(line-1) stop in
 
3085
                                                  input_buffer#apply_tag_by_name "error"
 
3086
                                                    ~start:starti
 
3087
                                                    ~stop:stopi;
 
3088
                                                  input_buffer#place_cursor starti;
 
3089
                                                  av#set_message error_msg;
 
3090
                                                  v.view#misc#grab_focus ()
 
3091
                                            with Not_found ->
 
3092
                                              last_make_index := 0;
 
3093
                                              let v = get_current_view () in
 
3094
                                              let av = Option.get v.analyzed_view in
 
3095
                                                av#set_message "No more errors.\n"
 
3096
                                          in
 
3097
                                          let _ = 
 
3098
                                            externals_factory#add_item "_Next error" 
 
3099
                                              ~key:GdkKeysyms._F7
 
3100
                                              ~callback:next_error in
 
3101
                                            
 
3102
 
 
3103
                                          (* Command/CoqMakefile Menu*)
 
3104
                                          let coq_makefile_f () =
 
3105
                                            let v = get_current_view () in
 
3106
                                            let av = Option.get v.analyzed_view in
 
3107
                                              match av#filename with
 
3108
                                                | None -> 
 
3109
                                                    !flash_info "Cannot make makefile: this buffer has no name"
 
3110
                                                | Some f ->
 
3111
                                                    let cmd = 
 
3112
                                                      "cd " ^ Filename.quote (Filename.dirname f) ^ "; " ^ !current.cmd_coqmakefile in
 
3113
                                                    let s,res = run_command av#insert_message cmd in
 
3114
                                                      !flash_info 
 
3115
                                                        (!current.cmd_coqmakefile ^ if s = Unix.WEXITED 0 then " succeeded" else " failed")
 
3116
                                          in
 
3117
                                          let _ = externals_factory#add_item "_Make makefile" ~callback:coq_makefile_f 
 
3118
                                          in
 
3119
                                            (* Windows Menu *)
 
3120
                                          let configuration_menu = factory#add_submenu "_Windows" in
 
3121
                                          let configuration_factory = new GMenu.factory configuration_menu 
 
3122
                                            ~accel_path:"<CoqIde MenuBar>/Windows"
 
3123
                                            ~accel_modi:[]
 
3124
                                            ~accel_group
 
3125
                                          in
 
3126
                                          let _ =
 
3127
                                            configuration_factory#add_item 
 
3128
                                              "Show/Hide _Query Pane"
 
3129
                                              ~key:GdkKeysyms._Escape
 
3130
                                              ~callback:(fun () -> if (Command_windows.command_window ())#frame#misc#visible then 
 
3131
                                                           (Command_windows.command_window ())#frame#misc#hide ()
 
3132
                                                         else
 
3133
                                                           (Command_windows.command_window ())#frame#misc#show ())
 
3134
                                          in  
 
3135
                                          let _ = 
 
3136
                                            configuration_factory#add_check_item 
 
3137
                                              "Show/Hide _Toolbar"             
 
3138
                                              ~callback:(fun _ ->  
 
3139
                                                           !current.show_toolbar <- not !current.show_toolbar; 
 
3140
                                                           !show_toolbar !current.show_toolbar) 
 
3141
                                          in
 
3142
                                          let _ = configuration_factory#add_item 
 
3143
                                            "Detach _Script Window"
 
3144
                                            ~callback:
 
3145
                                            (do_if_not_computing "detach script window" (sync
 
3146
                                                                                           (fun () -> 
 
3147
                                                                                              let nb = notebook () in
 
3148
                                                                                                if nb#misc#toplevel#get_oid=w#coerce#get_oid then
 
3149
                                                                                                  begin  
 
3150
                                                                                                    let nw = GWindow.window 
 
3151
                                                                                                      ~width:(!current.window_width*2/3)
 
3152
                                                                                                      ~height:(!current.window_height*2/3)
 
3153
                                                                                                      ~position:`CENTER
 
3154
                                                                                                      ~wm_name:"CoqIde"
 
3155
                                                                                                      ~wm_class:"CoqIde"
 
3156
                                                                                                      ~title:"Script" 
 
3157
                                                                                                      ~show:true () in
 
3158
                                                                                                    let parent = Option.get nb#misc#parent in
 
3159
                                                                                                      ignore (nw#connect#destroy 
 
3160
                                                                                                                ~callback:
 
3161
                                                                                                                (fun () -> nb#misc#reparent parent));
 
3162
                                                                                                      nw#add_accel_group accel_group;
 
3163
                                                                                                      nb#misc#reparent nw#coerce
 
3164
                                                                                                  end         
 
3165
                                                                                           )))
 
3166
                                          in
 
3167
(*                                        let _ = configuration_factory#add_item 
 
3168
                                            "Detach _Command Pane"
 
3169
                                            ~callback:
 
3170
                                            (do_if_not_computing "detach command pane" (sync
 
3171
                                                                                           (fun () -> 
 
3172
                                                                                              let command_object = Command_windows.command_window() in
 
3173
                                                                                              let queries_frame = command_object#frame in
 
3174
                                                                                                if queries_frame#misc#toplevel#get_oid=w#coerce#get_oid then
 
3175
                                                                                                  begin  
 
3176
                                                                                                    let nw = GWindow.window 
 
3177
                                                                                                      ~width:(!current.window_width*2/3)
 
3178
                                                                                                      ~height:(!current.window_height*2/3)
 
3179
                                                                                                      ~wm_name:"CoqIde"
 
3180
                                                                                                      ~wm_class:"CoqIde"
 
3181
                                                                                                      ~position:`CENTER 
 
3182
                                                                                                      ~title:"Queries" 
 
3183
                                                                                                      ~show:true () in
 
3184
                                                                                                    let parent = Option.get queries_frame#misc#parent in
 
3185
                                                                                                      ignore (nw#connect#destroy 
 
3186
                                                                                                                ~callback:
 
3187
                                                                                                                (fun () -> queries_frame#misc#reparent parent));
 
3188
                                                                                                      queries_frame#misc#show();
 
3189
                                                                                                      queries_frame#misc#reparent nw#coerce
 
3190
                                                                                                  end         
 
3191
                                                                                           )))
 
3192
                                          in
 
3193
*)
 
3194
                                          let _ = 
 
3195
                                            configuration_factory#add_item 
 
3196
                                              "Detach _View"
 
3197
                                              ~callback:
 
3198
                                              (do_if_not_computing "detach view"
 
3199
                                                 (fun () -> 
 
3200
                                                    match get_current_view () with  
 
3201
                                                      | {view=v;analyzed_view=Some av} -> 
 
3202
                                                          let w = GWindow.window ~show:true 
 
3203
                                                            ~width:(!current.window_width*2/3)
 
3204
                                                            ~height:(!current.window_height*2/3)
 
3205
                                                            ~position:`CENTER
 
3206
                                                            ~title:(match av#filename with
 
3207
                                                                      | None -> "*Unnamed*"
 
3208
                                                                      | Some f -> f) 
 
3209
                                                            () 
 
3210
                                                          in
 
3211
                                                          let sb = GBin.scrolled_window 
 
3212
                                                            ~packing:w#add () 
 
3213
                                                          in
 
3214
                                                          let nv = GText.view 
 
3215
                                                            ~buffer:v#buffer 
 
3216
                                                            ~packing:sb#add 
 
3217
                                                            ()
 
3218
                                                          in
 
3219
                                                            nv#misc#modify_font 
 
3220
                                                              !current.text_font; 
 
3221
                                                            ignore (w#connect#destroy 
 
3222
                                                                      ~callback:
 
3223
                                                                      (fun () -> av#remove_detached_view w));
 
3224
                                                            av#add_detached_view w
 
3225
                                                      | _ -> ()
 
3226
                                                          
 
3227
                                                 ))
 
3228
                                          in
 
3229
                                            (* Help Menu *)
 
3230
 
 
3231
                                          let help_menu = factory#add_submenu "_Help" in
 
3232
                                          let help_factory = new GMenu.factory help_menu  
 
3233
                                            ~accel_path:"<CoqIde MenuBar>/Help/"
 
3234
                                            ~accel_modi:[]
 
3235
                                            ~accel_group in
 
3236
                                          let _ = help_factory#add_item "Browse Coq _Manual" 
 
3237
                                            ~callback:
 
3238
                                            (fun () -> 
 
3239
                                               let av = Option.get ((get_current_view ()).analyzed_view) in 
 
3240
                                                 browse av#insert_message (!current.doc_url)) in
 
3241
                                          let _ = help_factory#add_item "Browse Coq _Library" 
 
3242
                                            ~callback:
 
3243
                                            (fun () -> 
 
3244
                                               let av = Option.get ((get_current_view ()).analyzed_view) in 
 
3245
                                                 browse av#insert_message !current.library_url) in
 
3246
                                          let _ = 
 
3247
                                            help_factory#add_item "Help for _keyword" ~key:GdkKeysyms._F1
 
3248
                                              ~callback:(fun () -> 
 
3249
                                                           let av = Option.get ((get_current_view ()).analyzed_view) in 
 
3250
                                                             av#help_for_keyword ())
 
3251
                                          in
 
3252
                                          let _ = help_factory#add_separator () in
 
3253
                                            (*
 
3254
                                              let faq_m = help_factory#add_item "_FAQ" in
 
3255
                                            *)
 
3256
                                          let about_m = help_factory#add_item "_About" in
 
3257
                                          (* End of menu *)
 
3258
 
 
3259
                                          (* The vertical Separator between Scripts and Goals *)
 
3260
                                          let queries_pane = GPack.paned `VERTICAL ~packing:(vbox#pack ~expand:true ) () in
 
3261
                                          let hb = GPack.paned `HORIZONTAL ~border_width:5 ~packing:(queries_pane#pack1 ~shrink:false ~resize:true) () in
 
3262
                                          let fr_notebook = GBin.frame ~shadow_type:`IN ~packing:hb#add1 () in
 
3263
                                            _notebook := Some (GPack.notebook ~border_width:2 ~show_border:false ~scrollable:true 
 
3264
                                                                 ~packing:fr_notebook#add
 
3265
                                                                 ());
 
3266
                                            update_notebook_pos ();
 
3267
                                            let nb = notebook () in
 
3268
                                            let hb2 = GPack.paned `VERTICAL ~packing:hb#add2 () in
 
3269
                                            let fr_a = GBin.frame ~shadow_type:`IN ~packing:hb2#add () in
 
3270
                                            let fr_b = GBin.frame ~shadow_type:`IN ~packing:hb2#add () in
 
3271
                                            let sw2 = GBin.scrolled_window 
 
3272
                                              ~vpolicy:`AUTOMATIC 
 
3273
                                              ~hpolicy:`AUTOMATIC
 
3274
                                              ~packing:(fr_a#add) () in
 
3275
                                            let sw3 = GBin.scrolled_window 
 
3276
                                              ~vpolicy:`AUTOMATIC 
 
3277
                                              ~hpolicy:`AUTOMATIC
 
3278
                                              ~packing:(fr_b#add) () in
 
3279
                                            let command_object = Command_windows.command_window() in
 
3280
                                            let queries_frame = command_object#frame in
 
3281
                                              queries_pane#pack2 ~shrink:false ~resize:false (queries_frame#coerce);
 
3282
                                            let lower_hbox = GPack.hbox ~homogeneous:false ~packing:vbox#pack () in
 
3283
                                            let status_bar = GMisc.statusbar ~packing:(lower_hbox#pack ~expand:true) () 
 
3284
                                            in
 
3285
                                            let search_lbl = GMisc.label ~text:"Search:"
 
3286
                                              ~show:false
 
3287
                                              ~packing:(lower_hbox#pack ~expand:false) () 
 
3288
                                            in
 
3289
                                            let search_history = ref [] in
 
3290
                                            let search_input = GEdit.combo ~popdown_strings:!search_history
 
3291
                                              ~enable_arrow_keys:true
 
3292
                                              ~show:false
 
3293
                                              ~packing:(lower_hbox#pack ~expand:false) () 
 
3294
                                            in
 
3295
                                              search_input#disable_activate ();
 
3296
                                              let ready_to_wrap_search = ref false in
 
3297
 
 
3298
                                              let start_of_search = ref None in
 
3299
                                              let start_of_found = ref None in
 
3300
                                              let end_of_found = ref None in
 
3301
                                              let search_forward = ref true in
 
3302
                                              let matched_word = ref None in
 
3303
 
 
3304
                                              let memo_search () = 
 
3305
                                                matched_word := Some search_input#entry#text
 
3306
 
 
3307
                                              (*     if not (List.mem search_input#entry#text !search_history) then
 
3308
                                                     (search_history := 
 
3309
                                                     search_input#entry#text::!search_history;
 
3310
                                                     search_input#set_popdown_strings !search_history);
 
3311
                                                     start_of_search := None;
 
3312
                                                     ready_to_wrap_search := false
 
3313
                                              *)
 
3314
 
 
3315
                                              in
 
3316
                                              let end_search () = 
 
3317
                                                prerr_endline "End Search";
 
3318
                                                memo_search ();
 
3319
                                                let v = (get_current_view ()).view in
 
3320
                                                  v#buffer#move_mark `SEL_BOUND (v#buffer#get_iter_at_mark `INSERT);
 
3321
                                                  v#coerce#misc#grab_focus ();
 
3322
                                                  search_input#entry#set_text "";
 
3323
                                                  search_lbl#misc#hide ();
 
3324
                                                  search_input#misc#hide ()
 
3325
                                              in
 
3326
                                              let end_search_focus_out () = 
 
3327
                                                prerr_endline "End Search(focus out)";
 
3328
                                                memo_search ();
 
3329
                                                let v = (get_current_view ()).view in
 
3330
                                                  v#buffer#move_mark `SEL_BOUND (v#buffer#get_iter_at_mark `INSERT);
 
3331
                                                  search_input#entry#set_text "";
 
3332
                                                  search_lbl#misc#hide ();
 
3333
                                                  search_input#misc#hide ()
 
3334
                                              in
 
3335
                                                ignore (search_input#entry#connect#activate ~callback:end_search);
 
3336
                                                ignore (search_input#entry#event#connect#key_press 
 
3337
                                                          ~callback:(fun k -> let kv = GdkEvent.Key.keyval k in
 
3338
                                                                                if 
 
3339
                                                                                  kv = GdkKeysyms._Right
 
3340
                                                                                  || kv = GdkKeysyms._Up 
 
3341
                                                                                  || kv = GdkKeysyms._Left
 
3342
                                                                                  || (kv = GdkKeysyms._g 
 
3343
                                                                                      && (List.mem `CONTROL (GdkEvent.Key.state k)))
 
3344
                                                                                then end_search (); 
 
3345
                                                                       false));
 
3346
                                                ignore (search_input#entry#event#connect#focus_out
 
3347
                                                          ~callback:(fun _ -> end_search_focus_out (); false));
 
3348
                                                to_do_on_page_switch := 
 
3349
                                                  (fun i -> 
 
3350
                                                     start_of_search := None;
 
3351
                                                     ready_to_wrap_search:=false)::!to_do_on_page_switch;
 
3352
 
 
3353
                                                (* TODO : make it work !!! *)
 
3354
                                                let rec search_f () = 
 
3355
                                                  search_lbl#misc#show ();
 
3356
                                                  search_input#misc#show ();
 
3357
 
 
3358
                                                  prerr_endline "search_f called";
 
3359
                                                  if !start_of_search = None then begin
 
3360
                                                      (* A full new search is starting *)
 
3361
                                                      start_of_search := 
 
3362
                                                        Some ((get_current_view ()).view#buffer#create_mark 
 
3363
                                                                ((get_current_view ()).view#buffer#get_iter_at_mark `INSERT));
 
3364
                                                      start_of_found := !start_of_search;
 
3365
                                                      end_of_found := !start_of_search;
 
3366
                                                      matched_word := Some "";
 
3367
                                                    end;
 
3368
                                                  let txt = search_input#entry#text in 
 
3369
                                                  let v = (get_current_view ()).view in
 
3370
                                                  let iit = v#buffer#get_iter_at_mark `SEL_BOUND 
 
3371
                                                  and insert_iter = v#buffer#get_iter_at_mark `INSERT
 
3372
                                                  in
 
3373
                                                    prerr_endline ("SELBOUND="^(string_of_int iit#offset));
 
3374
                                                    prerr_endline ("INSERT="^(string_of_int insert_iter#offset));
 
3375
                                                    
 
3376
                                                    (match
 
3377
                                                         if !search_forward then iit#forward_search txt 
 
3378
                                                         else let npi = iit#forward_chars (Glib.Utf8.length txt) in
 
3379
                                                                match 
 
3380
                                                                  (npi#offset = (v#buffer#get_iter_at_mark `INSERT)#offset),
 
3381
                                                                  (let t = iit#get_text ~stop:npi in 
 
3382
                                                                     !flash_info (t^"\n"^txt);
 
3383
                                                                     t = txt)
 
3384
                                                                with 
 
3385
                                                                  | true,true -> 
 
3386
                                                                      (!flash_info "T,T";iit#backward_search txt)
 
3387
                                                                  | false,true -> !flash_info "F,T";Some (iit,npi)
 
3388
                                                                  | _,false ->
 
3389
                                                                      (iit#backward_search txt)
 
3390
 
 
3391
                                                     with 
 
3392
                                                       | None -> 
 
3393
                                                           if !ready_to_wrap_search then begin
 
3394
                                                               ready_to_wrap_search := false;
 
3395
                                                               !flash_info "Search wrapped";
 
3396
                                                               v#buffer#place_cursor 
 
3397
                                                                 (if !search_forward then v#buffer#start_iter else
 
3398
                                                                      v#buffer#end_iter);
 
3399
                                                               search_f ()
 
3400
                                                             end else begin
 
3401
                                                                 if !search_forward then !flash_info "Search at end"
 
3402
                                                                 else !flash_info "Search at start";
 
3403
                                                                 ready_to_wrap_search := true
 
3404
                                                               end
 
3405
                                                       | Some (start,stop) -> 
 
3406
                                                           prerr_endline "search: before moving marks";
 
3407
                                                           prerr_endline ("SELBOUND="^(string_of_int (v#buffer#get_iter_at_mark `SEL_BOUND)#offset));
 
3408
                                                           prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset));
 
3409
 
 
3410
                                                           v#buffer#move_mark `SEL_BOUND start;
 
3411
                                                           v#buffer#move_mark `INSERT stop;
 
3412
                                                           prerr_endline "search: after moving marks";
 
3413
                                                           prerr_endline ("SELBOUND="^(string_of_int (v#buffer#get_iter_at_mark `SEL_BOUND)#offset));
 
3414
                                                           prerr_endline ("INSERT="^(string_of_int (v#buffer#get_iter_at_mark `INSERT)#offset));
 
3415
                                                           v#scroll_to_mark `SEL_BOUND
 
3416
                                                    )
 
3417
                                                in
 
3418
                                                  ignore (search_input#entry#event#connect#key_release 
 
3419
                                                            ~callback:
 
3420
                                                            (fun ev ->
 
3421
                                                               if GdkEvent.Key.keyval ev = GdkKeysyms._Escape then begin
 
3422
                                                                   let v = (get_current_view ()).view in
 
3423
                                                                     (match !start_of_search with 
 
3424
                                                                        | None -> 
 
3425
                                                                            prerr_endline "search_key_rel: Placing sel_bound";
 
3426
                                                                            v#buffer#move_mark 
 
3427
                                                                              `SEL_BOUND 
 
3428
                                                                              (v#buffer#get_iter_at_mark `INSERT)
 
3429
                                                                        | Some mk -> let it = v#buffer#get_iter_at_mark 
 
3430
                                                                            (`MARK mk) in
 
3431
                                                                                       prerr_endline "search_key_rel: Placing cursor";
 
3432
                                                                            v#buffer#place_cursor it;
 
3433
                                                                            start_of_search := None
 
3434
                                                                     );
 
3435
                                                                     search_input#entry#set_text ""; 
 
3436
                                                                     v#coerce#misc#grab_focus ();
 
3437
                                                                 end; 
 
3438
                                                               false
 
3439
                                                            ));
 
3440
                                                  ignore (search_input#entry#connect#changed search_f);
 
3441
                                                  
 
3442
                                                  (*
 
3443
                                                    ignore (search_if#connect#activate
 
3444
                                                    ~callback:(fun b -> 
 
3445
                                                    search_forward:= true;
 
3446
                                                    search_input#entry#coerce#misc#grab_focus ();
 
3447
                                                    search_f ();
 
3448
                                                    )
 
3449
                                                    );
 
3450
                                                    ignore (search_ib#connect#activate
 
3451
                                                    ~callback:(fun b ->
 
3452
                                                    search_forward:= false;
 
3453
 
 
3454
                                                  (* Must restore the SEL_BOUND mark after 
 
3455
                                                    grab_focus ! *)
 
3456
                                                    let v = (get_current_view ()).view in
 
3457
                                                    let old_sel = v#buffer#get_iter_at_mark `SEL_BOUND 
 
3458
                                                    in
 
3459
                                                    search_input#entry#coerce#misc#grab_focus ();
 
3460
                                                    v#buffer#move_mark `SEL_BOUND old_sel;
 
3461
                                                    search_f ();
 
3462
                                                    ));
 
3463
                                                  *)
 
3464
                                                  let status_context = status_bar#new_context "Messages" in
 
3465
                                                  let flash_context = status_bar#new_context "Flash" in
 
3466
                                                    ignore (status_context#push "Ready");
 
3467
                                                    status := Some status_bar;
 
3468
                                                    push_info := (fun s -> ignore (status_context#push s));
 
3469
                                                    pop_info := (fun () -> status_context#pop ());
 
3470
                                                    flash_info := (fun ?(delay=5000) s -> flash_context#flash ~delay s);
 
3471
 
 
3472
                                                    (* Location display *)
 
3473
                                                    let l = GMisc.label
 
3474
                                                      ~text:"Line:     1 Char:   1" 
 
3475
                                                      ~packing:lower_hbox#pack () in 
 
3476
                                                      l#coerce#misc#set_name "location";
 
3477
                                                      set_location := l#set_text;
 
3478
 
 
3479
                                                      (* Progress Bar *)
 
3480
                                                      pulse := 
 
3481
                                                        (let pb = GRange.progress_bar ~pulse_step:0.2 ~packing:lower_hbox#pack ()
 
3482
                                                         in pb#set_text "CoqIde started";pb)#pulse;
 
3483
                                                      let tv2 = GText.view ~packing:(sw2#add) () in
 
3484
                                                        tv2#misc#set_name "GoalWindow";
 
3485
                                                        let _ = tv2#set_editable false in
 
3486
                                                        let _ = tv2#buffer in
 
3487
                                                        let tv3 = GText.view ~packing:(sw3#add) () in
 
3488
                                                          tv2#misc#set_name "MessageWindow";
 
3489
                                                          let _ = tv2#set_wrap_mode `CHAR in
 
3490
                                                          let _ = tv3#set_wrap_mode `WORD in
 
3491
                                                          let _ = tv3#set_editable false in
 
3492
                                                          let _ = GtkBase.Widget.add_events tv2#as_widget
 
3493
                                                            [`ENTER_NOTIFY;`POINTER_MOTION] in
 
3494
                                                          let _ =
 
3495
                                                            tv2#event#connect#motion_notify
 
3496
                                                              ~callback:
 
3497
                                                              (fun e -> 
 
3498
                                                                 let win = match tv2#get_window `WIDGET with
 
3499
                                                                   | None -> assert false
 
3500
                                                                   | Some w -> w in
 
3501
                                                                 let x,y = Gdk.Window.get_pointer_location win in
 
3502
                                                                 let b_x,b_y = tv2#window_to_buffer_coords ~tag:`WIDGET ~x ~y in
 
3503
                                                                 let it = tv2#get_iter_at_location ~x:b_x ~y:b_y in
 
3504
                                                                 let tags = it#tags in
 
3505
                                                                   List.iter 
 
3506
                                                                     (fun t ->
 
3507
                                                                        ignore(GtkText.Tag.event t#as_tag tv2#as_widget e it#as_iter))
 
3508
                                                                     tags;
 
3509
                                                                   false) in
 
3510
                                                            change_font := 
 
3511
                                                              (fun fd -> 
 
3512
                                                                 tv2#misc#modify_font fd;
 
3513
                                                                 tv3#misc#modify_font fd;
 
3514
                                                                 Vector.iter 
 
3515
                                                                   (fun {view=view} -> view#misc#modify_font fd)
 
3516
                                                                   input_views;
 
3517
                                                              );
 
3518
                                                            let about_full_string =
 
3519
                                                              "\nCoq is developed by the Coq Development Team\
 
3520
       \n(INRIA - CNRS - University Paris 11 and partners)\
 
3521
       \nWeb site: " ^ Coq_config.wwwcoq ^
 
3522
       "\nFeature wish or bug report: http://logical.saclay.inria.fr/coq-bugs\
 
3523
       \n\
 
3524
       \nCredits for CoqIDE, the Integrated Development Environment for Coq:\
 
3525
       \n\
 
3526
       \nMain author  : Benjamin Monate\
 
3527
       \nContributors : Jean-Christophe Filliâtre\
 
3528
       \n               Pierre Letouzey, Claude Marché\
 
3529
       \n               Bruno Barras, Pierre Corbineau\
 
3530
       \n               Julien Narboux, Hugo Herbelin, ... \
 
3531
       \n\
 
3532
       \nVersion information\
 
3533
       \n-------------------\
 
3534
       \n"
 
3535
                                                            in
 
3536
                                                            let initial_about (b:GText.buffer) =
 
3537
                                                              let initial_string = "Welcome to CoqIDE, an Integrated Development Environment for Coq\n" in
 
3538
                                                              let coq_version = Coq.short_version () in
 
3539
                                                                b#insert ~iter:b#start_iter "\n\n";
 
3540
                                                                if Glib.Utf8.validate ("You are running " ^ coq_version) then b#insert ~iter:b#start_iter ("You are running " ^ coq_version);
 
3541
                                                                if Glib.Utf8.validate initial_string then b#insert ~iter:b#start_iter initial_string;
 
3542
                                                                (try 
 
3543
                                                                    let image = lib_ide_file "coq.png" in
 
3544
                                                                    let startup_image = GdkPixbuf.from_file image in
 
3545
                                                                      b#insert ~iter:b#start_iter "\n\n";
 
3546
                                                                      b#insert_pixbuf ~iter:b#start_iter ~pixbuf:startup_image;
 
3547
                                                                      b#insert ~iter:b#start_iter "\n\n\t\t   "
 
3548
                                                                  with _ -> ())
 
3549
                                                            in
 
3550
 
 
3551
                                                            let about (b:GText.buffer) =
 
3552
                                                              (try 
 
3553
                                                                  let image = lib_ide_file "coq.png" in
 
3554
                                                                  let startup_image = GdkPixbuf.from_file image in
 
3555
                                                                    b#insert ~iter:b#start_iter "\n\n";
 
3556
                                                                    b#insert_pixbuf ~iter:b#start_iter ~pixbuf:startup_image;
 
3557
                                                                    b#insert ~iter:b#start_iter "\n\n\t\t   "
 
3558
                                                                with _ -> ());
 
3559
                                                                if Glib.Utf8.validate about_full_string
 
3560
                                                                then b#insert about_full_string;
 
3561
                                                                let coq_version = Coq.version () in
 
3562
                                                                  if Glib.Utf8.validate coq_version
 
3563
                                                                  then b#insert coq_version
 
3564
 
 
3565
                                                            in
 
3566
                                                              initial_about tv2#buffer;
 
3567
                                                              w#add_accel_group accel_group;
 
3568
                                                              (* Remove default pango menu for textviews *)
 
3569
                                                              ignore (tv2#event#connect#button_press ~callback:
 
3570
                                                                        (fun ev -> GdkEvent.Button.button ev = 3));
 
3571
                                                              ignore (tv3#event#connect#button_press ~callback:
 
3572
                                                                        (fun ev -> GdkEvent.Button.button ev = 3));
 
3573
                                                              tv2#misc#set_can_focus true;
 
3574
                                                              tv3#misc#set_can_focus true;
 
3575
                                                              ignore (tv2#buffer#create_mark 
 
3576
                                                                        ~name:"end_of_conclusion" 
 
3577
                                                                        tv2#buffer#start_iter);
 
3578
                                                              ignore (tv3#buffer#create_tag 
 
3579
                                                                        ~name:"error" 
 
3580
                                                                        [`FOREGROUND "red"]);
 
3581
                                                              w#show ();
 
3582
                                                              message_view := Some tv3;
 
3583
                                                              proof_view := Some tv2;
 
3584
                                                              tv2#misc#modify_font !current.text_font; 
 
3585
                                                              tv3#misc#modify_font !current.text_font;
 
3586
                                                              ignore (about_m#connect#activate 
 
3587
                                                                        ~callback:(fun () -> tv2#buffer#set_text ""; about tv2#buffer));
 
3588
                                                              (*
 
3589
                                                                ignore (faq_m#connect#activate 
 
3590
                                                                ~callback:(fun () -> 
 
3591
                                                                load (lib_ide_file "FAQ")));
 
3592
                                                                
 
3593
                                                              *)
 
3594
                                                              resize_window := (fun () -> 
 
3595
                                                                                  w#resize 
 
3596
                                                                                    ~width:!current.window_width
 
3597
                                                                                    ~height:!current.window_height);
 
3598
 
 
3599
                                                              ignore (w#misc#connect#size_allocate 
 
3600
                                                                        (let old_w = ref 0 
 
3601
                                                                         and old_h = ref 0 in
 
3602
                                                                           fun {Gtk.width=w;Gtk.height=h} -> 
 
3603
                                                                             if !old_w <> w or !old_h <> h then
 
3604
                                                                               begin
 
3605
                                                                                 old_h := h;
 
3606
                                                                                 old_w := w;
 
3607
                                                                                 hb#set_position (w/2);
 
3608
                                                                                 hb2#set_position (h/2);
 
3609
                                                                                 !current.window_height <- h;
 
3610
                                                                                 !current.window_width <- w;
 
3611
                                                                               end
 
3612
                                                                        ));
 
3613
                                                              ignore(nb#connect#switch_page
 
3614
                                                                       ~callback:
 
3615
                                                                       (fun i -> 
 
3616
                                                                          prerr_endline ("switch_page: starts " ^ string_of_int i);
 
3617
                                                                          List.iter (function f -> f i) !to_do_on_page_switch;
 
3618
                                                                          prerr_endline "switch_page: success")
 
3619
                                                                    );
 
3620
                                                              ignore(tv2#event#connect#enter_notify
 
3621
                                                                       (fun _ -> 
 
3622
                                                                          if !current.contextual_menus_on_goal then
 
3623
                                                                            begin
 
3624
                                                                              let w = (Option.get (get_active_view ()).analyzed_view) in
 
3625
                                                                                !push_info "Computing advanced goal's menus";
 
3626
                                                                                prerr_endline "Entering Goal Window. Computing Menus....";
 
3627
                                                                                w#show_goals_full;
 
3628
                                                                                prerr_endline "....Done with Goal menu";
 
3629
                                                                                !pop_info();
 
3630
                                                                            end;
 
3631
                                                                          false;
 
3632
                                                                       ));
 
3633
                                                              if List.length files >=1 then
 
3634
                                                                begin
 
3635
                                                                  List.iter (fun f -> 
 
3636
                                                                               if Sys.file_exists f then load f else 
 
3637
                                                                                 let f = if Filename.check_suffix f ".v" then f else f^".v" in
 
3638
                                                                                 load_file (fun s -> print_endline s; exit 1) f)
 
3639
                                                                    files;
 
3640
                                                                  activate_input 0
 
3641
                                                                end
 
3642
                                                              else
 
3643
                                                                begin
 
3644
                                                                  let view = create_input_tab "*Unnamed Buffer*" in
 
3645
                                                                  let index = add_input_view {view = view;
 
3646
                                                                                              analyzed_view = None;
 
3647
                                                                                             }
 
3648
                                                                  in
 
3649
                                                                    (get_input_view index).analyzed_view <- Some (new analyzed_view index);
 
3650
                                                                    activate_input index;
 
3651
                                                                    set_tab_image index ~icon:`YES;
 
3652
                                                                    view#misc#modify_font !current.text_font
 
3653
                                                                end;
 
3654
 
 
3655
;;
 
3656
 
 
3657
(* This function check every half of second if GeoProof has send 
 
3658
   something on his private clipboard *)
 
3659
 
 
3660
let rec check_for_geoproof_input () = 
 
3661
  let cb_Dr = GData.clipboard (Gdk.Atom.intern "_GeoProof") in
 
3662
    while true do
 
3663
      Thread.delay 0.1;
 
3664
      let s = cb_Dr#text in
 
3665
        (match s with 
 
3666
             Some s -> 
 
3667
               if s <> "Ack" then
 
3668
                 (get_current_view()).view#buffer#insert (s^"\n");
 
3669
               cb_Dr#set_text "Ack"
 
3670
           | None -> ()
 
3671
        );
 
3672
        (* cb_Dr#clear does not work so i use : *)
 
3673
        (* cb_Dr#set_text "Ack" *) 
 
3674
    done
 
3675
      
 
3676
      
 
3677
let start () = 
 
3678
  let files = Coq.init () in
 
3679
    ignore_break ();
 
3680
    GtkMain.Rc.add_default_file (lib_ide_file ".coqide-gtk2rc");
 
3681
    (try 
 
3682
         GtkMain.Rc.add_default_file (Filename.concat System.home ".coqide-gtk2rc");
 
3683
     with Not_found -> ());
 
3684
    ignore (GtkMain.Main.init ());
 
3685
    GtkData.AccelGroup.set_default_mod_mask 
 
3686
      (Some [`CONTROL;`SHIFT;`MOD1;`MOD3;`MOD4]);
 
3687
    cb_ := Some (GData.clipboard Gdk.Atom.primary);
 
3688
    ignore (
 
3689
             Glib.Message.set_log_handler ~domain:"Gtk" ~levels:[`ERROR;`FLAG_FATAL;
 
3690
                                                                 `WARNING;`CRITICAL]
 
3691
               (fun ~level msg -> 
 
3692
                  if level land Glib.Message.log_level `WARNING <> 0
 
3693
                  then Pp.warning msg
 
3694
                  else failwith ("Coqide internal error: " ^ msg)));
 
3695
    Command_windows.main ();
 
3696
    Blaster_window.main 9;
 
3697
    init_stdout ();
 
3698
    main files;
 
3699
    if !Coq_config.with_geoproof then ignore (Thread.create check_for_geoproof_input ()); 
 
3700
    while true do 
 
3701
      try 
 
3702
        GtkThread.main ()       
 
3703
      with
 
3704
        | Sys.Break -> prerr_endline "Interrupted." ; flush stderr
 
3705
        | e -> 
 
3706
            Pervasives.prerr_endline ("CoqIde unexpected error:" ^ (Printexc.to_string e));
 
3707
            flush stderr;
 
3708
            crash_save 127
 
3709
    done