[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: catch-cancel



Although I can't tell you exactly where the mysterious and
omnipresent CATCH-CANCEL sits, I can suggest a way to avoid
the problem in general. 

Rather than using CATCH/THROW (and kin) with their dynamic
tags, use BLOCK/RETURN-FROM. These are lexically scoped
and a lot less prone to funny interactions with other code.

Below is a simple example how to interrupt a process with a
button action using BLOCK/RETURN-FROM.


;;; Implementation notes:
;;;
;;; 1. The window created is initially hidden, so that the cancel
;;;    button can't be clicked until after the UNWIND-PROTECT
;;;    starts.
;;; 2. The BLOCK is not really needed here. We could just say
;;;    (RETURN-FROM TEST-CANCEL ...).
;;; 3. For maintenance and generality, I deliberately set things
;;;    up so that the example-specific return values (:CANCELLED
;;;    and :FINISHED) appear in the same place (the calling function).


(defun test-cancel ()
  (block search-loop
    (let ((w (make-button-window
              #'(lambda (dialog-item)
                  (declare (ignore dialog-item))
                  (return-from search-loop :cancelled)))))
      (unwind-protect
        (progn (window-show w)
               (dotimes (i 200 :finished) ;; standing in for a real search
                 (princ ".")))
        (window-close w)))))

(defun make-button-window (exit-fn)
  (make-instance 'window
    :window-show nil
    :view-position :centered
    :view-size #@(100 100)
    :view-subviews (list (make-cancel-button exit-fn))))

(defun make-cancel-button (exit-fn)
  (make-dialog-item 'button-dialog-item
                    #@(20 30) #@(60 20)
                    "Cancel"
                    exit-fn))

-- 
Chris