;;; -*- Mode: Lisp; Package: Hacks; Lowercase: Yes; Base: 10 -*- ;;; Dcrock. ;;; Note: This file is in decimal, not octal. ;;; Settable parameters. (defconst *dc-height* 80) ; Character height in pixels. (defconst *dc-width* 60) ; Character width in pixels. (defconst *dc-thickness* 6) ; Character stroke thickness. (defconst *dc-offset* 10) ; Slant -- difference in x pos from bottom to top. (defconst *dc-colon-size* 7) ; Width and height of colon dots. (defconst *dc-char-spacing* 25) ; Char-to-char spacing. (defconst *dc-colon-spacing* 20) ; Char-to-colon spacing. (defconst *dc-colon-separation* 20) (defconst *dc-start-x* 10) ; Distance from left edge of window to first digit. (defconst *dc-start-y* 10) ; Distance from top edge of window to tops of digits. ;;; Derived parameters. (defconst *dc-total-width* ; Width of working part of window. (+ (* 6 *dc-width*) ; six digits (* 3 *dc-char-spacing*) ; three char-to-char gaps (* 2 *dc-colon-size*) ; two colons (* 4 *dc-colon-spacing*) ; four char-to-colon gaps (* 2 *dc-start-x*) *dc-offset*)) (defconst *dc-total-height* (+ *dc-height* (* 2 *dc-start-y*))) (defconst *dc-half-thickness* (// *dc-thickness* 2)) (defconst *dc-half-height* (// *dc-height* 2)) (defconst *dc-slope* (// (small-float *dc-offset*) *dc-height*)) (defconst *dc-whiteness* (make-array '(32 32) ':type 'art-1b)) (dotimes (x 32) (dotimes (y 32) (aset 0 *dc-whiteness* x y))) (defconst *dc-x-offsets* (make-array 6)) (loop for form in '((- *dc-start-x* *dc-width*) *dc-char-spacing* (+ *dc-colon-size* (* 2 *dc-colon-spacing*)) *dc-char-spacing* (+ *dc-colon-size* (* 2 *dc-colon-spacing*)) *dc-char-spacing*) for i from 0 with x = 0 do (setq x (+ x *dc-width* (eval form))) (aset x *dc-x-offsets* i)) (defmacro draw-stroke (x1-form y1-form width-form height-form array-form) `(let* ((y1 (+ base-y ,y1-form)) (x1 (+ base-x ,x1-form (fix (* (- *dc-height* ,y1-form) *dc-slope*)))) (x1-offset (+ base-x ,x1-form (fix (* (- *dc-height* (+ ,y1-form ,height-form)) *dc-slope*))))) (sys:%draw-triangle x1 y1 x1-offset (+ y1 ,height-form) (+ x1-offset ,width-form) (+ y1 ,height-form) tv:alu-ior ,array-form) (sys:%draw-triangle x1 y1 (+ x1 ,width-form) y1 (+ x1-offset ,width-form) (+ y1 ,height-form) tv:alu-ior ,array-form))) (defun draw-stroke-one (base-x base-y array) (draw-stroke 0 0 *dc-width* *dc-thickness* array)) (defun draw-stroke-two (base-x base-y array) (draw-stroke (- *dc-width* *dc-thickness*) 0 *dc-thickness* (+ *dc-half-height* *dc-half-thickness*) array)) (defun draw-stroke-three (base-x base-y array) (draw-stroke (- *dc-width* *dc-thickness*) (- *dc-half-height* *dc-half-thickness*) *dc-thickness* (+ *dc-half-height* *dc-half-thickness*) array)) (defun draw-stroke-four (base-x base-y array) (draw-stroke 0 (- *dc-height* *dc-thickness*) *dc-width* *dc-thickness* array)) (defun draw-stroke-five (base-x base-y array) (draw-stroke 0 (- *dc-half-height* *dc-half-thickness*) *dc-thickness* (+ *dc-half-height* *dc-half-thickness*) array)) (defun draw-stroke-six (base-x base-y array) (draw-stroke 0 0 *dc-thickness* (+ *dc-half-height* *dc-half-thickness*) array)) (defun draw-stroke-seven (base-x base-y array) (draw-stroke 0 (- *dc-half-height* *dc-half-thickness*) *dc-width* *dc-thickness* array)) (defun draw-colon (base-x base-y array) (draw-stroke 0 (+ *dc-half-height* *dc-colon-separation*) *dc-colon-size* *dc-colon-size* array) (draw-stroke 0 (- *dc-half-height* (+ *dc-colon-size* *dc-colon-separation*)) *dc-colon-size* *dc-colon-size* array)) (defconst *dc-stroke-list* '(draw-stroke-one draw-stroke-two draw-stroke-three draw-stroke-four draw-stroke-five draw-stroke-six draw-stroke-seven)) (defconst *dc-digit-array* (make-array 10)) (fillarray *dc-digit-array* '(( t t t t t t nil) ;0 (nil t t nil nil nil nil) ;1 ( t t nil t t nil t) ;2 ( t t t t nil nil t) ;3 (nil t t nil nil t t) ;4 ( t nil t t nil t t) ;5 ( t nil t t t t t) ;6 ( t t t nil nil nil nil) ;7 ( t t t t t t t) ;8 ( t t t nil nil t t) ;9 )) (defun draw-digit (digit base-x base-y array) (if (not (null digit)) (loop for on-p in (aref *dc-digit-array* digit) for fcn in *dc-stroke-list* when on-p do (funcall fcn base-x base-y array)))) (defflavor dc-window (old-digits new-digits working-array-1 working-array-2 go) (tv:process-mixin tv:window) (:default-init-plist :process '(dc-top-level) :blinker-p nil :label nil)) (defmethod (dc-window :after :init) (&rest ignore) (setq old-digits (make-array 6) new-digits (make-array 6) working-array-1 (tv:make-sheet-bit-array self (+ *dc-width* *dc-offset*) *dc-height*) working-array-2 (tv:make-sheet-bit-array self (+ *dc-width* *dc-offset*) *dc-height*) go nil)) (defmacro defun-dc (arglist &body body) `(declare-flavor-instance-variables (dc-window) (defun ,arglist . ,body))) (defun-dc change-digit (old-digit new-digit base-x base-y) (bitblt tv:alu-seta (+ *dc-width* *dc-offset*) *dc-height* *dc-whiteness* 0 0 working-array-1 0 0) (bitblt tv:alu-seta (+ *dc-width* *dc-offset*) *dc-height* *dc-whiteness* 0 0 working-array-2 0 0) (draw-digit old-digit 0 0 working-array-1) (draw-digit new-digit 0 0 working-array-2) (bitblt tv:alu-xor (+ *dc-width* *dc-offset*) *dc-height* working-array-1 0 0 working-array-2 0 0) (bitblt tv:alu-xor (+ *dc-width* *dc-offset*) *dc-height* working-array-2 0 0 tv:screen-array base-x base-y)) (defmethod (dc-window :after :refresh) (&optional ignore) (cond ((not tv:restored-bits-p) (get-new-time) (copy-array-contents new-digits old-digits) (dotimes (d 6) (draw-digit (aref old-digits d) (aref *dc-x-offsets* d) *dc-start-y* tv:screen-array)) (draw-colon (+ (aref *dc-x-offsets* 1) *dc-width* *dc-colon-spacing*) *dc-start-y* tv:screen-array) (draw-colon (+ (aref *dc-x-offsets* 3) *dc-width* *dc-colon-spacing*) *dc-start-y* tv:screen-array)))) (defun-dc update-time () (get-new-time) (tv:prepare-sheet (self) (dotimes (d 6) (let ((old (aref old-digits d)) (new (aref new-digits d))) (if (neq old new) (change-digit old new (aref *dc-x-offsets* d) *dc-start-y*))))) (copy-array-contents new-digits old-digits)) (defun-dc get-new-time () (multiple-value-bind (sec min hou) (time:get-time) (and (zerop sec) (zerop (\ min 30.)) (fboundp 'play-time) (play-time (if (zerop min) (\ hou 12.) 1))) (put-digits hou 0) (put-digits min 2) (put-digits sec 4) (if (zerop (aref new-digits 0)) (aset nil new-digits 0)))) (defun-dc put-digits (num i) (aset (// num 10) new-digits i) (aset (\ num 10) new-digits (1+ i))) (defun dc-top-level (window) (time:get-time) ; Make sure timebase initialized (funcall window ':top-level)) (defmethod (dc-window :top-level) () (process-wait "go" #'car (locate-in-instance self 'go)) (loop doing (update-time) (process-sleep 30.))) (defvar *dc* nil) (defun dc (&optional (superior tv:mouse-sheet)) (if (null *dc*) (setq *dc* (tv:make-window 'dc-window ':superior superior ':width *dc-total-width* ':height *dc-total-height*))) (multiple-value-bind (w h) (funcall superior ':inside-size) (funcall *dc* ':center-around (// w 2) (// h 2))) (funcall *dc* ':start) (funcall *dc* ':expose)) (defmethod (dc-window :start) () (setq go t)) (compile-flavor-methods dc-window) (defdemo "Digital Crock" "Standard digital clock" (dc-demo)) (defun dc-demo () (dc) (funcall tv:selected-window ':tyi) (funcall *dc* ':bury))