1 ;;; -*- Mode: Lisp; Syntax: Common-Lisp; Package: CLIM-USER; -*-
2 ;;; ---------------------------------------------------------------------------
4 ;;; Created: 2002-07-22
5 ;;; Author: Gilbert Baumann <gilbert@base-engineering.com>
6 ;;; License: MIT style (see below)
7 ;;; $Id: clim-gui.lisp,v 1.32 2007-06-30 14:00:04 dlichteblau Exp $
8 ;;; ---------------------------------------------------------------------------
9 ;;; (c) copyright 2002 by Gilbert Baumann
11 ;;; Permission is hereby granted, free of charge, to any person obtaining
12 ;;; a copy of this software and associated documentation files (the
13 ;;; "Software"), to deal in the Software without restriction, including
14 ;;; without limitation the rights to use, copy, modify, merge, publish,
15 ;;; distribute, sublicense, and/or sell copies of the Software, and to
16 ;;; permit persons to whom the Software is furnished to do so, subject to
17 ;;; the following conditions:
19 ;;; The above copyright notice and this permission notice shall be
20 ;;; included in all copies or substantial portions of the Software.
22 ;;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 ;;; EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 ;;; MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 ;;; IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
26 ;;; CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 ;;; TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 ;;; SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 ;; $Log: clim-gui.lisp,v $
31 ;; Revision 1.32 2007-06-30 14:00:04 dlichteblau
32 ;; New argument new-process to run-closure, which can be disabled to run
33 ;; closure in a "blocking" mode. Needed for clbuild, which wants to (quit)
34 ;; after the application is done.
36 ;; Revision 1.31 2007/02/04 15:10:01 dlichteblau
39 ;; Revision 1.30 2007/01/07 19:32:06 emarsden
40 ;; Follow HTTP redirects (HTML-level redirects still not supported).
42 ;; Revision 1.29 2007/01/03 16:14:57 emarsden
43 ;; - new function RENDER-LHTML that renders LHTML
44 ;; - new command "Inspect Page" that runs Clouseau on the current document
46 ;; Revision 1.28 2007/01/03 11:34:45 emarsden
47 ;; GUI: implement beginning-of-page and end-of-page commands; add
48 ;; keyboard shortcuts for back & forward.
50 ;; Revision 1.27 2006/12/31 15:42:40 dlichteblau
52 ;; Use Bordeaux Threads for all threading primitives, so that non-GUI parts of
53 ;; Closure don't have to depend on CLIM anymore.
55 ;; - Removed all mp/ functions from glisp.
57 ;; - Use condition variables instead of process-wait.
59 ;; Revision 1.26 2006/12/31 13:26:23 emarsden
60 ;; - add basic wholine support (currently title & last-modified information)
61 ;; - add "TeX mode On" and "TeX mode Off" commands (experimental)
63 ;; Revision 1.25 2006/12/30 15:13:54 emarsden
64 ;; - use CL from Closure packages
66 ;; - move PARSE-X11-COLOR from clim-user to ws/x11 package
68 ;; Revision 1.24 2006/12/30 15:07:31 emarsden
69 ;; Minor improvements to user interface:
70 ;; - enable double buffering
71 ;; - wait until page has been downloaded before erasing previous page
72 ;; - enable busy cursor while downloading and rendering
74 ;; Revision 1.23 2006/12/29 17:37:07 dlichteblau
75 ;; Make closure start on Gtkairo:
77 ;; * src/gui/clim-gui.lisp (WRITE-STATUS, FOO, COM-REDRAW): Replace
78 ;; calls to xlib:display-finish-output with
79 ;; clim-backend:port-force-output.
81 ;; Revision 1.22 2005/08/25 15:14:14 crhodes
82 ;; OpenMCL support (from Dave Murray aka JQS)
84 ;; Revision 1.21 2005/08/25 15:05:48 crhodes
85 ;; Work around problems related to *closure-inited-p* (see #lisp logs for
86 ;; 2005-08-25 for more discussion). Not clear where the fault lies: sbcl,
87 ;; clx, mcclim[-freetype] or closure itself.
89 ;; Revision 1.20 2005/07/11 15:58:03 crhodes
90 ;; Complete the renaming *MEDIUM* -> *PANE*.
92 ;; Panes are CLIM extended-streams, and remember output to them in output
93 ;; records. Mediums are much simpler, and don't have this kind of
94 ;; memory. So, though the same drawing functions (DRAW-TEXT, DRAW-LINE)
95 ;; can have the same initial effect applied to a pane and a medium, the
96 ;; output-record state is very different.
98 ;; Revision 1.19 2005/07/10 11:18:34 emarsden
99 ;; Distinguish between pane and medium in the CLIM GUI. This should
100 ;; fix image display.
102 ;; Revision 1.18 2005/07/10 10:57:20 emarsden
103 ;; Move a number of global variables from the CL-USER to the GUI package.
105 ;; Revision 1.17 2005/04/12 10:28:55 tdalyjr
106 ;; Since closure-frame-top-level is no longer used, comment it out.
108 ;; Use a :before method on run-frame-top-level to set
109 ;; *closure-inited-p*. (this used to be done by closure-frame-top-level)
111 ;; Reimplement the quit command using frame-exit, since the 'closure-quit
112 ;; catch tag no longer exists.
114 ;; Use process-interrupt from the clim-sys package, instead of from the
115 ;; mp package, since clim-sys should be more portable.
117 ;; Turn on scrollbars for the interactor pane, since otherwise it trashes
118 ;; the status line on the bottom of the window and stops updating.
120 ;; Revision 1.16 2005/03/13 21:17:28 emarsden
121 ;; - Implement PageUp and PageDown support in the CLIM GUI.
122 ;; - Add a Redraw command (with Ctrl-R accelerator)
124 ;; Revision 1.15 2005/03/13 21:15:06 emarsden
125 ;; Add zoom support to the renderer, accessible via the commands com-zoom-in,
126 ;; com-zoom-out and com-zoom-100%.
128 ;; Revision 1.14 2005/03/13 20:58:31 emarsden
129 ;; - Update to new McCLIM requirements on DEFINE-xx-COMMAND, adding :name t
130 ;; so that commands are available from listener pane
132 ;; Revision 1.13 2005/03/13 19:24:14 gbaumann
133 ;; make it at least compile and show a window with CMUCL 19a and cvs mcclim.
135 ;; Revision 1.12 2005/03/13 18:01:37 gbaumann
136 ;; Gross license change
138 ;; Revision 1.11 2003/06/15 17:24:24 gilbert
139 ;; fixes to the recent patches.
141 ;; Revision 1.10 2003/06/15 16:47:44 gilbert
142 ;; OpenMCL patches by Patrik Nordebo
144 ;; Revision 1.9 2003/03/16 17:46:19 gilbert
145 ;; we call xlib:display-finish-output when a page is finished.
147 ;; Revision 1.8 2003/03/14 17:06:16 dan
148 ;; replace defconstants for non-constant variables with defvar, to placate SBCL, which suffers from offensively ANSI behaviour with same
150 ;; Revision 1.7 2003/03/14 14:14:36 gilbert
151 ;; adjusted frame-top-level loop
153 ;; Revision 1.6 2003/03/13 20:17:23 gilbert
154 ;; CLX bug: xlib:put-image grind to halt when the image is widther than 2048 pixels.
156 ;; Revision 1.5 2003/03/13 19:29:17 gilbert
159 ;; Revision 1.4 2002/08/16 17:20:50 gilbert
162 ;; Revision 1.3 2002/07/29 12:39:08 gilbert
163 ;; - we pass more tests now
165 ;; Revision 1.2 2002/07/24 04:11:51 gilbert
166 ;; Tex Mode On and Tex Mode Off commands
168 ;; Revision 1.1.1.1 2002/07/22 02:27:22 gilbert
172 (in-package :CLIM-USER
)
181 (defvar *initial-url
* nil
)
183 (defvar *closure-process
* nil
)
185 (defclass closure-pane
(application-pane)
190 (defvar *back-history
* nil
)
191 (defvar *forw-history
* nil
)
193 (defun make-canvas (&key
(height 600) (min-height 600))
194 (scrolling (:width
830
196 :scroll-bar
:vertical
198 :min-height min-height
)
199 (make-pane 'closure-pane
204 (defmacro canvasly
(&rest spacereqs
)
206 (clim-tab-layout:with-tab-layout
207 ('clim-tab-layout
:tab-page
:name
'tab-layout
)
209 (make-canvas ,@spacereqs
)))))
211 (setf (slot-value *frame
* 'tabs
) tabs
)
214 (define-application-frame closure
()
216 (:menu-bar menubar-command-table
)
225 :incremental-redisplay t
227 :display-function
'aux-display
228 :display-time
:command-loop
)
229 (status :pointer-documentation
230 :text-style
(make-text-style :sans-serif
:roman
:normal
)
241 :background
(make-rgb-color 1 1 7/8)
242 :text-style
(make-text-style :sans-serif nil
:normal
)
243 :height
50 :min-height
50 :max-height
50
244 :scroll-bars t
:border nil
)
246 :pointer-documentation
:width
5 :max-width
+fill
+
248 :text-style
(make-text-style :sans-serif
:roman
10)
251 ;;(menu-bar (climi::make-menu-bar 'menubar-command-table :height 25))
256 (spacing (:thickness
5)
257 (canvasly :height
600 :min-height
400))
258 (spacing (:thickness
5)
260 (horizontally (:height
80 :min-height
80 :max-height
80)
266 (spacing (:thickness
5)
267 (canvasly :height
600 :min-height
600))
268 (horizontally (:height
80 :min-height
80 :max-height
80)
278 (canvasly :height
600 :min-height
400)))
283 ;; (:top-level (closure-frame-top-level . nil))
287 (make-command-table 'menubar-command-table
289 :menu
'(("File" :menu file-command-table
)
290 ("Go" :menu go-command-table
)
291 ;; ("Bookmarks" :menu bookmarks-command-table)
292 ;; ("View" :menu view-command-table)
293 ("Appearance" :menu appearance-command-table
)
296 (make-command-table 'appearance-command-table
:errorp nil
297 :menu
'(("Show Listener" :command com-show-listener
)
298 ("Hide Listener" :command com-hide-listener
)))
300 (make-command-table 'file-command-table
302 :menu
'(("New Tab" :command com-new-tab
)
303 ("Quit" :command com-quit
)))
305 (make-command-table 'go-command-table
307 :menu
'(("Back" :command com-back
)
308 ("Forward" :command com-forward
)
309 ("Home" :command com-home
)))
311 (make-command-table 'view-command-table
313 :menu
'(("Zoom" :menu zoom-command-table
)))
315 (make-command-table 'zoom-command-table
317 :menu
'(("Zoom In" :command com-zoom-in
)
318 ("Zoom Out" :command com-zoom-out
)
319 ("Zoom 100%" :command com-zoom-100%
)))
321 (make-command-table 'bookmarks-command-table
323 :menu
'(("Add" :command com-add-bookmark
)
324 ;;("Forward" :command com-forward)
327 ;;; This top level has been abandoned in favor of CLIM's built-in one,
328 ;;; but let's keep it for a little while to pillage. -- tpd 2005.4.9
329 ;; (defmethod closure-frame-top-level
330 ;; ((frame application-frame)
331 ;; &key (command-parser 'command-line-command-parser)
332 ;; (command-unparser 'command-line-command-unparser)
333 ;; (partial-command-parser
334 ;; 'command-line-read-remaining-arguments-for-partial-command)
335 ;; (prompt "Closure => "))
336 ;; (catch 'closure-quit
338 ;; (with-simple-restart (forget "Just forget this command, restart the command loop.")
339 ;; (let ((*standard-input* (frame-standard-input frame))
340 ;; (*standard-output* (frame-standard-output frame))
341 ;; (*query-io* (frame-query-io frame))
342 ;; (*pointer-documentation-output* (frame-pointer-documentation-output
344 ;; ;; during development, don't alter *error-output*
345 ;; ;; (*error-output* (frame-error-output frame))
346 ;; (*command-parser* command-parser)
347 ;; (*command-unparser* command-unparser)
348 ;; (*partial-command-parser* partial-command-parser)
349 ;; (prompt-style (make-text-style :sans-serif :bold :normal)))
350 ;; (let ((*application-frame* frame))
351 ;; (when *initial-url*
352 ;; (com-visit-url *initial-url*))
353 ;; (setf *initial-url* nil)
354 ;; (setf *closure-inited-p* t)
355 ;; (when *standard-input*
356 ;; (setf (cursor-visibility (stream-text-cursor *standard-input*)) t)
358 ;; (with-text-style (*standard-input* prompt-style)
359 ;; (if (stringp prompt)
360 ;; (write-string prompt *standard-input*)
361 ;; (funcall prompt *standard-input* frame))
362 ;; (finish-output *standard-input*)))
363 ;; (let ((command (read-frame-command frame)))
364 ;; (fresh-line *standard-input*)
365 ;; ;;(window-clear *standard-output*)
366 ;; (clim:window-clear *query-io*)
368 ;; (execute-frame-command frame command))
369 ;; (fresh-line *standard-input*)))))))))
371 (define-presentation-type url
())
372 (define-presentation-type r2
::pt
())
373 (define-presentation-type r2
::hyper-link
())
375 (defun scroller-child (scroller)
377 (find-if (lambda (x) (typep x
'climi
::viewport-pane
))
378 (sheet-children scroller
)))))
380 (defun current-page ()
381 (clim-tab-layout:tab-layout-enabled-page
(slot-value *frame
* 'tabs
)))
383 (defun current-pane ()
384 (scroller-child (clim-tab-layout:tab-page-pane
(current-page))))
386 ;; renders LHTML as per http://opensource.franz.com/xmlutils/xmlutils-dist/phtml.htm
387 (defun render-lhtml (location lhtml
)
388 (with-simple-restart (forget "Just forget rendering this page.")
389 (let* ((*package
* (find-package :r2
))
390 (*pane
* (current-pane))
391 (*medium
* (sheet-medium *pane
*))
392 (device (make-instance 'closure
/clim-device
::clim-device
:medium
*pane
*))
393 (doc (make-instance 'r2
::document
397 :pt
(sgml::lhtml-
>pt lhtml
)))
398 (*current-document
* doc
)
399 (closure-protocol:*user-agent
* nil
)
400 (closure-protocol:*document-language
* (make-instance 'r2
::html-4.0-document-language
))
401 (r2::*canvas-width
* (bounding-rectangle-width (sheet-parent *pane
*))))
402 (window-clear *pane
*)
403 (closure-protocol:render closure-protocol
:*document-language
*
406 (setf *current-pt
* (r2::document-pt doc
))
408 (clim-backend:port-force-output
(find-port))
411 ;;;; ----------------------------------------------------------------------------------------------------
415 (define-closure-command (com-remove-tab :name t
)
416 ((page 'clim-tab-layout
:tab-page
:prompt
"Tab page" :gesture
:delete
))
417 (clim-tab-layout:remove-page page
))
419 (define-closure-command (com-show-listener :name t
) ()
420 (setf (sheet-enabled-p (sheet-parent (find-pane-named *application-frame
* 'interactor
))) t
))
422 (define-closure-command (com-hide-listener :name t
) ()
423 (setf (sheet-enabled-p (sheet-parent (find-pane-named *application-frame
* 'interactor
))) nil
))
425 (define-closure-command (com-visit-url :name t
) ((url 'url
)) ;;; :gesture :select))
426 (let ((*standard-output
* *query-io
*)) ;;(find-pane-named *frame* 'interactor)))
427 (with-text-style (*standard-output
* (make-text-style :sans-serif
:roman
:normal
))
428 (format t
"You are visiting "))
430 (with-text-style (*standard-output
* (make-text-style :sans-serif
:roman
:normal
))
432 (setf *forw-history
* nil
433 *back-history
* (cons url
*back-history
*))
434 (let ((*standard-output
* *trace-output
*))
437 (define-gesture-name :visit-in-new-tab
:pointer-button-press
(:middle
))
439 (define-closure-command (com-visit-url-in-new-tab :name t
)
440 ((url 'url
:gesture
:visit-in-new-tab
))
442 (setf *pane
* (current-pane))
445 (define-closure-command (com-reflow :name t
) ()
448 (define-closure-command (com-back :name t
:keystroke
(:left
:control
)) ()
449 (let ((*standard-output
* *query-io
*))
450 (cond ((null (cdr *back-history
*))
451 (format t
"There is nowhere you can go back to.~%"))
453 (push (pop *back-history
*) *forw-history
*)
454 (format t
"Going back to ~S.~%" (first *back-history
*))
455 (foo (first *back-history
*))))))
457 (define-closure-command (com-forward :name t
:keystroke
(:right
:control
)) ()
458 (let ((*standard-output
* *query-io
*))
459 (cond ((null *forw-history
*)
460 (format t
"There is nowhere you can go forward to.~%"))
462 (push (pop *forw-history
*) *back-history
*)
463 (format t
"Going forward to ~S.~%" (first *back-history
*))
464 (foo (first *back-history
*))))))
466 (define-closure-command (com-reload :name t
) ()
467 (let ((*standard-output
* *query-io
*))
468 (cond ((null *back-history
*)
469 (format t
"There is nothing to reload.~%"))
471 (format t
"Reloading ~S.~%" (first *back-history
*))
472 (foo (first *back-history
*))))))
474 (define-closure-command (com-images-off :name t
) ()
475 (setf gui
:*user-wants-images-p
* nil
)
476 (format *query-io
* "Images are now off.~%"))
478 (define-closure-command (com-images-on :name t
) ()
479 (setf gui
:*user-wants-images-p
* t
)
480 (format *query-io
* "Images are now on. You may want to reload.~%"))
482 (define-closure-command (com-quit :name t
:keystroke
(#\q
:control
)) ()
483 (frame-exit *application-frame
*))
485 (defvar *open-new-tabs-in-background
* nil
)
487 (define-closure-command (com-new-tab :name t
:keystroke
(#\t :control
)) ()
488 (with-look-and-feel-realization
489 ((frame-manager *application-frame
*) *application-frame
*)
490 (clim-tab-layout:add-page
(make-instance 'clim-tab-layout
:tab-page
493 (slot-value *frame
* 'tabs
)
494 (not *open-new-tabs-in-background
*))))
496 (defun make-google-search-url (string)
498 (url:make-url
:query
(list
500 (cons "ie" "ISO-8859-1")
502 (url:parse-url
"http://www.google.com/search")))
504 (define-closure-command (com-reverse-search-google :name t
) ((url 'url
))
505 (let ((*standard-output
* *trace-output
*))
507 (make-google-search-url (format nil
"link:~A" url
)))))
509 (define-closure-command (com-search-google :name t
) ((what 'string
))
510 (com-visit-url (make-google-search-url what
)))
512 (define-closure-command (com-home :name t
) ()
513 (com-visit-url gui
:*home-page
*))
515 (define-presentation-translator fofo
518 :documentation
((object presentation stream
)
519 (princ "Goto " stream
)
520 (with-text-style (stream (make-text-style :fix nil nil
))
521 (princ (url:unparse-url object
) stream
))
526 (define-presentation-to-command-translator fofo
527 (url com-visit-url closure
529 :pointer-documentation
((object presentation stream
)
530 (princ "GOTO " stream
)
531 (with-text-style (stream (make-text-style :fix nil nil
))
532 (princ (if (url:url-p object
)
533 (url:unparse-url object
)
540 ;;;; ----------------------------------------------------------------------------------------------------
544 (defvar *closure-lock
* (clim-sys:make-recursive-lock
"Closure"))
546 (defmacro with-closure
(ignore &body body
)
547 (declare (ignore ignore
))
548 `(clim-sys:with-recursive-lock-held
(*closure-lock
*)
551 (defun parse-url* (url)
553 (string (url:parse-url url
))
556 (defun send-closure-command (command &rest args
)
559 (clim-sys:process-interrupt
*closure-process
*
560 #'(lambda () (apply command args
)))))
563 (defun closure:visit
(&optional
(url gui
:*home-page
*))
564 (and url
(setf url
(parse-url* url
)))
565 (cond ((and (null *closure-process
*) (null url
))
566 (setf *initial-url
* url
)
571 (send-closure-command 'com-visit-url url
)))))
573 (defun closure:start
()
576 (defun closure:stop
()
578 (when *closure-process
*
579 (send-closure-command 'com-quit
))))
581 (defvar *closure-inited-p
* nil
)
582 (defmethod clim:read-frame-command
:before
((frame closure
)
583 &key
&allow-other-keys
)
584 (unless *closure-inited-p
*
585 (setf *closure-inited-p
* t
)))
587 (defun ensure-closure ()
589 (unless *closure-process
*
590 (setf *closure-inited-p
* nil
)
592 (clim-sys:process-wait
"Waiting for closure init"
593 (lambda () *closure-inited-p
*)))))
595 (defun run-closure (&key
(new-process t
))
597 (let* ((proxy (glisp:getenv
"http_proxy"))
598 (url (and proxy
(url:parse-url proxy
))))
600 (equal (url:url-protocol url
) "http"))
601 (format t
"~:[~&;; Using HTTP proxy ~S port ~S~%~;~]"
602 (setf netlib
::*use-http-proxy-p
* t
)
603 (setf netlib
::*http-proxy-host
* (url:url-host url
))
604 (setf netlib
::*http-proxy-port
* (url:url-port url
))))
606 ;; we go without one:
607 (setf netlib
::*use-http-proxy-p
* nil
))))
609 (setf CLUE-GUI2
::*PIXMAP-CACHE
* nil
)
610 (setf CLUE-GUI2
::*PIXMAP-CACHE
* nil
)
611 (setf CLUE-GUI2
::*DCACHE
* nil
)
612 (setf climi
::*3d-dark-color
* (make-gray-color .45))
613 (setf climi
::*3d-normal-color
* (make-gray-color .75))
614 (setf climi
::*3d-light-color
* (make-gray-color .92))
615 (setf climi
::*3d-inner-color
* (make-gray-color .65))
616 (setf clim-clx
::*clx-text-sizes
*
629 (setf *frame
* (make-application-frame 'closure
))
631 (run-frame-top-level *frame
*))
632 (ignore-errors (ws/netlib
::commit-cache
))
633 (setf *closure-process
* nil
))))
635 (setf *closure-process
*
636 (clim-sys:make-process
#'run-frame
:name
"Closure")))
638 (setf *closure-process
* (clim-sys:current-process
))
641 (defun write-status (string)
642 (window-clear (find-pane-named *frame
* 'status
))
643 (write-string string
(find-pane-named *frame
* 'status
))
644 (clim-backend:port-force-output
(find-port)))
646 (defun write-wholine (string)
647 (let ((wholine (find-pane-named *frame
* 'wholine
)))
648 (window-clear wholine
)
649 (write-string string wholine
)
650 (clim-backend:port-force-output
(find-port))))
654 (let ((*standard-output
* *trace-output
*))
655 (clim-sys:make-process
657 (with-simple-restart (forget "Just forget rendering this page.")
658 (let* ((*package
* (find-package :r2
))
659 (*pane
* (current-pane)))
660 (with-sheet-medium (*medium
* *pane
*)
661 (let ((device (make-instance 'closure
/clim-device
::clim-device
:medium
*pane
*)))
662 (setf (sheet-pointer-cursor *pane
*) :busy
)
663 (setq url
(r2::parse-url
* url
))
664 (let ((request (clue-gui2::make-request
:url url
:method
:get
)))
665 (write-status "Fetching Document ...")
666 (multiple-value-bind (io header
)
667 (clue-gui2::open-document-4 request
)
668 (let ((new-location (netlib::get-header-field header
:location
)))
670 (unless (string-equal new-location
(url:unparse-url url
))
671 (setq url
(url:parse-url new-location
)))))
672 (let* ((doc (make-instance 'r2
::document
674 :location
(r2::parse-url
* url
)
676 :pt
(clue-gui2::make-pt-from-input
678 (netlib::get-header-field header
:content-type
) url
) )))
679 (write-status "Rendering ...")
680 (setf *current-document
* doc
)
681 (let ((closure-protocol:*document-language
*
682 (if (sgml::pt-p
(r2::document-pt doc
))
683 (make-instance 'r2
::html-4.0-document-language
)
684 (make-instance 'r2
::xml-style-document-language
)))
685 (closure-protocol:*user-agent
* nil
)
686 (r2::*canvas-width
* (bounding-rectangle-width (sheet-parent *pane
*))))
687 (window-clear *pane
*)
688 (closure-protocol:render
689 closure-protocol
:*document-language
*
692 (setf *current-pt
* (r2::document-pt doc
))
696 (setf (clim-tab-layout:tab-page-title
(current-page))
697 (renderer::document-title
*current-document
*))
698 (write-wholine (format nil
"Title: ~A~%~@[Modified: ~A~]"
699 (renderer::document-title
*current-document
*)
700 (or (netlib::get-header-field header
:last-modified
)
701 (netlib::get-header-field header
:date
))))
702 (let ((x2 (bounding-rectangle-max-x (stream-output-history *pane
*)))
703 (y2 (bounding-rectangle-max-y (stream-output-history *pane
*))))
704 (setf y2
(max y2 r2
::*document-height
*))
705 (clim:change-space-requirements
*pane
* :width x2
:height y2
)
706 ;; While we are at it, force a repaint
707 (handle-repaint *pane
* (sheet-region (pane-viewport *pane
*)))
708 (clim-backend:port-force-output
(find-port)))))))
709 (setf (sheet-pointer-cursor *pane
*) :default
)
710 (write-status "Done.")))))
711 #+nil
(clim-backend:port-force-output
(find-port))))))
714 (let ((*standard-output
* *trace-output
*))
715 (funcall ;;clim-sys:make-process
717 (with-simple-restart (forget "Just forget rendering this page.")
718 (let ((*package
* (find-package :r2
))
719 (*pane
* (current-pane)))
720 (window-clear *pane
*)
721 (with-sheet-medium (*medium
* *pane
*)
722 (write-status "Rendering ...")
723 (let ((closure-protocol:*document-language
*
724 (if (sgml::pt-p
(r2::document-pt
*current-document
*))
725 (make-instance 'r2
::html-4.0-document-language
)
726 (make-instance 'r2
::xml-style-document-language
)))
727 (closure-protocol:*user-agent
* nil
)
729 (bounding-rectangle-width (sheet-parent *pane
*))))
731 (let ((x2 (bounding-rectangle-max-x (stream-output-history *pane
*)))
732 (y2 (bounding-rectangle-max-y (stream-output-history *pane
*))))
733 (setf y2
(max y2 r2
::*document-height
*))
734 (clim:change-space-requirements
*pane
* :width x2
:height y2
)
735 ;; While we are at it, force a repaint
736 (handle-repaint *pane
* (sheet-region (pane-viewport *pane
*)))))
737 (write-status "Done."))))))))
739 (defvar *current-document
*)
740 (defvar *current-pt
*)
742 ;;;; ----------------------------------------------------------------------------------------------------
744 (define-presentation-translator url-from-string
749 (define-presentation-method accept
((type url
)
751 (view (eql +textual-view
+))
752 &key default default-type
)
753 (url:parse-url
(accept 'string
:stream stream
:prompt nil
)))
758 (define-closure-command (com-clear-interactor :name t
) ()
759 (clim:window-clear
(clim:frame-query-io clim
:*application-frame
*)))
761 ;;;; ----------------------------------------------------------------------------------------------------
764 (define-closure-command (com-zoom-100%
:name t
) ()
765 (setq gui
:*zoom-factor
* 1.0)
766 (send-closure-command 'com-reflow
))
768 (define-closure-command (com-zoom-in :name t
:keystroke
(#\
+ :control
)) ()
769 (write-status "Zooming in...")
770 (setq gui
:*zoom-factor
* (* gui
:*zoom-factor
* 1.2))
771 (send-closure-command 'com-reflow
))
773 (define-closure-command (com-zoom-out :name t
:keystroke
(#\-
:control
)) ()
774 (write-status "Zooming out...")
775 (setq gui
:*zoom-factor
* (* gui
:*zoom-factor
* 0.8))
776 (send-closure-command 'com-reflow
))
778 (define-closure-command (com-page-up :name t
779 :keystroke
:prior
) ()
780 (let* ((pane (current-pane))
781 (scrollbar (slot-value (pane-scroller pane
) 'climi
::vscrollbar
))
782 (current-y (gadget-value scrollbar
))
783 (window-height (bounding-rectangle-height (pane-viewport-region pane
))))
784 (scroll-extent pane
0 (max (gadget-min-value scrollbar
) (- current-y
(* 0.9 window-height
))))))
786 (define-closure-command (com-page-down :name t
788 (let* ((pane (current-pane))
789 (scrollbar (slot-value (pane-scroller pane
) 'climi
::vscrollbar
))
790 (current-y (gadget-value scrollbar
))
791 (window-height (bounding-rectangle-height (pane-viewport-region pane
))))
792 (scroll-extent pane
0
793 (min (gadget-max-value scrollbar
) (+ current-y
(* 0.9 window-height
))))))
795 (define-closure-command (com-beginning-of-page :name t
796 :keystroke
(:home
:control
)) ()
797 (let* ((pane (current-pane))
798 (scrollbar (slot-value (pane-scroller pane
) 'climi
::vscrollbar
)))
799 (scroll-extent pane
0 (gadget-min-value scrollbar
))))
801 (define-closure-command (com-end-of-page :name t
802 :keystroke
(:end
:control
)) ()
803 (let* ((pane (current-pane))
804 (scrollbar (slot-value (pane-scroller pane
) 'climi
::vscrollbar
)))
805 (scroll-extent pane
0 (gadget-max-value scrollbar
))))
807 (define-closure-command (com-redraw :name t
:keystroke
(#\r :control
)) ()
808 (let* ((*pane
* (current-pane)))
809 (handle-repaint *pane
* (sheet-region (pane-viewport *pane
*))))
810 (clim-backend:port-force-output
(find-port)))
812 (define-closure-command (com-tex-mode-on :name t
) ()
813 (setq renderer
:*tex-mode-p
* t
)
814 (setq renderer
:*hyphenate-p
* t
)
815 (send-closure-command 'com-reflow
))
817 (define-closure-command (com-tex-mode-off :name t
) ()
818 (setq renderer
:*tex-mode-p
* nil
)
819 (setq renderer
:*hyphenate-p
* nil
)
820 (send-closure-command 'com-reflow
))
822 ;; for Closure developers
823 (define-closure-command (com-inspect-page :name t
) ()
824 (write-status "Loading Clouseau")
825 (asdf:oos
'asdf
:load-op
:clouseau
)
826 (write-status "Starting inspector")
827 (funcall (find-symbol "INSPECTOR" :clouseau
) *current-document
* :new-process t
))