The KDE Linux desktop environment provides a standard dialog for printing a document to a printer, faxing it, generating a PDF/PostScript file or emailing a PDF file. This functionality is accessible from the shell via the `kprinter' command, which accepts a PostScript file from stdin.
I tried to use kprinter with McCLIM's PostScript backend and CMUCL Snapshot 2005-07 (19B) under Slackware Linux 10.0 with code like this:
;;; Requires CMUCL and KDE
(in-package :clim-user)
(define-application-frame kprinter () () (:panes (display :application :scroll-bars t :display-function 'display-graphics)) (:layouts (default display)))
(defun display-graphics (frame stream) (declare (ignore frame)) (draw-rectangle* stream 20 50 120 100 :filled t :ink +red+) (draw-circle* stream 220 150 30 :filled t :ink +green+) (draw-text* stream "CLIMz rulez" 320 250 :text-size :huge :ink +blue+))
(define-kprinter-command (com-quit :menu t :name t) () (frame-exit *application-frame*))
(define-kprinter-command (com-print :menu t :name t) () (let* ((process (ext:run-program "kprinter" nil :input :stream :wait nil)) (process-stream (ext:process-input process))) (unwind-protect (with-output-to-postscript-stream (stream process-stream) (display-graphics *application-frame* stream)) (finish-output process-stream) (ext:process-close process) (ext:process-wait process t))))
(defun print-dialog () (run-frame-top-level (make-application-frame 'kprinter :width 550 :height 350)))
This doesn't work as expected. If I confirm the dialog with the "Print" button, the print jobs is correctly generated, but the McCLIM application freezes and I have to abort the session. If I dismiss the dialog with "Cancel", I get this error:
* (clim-user::print-dialog)
Error in function UNIX::SIGPIPE-HANDLER: SIGPIPE at #x4011EC58. [Condition of type SIMPLE-ERROR]
Restarts: 0: [ABORT] Return to application command loop 1: Return to Top-Level.
Debug (type H for help)
(UNIX::SIGPIPE-HANDLER #<unused-arg> #<unused-arg> #.(SYSTEM:INT-SAP #x3FFFC5A0)) Source: Error finding source: Error in function DEBUG::GET-FILE-TOP-LEVEL-FORM: Source file no longer exists: target:code/signal.lisp. 0] backtrace
0: (UNIX::SIGPIPE-HANDLER #<unused-arg> #<unused-arg> #.(SYSTEM:INT-SAP #x3FFFC5A0)) 1: (UNIX::SIGPIPE-HANDLER 3 #<unused-arg> #<unused-arg> #.(SYSTEM:INT-SAP #x3FFFC5A0))[:EXTERNAL] 2: ("call_into_lisp+#x8C [#x805529C] cmucl") 3: ("funcall3+#x29 [#x805508D] cmucl") 4: ("interrupt_handle_now+#xFF [#x8050A03] cmucl") 5: ("NIL+#x8050E1B [#x8050E1B] cmucl") 6: ("NIL+#x4007A0A8 [#x4007A0A8] /lib/libc.so.6") 7: (LISP::DO-OUTPUT #<Stream for descriptor 7> #.(SYSTEM:INT-SAP #x4030C000) 0 3972 ...) 8: (LISP::FLUSH-OUTPUT-BUFFER #<Stream for descriptor 7>) 9: (LISP::FD-STREAM-MISC-ROUTINE #<Stream for descriptor 7> :FINISH-OUTPUT NIL #<unused-arg>) 10: (FINISH-OUTPUT #<Stream for descriptor 7>) 11: ((FLET #:G0 CLIM-POSTSCRIPT::INVOKE-WITH-OUTPUT-TO-POSTSCRIPT-STREAM))[:CLEANUP] 12: (CLIM-POSTSCRIPT::INVOKE-WITH-OUTPUT-TO-POSTSCRIPT-STREAM #<Function (FLET #:G26 CLIM-USER::COM-PRINT) {58D0D9B1}> #<Stream for descriptor 7> :DEVICE-TYPE NIL ...) 13: (CLIM-USER::COM-PRINT) 14: ((METHOD CLIM:DEFAULT-FRAME-TOP-LEVEL NIL (CLIM:APPLICATION-FRAME)) (#() . #(# # # # # ...)) #<unused-arg> #<CLIM-USER::KPRINTER {58143915}> NIL) 15: ("LAMBDA (.KEYARGS-START. .VALID-KEYS. G5411)" #<unused-arg> #<unused-arg> #<CLIM-USER::KPRINTER {58143915}> NIL) 16: ((METHOD CLIM:RUN-FRAME-TOP-LEVEL NIL (CLIM:APPLICATION-FRAME)) (#(20) . #()) #<unused-arg> #<CLIM-USER::KPRINTER {58143915}> #<unused-arg>) 17: ((METHOD CLIM:RUN-FRAME-TOP-LEVEL (:AROUND) (CLIM:APPLICATION-FRAME)) (#(16 15) . #(#)) #S(PCL::FAST-METHOD-CALL :FUNCTION #<Function # {116ABFF9}> :PV-CELL (# . #) :NEXT-METHOD-CALL NIL :ARG-INFO (1 . T)) #<CLIM-USER::KPRINTER {58143915}> NIL) 18: (INTERACTIVE-EVAL (CLIM-USER::PRINT-DIALOG)) 19: (LISP::%TOP-LEVEL) 20: ((LABELS LISP::RESTART-LISP SAVE-LISP))
0]
Is there any way of returning control back to the McCLIM application after printing? There's probably something fundamental about spawning external processes and their I/O streams I don't understand.
Paolo