(DEFINE-FILE-INFO READTABLE "XCL" PACKAGE "PLOT")(il:filecreated " 1-Dec-88 12:09:49" il:{qv}<idl>next>plot-fns.\;38 112101       il:|changes| il:|to:|  (il:functions interval-length ti-length apply-after-method copy-plot                                     default-tic-list-fn copy-plot-object icon-fn track-plot-object                                     effective-middle-menu delete-plot-objects delete-selected-object                                    default-menu setf-default-menu delete-plot-object)      il:|previous| il:|date:| "30-Nov-88 18:31:02" il:{qv}<idl>next>plot-fns.\;37); Copyright (c) 1988 by Xerox Corporation.  All rights reserved.(il:prettycomprint il:plot-fnscoms)(il:rpaqq il:plot-fnscoms          ((il:coms                   (il:* il:|;;| "datatype def's")                  (il:structures plot scale-info axis-interval axis-info tic-info margin extent)                                    (il:* il:|;;| "extended access functions")                  (il:functions plot-x-lower plot-x-upper plot-y-lower plot-y-upper interval-length                          ti-length)                  (il:structures plot-object plot-methods))           (il:coms                   (il:* il:|;;| "plot properties ")                  (il:functions plot-prop setf-plot-prop)                  (il:setfs plot-prop)                                    (il:* il:|;;| "plot-object props ")                  (il:functions plot-object-prop setf-plot-object-prop)                  (il:setfs plot-object-prop))           (il:functions apply-after-method)           (il:functions make-plot copy-plot)           (il:coms                   (il:* il:|;;| "Plot windows")                  (il:functions open-plot-window close-plot-window redraw-plot-window                          min-stream-region-size)                  (il:functions closest-plot-object)                  (il:functions repaint-fn close-fn copy-button-event-fn hardcopy-fn icon-fn)                  (il:functions button-event-fn track-plot-object effective-middle-menu)                  (il:functions print-plot-prompt))           (il:coms                   (il:* il:|;;| "rendering ")                  (il:variables *small-plot-font* *large-plot-font*)                  (il:functions draw-plot)                  (il:functions update-view-port box-region)                                    (il:* il:|;;| "Tics")                  (il:functions tics-p setf-tics-p)                  (il:functions make-tic-lists normalize-tic-list float-to-string enum-to-string                          fnum-to-string)                  (il:functions get-tic-list tic-list-fn setf-tic-list-fn default-tic-list-fn)                                    (il:* il:|;;| "margins")                  (il:functions compute-top-bottom-margin compute-left-right-margin)                  (il:functions draw-top-margin draw-bottom-margin draw-left-margin draw-right-margin                         )                  (il:functions draw-tics-top-bottom draw-tics-left-right)                  (il:functions draw-label-top-bottom draw-label-left-right)                                    (il:* il:|;;| "Plot scaling")                  (il:functions rescale-plot rescale-x-axis rescale-y-axis)                  (il:functions tic-info-fn setf-tic-info-fn default-tic-info-fn)                  (il:functions interval-fn setf-interval-fn default-interval-fn                          no-change-interval-fn)                  (il:functions scale plot-objects-extent)                  (il:functions adjust-scale-p update-extent add-extent-to-extent                          add-position-to-extent)                  (il:functions extend-axis extended-interval-fn)                  (il:functions plot-world-extent setf-plot-world-extent plot-interval                          setf-plot-interval)                  (il:functions region-to-extent extent-to-region))           (il:coms                   (il:* il:|;;| "plot labels")                  (il:functions plot-label setf-plot-label))           (il:coms                   (il:* il:|;;| "Plot object methods")                  (il:functions draw-plot-object erase-plot-object highlight-plot-object                          lowlight-plot-object plot-object-extent distance-to-plot-object                          label-plot-object unlabel-plot-object move-plot-object copy-plot-object)                  (il:functions add-plot-object add-plot-objects)                  (il:functions delete-plot-object delete-plot-objects)                  (il:functions relabel-selected-object delete-selected-object undelete-last-object)                  (il:functions translate-plot-object)                  (il:functions select-plot-object deselect-plot-object))           (il:coms                   (il:* il:|;;| "Plot menus ")                  (il:functions default-when-selected-fn)                  (il:functions plot-menu setf-plot-menu)                  (il:functions plot-menu-items setf-plot-menu-items add-plot-menu-items                          delete-plot-menu-items)                  (il:coms (il:variables *default-middle-menu* *default-right-menu*)                         (il:functions manually-rescale-plot ask-for-scale toggle-label ask-for-label                                ask-for-which-label toggle-tics toggle-fixed-right-menu))                  (il:functions default-menu setf-default-menu)                                    (il:* il:|;;| "Do we want this setf?")                  (il:setfs default-menu)                  (il:functions fix-right-menu unfix-right-menu remove-fixed-right-menu))           (il:coms                   (il:* il:|;;| "Misc functions")                  (il:functions which-plot))           (xcl:file-environments "PLOT-FNS")))(il:* il:|;;| "datatype def's")(defstruct (plot (:constructor %make-plot)                     (:copier %copy-plot))   objects   window   view-port   prompt-window   scale-info   left-margin   right-margin   top-margin   bottom-margin   middle-menu   right-menu   other-menus   selected-object   save-list   prop-list)(defstruct (scale-info (:conc-name "SI-"))   x-interval   x-axis-info   x-tic-info   y-interval   y-axis-info   y-tic-info)(defstruct (axis-interval (:conc-name "INTERVAL-")                              (:type list))   min   max)(defstruct (axis-info (:conc-name "AI-")                          (:type list))   (interval-fn 'default-interval-fn)   (tic-info-fn 'default-tic-info-fn))(defstruct (tic-info (:conc-name "TI-"))   min   max   inc   n)(defstruct margin   label   tic-list   (tic-list-fn 'default-tic-list-fn)   tics-p)(defstruct extent   min-x   max-x   min-y   max-y)(il:* il:|;;| "extended access functions")(defmacro plot-x-lower (plot)   `(interval-min (si-x-interval (plot-scale-info ,plot))))(defmacro plot-x-upper (plot)   `(interval-max (si-x-interval (plot-scale-info ,plot))))(defmacro plot-y-lower (plot)   `(interval-min (si-y-interval (plot-scale-info ,plot))))(defmacro plot-y-upper (plot)   `(interval-max (si-y-interval (plot-scale-info ,plot))))(defmacro interval-length (interval)   (pt:once-only (interval)          `(- (interval-max ,interval)              (interval-min ,interval))))(defmacro ti-length (ti)   (pt:once-only (ti)          `(- (ti-max ,ti)              (ti-min ,ti))))(defstruct (plot-object (:constructor nil)                            (:copier nil))   methods   menu   label   prop-list)(defstruct (plot-methods (:conc-name "PM-"))   draw-fn   erase-fn   highlight-fn   lowlight-fn   extent-fn   distance-fn   label-fn   move-fn   copy-fn   put-fn   get-fn)(il:* il:|;;| "plot properties ")(defmacro plot-prop (plot prop)   `(getf (plot-prop-list ,plot)          ,prop))(defun setf-plot-prop (plot prop new-value)   (setf (getf (plot-prop-list plot)               prop)         new-value))(defsetf plot-prop setf-plot-prop)(il:* il:|;;| "plot-object props ")(defmacro plot-object-prop (object prop)   `(getf (plot-object-prop-list ,object)          ,prop))(defun setf-plot-object-prop (object prop new-value)   (setf (getf (plot-object-prop-list object)               prop)         new-value))(defsetf plot-object-prop setf-plot-object-prop)(defmacro apply-after-method (method &rest args)   (pt:once-only (method)          `(and ,method (funcall ,method ,@args))))(defun make-plot (&key region title border open-window-p                           (initial-world-extent (make-extent :min-x 0.0 :max-x 1.0 :min-y 0.0 :max-y                                                        1.0)))   (il:* il:|;;| "Creates a PLOT.  If OPEN-WINDOW-P is T then the PLOT's asssociated window is opened.  The other arguments are passed to make-window.")   (let ((plot (%make-plot :scale-info (let ((min-x (extent-min-x initial-world-extent))                                             (max-x (extent-max-x initial-world-extent))                                             (min-y (extent-min-y initial-world-extent))                                             (max-y (extent-max-y initial-world-extent)))                                            (make-scale-info :x-interval (make-axis-interval :min                                                                                 min-x :max max-x)                                                   :x-axis-info                                                   (make-axis-info)                                                   :x-tic-info                                                   (default-tic-info-fn min-x max-x)                                                   :y-interval                                                   (make-axis-interval :min min-y :max max-y)                                                   :y-axis-info                                                   (make-axis-info)                                                   :y-tic-info                                                   (default-tic-info-fn min-y max-y)))                      :left-margin                      (make-margin)                      :right-margin                      (make-margin)                      :top-margin                      (make-margin)                      :bottom-margin                      (make-margin)                      :middle-menu                      (default-menu :middle)                      :right-menu                      (default-menu :right))))        (il:* il:|;;| "Cache display parameters until OPENPLOTWINDOW is called")        (if (or region title border)            (setf (plot-window plot)                  (list region title border)))        (if open-window-p (open-plot-window plot))        plot))(defun copy-plot (plot &key region title border open-p)   (il:* il:|;;| "Copies a PLOT.  Copying of PLOT-PROP's is handled as follows.  If PLOT has a COPY-FN, calls it with NEW-PLOT, PLOT as args, and expects it to copy the PLOT-PROPS intelligently, else only copies the top-level list structure.")   (let ((new-plot (%copy-plot plot)))        (il:* il:|;;| "Plot objects are not shared since they may be destructively modified")        (setf (plot-objects new-plot)              (mapcar #'(lambda (object)                               (copy-plot-object object))                     (plot-objects plot)))        (il:* il:|;;| "Don't share any display associated objects")        (setf (plot-window new-plot)              nil)        (setf (plot-view-port new-plot)              nil)        (setf (plot-prompt-window new-plot)              nil)        (il:* il:|;;| "scale-info and margins are side-effected, hence must be copied")        (setf (plot-scale-info new-plot)              (copy-scale-info (plot-scale-info plot)))        (setf (plot-left-margin new-plot)              (copy-margin (plot-left-margin plot)))        (setf (plot-right-margin new-plot)              (copy-margin (plot-right-margin plot)))        (setf (plot-top-margin new-plot)              (copy-margin (plot-top-margin plot)))        (setf (plot-bottom-margin new-plot)              (copy-margin (plot-bottom-margin plot)))        (il:* il:|;;| "OK to share Menus")        (setf (plot-selected-object new-plot)              nil)        (setf (plot-save-list new-plot)              nil)        (il:* il:|;;| "Hook for copying plot props")        (setf (plot-prop-list new-plot)              (pt:with-collection (do* ((prop-name-tail (plot-prop-list plot)                                               (cddr prop-name-tail))                                        (prop-name (car prop-name-tail)                                               (car prop-name-tail))                                        (prop-value-tail (cdr prop-name-tail)                                               (cdr prop-name-tail))                                        (prop-value (car prop-value-tail)                                               (car prop-value-tail)))                                       ((null prop-name-tail))                                     (when prop-value                                         (pt:collect prop-name)                                         (pt:collect prop-value)))))        (if (or region title border)            (il:* il:|;;| "Cache the display parameters")            (setf (plot-window new-plot)                  (list region title border)))        (apply-after-method (plot-prop plot :when-copied)               plot new-plot)        (if open-p (open-plot-window new-plot))        new-plot))(il:* il:|;;| "Plot windows")(defun open-plot-window (plot)   (il:* il:|;;|  "Open window associated with PLOT.  Creates circularities later broken by PLOT-CLOSE-FN")   (let ((window (plot-window plot)))        (unless (open-window-p window)            (if (shrunken-window-p window)                (il:* il:|;;| "Shrunken window")                (expand-window window)                (il:* il:|;;| "Closed window")                (let ((prompt-window (plot-prompt-window plot))                      reshape-p prompt-created-p)                     (if (not (window-p window))                         (let ((region (if (consp window)                                           (first window)                                           (make-region 0 0 100 100)))                               (title (if (consp window)                                          (second window)                                          "Plot Window"))                               (border (if (consp window)                                           (third window))))                              (if (null window)                                  (setq reshape-p t))                              (setf (plot-window plot)                                    (setq window (make-window :region region :title title                                                         :border-size border :not-open-p t)))))                     (il:* il:|;;| "setup plot window methods")                     (setf (window-method window :repaint)                           'repaint-fn)                     (add-window-method window :reshape 'repaint-fn)                     (add-window-method window :close 'close-fn)                     (setf (window-method window :button-event)                           'button-event-fn)                     (setf (window-method window :right-button-event)                           'button-event-fn)                     (setf (window-method window :copy-button-event)                           'copy-button-event-fn)                     (setf (window-method window :hardcopy)                           'hardcopy-fn)                     (setf (window-method window :shrink)                           'icon-fn)                     (il:* il:|;;| "setup plot window props")                     (setf (window-prop window ':plot)                           plot)                     (il:* il:|;;| "Rest of VIEWPORT initializations in REDRAWPLOTWINDOW")                     (setf (plot-view-port plot)                           (make-view-port (window-dsp window)))                     (il:* il:|;;| "Get a prompt window, if none exists")                     (when (null prompt-window)                         (setf (plot-prompt-window plot)                               (setq prompt-window (make-window :region                                                          (make-region 0 0 100                                                                 (height-if-window                                                                  (font-height (default-font :display                                                                                      ))))                                                          :not-open-p t)))                         (setf (stream-scroll prompt-window)                               :on)                         (setf (window-method prompt-window :page-full)                               'identity)                         (setf (window-max-size prompt-window)                               (cons most-positive-fixnum (region-height (window-region prompt-window                                                                                ))))                         (setq prompt-created-p t))                     (il:* il:|;;| "Establish a min size for the window")                     (make-tic-lists plot)                     (let* ((min-size (min-stream-region-size (window-dsp window)                                             plot))                            (min-extent (cons (width-if-window (car min-size)                                                     (window-border window))                                              (height-if-window (cdr min-size)                                                     (window-title window)                                                     (window-border window)))))                           (if (null (attached-windows window))                               (setf (window-min-size window)                                     min-extent)                               (setf (main-window-min-size window)                                     min-extent))                           (when (and (not reshape-p)                                      (or (< (window-width window)                                             (car min-size))                                          (< (window-height window)                                             (cdr min-size))))                               (setq reshape-p t)                               (print-prompt "Window too small: reshape")))                     (if reshape-p                         (il:* il:|;;| "Shaping window implies redrawing it")                         (reshape-window window)                         (let ((view-port (plot-view-port plot))                               (selected-object (plot-selected-object plot)))                              (open-window window)                              (update-view-port view-port (stream-clipping-region window)                                     plot)                              (draw-plot plot (window-dsp window)                                     view-port                                     (stream-clipping-region window))                              (if selected-object (highlight-plot-object selected-object plot))))                     (il:* il:|;;| "Attach the promptwindow if necessary")                     (attach-window prompt-window window :top)                     (il:* il:|;;| "attach the fixed menu")                     (if (plot-prop plot :fixed-right-menu-p)                         (fix-right-menu plot))                     (il:* il:|;;| "A user hook")                     (apply-after-method (plot-prop plot :when-opened)                            plot))))        window))(defun close-plot-window (plot)   (let ((plot-window (plot-window plot)))        (il:* il:|;;| "Unfix the right menu")        (unfix-right-menu plot)        (il:* il:|;;| "Cleanup window methods and props ")        (when (window-p plot-window)            (setf (window-prop plot-window :plot)                  nil)            (delete-window-method plot-window :reshape 'repaint-fn)            (delete-window-method plot-window :close 'close-fn)            (setf (window-method plot-window :button-event)                  'il:totopw)            (setf (window-method plot-window :repaint)                  nil)            (setf (window-method plot-window :right-button-event)                  nil)            (setf (window-method plot-window :copy-button-event)                  nil)            (setf (window-method plot-window :hardcopy)                  nil)            (setf (window-method plot-window :shrink)                  nil)            (detach-all-windows plot-window)            (close-window plot-window))        (il:* il:|;;| "A user hook")        (apply-after-method (plot-prop plot ':when-closed)               plot)))(defun redraw-plot-window (plot)   (il:* il:|;;| "Redraws the PLOTWINDOW of a PLOT")   (let ((plot-window (plot-window plot)))        (if (not (open-window-p plot-window))            (il:* il:|;;| "Assumes OPENPLOTWINDOW will call REDRAWPLOTWINDOW")            (open-plot-window plot)            (let ((view-port (plot-view-port plot))                  (selected-object (plot-selected-object plot))                  min-size)                 (il:* il:|;;| "Setup the tic lists ")                 (make-tic-lists plot)                 (il:* il:|;;| "Establish a min size for the WINDOW")                 (setq min-size (min-stream-region-size (window-dsp plot-window)                                       plot))                 (il:* il:|;;|                "Uses MAINWINDOWMINSIZE since PLOTWINDOW is the main window of a group")                 (setf (main-window-min-size plot-window)                       (cons (width-if-window (car min-size)                                    (window-border plot-window))                             (height-if-window (cdr min-size)                                    (window-title plot-window)                                    (window-border plot-window))))                 (if (or (< (window-width plot-window)                            (car min-size))                         (< (window-height plot-window)                            (cdr min-size)))                     (progn (print-prompt "Plotwindow too small: reshape")                            (il:* il:|;;| "Assumes RESHAPE-WINDOW will call REDRAW-PLOT-WINDOW")                            (reshape-window plot-window))                     (progn (update-view-port view-port (stream-clipping-region plot-window)                                   plot)                            (clear-window plot-window)                            (draw-plot plot (window-dsp plot-window)                                   view-port                                   (stream-clipping-region plot-window))                            (if selected-object (highlight-plot-object selected-object view-port plot                                                       ))))))))(defun min-stream-region-size (stream plot)   (il:* il:|;;| "Compute the minimun acceptable size for a plot STREAMREGION.  In the case of PLOTWINDOWS, corresponds to the min exceptable interior size of the WINDOW.  Returns a dotted pair (MINX  . MINY)")   (il:* il:|;;| "Sizes are (width  . height) pairs")   (let ((bottom-margin-size (compute-top-bottom-margin stream (plot-bottom-margin plot)                                    plot))         (left-margin-size (compute-left-right-margin stream (plot-left-margin plot)                                  plot))         (right-margin-size (compute-left-right-margin stream (plot-right-margin plot)                                   plot))         (top-margin-size (compute-top-bottom-margin stream (plot-top-margin plot)                                 plot))         min-x min-y)        (il:* il:|;;| "The constant 100 is heuristic")        (setq min-x (+ (car left-margin-size)                       (max (car bottom-margin-size)                            (car top-margin-size)                            100)                       (car right-margin-size)))        (setq min-y (+ (cdr bottom-margin-size)                       (max (cdr left-margin-size)                            (cdr right-margin-size)                            100)                       (cdr top-margin-size)))        (cons min-x min-y)))(defun closest-plot-object (plot stream-position)   (let (min min-object)        (dolist (object (plot-objects plot))            (let ((dist (distance-to-plot-object object stream-position plot)))                 (if (or (null min)                         (< dist min))                     (setq min dist min-object object))))        min-object))(defun repaint-fn (window)   (il:* il:|;;| "Redraws a PLOT WINDOW based on data stored on property list of WINDOW")   (redraw-plot-window (window-prop window ':plot)))(defun close-fn (window)   (close-plot-window (window-prop window ':plot)))(defun copy-button-event-fn (window)   (il:* il:|;;| "Allows plots to be copy selected")   (let ((plot (window-prop window ':plot)))        (invert-window window)        (until-mouse-state :up)        (invert-window window)        (when (inside-p window (window-cursor window))            (let ((imageobj (case (pop-up-menu (il:constant (make-menu :items                                                                   '(("Plot" 'plot)                                                                     ("Bitmap" 'bitmap)))))                                (plot (make-plot-image-object plot))                                (bitmap (make-plot-bitmap-object plot)))))                 (if imageobj (il:copyinsert imageobj))))))(defun hardcopy-fn (window printer-stream)   (il:* il:|;;| "Modified to allow hardcopy of plots on PRESS printers -- no landscape drawing")   (il:* il:|;;| "Modified to center plot on page")   (let ((window-region (stream-clipping-region window))         (plot (window-prop window ':plot))         (printer-view-port (make-view-port printer-stream))         printer-clipping-region stream-region)        (if (eq (il:imagestreamtype printer-stream)                'il:interpress)            (let ((micasperinch 2540))                 (if (> (region-width window-region)                        (region-height window-region))                     (progn                             (il:* il:|;;| "Print in landscape mode")                            (il:rotate.ip printer-stream 90)                            (il:concatt.ip printer-stream)                            (il:translate.ip printer-stream 0 (truncate (- (* 8.5 micasperinch))))                            (il:concatt.ip printer-stream)                            (il:* il:|;;| "Make sure the clippingregion is rational")                            (il:dspclippingregion (make-region (truncate (* 0.5 micasperinch))                                                         (truncate (* 0.5 micasperinch))                                                         (truncate (* 10 micasperinch))                                                         (truncate (* 7.5 micasperinch)))                                   printer-stream))                     (il:* il:|;;| "Make sure the clippingregion is rational")                     (il:dspclippingregion (make-region (truncate (* 0.5 micasperinch))                                                  (truncate (* 0.5 micasperinch))                                                  (truncate (* 7.5 micasperinch))                                                  (truncate (* 10 micasperinch)))                            printer-stream))))        (setq printer-clipping-region (stream-clipping-region printer-stream))        (il:* il:|;;| "Reset the margins")        (setf (stream-margin printer-stream :left)              (region-left printer-clipping-region))        (setf (stream-margin printer-stream :bottom)              (region-bottom printer-clipping-region))        (setf (stream-margin printer-stream :right)              (1- (+ (region-left printer-clipping-region)                     (region-width printer-clipping-region))))        (setf (stream-margin printer-stream :top)              (1- (+ (region-bottom printer-clipping-region)                     (region-height printer-clipping-region))))        (setq stream-region (let* ((k                                       (il:* il:|;;| "maintain the PLOTWINDOW's aspect ratio")                                      (min (truncate (region-width printer-clipping-region)                                                  (region-width window-region))                                           (truncate (region-height printer-clipping-region)                                                  (region-height window-region))))                                   (swidth (* k (region-width window-region)))                                   (sheight (* k (region-height window-region))))                                  (il:* il:|;;| "Center plot on page")                                  (make-region (+ (region-left printer-clipping-region)                                                  (truncate (- (region-width printer-clipping-region)                                                               swidth)                                                         2))                                         (+ (region-bottom printer-clipping-region)                                            (truncate (- (region-height printer-clipping-region)                                                         sheight)                                                   2))                                         swidth sheight)))        (make-tic-lists plot)        (update-view-port printer-view-port stream-region plot)        (draw-plot plot printer-stream printer-view-port stream-region)))(defun icon-fn (window old-icon)   (let ((plot (window-prop window ':plot))         (title-font (il:windowtitlefont))         icon-width icon-height subregion iconw view-port)        (if (> (window-width window)               (window-height window))            (setq icon-width (width-if-window 100)                  icon-height                  (height-if-window (truncate (* 100 (/ (window-height window)                                                        (window-width window))))))            (setq icon-width (width-if-window (truncate (* 100 (/ (window-width window)                                                                  (window-height window)))))                  icon-height                  (height-if-window 100)))        (if old-icon            (progn (reshape-window old-icon (make-region (region-left (window-region old-icon))                                                   (region-bottom (window-region old-icon))                                                   icon-width icon-height))                   (setq iconw old-icon))            (progn (setq iconw (make-window :region (position-region icon-width icon-height)))                   (il:dspfont title-font iconw)))        (clear-window iconw)        (setq subregion (make-region (truncate (* 0.1 (window-width iconw)))                               (truncate (* 0.1 (window-height iconw)))                               (truncate (* 0.8 (window-width iconw)))                               (truncate (* 0.8 (window-height iconw)))))        (setq view-port (make-view-port (window-dsp iconw)                               subregion                               (vp-world-region (plot-view-port plot))))        (box-region subregion iconw)        (let* ((objects (plot-objects plot))               (n (length objects)))              (if (< n 50)                  (il:* il:|;;| "few enough objects so that all of them may be drawn")                  (dolist (object objects)                      (draw-plot-object object view-port plot))                  (il:* il:|;;| "Sample the display list")                  (let ((sampling-rate (truncate n 50))                        (i 0))                       (dolist (object objects)                           (if (pt:fixnum-eq i sampling-rate)                               (progn (draw-plot-object object view-port plot)                                      (setq i 0))                               (incf i))))))        (il:centerprintinregion (or (plot-label plot ':top)                                    (if (not (string= (window-title window)                                                    "Plot Window"))                                        (window-title window))                                    "Plot Icon")               nil iconw)        iconw))(defun button-event-fn (window)   (to-top-window window)   (let* ((plot (window-prop window ':plot))          (view-port (plot-view-port plot))          (prompt-window (plot-prompt-window plot))          (selected-object (plot-selected-object plot)))         (cond            ((last-mouse-state-p :left)             (il:* il:|;;| "Plot object tracking")             (track-plot-object window))            ((last-mouse-state-p :middle)             (when selected-object                 (let ((menu (effective-middle-menu selected-object plot)))                      (when menu                          (il:* il:|;;| "establish then break circularities")                          (setf (menu-prop menu ':plot)                                plot)                          (setf (menu-prop menu ':mode)                                :middle)                          (pop-up-menu menu)                          (setf (menu-prop menu ':mode)                                nil)                          (setf (menu-prop menu ':plot)                                nil)))))            ((last-mouse-state-p :right)             (let ((right-menu (plot-right-menu plot)))                  (if (or (plot-prop plot ':fixed-right-menu-p)                          (> (position-y (window-cursor window))                             (window-height window))                          (null right-menu))                      (il:* il:|;;| "bring up the window-manager menu")                      (il:dowindowcom window)                      (progn (setf (menu-prop right-menu ':plot)                                   plot)                             (pop-up-menu right-menu)                             (setf (menu-prop right-menu ':plot)                                   nil))))))))(defun track-plot-object (window)   (let* ((plot (window-prop window ':plot))          (view-port (plot-view-port plot))          (prompt-window (plot-prompt-window plot))          (selected-object (plot-selected-object plot))          (old-x 0)          (old-y 0)          (stream-subregion (vp-stream-subregion view-port))          (position (make-position))          new-x new-y new-selected-object)         (loop (unless (mouse-state-p :left)                      (return nil))               (setf (position-x position)                     (setq new-x (last-mouse-x window)))               (setf (position-y position)                     (setq new-y (last-mouse-y window)))               (if (inside-p stream-subregion position)                   (unless (and (pt:fixnum-eq old-x new-x)                                (pt:fixnum-eq old-y new-y))                       (setq new-selected-object (closest-plot-object plot position))                       (when (and new-selected-object (not (eq new-selected-object selected-object)))                           (if selected-object (lowlight-plot-object selected-object view-port plot))                           (highlight-plot-object new-selected-object view-port plot)                           (setf (plot-selected-object plot)                                 (setq selected-object new-selected-object))                           (il:* il:|;;|                          "Try to print a meaningfull message in the PLOTPROMPTWINDOW")                           (let ((label (plot-object-label new-selected-object)))                                (if label                                    (print-plot-prompt label plot)                                    (terpri prompt-window)))))                   (when selected-object                       (lowlight-plot-object selected-object view-port plot)                       (setf (plot-selected-object plot)                             (setq selected-object nil))))               (setq old-x new-x)               (setq old-y new-y))))(defun effective-middle-menu (selected-object plot)   (let* ((object-menu (plot-object-menu selected-object))          (other-menus (plot-other-menus plot)))         (if object-menu             (if (menu-p object-menu)                 object-menu                 (il:* il:|;;| "Should be a symbol")                 (getf other-menus object-menu))             (let ((object-type (type-of-object selected-object)))                  (or (getf other-menus object-type)                      (if (pt:memq object-type *plot-object-types*)                          (let ((default-menu (default-menu object-type)))                               (and default-menu (setf-plot-menu plot object-type default-menu t))))                      (plot-middle-menu plot))))))(defun print-plot-prompt (text plot)   (let ((prompt-window (plot-prompt-window plot)))        (terpri prompt-window)        (princ text prompt-window)))(il:* il:|;;| "rendering ")(defvar *small-plot-font* (make-font :family '(:gacha 8 :mrr)))(defvar *large-plot-font* (make-font :family '(:gacha 12 :brr)))(defun draw-plot (plot stream view-port stream-region)   (il:* il:|;;| "Draws a plot on STREAM.  STREAM-REGION is the region the PLOT will occupy.  Does not clear STREAM-REGION before drawing.")   (il:* il:|;;| "Will not check, for the moment, that the stream-region is large enough")   (box-region (vp-stream-subregion view-port)          stream)   (draw-bottom-margin stream view-port stream-region plot)   (draw-left-margin stream view-port stream-region plot)   (draw-top-margin stream view-port stream-region plot)   (draw-right-margin stream view-port stream-region plot)   (dolist (object (plot-objects plot))       (draw-plot-object object view-port plot)))(defun update-view-port (view-port stream-region plot)   (let* ((scale-info (plot-scale-info plot))          (parent-stream (vp-parent-stream view-port))          (top-margin-size (compute-top-bottom-margin parent-stream (plot-top-margin plot)                                  plot))          (bottom-margin-size (compute-top-bottom-margin parent-stream (plot-bottom-margin plot)                                     plot))          (left-margin-size (compute-left-right-margin parent-stream (plot-left-margin plot)                                   plot))          (right-margin-size (compute-left-right-margin parent-stream (plot-right-margin plot)                                    plot)))         (setf (vp-world-region view-port)               (make-region (interval-min (si-x-interval scale-info))                      (interval-min (si-y-interval scale-info))                      (interval-length (si-x-interval scale-info))                      (interval-length (si-y-interval scale-info))))         (setf (vp-stream-subregion view-port)               (make-region (+ (region-left stream-region)                               (car left-margin-size))                      (+ (region-bottom stream-region)                         (cdr bottom-margin-size))                      (- (region-width stream-region)                         (+ (car left-margin-size)                            (car right-margin-size)))                      (- (region-height stream-region)                         (+ (cdr bottom-margin-size)                            (cdr top-margin-size)))))         (compute-transform view-port)))(defun box-region (region stream)               (il:* il:\; "Edited  5-May-87 18:16 by jop")   (il:* il:|;;| "Draw a box around a region in STREAM")   (let ((rleft (region-left region))         (rbottom (region-bottom region))         (rright (region-right region))         (rtop (region-top region))         (linewidth (stream-scale stream)))        (stream-draw-line rleft rbottom rright rbottom stream :width linewidth :operation boole-1)        (stream-draw-line rright rbottom rright rtop stream :width linewidth :operation boole-1)        (stream-draw-line rright rtop rleft rtop stream :width linewidth :operation boole-1)        (stream-draw-line rleft rtop rleft rbottom stream :width linewidth :operation boole-1)))(il:* il:|;;| "Tics")(defun tics-p (plot margin-name)   (margin-tics-p (ecase margin-name                      (:bottom (plot-bottom-margin plot))                      (:left (plot-left-margin plot))                      (:top (plot-top-margin plot))                      (:right (plot-right-margin plot)))))(defun setf-tics-p (plot margin-name new-state &optional no-update-p)   (let ((margin (ecase margin-name                     (:bottom (plot-bottom-margin plot))                     (:left (plot-left-margin plot))                     (:top (plot-top-margin plot))                     (:right (plot-right-margin plot)))))        (setf (margin-tics-p margin)              new-state)        (if (null no-update-p)            (redraw-plot-window plot))        new-state))(defun make-tic-lists (plot)                    (il:* il:\; "Edited  7-May-87 18:08 by jop")   (flet ((make-margin-tics (margin tic-info scale-info plot)                 (if (margin-tics-p margin)                     (setf (margin-tic-list margin)                           (normalize-tic-list (get-tic-list margin tic-info scale-info plot))))))         (let ((scale-info (plot-scale-info plot)))              (make-margin-tics (plot-bottom-margin plot)                     (si-x-tic-info scale-info)                     scale-info plot)              (make-margin-tics (plot-left-margin plot)                     (si-y-tic-info scale-info)                     scale-info plot)              (make-margin-tics (plot-right-margin plot)                     (si-y-tic-info scale-info)                     scale-info plot)              (make-margin-tics (plot-top-margin plot)                     (si-x-tic-info scale-info)                     scale-info plot)              nil)))(defun normalize-tic-list (tic-list)            (il:* il:\; "Edited 27-May-87 18:19 by jop")   (mapcar #'(lambda (tic)                    (let (value label)                         (if (consp tic)                             (setq value (car tic)                                   label                                   (cdr tic))                             (setq value (setq label tic)))                         (cons value (if (floatp label)                                         (float-to-string label)                                         label))))          tic-list))(defun float-to-string (x)                      (il:* il:\; "Edited  7-May-87 17:23 by jop")   (setq x (float x))   (il:* il:|;;| "Pure common lisp would be: ")   (il:* il:|;;| "(string-left-trim '(#\\Space) (if (let ((abs-x (abs x))) (and (not (zerop abs-x)) (or (< abs-x 0.001) (>= abs-x 1.0E+7)))) (format nil \"~10e\" x) (format nil \"~7f\" x)))")   (let ((string (make-array 14 :element-type 'string-char :fill-pointer 0))         (minus-p (and (< x 0.0)                       (setq x (- x))))         (round 6)         numstr intexp)        (if (and (not (zerop x))                 (or (< x 0.001)                     (>= x 1.0E+7)))            (multiple-value-bind (numstr intexp)                   (il:fltstr x round)                   (enum-to-string string numstr intexp minus-p))            (multiple-value-bind (numstr intexp)                   (il:fltstr x round)                   (fnum-to-string string numstr intexp minus-p)))))(defun enum-to-string (output-string mantissa-string integer-exponent minus-p)   (il:* il:|;;| "Prints exponential notation observing rounding & exponent spacing")   (macrolet ((push-output (char)                     `(progn (setf (aref output-string index)                                   ,char)                             (setq index (1+ index)))))          (let ((digits (length mantissa-string))                (index 0)                exp-offset)               (when minus-p (push-output #\-))               (il:* il:|;;| "Print the mantissa")               (push-output (aref mantissa-string 0))               (push-output #\.)               (do ((i 1 (1+ i)))                   ((eq i digits))                 (push-output (aref mantissa-string i)))               (il:* il:|;;| "Trim off extraneous zeros")               (do ((i (1- index)                       (1- i)))                   ((not (eq (aref output-string i)                             #\0))                    (if (not (eq (aref output-string i)                                 #\.))                        (setq index (1+ i))                        (setq index (+ i 2)))))               (il:* il:|;;| "mantissa done - now for the exponent")               (setq exp-offset (il:mkstring (- (+ integer-exponent digits)                                                1)))               (push-output #\E)               (dotimes (i (length exp-offset))                   (push-output (aref exp-offset i)))               (setf (fill-pointer output-string)                     index)               output-string)))(defun fnum-to-string (output-string mantissa-string integer-exponent minus-p)   (macrolet ((push-output (char)                     `(progn (setf (aref output-string index)                                   ,char)                             (setq index (1+ index)))))          (let* ((digits (length mantissa-string))                 (point-place (+ digits integer-exponent))                 (index 0))                (if minus-p (push-output #\-))                (cond                   ((< point-place 0)                    (push-output #\0)                    (push-output #\.)                    (dotimes (i (- point-place))                        (push-output #\0))                    (dotimes (i digits)                        (push-output (aref mantissa-string i))))                   ((< integer-exponent 0)                    (dotimes (i point-place)                        (push-output (aref mantissa-string i)))                    (push-output #\.)                    (do ((i point-place (1+ i)))                        ((eq i digits))                      (push-output (aref mantissa-string i))))                   (t (dotimes (i digits)                          (push-output (aref mantissa-string i)))                      (dotimes (i integer-exponent)                          (push-output #\0))                      (push-output #\.)                      (push-output #\0)))                (if (or (< point-place 0)                        (< integer-exponent 0))                    (il:* il:|;;| "Trim off extraneous zeros")                    (do ((i (1- index)                            (1- i)))                        ((not (eq (aref output-string i)                                  #\0))                         (if (not (eq (aref output-string i)                                      #\.))                             (setq index (1+ i))                             (setq index (+ i 2))))))                (setf (fill-pointer output-string)                      index)                output-string)))(defun get-tic-list (margin tic-info scale-info plot)   (let ((ticmethod (margin-tic-list-fn margin)))        (if (and (consp ticmethod)                 (not (eq (car ticmethod)                          'lambda)))            ticmethod            (funcall ticmethod tic-info scale-info plot))))(defun tic-list-fn (plot margin-name)   (margin-tic-list-fn (ecase margin-name                           (:bottom (plot-bottom-margin plot))                           (:left (plot-left-margin plot))                           (:top (plot-top-margin plot))                           (:right (plot-right-margin plot)))))(defun setf-tic-list-fn (plot margin-name new-method &optional no-update-p)   (il:* il:|;;| "NEW-METHOD may be a list of numbers, or a list of CONS pairs (VALUE  . LABEL), or a function to be APPLIED to MARGIN SCALE-INFO PLOT.")   (let ((margin (ecase margin-name                     (:bottom (plot-bottom-margin plot))                     (:left (plot-left-margin plot))                     (:top (plot-top-margin plot))                     (:right (plot-right-margin plot)))))        (setf (margin-tic-list-fn margin)              new-method)        (if (and (null no-update-p)                 (margin-tics-p margin))            (redraw-plot-window plot))        new-method))(defun default-tic-list-fn (tic-info scale-info &optional plot)   (declare (ignore scale-info plot))   (il:* il:|;;| "Return the default tic list based on the values of PLOTSCALE")   (let ((tic-inc (ti-inc tic-info)))        (cond           ((consp tic-inc)            tic-inc)           ((numberp tic-inc)            (il:* il:|;;| "Be carefull that min and max tics correspond to min and max of interval")            (nconc (let ((x (ti-min tic-info)))                        (pt:with-collection (dotimes (i (1- (ti-n tic-info)))                                                (pt:collect x)                                                (incf x tic-inc))))                   (list (ti-max tic-info))))           (t (error "Invalid increment: ~s" tic-inc)))))(il:* il:|;;| "margins")(defun compute-top-bottom-margin (stream top-bottom-margin plot)   (il:* il:|;;| "Returns a size cons pair (width  . height) in stream coordinates")   (let* ((small-font (coerce-font *small-plot-font* stream))          (large-font (coerce-font *large-plot-font* stream))          (tics-p (margin-tics-p top-bottom-margin))          (label (margin-label top-bottom-margin))          (width 0)          (small-ascent (font-ascent small-font))          (large-height (font-height large-font))          (height (if (or tics-p label)                      large-height                      (il:* il:|;;| "margin of at least one LARGE-HEIGHT")                      (* 2 large-height))))         (if tics-p             (incf height (* 3 small-ascent)))         (if label             (setq height (+ height (* 2 large-height))                   width                   (string-width label large-font)))         (cons width height)))(defun compute-left-right-margin (stream left-right-margin plot)   (il:* il:|;;| "Returns a size cons pair (width  . height) in stream coordinates")   (let* ((small-font (coerce-font *small-plot-font* stream))          (large-font (coerce-font *large-plot-font* stream))          (tics-p (margin-tics-p left-right-margin))          (tic-list (margin-tic-list left-right-margin))          (label (margin-label left-right-margin))          (height 0)          (il:* il:|;;| "Assumes fixed-pitch font")          (small-width (string-width #\a small-font))          (large-width (string-width #\a large-font))          (width (if (or tics-p label)                     large-width                     (* 2 large-width))))         (if tics-p             (incf width (+ (* 2 small-width)                            (let ((tic-width-max 0))                                 (dolist (pair tic-list)                                     (let ((length (string-width (cdr pair)                                                          small-font)))                                          (if (> length tic-width-max)                                              (setq tic-width-max length))))                                 tic-width-max))))         (if label             (setq width (+ width (* 2 large-width))                   height                   (* (length label)                      (font-height large-font))))         (cons width height)))(defun draw-top-margin (stream view-port stream-region plot)   (il:* il:|;;| "DRAW the Top MARGIN")   (let* ((top-margin (plot-top-margin plot))          (small-font (coerce-font *small-plot-font* stream))          (large-font (coerce-font *large-plot-font* stream))          (label (margin-label top-margin))          (x-interval (si-x-interval (plot-scale-info plot)))          (small-ascent (font-ascent small-font))          (top (region-top (vp-stream-subregion view-port))))         (if (margin-tics-p top-margin)             (il:* il:|;;| "DRAW TICS and TIC labels if necessary")             (draw-tics-top-bottom (margin-tic-list top-margin)                    (interval-min x-interval)                    (interval-max x-interval)                    (+ small-ascent top)                    (- top small-ascent)                    small-ascent small-font stream view-port))         (if label             (draw-label-top-bottom label large-font (- (region-top stream-region)                                                        (+ (font-height large-font)                                                           (font-ascent stream)))                    stream-region stream))))(defun draw-bottom-margin (stream view-port stream-region plot)   (il:* il:|;;| "DRAW the bottom MARGIN")   (let* ((bottom-margin (plot-bottom-margin plot))          (small-font (coerce-font *small-plot-font* stream))          (large-font (coerce-font *large-plot-font* stream))          (label (margin-label bottom-margin))          (x-interval (si-x-interval (plot-scale-info plot)))          (small-ascent (font-ascent small-font))          (bottom (region-bottom (vp-stream-subregion view-port))))         (if (margin-tics-p bottom-margin)             (il:* il:|;;| "DRAW TICS and TIC labels if necessary")             (draw-tics-top-bottom (margin-tic-list bottom-margin)                    (interval-min x-interval)                    (interval-max x-interval)                    (+ small-ascent bottom)                    (- bottom small-ascent)                    (* 2 small-ascent)                    small-font stream view-port t))         (if label             (draw-label-top-bottom label large-font (+ (region-bottom stream-region)                                                        (+ (font-descent stream)                                                           (font-height large-font)))                    stream-region stream))))(defun draw-left-margin (stream view-port stream-region plot)   (il:* il:|;;| "DRAW the left MARGIN")   (let* ((left-margin (plot-left-margin plot))          (small-font (coerce-font *small-plot-font* stream))          (large-font (coerce-font *large-plot-font* stream))          (label (margin-label left-margin))          (y-interval (si-y-interval (plot-scale-info plot)))          (small-width (string-width #\a small-font))          (left (region-left (vp-stream-subregion view-port))))         (if (margin-tics-p left-margin)             (il:* il:|;;| "DRAW TICS and TIC labels if necessary")             (draw-tics-left-right (margin-tic-list left-margin)                    (interval-min y-interval)                    (interval-max y-interval)                    (+ small-width left)                    (- left small-width)                    small-width small-font stream view-port t))         (if label             (draw-label-left-right label large-font (+ (region-left stream-region)                                                        (string-width #\a large-font))                    stream-region stream))))(defun draw-right-margin (stream view-port stream-region plot)   (il:* il:|;;| "DRAW the right MARGIN")   (let* ((right-margin (plot-right-margin plot))          (small-font (coerce-font *small-plot-font* stream))          (large-font (coerce-font *large-plot-font* stream))          (label (margin-label right-margin))          (y-interval (si-y-interval (plot-scale-info plot)))          (small-width (string-width #\a small-font))          (right (region-right (vp-stream-subregion view-port))))         (if (margin-tics-p right-margin)             (il:* il:|;;| "DRAW TICS and TIC labels if necessary")             (draw-tics-left-right (margin-tic-list right-margin)                    (interval-min y-interval)                    (interval-max y-interval)                    (+ small-width right)                    (- right small-width)                    small-width small-font stream view-port))         (if label             (draw-label-left-right label large-font (- (region-right stream-region)                                                        (* 2 (string-width #\a large-font)))                    stream-region stream))))(defun draw-tics-top-bottom (ticlist min max top-of-tic bottom-of-tic tic-offset tic-font stream                                       view-port bottom-p)   (let ((font (stream-font stream)))        (setf (stream-font stream)              tic-font)        (let (x-window-loc)             (dolist (ticpair ticlist)                 (let ((tic-value (car ticpair))                       (tic-label (cdr ticpair)))                      (when (and (>= tic-value min)                                 (<= tic-value max))                          (setq x-window-loc (world-to-stream-x tic-value view-port))                          (il:* il:|;;| "always draw the tic mark")                          (stream-move-to x-window-loc top-of-tic stream)                          (stream-draw-to x-window-loc bottom-of-tic stream :width (stream-scale                                                                                    stream)                                 :operation boole-1)                          (when tic-label                              (if bottom-p                                  (stream-move-to x-window-loc (- bottom-of-tic tic-offset)                                         stream)                                  (stream-move-to x-window-loc (+ top-of-tic tic-offset)                                         stream))                              (stream-relative-move-to (- (truncate (string-width tic-label tic-font)                                                                 2))                                     0 stream)                              (princ tic-label stream))))))        (setf (stream-font stream)              font)))(defun draw-tics-left-right (ticlist min max right-tic left-tic tic-offset tic-font stream                                        view-port left-p)   (let ((font (stream-font stream)))        (setf (stream-font stream)              tic-font)        (let (y-window-loc)             (dolist (ticpair ticlist)                 (let ((tic-value (car ticpair))                       (tic-label (cdr ticpair)))                      (when (and (>= tic-value min)                                 (<= tic-value max))                          (setq y-window-loc (world-to-stream-y tic-value view-port))                          (stream-move-to left-tic y-window-loc stream)                          (stream-draw-to right-tic y-window-loc stream :width (stream-scale stream)                                 :operation boole-1)                          (when tic-label                              (if left-p                                  (stream-move-to (- left-tic (+ tic-offset (string-width tic-label                                                                                    stream)))                                         y-window-loc stream)                                  (stream-move-to (+ right-tic tic-offset)                                         y-window-loc stream))                              (princ tic-label stream))))))        (setf (stream-font stream)              font)))(defun draw-label-top-bottom (label label-font y-offset stream-region stream)   (let ((font (stream-font stream)))        (setf (stream-font stream)              label-font)        (stream-move-to (+ (region-left stream-region)                           (max 0 (truncate (- (region-width stream-region)                                               (string-width label stream))                                         2)))               y-offset stream)        (princ label stream)        (setf (stream-font stream)              font)))(defun draw-label-left-right (label label-font x-offset stream-region stream)   (let ((font (stream-font stream)))        (setf (stream-font stream)              label-font)        (stream-move-to x-offset (- (region-top stream-region)                                    (truncate (- (region-height stream-region)                                                 (* (font-height stream)                                                    (length label)))                                           2))               stream)        (let ((lf (stream-line-feed stream)))             (dotimes (i (length label))                 (princ (aref label i)                        stream)                 (stream-move-to x-offset (+ (stream-y stream)                                             lf)                        stream)))        (setf (stream-font stream)              font)))(il:* il:|;;| "Plot scaling")(defun rescale-plot (plot &optional (axis :both)                              no-update-p)   (let ((plot-extent (plot-objects-extent (plot-objects plot)                             plot)))        (when plot-extent            (let ((min-x (extent-min-x plot-extent))                  (max-x (extent-max-x plot-extent))                  (min-y (extent-min-y plot-extent))                  (max-y (extent-max-y plot-extent)))                 (if (and (or (eq axis ':both)                              (eq axis ':x))                          (> max-x min-x))                     (rescale-x-axis plot min-x max-x))                 (if (and (or (eq axis ':both)                              (eq axis ':y))                          (> max-y min-y))                     (rescale-y-axis plot min-y max-y))                 (if (null no-update-p)                     (redraw-plot-window plot))))))(defun rescale-x-axis (plot min max &key tic-info-fn interval-fn)   (let* ((scale-info (plot-scale-info plot))          (axis-info (si-x-axis-info scale-info))          (tic-info (funcall (or tic-info-fn (ai-tic-info-fn axis-info))                           min max plot))          (interval (funcall (or interval-fn (ai-interval-fn axis-info))                           min max tic-info plot)))         (setf (si-x-tic-info scale-info)               tic-info)         (setf (si-x-interval scale-info)               interval)))(defun rescale-y-axis (plot min max &key tic-info-fn interval-fn)   (let* ((scale-info (plot-scale-info plot))          (axis-info (si-y-axis-info scale-info))          (tic-info (funcall (or tic-info-fn (ai-tic-info-fn axis-info))                           min max plot))          (interval (funcall (or interval-fn (ai-interval-fn axis-info))                           min max tic-info plot)))         (setf (si-y-tic-info scale-info)               tic-info)         (setf (si-y-interval scale-info)               interval)))(defun tic-info-fn (plot axis)   (ai-tic-info-fn (ecase axis                       (:x (si-x-axis-info (plot-scale-info plot)))                       (:y (si-y-axis-info (plot-scale-info plot))))))(defun setf-tic-info-fn (plot axis new-fn &optional no-update-p)   (let ((axis-info (ecase axis                        (:x (si-x-axis-info (plot-scale-info plot)))                        (:y (si-y-axis-info (plot-scale-info plot))))))        (setf (ai-tic-info-fn axis-info)              new-fn)        (rescale-plot plot axis no-update-p)        new-fn))(defun default-tic-info-fn (min max &optional plot (tics '(3 4 5 6 7 8)))   (declare (ignore plot default-tic-info-fn))   (il:* il:|;;| "Computes an interval that includes (MIN,MAX) and can be exactly spanned by (NTICS-1) *some increment.")   (let* ((shortest (scale min max (car tics)))          (shortest-length (ti-length shortest)))         (dolist (n-tics (cdr tics))             (let* ((current (scale min max n-tics))                    (current-length (ti-length current)))                   (if (< current-length shortest-length)                       (setq shortest-length current-length shortest current))))         shortest))(defun interval-fn (plot axis)   (ai-interval-fn (ecase axis                       (:x (si-x-axis-info (plot-scale-info plot)))                       (:y (si-y-axis-info (plot-scale-info plot))))))(defun setf-interval-fn (plot axis new-fn &optional no-update-p)   (let ((axis-info (ecase axis                        (:x (si-x-axis-info (plot-scale-info plot)))                        (:y (si-y-axis-info (plot-scale-info plot))))))        (setf (ai-interval-fn axis-info)              new-fn)        (rescale-plot plot axis no-update-p)        new-fn))(defun default-interval-fn (min max tic-info &optional plot)   (declare (ignore min max plot))   (make-axis-interval :min (ti-min tic-info)          :max          (ti-max tic-info)))(defun no-change-interval-fn (min max tic-info plot)   (declare (ignore tic-info plot))   (make-axis-interval :min min :max max))(defun scale (min max n-tics &optional (round                                                   (il:* il:|;;|                    "Rounding Constants.  Notice that they are in decreasing order and end with 1.0")                                                  '(5.0 2.5 2.0 1.5 1.0))                      power)   (il:* il:|;;| "Scaling algorithm for plots.  NTICS is the desired number of tics.  Round is a list of acceptable scaling factors.  POWER is the power of ten to use.  Returns a TICINFO including NEWMAX, NEWMIN, INC, and NTICS")   (let* ((n-inc (1- n-tics))          (raw-inc (/ (float (- max min))                      n-inc))          mantissa index)         (il:* il:|;;| "POWER is the power of ten")         (setq power (expt 10.0 (or power (floor (log raw-inc 10.0)))))         (il:* il:|;;| "MANTISSA is the scale factor")         (setq mantissa (/ raw-inc power))         (if (> mantissa (first round))             (setq power (* 10.0 power)                   index                   (last round))             (setq index (do ((mark round (cdr mark)))                             ((null (cdr mark))                              mark)                           (if (> mantissa (second mark))                               (return mark)))))         (il:* il:|;;| "Find new max and new min")         (let ((new-max min)               new-min inc factor lower-mult upper-mult)              (loop (unless (< new-max max)                        (return (make-tic-info :min new-min :max new-max :inc inc :n n-tics)))                    (setq inc (* (first index)                                 power))                    (setq factor (/ (- (+ max min)                                       (* n-inc inc))                                    (* 2.0 inc)))                    (setq new-min (* inc (setq lower-mult (ceiling factor))))                    (if (> new-min min)                        (setq new-min (* inc (setq lower-mult (1- lower-mult)))))                    (if (and (>= min 0.0)                             (minusp new-min))                        (setq lower-mult 0 new-min 0.0))                    (setq upper-mult (+ lower-mult n-inc))                    (setq new-max (* inc upper-mult))                    (if (and (<= max 0.0)                             (> new-max 0.0))                        (setq upper-mult 0 new-max 0.0 lower-mult (- n-inc)                              new-min                              (* inc lower-mult)))                    (if (eq round index)                        (setq index (last round)                              power                              (* 10.0 power))                        (setq index (do ((mark round (cdr mark)))                                        ((eq (cdr mark)                                             index)                                         mark))))))))(defun plot-objects-extent (objects plot)   (il:* il:|;;| "May return NIL if no objects report a bounding box.")   (let (extent)        (dolist (object objects)            (let ((object-info (plot-object-extent object plot)))                 (when object-info                     (setq extent (if (null extent)                                      object-info                                      (if (                                           (il:* il:|;;| "should be position-p")                                           consp object-info)                                          (il:* il:|;;| "A position reported")                                          (if (consp extent)                                              (make-extent :min-x (min (position-x extent)                                                                       (position-x object-info))                                                     :max-x                                                     (max (position-x extent)                                                          (position-x object-info))                                                     :min-y                                                     (min (position-y extent)                                                          (position-y object-info))                                                     :max-y                                                     (max (position-y extent)                                                          (position-y object-info)))                                              (add-position-to-extent extent object-info))                                          (il:* il:|;;| "an extent reported")                                          (if (consp extent)                                              (add-position-to-extent (copy-extent object-info)                                                     extent)                                              (add-extent-to-extent extent object-info))))))))        (if (consp extent)            (add-position-to-extent (plot-world-extent plot)                   extent)            extent)))(defun adjust-scale-p (extent plot)   (il:* il:|;;| "Determines whether the plotting scale must be adjusted to included the extrema 'min-x' , 'max-x' , etc.  If so returns T.  Side effects the scale-info of PLOT")   (when extent       (let* ((scale-info (plot-scale-info plot))              (x-interval (si-x-interval scale-info))              (y-interval (si-y-interval scale-info))              min-x max-x min-y max-y changed-p)             (if (position-p extent)                 (setq min-x (position-x extent)                       max-x                       (position-x extent)                       min-y                       (position-y extent)                       max-y                       (position-y extent))                 (setq min-x (extent-min-x extent)                       max-x                       (extent-max-x extent)                       min-y                       (extent-min-y extent)                       max-y                       (extent-max-y extent)))             (when (or (< min-x (interval-min x-interval))                       (> max-x (interval-max x-interval)))                 (setq changed-p t)                 (rescale-x-axis plot (min min-x (interval-min x-interval))                        (max max-x (interval-max x-interval))))             (when (or (< min-y (interval-min y-interval))                       (> max-y (interval-max y-interval)))                 (setq changed-p t)                 (rescale-y-axis plot (min min-y (interval-min y-interval))                        (max max-y (interval-max y-interval))))             changed-p)))(defun update-extent (old-extent new-extent)   (il:* il:|;;| "side effects OLD-EXTENT")   (if (< (extent-min-x new-extent)          (extent-min-x old-extent))       (setf (extent-min-x old-extent)             (extent-min-x new-extent)))   (if (> (extent-max-x new-extent)          (extent-max-x old-extent))       (setf (extent-max-x old-extent)             (extent-max-x new-extent)))   (if (< (extent-min-y new-extent)          (extent-min-y old-extent))       (setf (extent-min-y old-extent)             (extent-min-y new-extent)))   (if (> (extent-max-y new-extent)          (extent-max-y old-extent))       (setf (extent-max-y old-extent)             (extent-max-y new-extent)))   old-extent)(defun add-extent-to-extent (old-extent new-extent)   (il:* il:|;;| "side effects OLD-EXTENT")   (if (< (extent-min-x new-extent)          (extent-min-x old-extent))       (setf (extent-min-x old-extent)             (extent-min-x new-extent)))   (if (> (extent-max-x new-extent)          (extent-max-x old-extent))       (setf (extent-max-x old-extent)             (extent-max-x new-extent)))   (if (< (extent-min-y new-extent)          (extent-min-y old-extent))       (setf (extent-min-y old-extent)             (extent-min-y new-extent)))   (if (> (extent-max-y new-extent)          (extent-max-y old-extent))       (setf (extent-max-y old-extent)             (extent-max-y new-extent)))   old-extent)(defun add-position-to-extent (old-extent position)   (il:* il:|;;| "side effects OLD-EXTENT")   (let ((x (position-x position))         (y (position-y position)))        (if (< x (extent-min-x old-extent))            (setf (extent-min-x old-extent)                  x)            (if (> x (extent-max-x old-extent))                (setf (extent-max-x old-extent)                      x)))        (if (< y (extent-min-y old-extent))            (setf (extent-min-y old-extent)                  y)            (if (> y (extent-max-y old-extent))                (setf (extent-max-y old-extent)                      y))))   old-extent)(defun extend-axis (plot axis &optional no-update-p)   (ecase axis       (:x (rescale-x-axis plot (plot-x-lower plot)                  (plot-x-upper plot)                  :interval-fn                  'extended-interval-fn))       (:y (rescale-y-axis plot (plot-y-lower plot)                  (plot-y-upper plot)                  :interval-fn                  'extended-interval-fn)))   (if (null no-update-p)       (redraw-plot-window plot)))(defun extended-interval-fn (min max tic-info)   (let* ((new-min (ti-min tic-info))          (new-max (ti-max tic-info))          (episilon 0.05)          (delta (* episilon (- new-max new-min))))         (make-axis-interval :min (- new-min delta)                :max                (+ new-max delta))))(defun plot-world-extent (plot)   (make-extent :min-x (plot-x-lower plot)          :max-x          (plot-x-upper plot)          :min-y          (plot-y-lower plot)          :max-y          (plot-y-upper plot)))(defun setf-plot-world-extent (plot new-extent &optional no-update-p)   (let* ((x-lower (extent-min-x new-extent))          (x-upper (extent-max-x new-extent))          (y-lower (extent-min-y new-extent))          (y-upper (extent-max-y new-extent)))         (rescale-x-axis plot x-lower x-upper :interval-fn 'no-change-interval-fn)         (rescale-y-axis plot y-lower y-upper :interval-fn 'no-change-interval-fn)         (if (null no-update-p)             (redraw-plot-window plot))))(defun plot-interval (plot axis)   (ecase axis       (:x (copy-axis-interval (si-x-interval (plot-scale-info plot))))       (:y (copy-axis-interval (si-y-interval (plot-scale-info plot))))))(defun setf-plot-interval (plot axis new-interval &optional no-update-p)   (ecase axis       (:x (rescale-x-axis plot (interval-min new-interval)                  (interval-max new-interval)                  :interval-fn                  'no-change-interval-fn))       (:y (rescale-y-axis plot (interval-min new-interval)                  (interval-max new-interval)                  :interval-fn                  'no-change-interval-fn)))   (if (null no-update-p)       (redraw-plot-window plot)))(defun region-to-extent (region)   (let ((min-x (region-left region))         (min-y (region-bottom region)))        (make-extent :min-x min-x :max-x (+ min-x (region-width region))               :min-y min-y :max-y (+ min-y (region-height region)))))(defun extent-to-region (extent)   (let ((min-x (extent-min-x extent))         (min-y (extent-min-y extent)))        (make-region min-x min-y (- (extent-max-x extent)                                    min-x)               (- (extent-max-y extent)                  min-y))))(il:* il:|;;| "plot labels")(defun plot-label (plot label-position)   (margin-label (ecase label-position                     (:bottom (plot-bottom-margin plot))                     (:left (plot-left-margin plot))                     (:top (plot-top-margin plot))                     (:right (plot-right-margin plot)))))(defun setf-plot-label (plot label-position new-label &optional no-update-p)   (let ((margin (ecase label-position                     (:bottom (plot-bottom-margin plot))                     (:left (plot-left-margin plot))                     (:top (plot-top-margin plot))                     (:right (plot-right-margin plot)))))        (setf (margin-label margin)              (and new-label (string new-label)))        (if (null no-update-p)            (redraw-plot-window plot))))(il:* il:|;;| "Plot object methods")(defun draw-plot-object (object view-port plot)   (let ((text-object (plot-object-prop object :label-object)))        (funcall (pm-draw-fn (plot-object-methods object))               object view-port plot)        (if text-object (draw-plot-object text-object view-port plot))        (apply-after-method (plot-object-prop object ':when-drawn)               object view-port plot)))(defun erase-plot-object (object view-port plot)   (let ((text-object (plot-object-prop object :label-object)))        (funcall (pm-erase-fn (plot-object-methods object))               object view-port plot)        (if text-object (erase-plot-object text-object view-port plot))        (apply-after-method (plot-object-prop object ':when-erased)               object view-port plot)))(defun highlight-plot-object (object view-port plot)   (let ((text-object (plot-object-prop object :label-object)))        (funcall (pm-highlight-fn (plot-object-methods object))               object view-port plot)        (if text-object (highlight-plot-object text-object view-port plot))        (apply-after-method (plot-object-prop object ':when-highlighted)               object view-port plot)))(defun lowlight-plot-object (object view-port plot)   (let ((text-object (plot-object-prop object :label-object)))        (funcall (pm-lowlight-fn (plot-object-methods object))               object view-port plot)        (if text-object (lowlight-plot-object text-object view-port plot))        (apply-after-method (plot-object-prop object ':when-lowlighted)               object view-port plot)))(defun plot-object-extent (object plot)   (il:* il:|;;| "May return NIL, a position or an extent")   (funcall (pm-extent-fn (plot-object-methods object))          object plot))(defun distance-to-plot-object (object stream-position plot)   (funcall (pm-distance-fn (plot-object-methods object))          object stream-position plot))(defun label-plot-object (object plot)   (if (plot-object-label object)       (progn (setf (plot-object-prop object :label-object)                    (funcall (pm-label-fn (plot-object-methods object))                           object plot))              (apply-after-method (plot-object-prop object :when-labeled)                     object plot))       (print-plot-prompt "Object has no label" plot)))(defun unlabel-plot-object (object plot)   (let ((text-object (plot-object-prop object ':label-object)))        (if text-object            (let ((view-port (plot-view-port plot)))                 (erase-plot-object text-object view-port plot)                 (setf (plot-object-prop object ':label-object)                       nil)                 (apply-after-method (plot-object-prop object :when-unlabeled)                        object plot))            (print-plot-prompt "Not a labeled object" plot))))(defun move-plot-object (object dx dy plot)   (funcall (pm-move-fn (plot-object-methods object))          object dx dy plot))(defun copy-plot-object (plot-object)   (il:* il:|;;| "Returns a copy of PLOT-OBJECT.  PLOT-OBJECT props are handled as follows.  If the PLOT-OBJECT has a COPY-FN on its prop list, apply it to NEW-PLOT-OBJECT, PLOT-OBJECT and PROP-NAME by PROP and expect it to copy the PROP's, else just copy the top-level list structure.")   (let ((new-plot-object (funcall (pm-copy-fn (plot-object-methods plot-object))                                 plot-object)))        (setf (plot-object-prop-list new-plot-object)              (pt:with-collection (do* ((prop-name-tail (plot-object-prop-list plot-object)                                               (cddr prop-name-tail))                                        (prop-name (car prop-name-tail)                                               (car prop-name-tail))                                        (prop-value-tail (cdr prop-name-tail)                                               (cdr prop-name-tail))                                        (prop-value (car prop-value-tail)                                               (car prop-value-tail)))                                       ((null prop-name-tail))                                     (when prop-value                                         (pt:collect prop-name)                                         (pt:collect (if (eq prop-name :label-object)                                                         (il:* il:|;;| "Cached label")                                                         (copy-plot-object prop-value)                                                         prop-value))))))        (apply-after-method (plot-object-prop plot-object :when-copied)               plot-object new-plot-object)        new-plot-object))(defun add-plot-object (object plot &optional no-update-p)   (let ((plot-objects (plot-objects plot))         (redraw-p nil))        (push object (plot-objects plot))        (if (adjust-scale-p (plot-object-extent object plot)                   plot)            (setq redraw-p t))        (if (null no-update-p)            (if (or redraw-p (not (open-window-p (plot-window plot))))                (redraw-plot-window plot)                (draw-plot-object object (plot-view-port plot)                       plot)))        (apply-after-method (plot-object-prop object :when-added)               object plot no-update-p)        object))(defun add-plot-objects (objects plot &optional no-update-p)   (let* ((plot-objects (plot-objects plot))          (redraw-p nil))         (il:* il:|;;| "Update display list")         (setf (plot-objects plot)               (append objects plot-objects))         (if (adjust-scale-p (plot-objects-extent objects plot)                    plot)             (setq redraw-p t))         (if (null no-update-p)             (if (or redraw-p (not (open-window-p (plot-window plot))))                 (redraw-plot-window plot)                 (let ((view-port (plot-view-port plot)))                      (dolist (object objects)                          (draw-plot-object object view-port plot)))))         (dolist (object objects)             (apply-after-method (plot-object-prop object :when-added)                    object plot no-update-p))         objects))(defun delete-plot-object (object plot &optional no-update-p no-save-p)   (il:* il:|;;| "Delete object from display list of plot.  If (NULL NO-UPDATE-P) then update the associated display (open it if necessary). If SAVE-P then intern the object on the plot's save list.")   (let ((plot-objects (plot-objects plot)))        (let ((plot-window (plot-window plot))              (view-port (plot-view-port plot))              (selected-object (plot-selected-object plot)))             (when (eq object selected-object)                 (if (and (null no-update-p)                          (open-window-p plot-window))                     (lowlight-plot-object object view-port plot))                 (setf (plot-selected-object plot)                       nil))             (setf (plot-objects plot)                   (delete object plot-objects))             (if (null no-save-p)                 (push object (plot-save-list plot)))             (if (null no-update-p)                 (if (not (open-window-p plot-window))                     (open-plot-window plot)                     (erase-plot-object object view-port plot)))             (apply-after-method (plot-object-prop object :when-deleted)                    object plot no-update-p no-save-p)             object)))(defun delete-plot-objects (objects plot &optional no-update-p no-save-p)   (il:* il:|;;| "Delete object from display list of plot.  If (NULL NO-UPDATE-P) then update the associated display (open it if necessary). If SAVE-P then intern the object on the plot's save list.")   (let* ((plot-objects (plot-objects plot))          (trimmed-objects (mapcan #'(lambda (object)                                            (if (pt:memq object plot-objects)                                                (list object)))                                  (delete-duplicates objects))))         (when trimmed-objects             (let ((plot-window (plot-window plot))                   (view-port (plot-view-port plot))                   (selected-object (plot-selected-object plot)))                  (when (pt:memq selected-object trimmed-objects)                      (if (and (null no-update-p)                               (open-window-p plot-window))                          (lowlight-plot-object selected-object view-port plot))                      (setf (plot-selected-object plot)                            nil))                  (setf (plot-objects plot)                        (nset-difference plot-objects trimmed-objects))                  (if (null no-save-p)                      (setf (plot-save-list plot)                            (append trimmed-objects (plot-save-list plot))))                  (if (null no-update-p)                      (if (not (open-window-p plot-window))                          (open-plot-window plot)                          (dolist (object trimmed-objects)                              (erase-plot-object object view-port plot))))                  (dolist (object trimmed-objects)                      (apply-after-method (plot-object-prop object :when-deleted)                             object plot no-update-p no-save-p))                  objects))))(defun relabel-selected-object (selected-object plot)   (let ((plot-prompt-window (plot-prompt-window plot))         label)        (il:* il:|;;| "If the object is labeled, delete the label.")        (if (plot-object-prop selected-object :label-object)            (unlabel-plot-object selected-object plot))        (terpri plot-prompt-window)        (let ((new-label (il:promptforword "Type new label :" (plot-object-label selected-object)                                "Enter NIL for no label" plot-prompt-window nil nil                                (il:constant (list (char-code #\Newline)                                                   (char-code #\Linefeed)                                                   (char-code #\Escape)                                                   (char-code #\Tab))))))             (when (setf (plot-object-label selected-object)                         new-label)                   (label-plot-object selected-object plot)))))(defun delete-selected-object (object plot &optional no-update-p no-save-p)   (let ((plot-objects (plot-objects plot))         (plot-window (plot-window plot)))        (when (pt:memq object plot-objects)            (when (eq object (plot-selected-object plot))                (if (null no-update-p)                    (if (open-window-p plot-window)                        (lowlight-plot-object object plot)))                (setf (plot-selected-object plot)                      nil))            (setf (plot-objects plot)                  (delete object plot-objects))            (if (null no-save-p)                (push object (plot-save-list plot)))            (if (null no-update-p)                (if (not (open-window-p plot-window))                    (open-plot-window plot)                    (erase-plot-object object (plot-view-port plot)                           plot)))            (apply-after-method (plot-object-prop object :when-deleted)                   object plot no-update-p no-save-p)            object)))(defun undelete-last-object (plot)   (let ((object (pop (plot-save-list plot))))        (if object            (add-plot-object object plot)            (print-plot-prompt "No object to undelete" plot))))(defun translate-plot-object (object dx dy plot &optional no-update-p)   (let ((text-object (plot-object-prop object ':label-object))         (view-port (plot-view-port plot)))        (if (null no-update-p)            (let ((selected-object (plot-selected-object plot)))                 (when (eq object selected-object)                     (lowlight-plot-object selected-object view-port plot)                     (setf (plot-selected-object plot)                           nil))                 (erase-plot-object object view-port plot)))        (il:* il:|;;| "Destructively modify the data structure for OBJECT")        (move-plot-object object dx dy plot)        (if (null no-update-p)            (draw-plot-object object view-port plot))        (if text-object (translate-plot-object text-object dx dy plot no-update-p))        (apply-after-method (plot-object-prop object ':when-translated)               object dx dy plot no-update-p)))(defun select-plot-object (plot-object plot)   (let ((selected-object (plot-selected-object plot))         (view-port (plot-view-port plot)))        (when selected-object            (lowlight-plot-object selected-object view-port)            (setf (plot-selected-object plot)                  nil))        (when plot-object            (highlight-plot-object plot-object view-port plot)            (setf (plot-selected-object plot)                  plot-object))))(defun deselect-plot-object (plot-object plot)   (let ((selected-object (plot-selected-object plot)))        (when (and selected-object (eq selected-object plot-object))            (lowlight-plot-object selected-object (plot-view-port plot))            (setf (plot-selected-object plot)                  nil))))(il:* il:|;;| "Plot menus ")(defun default-when-selected-fn (item menu)   (let* ((plot (or (menu-prop menu :plot)                    (window-prop (main-window (window-from-menu menu))                           :plot)))          (mode (menu-prop menu :mode))          (selected-object (plot-selected-object plot))          (selected-fn (second item))          extra-args args-to-pass)         (when (consp selected-fn)             (setq extra-args (cdr selected-fn))             (setq selected-fn (car selected-fn)))         (setq args-to-pass (mapcar #'eval extra-args))         (if (eq mode :middle)             (progn (lowlight-plot-object selected-object (plot-view-port plot)                           plot)                    (setf (plot-selected-object plot)                          nil)                    (apply selected-fn selected-object plot args-to-pass))             (apply selected-fn plot args-to-pass))))(defun plot-menu (plot menu-name)   (case menu-name       (:middle (plot-middle-menu plot))       (:right (plot-right-menu plot))       (otherwise (getf (plot-other-menus plot)                        menu-name))))(defun setf-plot-menu (plot menu-position new-menu &optional no-update-p)   (if (not (or (null new-menu)                (menu-p new-menu)))       (error "Not a menu: ~s" new-menu)       (if (and new-menu (null (menu-when-selected-fn new-menu)))           (setf (menu-when-selected-fn new-menu)                 'default-when-selected-fn)))   (case menu-position       (:middle (setf (plot-middle-menu plot)                      new-menu))       (:right (setf (plot-right-menu plot)                     new-menu))       (otherwise (setf (getf (plot-other-menus plot)                              menu-position)                        new-menu)))   (when (and (eq menu-position :right)              (plot-prop plot :fixed-right-menu-p)              (null no-update-p)              (open-window-p (plot-window plot)))       (il:* il:|;;| "Update the fixed menu")       (unfix-right-menu plot)       (fix-right-menu plot))   new-menu)(defun plot-menu-items (plot menu-position)   (case menu-position       (:middle (menu-items (plot-middle-menu plot)))       (:right (menu-items (plot-right-menu plot)))       (otherwise (let ((menu (getf (plot-other-menus plot)                                    menu-position)))                       (and menu (menu-items menu))))))(defun setf-plot-menu-items (plot menu-position new-items &optional no-update-p)   (il:* il:|;;| "Replace the cached menu with the new list of items")   (let ((menu (case menu-position                   (:middle (plot-middle-menu plot))                   (:right (plot-right-menu plot))                   (otherwise (getf (plot-other-menus plot)                                    menu-position)))))        (setq menu (and new-items (if menu                                      (copy-menu menu :new-items new-items)                                      (make-menu :items new-items))))        (setf-plot-menu plot menu-position menu no-update-p)        new-items))(defun add-plot-menu-items (plot menu-name items-to-add &optional no-update-p)   (il:* il:|;;| "Add ITEMSTOADD to end of menu MENUNAME item list")   (let* ((menu (case menu-name                    (:middle (plot-middle-menu plot))                    (:right (plot-right-menu plot))                    (otherwise (getf (plot-other-menus plot)                                     menu-name))))          (menu-items (plot-menu-items plot menu-name)))         (when items-to-add             (setq items-to-add (mapcan #'(lambda (item)                                                 (if (not (member item menu-items :test 'equal))                                                     (list item)))                                       items-to-add))             (setf-plot-menu-items plot menu-name (append menu-items items-to-add)                    no-update-p))         items-to-add))(defun delete-plot-menu-items (plot menu-name items-to-delete &optional no-update-p)   (il:* il:|;;| "Delete ITEMSTODELETE from menu MENUNAME item list.  RETURNS new item list if something deleted or else NIL.  ITEMSTODELETE may be a list of lists or of atoms, in which case the atoms are compared to secessive CARS of MENUNAME's item list")   (let ((menu (case menu-name                   (:middle (plot-middle-menu plot))                   (:right (plot-right-menu plot))                   (otherwise (getf (plot-other-menus plot)                                    menu-name))))         (menu-items (plot-menu-items plot menu-name)))        (setq items-to-delete              (mapcan #'(lambda (item)                               (let ((target (car (if (consp item)                                                      (member item menu-items :test 'equal)                                                      (member item menu-items :test 'equal :key                                                             'car)))))                                    (if target (list target))))                     (if (listp items-to-delete)                         items-to-delete                         (list items-to-delete))))        (setf-plot-menu-items plot menu-name (set-difference menu-items items-to-delete)               no-update-p)        items-to-delete))(defvar *default-middle-menu*   (make-menu :items '(("Label" toggle-label "Toggle label on/off" (:subitems ("Relabel"                                                                               relabel-selected-object                                                                                     "Change label"))                              )                       ("Delete" delete-selected-object "Delete object"))          :when-selected-fn          'default-when-selected-fn :track-cursor-p t))(defvar *default-right-menu*   (make-menu :items '(("Layout" make-plot-sketch "Create a sketch of the PLOT")                       ("Redraw" redraw-plot-window "Redraw plot")                       ("Rescale" rescale-plot "Rescale plot axes"                              (:subitems ("X Axis" (rescale-plot :x)                                                "Rescale X axis"                                                (:subitems ("Automatic" (rescale-plot :x)                                                                  "Rescale automatically")                                                       ("Manual" (manually-rescale-plot :x)                                                              "Rescale manually")))                                     ("Y Axis" (rescale-plot :y)                                            "Rescale Y axis"                                            (:subitems ("Automatic" (rescale-plot :y)                                                              "Rescale automatically")                                                   ("Manual" (manually-rescale-plot :y)                                                          "Rescale manually")))))                       ("Extend" extend-axis "Extend plot axes on/off" (:subitems ("X Axis"                                                                                   (extend-axis                                                                                    :x)                                                                                                                                                                  "Extend X axis on/off"                                                                                   )                                                                              ("Y Axis" (extend-axis                                                                                         :y)                                                                                                                                                                    "Extend Y axis on/off"                                                                                     )))                       ("Labels" ask-for-which-label "Relabel plot" (:subitems ("Title" (                                                                                        ask-for-label                                                                                         :top)                                                                                      "Title plot")                                                                           ("Left" (ask-for-label                                                                                    :left)                                                                                                                                                                   "Label left of plot"                                                                                  )                                                                           ("Bottom" (ask-for-label                                                                                      :bottom)                                                                                                                                                                 "Label bottom of plot"                                                                                  )                                                                           ("Right" (ask-for-label                                                                                     :right)                                                                                                                                                                  "Label right of plot"                                                                                  )))                       ("Tics" toggle-tics "Tics on or off" (:subitems ("Top" (toggle-tics :top)                                                                              "Top tics on/off")                                                                   ("Left" (toggle-tics :left)                                                                          "Left tics on/off")                                                                   ("Bottom" (toggle-tics :bottom)                                                                          "Bottom tics on/off")                                                                   ("Right" (toggle-tics :right)                                                                          "Right tics on/off")))                       ("Undelete" undelete-last-object "Undelete last deleted object")                       ("Fixed Menu" toggle-fixed-right-menu "Fix right plot menu"))          :when-selected-fn          'default-when-selected-fn :track-cursor-p t))(defun manually-rescale-plot (plot &optional (axis :both))   (let ((scale-info (plot-scale-info plot))         (plot-objects (plot-objects plot)))        (if (or (eq axis ':both)                (eq axis ':x))            (let ((new-interval (ask-for-scale plot ':x)))                 (when (> (interval-max new-interval)                          (interval-min new-interval))                       (setf-plot-interval plot :x new-interval t))))        (if (or (eq axis ':both)                (eq axis ':y))            (let ((new-interval (ask-for-scale plot ':y)))                 (when (> (interval-max new-interval)                          (interval-min new-interval))                       (setf-plot-interval plot :y new-interval t))))        (redraw-plot-window plot)))(defun ask-for-scale (plot axis)   (let ((eol-chars (il:constant (list (char-code #\Newline)                                       (char-code #\Linefeed)                                       (char-code #\Escape)                                       (char-code #\Tab))))         (plot-prompt-window (plot-prompt-window plot))         (upper (ecase axis                    (:x (plot-x-upper plot))                    (:y (plot-y-upper plot))))         (lower (case axis                    (:x (plot-x-lower plot))                    (:y (plot-y-lower plot)))))        (terpri plot-prompt-window)        (setq lower (read-from-string (il:promptforword (concatenate 'string (string axis)                                                               " axis: From ")                                             lower "Type a number" plot-prompt-window nil nil                                              eol-chars)))        (setq upper (read-from-string (il:promptforword " to " upper "Type a number"                                              plot-prompt-window nil nil eol-chars)))        (make-axis-interval :min lower :max upper)))(defun toggle-label (selected-object plot)   (if (plot-object-prop selected-object :label-object)       (unlabel-plot-object selected-object plot)       (label-plot-object selected-object plot)))(defun ask-for-label (plot margin-name)   (il:* il:|;;| "Prompt for new label and make the required call to LABELPLOT")   (if (eq margin-name ':title)       (setq margin-name ':top))   (let ((plot-prompt (plot-prompt-window plot))         (margin (ecase margin-name                     (:bottom (plot-bottom-margin plot))                     (:left (plot-left-margin plot))                     (:top (plot-top-margin plot))                     (:right (plot-right-margin plot))))         newlabel)        (terpri plot-prompt)        (setq newlabel (il:promptforword (case margin-name                                             (:bottom "Bottom margin label?")                                             (:left "Left margin label?")                                             (:top "Title?")                                             (:right "Right margin label?"))                              (margin-label margin)                              "Type a label" plot-prompt nil nil (il:constant (list (char-code                                                                                            #\Newline)                                                                                    (char-code                                                                                            #\Linefeed                                                                                           )                                                                                    (char-code                                                                                            #\Escape)                                                                                    (char-code #\Tab)                                                                                    ))))        (if (or (null newlabel)                (not (string= newlabel (margin-label margin))))            (setf-plot-label plot margin-name newlabel))))(defun ask-for-which-label (plot)   (il:* il:|;;| "Prompt for new label and make the required call to ASKFORLABEL")   (let ((lmenu (il:constant (make-menu :items '(:top :left :bottom :right))))         margin)        (print-plot-prompt "Select a margin" plot)        (setq margin (pop-up-menu lmenu))        (and margin (ask-for-label plot margin))))(defun toggle-tics (plot &optional margin-name no-update-p)   (if (null margin-name)       (progn (toggle-tics plot :bottom t)              (toggle-tics plot :left))       (setf-tics-p plot margin-name (not (tics-p plot margin-name))              no-update-p)))(defun toggle-fixed-right-menu (plot)   (if (plot-prop plot :fixed-right-menu-p)       (unfix-right-menu plot)       (fix-right-menu plot)))(defun default-menu (menu-position)   (case menu-position       (:middle (and *default-middle-menu* (copy-menu *default-middle-menu*)))       (:right (and *default-middle-menu* (copy-menu *default-right-menu*)))       (otherwise (if (pt:memq menu-position *plot-object-types*)                      (let ((menu (gethash menu-position *plot-object-menus*)))                           (and menu (copy-menu menu)))))))(defun setf-default-menu (menu-position new-menu)   (let ((new-value (and new-menu (copy-menu new-menu))))        (case menu-position            (:middle (setq *default-middle-menu* new-value))            (:right (setq *default-right-menu* new-value))            (otherwise (if (pt:memq menu-position *plot-object-types*)                           (setf (gethash menu-position *plot-object-menus*)                                 new-value))))))(il:* il:|;;| "Do we want this setf?")(defsetf default-menu setf-default-menu)(defun fix-right-menu (plot)   (if (null (plot-prop plot :fixed-right-menu-p))       (let ((plot-window (plot-window plot)))            (setf (plot-prop plot :fixed-right-menu-p)                  (and (open-window-p (plot-window plot))                       (attach-menu (plot-right-menu plot)                              plot-window :right :top))))))(defun unfix-right-menu (plot)   (let ((fixed-menu (plot-prop plot :fixed-right-menu-p)))        (when fixed-menu            (close-window fixed-menu)            (detach-window fixed-menu)            (setf (plot-prop plot :fixed-right-menu-p)                  nil))))(defun remove-fixed-right-menu (plot)   (let ((fixed-menu (plot-prop plot :fixed-right-menu-p)))        (when fixed-menu            (close-window fixed-menu)            (detach-window fixed-menu)            (setf (plot-prop plot :fixed-right-menu-p)                  nil))))(il:* il:|;;| "Misc functions")(defun which-plot (&optional window-or-x y)     (il:* il:\; "Edited  6-May-87 09:27 by jop")   (il:* il:|;;| "like WHICHW but returns corresponding plot.  First arg may be a window")   (let* ((w (or (window-p window-or-x)                 (il:whichw window-or-x y)))          (plot (or (window-prop w :plot)                    (window-prop (window-prop w 'il:iconfor)                           :plot))))         (if (typep plot 'plot)             plot)))(xcl:define-file-environment "PLOT-FNS" :package "PLOT"   :compiler :compile-file   :readtable "XCL")(il:putprops il:plot-fns il:copyright ("Xerox Corporation" 1988))(il:declare\: il:dontcopy  (il:filemap (nil)))il:stop