;;;-*- Mode:LISP; Package:window-maker; Base:8; Fonts:(CPTFONT) -*- ;;; Copyright C LISP MACHINE INC., 1985. ;;; ;;; ;;; Functions which help choose a slicing point. ;;; (defun output-number-on-the-panel (number) (let ((string-to-output (format nil "~D" number)) length-of-string) (if (< (setq length-of-string (string-length string-to-output)) 4) (setq string-to-output (string-append (make-string (- 4 length-of-string) ':initial-element #\space) string-to-output))) (funcall *instrument-pane* ':clear-screen) (funcall *instrument-pane* ':string-out-explicit string-to-output 20. (// (funcall *instrument-pane* ':height) 6) nil nil fonts:43vxms tv:alu-ior))) (defun get-point-of-slicing (direction top left lower-limit upper-limit frame &optional (flag NIL) &aux (slicing-point NIL)) (funcall *instrument-pane* :set-label '(:string "Percent" :font fonts:cptfontb)) (multiple-value-bind (x-off y-off) (tv:sheet-calculate-offsets *graphic-window-area* (funcall *graphic-window-area* :superior)) ;; clear io buffer from possible mouse-clicks and mouse-moves (tv:io-buffer-clear (funcall *graphic-window-area* :io-buffer)) (let* ((direction-flag (equal direction ':horizontal)) (blinker (if direction-flag #/ #/)) ;first is the left arrow the second the up arrow (cursor-x-position (if direction-flag left (if flag upper-limit left))) (cursor-y-position (if direction-flag (if flag upper-limit top) top)) (max-percent (funcall frame :compute-percent lower-limit upper-limit direction))) (funcall *graphic-window-area* :set-in-slicing-procedures "click left to take slicing point, middle or right to abort operation") (funcall *graphic-window-area* :draw-char fonts:mouse blinker (if direction-flag cursor-x-position (- cursor-x-position 8.)) (if direction-flag (- cursor-y-position 8.) cursor-y-position) tv:alu-xor) ;; position the mouse (tv:mouse-warp (+ cursor-x-position x-off) (+ cursor-y-position y-off)) (output-number-on-the-panel (if flag (- max-percent (funcall frame :compute-percent lower-limit (if direction-flag cursor-y-position cursor-x-position) direction)) (funcall frame :compute-percent lower-limit (if direction-flag cursor-y-position cursor-x-position) direction))) (unwind-protect (loop as blip = (funcall *graphic-window-area* :list-tyi) with mouse-x and mouse-y do (selectq (first blip) (:my-mouse-move (funcall *graphic-window-area* :draw-char fonts:mouse blinker (if direction-flag cursor-x-position (- cursor-x-position 8.)) (if direction-flag (- cursor-y-position 8.) cursor-y-position) tv:alu-xor) (multiple-value (mouse-x mouse-y) (apply #'values (cdr blip))) (if direction-flag (setq cursor-y-position (if (and (>= mouse-y lower-limit) (<= mouse-y upper-limit)) mouse-y cursor-y-position)) (setq cursor-x-position (if (and (>= mouse-x lower-limit) (<= mouse-x upper-limit)) mouse-x cursor-x-position))) ; force the blinker mouse to occupy the same place as before in on of the coordinates. (tv:mouse-warp (+ x-off cursor-x-position) (+ y-off cursor-y-position)) (funcall *graphic-window-area* :draw-char fonts:mouse blinker (if direction-flag cursor-x-position (- cursor-x-position 8.)) (if direction-flag (- cursor-y-position 8.) cursor-y-position) tv:alu-xor) (output-number-on-the-panel (if flag (- max-percent (funcall frame :compute-percent lower-limit (if direction-flag cursor-y-position cursor-x-position) direction)) (funcall frame :compute-percent lower-limit (if direction-flag cursor-y-position cursor-x-position) direction)))) (:my-mouse-click (setq slicing-point (selectq (second blip) (#/mouse-1-1 (if direction-flag (fourth blip) (third blip))) (#/mouse-2-1 nil))) (return nil)))) (funcall *graphic-window-area* :draw-char fonts:mouse blinker (if direction-flag cursor-x-position (- cursor-x-position 8.)) (if direction-flag (- cursor-y-position 8.) cursor-y-position) tv:alu-xor) (funcall *graphic-window-area* :set-in-slicing-procedures NIL) (funcall *instrument-pane* :set-label nil) (funcall *instrument-pane* :clear-screen) ))) slicing-point) (defun get-number-of-characters (lower-limit upper-limit frame flag &optional (char-number nil)) (let* ((line-height (funcall *Graphic-window-area* :line-height)) (character-width (funcall *graphic-window-area* :char-width)) (max-number-of-char (// (- upper-limit lower-limit) character-width)) (io-buffer (funcall *graphic-window-area* :io-buffer)) left top right bottom bottom-side cursor-x-position cursor-y-position x-off y-off) (if (not flag) (setq char-number max-number-of-char)) (multiple-value (left top right bottom) (funcall frame :get-slots)) (multiple-value (x-off y-off) (tv:sheet-calculate-offsets *graphic-window-area* (funcall *graphic-window-area* :superior))) (setq cursor-x-position (+ lower-limit (* (1- (if flag 1 max-number-of-char)) character-width)) cursor-y-position (+ top 1) bottom-side (+ cursor-y-position line-height)) (funcall *graphic-window-area* :set-in-slicing-procedures "click left to take slicing point, middle or right to abort operation") (funcall *instrument-pane* ':set-label '(:string "characters" :font fonts:cptfontb)) (output-number-on-the-panel 1) (draw-box cursor-x-position cursor-y-position (+ cursor-x-position character-width) bottom-side) (tv:mouse-warp (+ cursor-x-position x-off) (+ cursor-y-position y-off)) (tv:io-buffer-clear io-buffer) ;clear io-buffer from accidentally generated blips (unwind-protect (loop as blip = (funcall *graphic-window-area* :list-tyi) with mouse-x with mouse-y with computed-char-number = (if flag 1 max-number-of-char) do (selectq (car blip) (:my-mouse-move ;; erase current position of the character box. (draw-box cursor-x-position cursor-y-position (+ cursor-x-position character-width) bottom-side) (multiple-value (mouse-x mouse-y) (apply #'values (cdr blip))) (if (and (>= mouse-x lower-limit) (<= mouse-x upper-limit)) (setq computed-char-number (1+ (// (- mouse-x lower-limit) character-width)) cursor-x-position (+ lower-limit (* (1- computed-char-number) character-width)))) (output-number-on-the-panel (if flag computed-char-number (- max-number-of-char computed-char-number -1))) (draw-box cursor-x-position cursor-y-position (+ cursor-x-position character-width) bottom-side) (tv:mouse-warp (+ mouse-x x-off) (+ cursor-y-position y-off))) (:my-mouse-click (setq char-number (selectq (second blip) (#/mouse-1-1 (if flag computed-char-number (- max-number-of-char computed-char-number -1))) (#/mouse-2-1 nil))) (return nil)))) ;; now clean up after you. (funcall *graphic-window-area* :set-in-slicing-procedures NIL) (funcall *instrument-pane* :set-label nil) (funcall *instrument-pane* :clear-screen) (draw-box cursor-x-position cursor-y-position (+ cursor-x-position character-width) bottom-side)) (values char-number (and char-number (+ cursor-x-position character-width))))) (defun get-number-of-lines (lower-limit upper-limit frame flag &optional (line-number nil)) "routine to do the graphic to the *window-maker* and get the number of lines" (let* ((line-height (funcall *graphic-window-area* ':line-height)) (max-number-of-lines (// (- upper-limit lower-limit) line-height)) right-side left top right bottom cursor-x-position cursor-y-position x-off y-off) (multiple-value (left top right bottom) (funcall frame :get-slots)) (multiple-value (x-off y-off) (tv:sheet-calculate-offsets *graphic-window-area* (funcall *graphic-window-area* :superior))) (setq right-side (1- right)) (funcall *instrument-pane* ':set-label '(:string "lines" :font fonts:cptfontb)) (output-number-on-the-panel 1) (setq cursor-x-position (1+ left) cursor-y-position (+ lower-limit (* (1- (if flag 1 max-number-of-lines)) line-height))) (funcall *graphic-window-area* :set-in-slicing-procedures "click left to take slicing point, middle or right to abort operation") (draw-box cursor-x-position cursor-y-position right-side (+ cursor-y-position line-height)) (tv:mouse-warp (+ cursor-x-position x-off) (+ cursor-y-position y-off)) ;; now clear the io buffer from any pending blips or character input. (tv:io-buffer-clear (funcall *graphic-window-area* :io-buffer)) (unwind-protect (loop as blip = (funcall *graphic-window-area* :list-tyi) with mouse-x and mouse-y with new-line-number = (if flag 1 max-number-of-lines) do (selectq (car blip) (:my-mouse-move ;; erase current position of cursor. (draw-box cursor-x-position cursor-y-position right-side (+ cursor-y-position line-height)) (multiple-value (mouse-x mouse-y) (apply #'values (cdr blip))) (if (and (>= mouse-y lower-limit) (<= mouse-y upper-limit)) (setq new-line-number (1+ (// (- mouse-y lower-limit) line-height)) cursor-y-position (+ lower-limit (* (1- new-line-number) line-height)))) (output-number-on-the-panel (if flag new-line-number (- max-number-of-lines new-line-number -1))) (draw-box cursor-x-position cursor-y-position right-side (+ cursor-y-position line-height)) (tv:mouse-warp (+ cursor-x-position x-off) (+ mouse-y y-off))) (:my-mouse-click (setq line-number (selectq (second blip) (#/mouse-1-1 (if flag new-line-number (- max-number-of-lines new-line-number -1))) (#/mouse-2-1 nil))) (return nil)))) ;; clean after you. (funcall *instrument-pane* :set-label nil) (funcall *instrument-pane* :clear-screen) (draw-box cursor-x-position cursor-y-position right-side (+ cursor-y-position line-height)) (funcall *graphic-window-area* :set-in-slicing-procedures NIL)) (values line-number (and line-number (+ cursor-y-position line-height))))) (defun get-number-of-pixels (direction left top lower-limit upper-limit flag &optional (pixel-number 1) &aux x-off y-off max-number-of-pixels slicing-point cursor-x-position cursor-y-position) (funcall *instrument-pane* ':set-label '(:string "pixels" :font fonts:cptfontb)) (output-number-on-the-panel 1) (setq cursor-x-position left cursor-y-position top slicing-point nil) (setq max-number-of-pixels (- upper-limit lower-limit)) (multiple-value (x-off y-off) (tv:sheet-calculate-offsets *graphic-window-area* (funcall *graphic-window-area* :superior))) (funcall *graphic-window-area* :draw-char fonts:mouse #/ (- cursor-x-position 6) (- cursor-y-position 6) tv:alu-xor) (tv:mouse-warp (+ cursor-x-position x-off) (+ cursor-y-position y-off)) (tv:io-buffer-clear (funcall *graphic-window-area* :io-buffer)) (funcall *graphic-window-area* :set-in-slicing-procedures "click left to take slicing point, middle or right to abort operation") (unwind-protect (loop as blip = (funcall *graphic-window-area* :list-tyi) with mouse-x and mouse-y with computed-pixel-number = 1 do (selectq (car blip) (:my-mouse-move (funcall *graphic-window-area* :draw-char fonts:mouse #/ (- cursor-x-position 6) (- cursor-y-position 6) tv:alu-xor) (multiple-value (mouse-x mouse-y) (apply #'values (cdr blip))) (if (equal direction ':horizontal) (if (and (>= mouse-y lower-limit) (<= mouse-y upper-limit)) (setq cursor-y-position mouse-y computed-pixel-number (1+ (if flag (- mouse-y lower-limit) (- upper-limit mouse-y))))) (if (and (>= mouse-x lower-limit) (<= mouse-x upper-limit)) (setq cursor-x-position mouse-x computed-pixel-number (1+ (if flag (- mouse-x lower-limit) (- upper-limit mouse-x)))))) (output-number-on-the-panel computed-pixel-number) (funcall *graphic-window-area* :draw-char fonts:mouse #/ (- cursor-x-position 6) (- cursor-y-position 6) tv:alu-xor) (tv:mouse-warp (+ cursor-x-position x-off) (+ cursor-y-position y-off))) (:my-mouse-click (setq pixel-number (selectq (second blip) (#/mouse-1-1 computed-pixel-number) (#/mouse-2-1 nil))) (return nil)))) ;; now clean up after you. (funcall *graphic-window-area* :set-in-slicing-procedures nil) (funcall *instrument-pane* :set-label nil) (funcall *instrument-pane* :clear-screen) (funcall *graphic-window-area* :draw-char fonts:mouse #/ (- cursor-x-position 6) (- cursor-y-position 6) tv:alu-xor)) (values pixel-number (if (equal direction ':horizontal) cursor-y-position cursor-x-position))) (defun get-argument-for-other-keyword (key direction frame lower-limit upper-limit &optional (flag nil) &aux number-to-return slicing-point left top) "this function is to provide the user for communicating the absolute size either in :lines or :characters or :pixels" (selectq key (:lines (multiple-value (number-to-return slicing-point) (get-number-of-lines lower-limit upper-limit frame flag))) (:characters (multiple-value (number-to-return slicing-point) (get-number-of-characters lower-limit upper-limit frame flag))) (:pixels (if (equal direction ':horizontal) (setq left (funcall frame ':left) top (if flag lower-limit upper-limit)) (setq left (if flag lower-limit upper-limit) top (funcall frame ':top))) (multiple-value (number-to-return slicing-point) (get-number-of-pixels direction left top lower-limit upper-limit flag)))) (values number-to-return slicing-point)) (defun get-arguments-for-slicing-for-absolute-size (direction lower-limit upper-limit frame) (let (key1 key2 left1 left2 right1 right2 top1 top2 bottom1 bottom2 l t1 r b (pane nil) (slicing-point nil) (number1 nil) (number2 nil) (flag nil) slicing-point1 slicing-point2) (multiple-value (l t1 r b) (funcall frame ':get-slots)) (setq key1 (tv:menu-choose (if (equal direction ':horizontal) *menu-2* *menu-3*) '(:string "Specify size for first pane in:" :font fonts:metsi))) (or (equal key1 ':EVEN) (and (setq flag t) nil) (multiple-value (number1 slicing-point1) (get-argument-for-other-keyword key1 direction frame lower-limit upper-limit t))) (setq key2 (tv:menu-choose (if (equal direction ':horizontal) *menu-2* *menu-3*) '(:string "Specify size for second pane in:" :font fonts:metsi))) (or (equal key2 ':EVEN) (multiple-value (number2 slicing-point2) (get-argument-for-other-keyword key2 direction frame (if flag slicing-point1 lower-limit) upper-limit flag))) (if (and key1 key2 (or (equal key1 ':EVEN) number1) (or (equal key2 ':EVEN) number2)) (progn (if (and (equal key1 ':EVEN) (equal key2 ':EVEN)) ; it is the case of slicing the window evenly (setq slicing-point (+ lower-limit (// (- upper-limit lower-limit) 2)) slicing-point1 slicing-point slicing-point2 slicing-point) (if (equal key1 ':EVEN) (setq slicing-point slicing-point2 slicing-point1 slicing-point2) (if (equal key2 ':EVEN) (setq slicing-point slicing-point1 slicing-point2 slicing-point1)))) (if slicing-point ;; ;; Either window or both have keyword :EVEN ;; (if (equal direction ':horizontal) (setq left1 l right1 r top1 lower-limit bottom1 (1- slicing-point) left2 l right2 r top2 (1+ slicing-point) bottom2 upper-limit) (setq left1 lower-limit top1 t1 right1 (1- slicing-point) bottom1 b left2 (1+ slicing-point) top2 t1 right2 upper-limit bottom2 b)) ;; ;; this means that both windows have been specified with absolute measures. ;; (if (equal direction ':horizontal) (setq left1 l top1 lower-limit right1 r bottom1 (1- slicing-point1) left2 l top2 (1+ slicing-point1) right2 r bottom2 (1- slicing-point2) pane (make-instance 'pane :owner frame :left l :top (1+ slicing-point2) :right r :bottom upper-limit :keyword ':EVEN)) (setq left1 lower-limit top1 t1 right1 (1- slicing-point1) bottom1 b left2 (1+ slicing-point1) top2 t1 right2 (1- slicing-point2) bottom2 b pane (make-instance 'pane :owner frame :left (1+ slicing-point2) :top t1 :right upper-limit :bottom b :keyword ':PERCENTWISE))))) ;; prevents it from breaking if somebody has clicked middle when selecting the slicing point. (setq key1 nil key2 nil)) (values slicing-point1 number1 slicing-point2 number2 key1 key2 left1 left2 right1 right2 bottom1 bottom2 top1 top2 pane))) (defun sort-lines (list-of-lines) (let ((direction (equal (funcall (first list-of-lines) :direction) ':horizontal)) (first-line (first list-of-lines)) (second-line (second list-of-lines)) x-pos-1 y-pos-1 x-pos-2 y-pos-2) (multiple-value (x-pos-1 y-pos-1 x-pos-2 y-pos-2) (apply #'values (list (funcall first-line :x-position) (funcall first-line :y-position) (funcall second-line :x-position) (funcall second-line :y-position)))) (if direction (if (> y-pos-1 y-pos-2) (list second-line first-line) list-of-lines) (if (> x-pos-1 x-pos-2) (list second-line first-line) list-of-lines)))) (defun update-owner-ship-of-lines-of-frame-to-change (pane line frame-to-change location) (let ((lines-border-frame-to-change (funcall frame-to-change :list-of-border-lines)) line-to-share border-pane-or-frame) (if (= (length lines-border-frame-to-change) 1) ;; only one line. Check to see if line has to be shared or not. (if (member location '(:top :left)) ;; pane inserted does not have to share the line of frame-to-change. ;; but it has to share its own. (progn (funcall line :set-owner2 frame-to-change) (funcall frame-to-change :update-list-of-border-lines line)) (setq line-to-share (first lines-border-frame-to-change)) (funcall line :set-owner2 frame-to-change) (funcall frame-to-change :delete-line-from-border-list line-to-share) (funcall frame-to-change :update-list-of-border-lines line) (funcall line-to-share :update-owner frame-to-change pane) (funcall pane :update-list-of-border-lines line-to-share)) ;; otherwise sort them both (setq lines-border-frame-to-change (sort-lines lines-border-frame-to-change) line-to-share (if (member location '(:top :left)) (first lines-border-frame-to-change) (second lines-border-frame-to-change)) border-pane-or-frame (funcall line-to-share :get-other-window frame-to-change)) (funcall frame-to-change :delete-line-from-border-list line-to-share) (funcall frame-to-change :update-list-of-border-lines line) (funcall line :set-owner2 frame-to-change) (funcall pane :update-list-of-border-lines line-to-share) (funcall line-to-share :replace-element frame-to-change pane)))) (defun sort-lines-by-position (list-of-lines) (selectq (length list-of-lines) ((0 1) list-of-lines) (otherwise (if (equal (funcall (first list-of-lines) :direction) ':horizontal) (if (> (funcall (first list-of-lines) :y-position) (funcall (second list-of-lines) :y-position)) (list (second list-of-lines) (first list-of-lines)) list-of-lines) (if (> (funcall (first list-of-lines) :x-position) (funcall (second list-of-lines) :x-position)) (list (second list-of-lines) (first list-of-lines)) list-of-lines))))) ;; ;; This function make sure that all the graphic is done right. The reason is, there is a problem when ;; shrinking down the size of the panes. At some point of time the borders between two panes might overlap ;; This function makes sure that the borders never overlapp. ;; (defun fix-all-new-coordinates (frame list-of-panes-or-frames) (let ((direction (equal (funcall frame :direction-of-slice) ':horizontal)) (sorted-list-of-panes-or-frames (sort-panes-and-frames-in-frame list-of-panes-or-frames (funcall frame :direction-of-slice)))) (loop for pane-or-frame in (butlast (cdr sorted-list-of-panes-or-frames)) with set-operation = (if direction ':set-top ':set-left) with get-operation = (if direction ':bottom ':right) with current-slot = (funcall (first sorted-list-of-panes-or-frames) get-operation) with last-pane-or-frame = (nth (1- (length sorted-list-of-panes-or-frames)) sorted-list-of-panes-or-frames) when (typep pane-or-frame 'frame) DO (funcall pane-or-frame set-operation (+ current-slot 2)) (setq current-slot (funcall pane-or-frame get-operation)) ELSE DO (multiple-value-bind (x y z s) (funcall pane-or-frame :get-slots) (draw-box x y z s)) (funcall pane-or-frame set-operation (+ current-slot 2)) (setq current-slot (funcall pane-or-frame get-operation)) (multiple-value-bind (x y z s) (funcall pane-or-frame :get-slots) (draw-box x y z s)) finally (if (typep last-pane-or-frame 'frame) (funcall last-pane-or-frame set-operation (+ current-slot 2)) (multiple-value-bind (x y z s) (funcall last-pane-or-frame :get-slots) (draw-box x y z s)) (funcall last-pane-or-frame set-operation (+ current-slot 2)) (multiple-value-bind (x y z s) (funcall last-pane-or-frame :get-slots) (draw-box x y z s))))))