; .EnTete "Programmer en Ceyx" "" "Annexe VI: Les Traceurs" ; .Annexe VI "Les Traceurs" ; .Titre "Logiciel de Guidage des Traceurs HP7221" ; .Auteur "O. Guillaumin, J.-M. Hullot et B. Serlet" (ceyx-load coord) (ceyx-load stream) ; .Section "De'finition d'une Machine Virtuelle de Trac/age" ; .SSection "Introduction" ; Le but de ce court fichier est de donner une spe'cification unifie'e ; de deux dispositifs de sortie: l'e'cran colorix et le plotter HP. ; .br ; Une tre`s petite partie de ce code est de'pendante du syste`me. ; Elle est indique'e par ; .br ; \fB;** System dependant\fR. ; .SSection "Le type ge'ne'rique" (deftclass OutputDevice) ; Le dispositif de sortie courant de sortie: (defvar *output-device* (omakeq OutputDevice)) ; .SSection "Fonctions de renvoi des messages" ; Les fonctions suivantes de'finissent des abre'viations pour travailler ; sur le dispositif de sortie courant, qui est cense' e↑tre dans la variable ; \fB*output-device*\fR. (de display-init () (send 'display-init *output-device*)) (de display-end () (send 'display-end *output-device*)) (de display-frame (rect color) (send 'display-frame *output-device* rect color)) (de display-box (rect color) (send 'display-box *output-device* rect color)) (de display-vector (rect color) (send 'display-vector *output-device* rect color)) (de display-text (rect lines rot color) (send 'display-text *output-device* rect lines rot color)) ; .SSection "Se'mantiques par de'faut pour faciliter la mise au point" (de {OutputDevice}:display-init (device) (print 'display-init device)) (de {OutputDevice}:display-end (device) (print 'display-end device)) (de {OutputDevice}:display-frame (device rect color) (print 'display-frame device rect color)) (de {OutputDevice}:display-box (device rect color) (print 'display-box device rect color)) (de {OutputDevice}:display-vector (device rect color) (print 'display-vector device rect color)) (de {OutputDevice}:display-text (device rect lines rot color) (print 'display-text device rect lines rot color)) ; .Section "LES TRACEURS; LE TRACEUR HP7221" ; Ces utilitaires de'crivent une machine virtuelle bien re'elle cette fois ci: ; le traceur HP servant a` faire des sorties papier ou sur transparents. ; Ce traceur est donc utile pour dessiner du Lucifer ou du Luciflip. ; Une premie`re version en Le←Lisp a e'te' re'alise'e par JMH, ; et BS l'a mise au gou↑t de la version 4 de Ceyx. ; .SSection "Le type ge'ne'rique de tous les traceurs HP 7221" ; On de'finit d'abord un enregistrement auxiliaire me'morisant ; chaque fichier destine' a` e↑tre plotte'. (deflrecord PlotterFile color name chan empty) ; Le type Plotter ge'ne'ral: (deftclass {OutputDevice}:Plotter files~(List {PlotterFile}) curchan ; le canal courant (nb-colors 0) ; le nombre de couleurs du Plotter ) ; Le Plotter HP7221 lui-me↑me: (deftclass {Plotter}:HP7221) ; Une instance de Plotter, pour savoir a` qui l'on s'adresse (defvar *plotter* (omakeq HP7221)) ; Les couleurs sont des constantes pour qu'on ne soit pas oblige' de ; les quoter. (defvar bleu 'bleu noir 'noir vert 'vert rouge 'rouge violet 'violet dore 'dore brun 'brun citron 'citron) ; .SSection "Les Fonctions de plus bas niveau d'envoi des caracte`res" ; Toutes ces fonctions utilisent le plotter courant : \fB*plotter*\fR. ; .SSSection "Envoi d'un octet, d'un caracte`re, d'une chai↑ne" (de {HP7221}:princn (x) (with ((outchan ({Plotter}:curchan *plotter*))) (princn x) (flush))) (de {HP7221}:princh (char) (with ((outchan ({Plotter}:curchan *plotter*))) (princh char) (flush))) (de {HP7221}:prinstring (string) (with ((outchan ({Plotter}:curchan *plotter*))) (prinflush string))) ; .SSSection "Envoi de se'quences d'e'chappement" (de {HP7221}:prin-ESC (string) ({HP7221}:princn 27) ({HP7221}:prinstring string)) ; .SSSection "Envoi de coordonne'es au format HP" (de {HP7221}:out-sbn (n) ({HP7221}:princn (if (< n 32) (+ n 64) n))) (de {HP7221}:out-2-sbn (n) ({HP7221}:out-sbn (div n 64)) ({HP7221}:out-sbn (rem n 64))) (de {HP7221}:out-mbn (n) (cond ((< n 16) ({HP7221}:princn (+ n 96))) ((< n 1024) ({HP7221}:princn (+ (div n 64) 96)) ({HP7221}:out-sbn (rem n 64))) ((<= n 32767) ({HP7221}:princn (+ (div n 4096) 96)) ({HP7221}:out-2-sbn (rem n 4096))) (t ({HP7221}:error "MBN out of range" n)))) (de {HP7221}:out-mbp (nx ny) (let ((n (max nx ny)) (nxr (rem nx 128)) (nxs (rem nx 1024))) (cond ((< n 4) ({HP7221}:princn (+ ny 96 (* 4 nx)))) ((< n 32) ({HP7221}:princn (+ (div nx 2) 96)) ({HP7221}:out-sbn (+ ny (* 32 (rem nx 2))))) ((< n 256) ({HP7221}:princn (+ (div nx 16) 96)) ({HP7221}:out-sbn (+ (div ny 64) (* 4 (rem nx 16)))) ({HP7221}:out-sbn (rem ny 64))) ((< n 2048) ({HP7221}:princn (+ (div nx 128) 96)) ({HP7221}:out-sbn (div nxr 2)) ({HP7221}:out-sbn (+ (div ny 64) (* 32 (rem nxr 2)))) ({HP7221}:out-sbn (rem ny 64))) ((< n 16384) ({HP7221}:princn (+ (div nx 1024) 96)) ({HP7221}:out-sbn (div nxs 16)) ({HP7221}:out-sbn (+ (div ny 4096) (* 4 (rem nxs 16)))) ({HP7221}:out-2-sbn (rem ny 4096))) (t ({HP7221}:error "MBP out of range" n))))) (de {HP7221}:out-pmb (x y) ({HP7221}:out-pmb1 x 64) ({HP7221}:out-pmb1 y 32)) (de {HP7221}:princn-2 (n flag) ({HP7221}:princn (+ (div n 32) flag)) ({HP7221}:princn (+ (rem n 32) flag))) (de {HP7221}:princn-3 (n flag) ({HP7221}:princn (+ (div n 1024) flag)) ({HP7221}:princn-2 (rem n 1024) flag)) (de {HP7221}:out-pmb1 (nx flag) (if (< nx 0) (cond ((> nx -17) ({HP7221}:princn (+ nx 32 flag))) ((> nx -513) ({HP7221}:princn-2 (+ nx 1024) flag)) ((> nx -16385) (incr nx 16384) (incr nx 16384) ({HP7221}:princn-3 nx flag)) (t ({HP7221}:error "PMB out of range" nx))) (cond ((< nx 16) ({HP7221}:princn (+ nx flag))) ((< nx 512) ({HP7221}:princn-2 nx flag)) ((< nx 16384) ({HP7221}:princn-3 nx flag)) (t ({HP7221}:error "PMB out of range" nx))))) ; .SSection "Actions Physiques sur le Traceur" ; .SSSection "Mise en Route et Arre↑t" (de {HP7221}:on () ; en route ({HP7221}:prin-ESC ".(") ; configuration ({HP7221}:prin-ESC ".@;4:") ; handshake mode 2 ({HP7221}:prin-ESC ".I1528;20;18:~←")) (de {HP7221}:off () ; store-pen ({HP7221}:princh "v") ({HP7221}:out-sbn 0) ; pen range'! ({HP7221}:princh "p") ({HP7221}:out-mbp 3040 2000) ({HP7221}:princh "}") ({HP7221}:prin-ESC ".)")) (de {HP7221}:error (y z) ({HP7221}:close) (syserror 'Plotter y z)) ; .SSSection "Se'lection de Divers Parame`tres" ; Se'lection du crayon (de {HP7221}:select-pen (couleur) (let ((code)) (setq code (cassq couleur '((blanc . 0) (bleu . 1) (noir . 2) (vert . 3) (rouge . 4)))) (unless code (setq code (cassq couleur '((violet . 5) (dore . 6) (brun . 7) (citron . 8)))) (unless code ({HP7221}:error "not a color" couleur)) (when (eq ({Plotter}:nb-colors *plotter*) 8) (setq code 2))) ({HP7221}:princh "v") ({HP7221}:out-sbn code))) ; Se'lection de la taille de la fonte (de {HP7221}:font-size (space line) ({HP7221}:prinstring "~%") ({HP7221}:out-mbp space line)) ; .SSSection "Avance et De'coupe du papier" (de {HP7221}:cutter-disable (*plotter*) ({HP7221}:prinstring "~)")) (de {HP7221}:cutter-enable (*plotter*) ({HP7221}:prinstring "~(")) (de {HP7221}:advance-full-page (*plotter*) ({HP7221}:prinstring "~+")) (de {HP7221}:advance-half-page (*plotter*) ({HP7221}:prinstring "~-")) ; .SSection "De'placements du Crayon et Dessin" ; .SSSection "De'placements absolus" ; x et y sont des coordonne'es standards: ; pour passer aux coordonne'es hp, il faut changer de sens l'axe des y. (de {HP7221}:move (x y) ({HP7221}:princh "p") ({HP7221}:out-mbp x (- 2000 y)) ({HP7221}:princh "}")) (de {HP7221}:draw (x y) ({HP7221}:princh "q") ({HP7221}:out-mbp x (- 2000 y)) ({HP7221}:princh "}")) ; .SSSection "De'placements Relatifs" (de {HP7221}:imove (x y) ({HP7221}:princh "r") ({HP7221}:out-pmb x y) ({HP7221}:princh "}")) (de {HP7221}:idraw (x y) ({HP7221}:princh "s") ({HP7221}:out-pmb x y) ({HP7221}:princh "}")) (de {HP7221}:up (x) ({HP7221}:imove 0 x)) (de {HP7221}:down (x) ({HP7221}:imove 0 (- x))) (de {HP7221}:left (x) ({HP7221}:imove (- x) 0)) (de {HP7221}:right (x) ({HP7221}:imove x 0)) (de {HP7221}:wup (x) ({HP7221}:idraw 0 x)) (de {HP7221}:wdown (x) ({HP7221}:idraw 0 (- x))) (de {HP7221}:wleft (x) ({HP7221}:idraw (- x) 0)) (de {HP7221}:wright (x) ({HP7221}:idraw x 0)) ; .SSSection "Dessin de Figures" ; Le rectangle (simplement le cadre) (de {HP7221}:frame (x y xdim ydim) ({HP7221}:move x y) ({HP7221}:wright xdim) ({HP7221}:wdown ydim) ({HP7221}:wleft xdim) ({HP7221}:wup ydim)) ; Le rectangle plein (de {HP7221}:rect (x y xdim ydim) (if (<= xdim ydim) (if (< xdim 8) ({HP7221}:frame x y xdim ydim) ({HP7221}:frame x y 4 ydim) ({HP7221}:rect (+ x 8) y (- xdim 8) ydim)) (if (< ydim 8) ({HP7221}:frame x y xdim ydim) ({HP7221}:frame x y xdim 4) ({HP7221}:rect x (+ y 8) xdim (- ydim 8))))) ; Le vecteur (de {HP7221}:vector (x1 y1 xdim ydim) ({HP7221}:move x1 (+ y1 ydim)) ({HP7221}:idraw xdim (- ydim))) ; Le cercle (de {HP7221}:circle (r) ({HP7221}:princh "t") ({HP7221}:out-mbn r) ({HP7221}:princh "}")) ; .SSSection "Ecriture de Texte" ; Rotation du texte d'un angle de 0,90,180 ou 270 degres (angle= 0 ,1,2 ou 3) (de {HP7221}:Rot (angle) ({HP7221}:prinstring "ww") ({HP7221}:princn (+ (* angle 4) 96))) ; Ecrit la LISTE de lignes de texte dans la boi↑te de taille xdim,ydim ; (coordonne'es standard (non hp)) situee en x,y. ; Le texte s'e'crit suivant l'angle angle (compris entre 0 et 3) (de {HP7221}:plot-text (x y xdim ydim liste angle) (let ((nbligne (length liste)) ; nombre de lignes a` e'crire (width 0) ; largeur max des lignes (largeur (if (oddp angle) ydim xdim)) ; largeur boite (hauteur (if (oddp angle) xdim ydim)) ; hauteur boite (margeg) ; marge a` gauche (margeh) ; marge au dessus du texte (chasse) ; taille horiz des caracte`res (ecartligne)) ;taille verticale des caracteres ; on calcule la longueur maximale des lignes (let ((liste liste)) (while liste (setq width (max (plength (nextl liste)) width)))) (setq ecartligne (div hauteur (+ nbligne 1)) margeh (div (* ecartligne 4) 3) ; pour l'esthe'tique chasse (min (div ecartligne 2) (div largeur (+ width 6))) margeg (div (- largeur (* chasse width)) 2)) ; on se'lectionne la fonte ({HP7221}:font-size chasse ecartligne) ; on calcule ou` commencer a` e'crire le 1er caracte`re (selectq angle (0 ({HP7221}:move (+ margeg x) (+ y margeh))) (1 ({HP7221}:move (+ margeh x) (+ y ydim (- margeg)))) (2 ({HP7221}:move (- (+ x xdim) margeg) (+ y ydim (- margeh)))) (3 ({HP7221}:move (- (+ x xdim) margeh) (+ y margeg))) (t ({HP7221}:error "Angle should be 0,1,2,3" angle))) ; on positionne l'angle de rotation ({HP7221}:Rot angle) ({HP7221}:prinstring "~'") ; label-on ; on envoie pour chaque ligne de texte les caracteres suivis de CR LF (while liste ({HP7221}:prinstring (nextl liste)) ({HP7221}:princn 13) ; CR ({HP7221}:princn 10)) ; LF ({HP7221}:princn 3) ; label-off ({HP7221}:Rot 0))) ; .SSection "Re'ponse aux Messages de la Machine Virtuelle Standard" ; Rappelons que la machine virtuelle doit re'pondre aux messages ; de la machine virtuelle standard, a` savoir: ; .br ; - display-init (device) allumant la machine ; .br ; - display-end (device) e'teignant la machine ; .br ; - display-frame (device rect color) affichage d'un cadre ; .br ; - display-box (device rect color) affichage d'une boite pleine ; .br ; - display-vector (device rect color) affichage d'un vecteur ; .br ; - display-text (device rect lines rot color) affichage de lignes de texte ; On utilise des fichiers situe's dans un directory de fichiers ; temporaires ; Cette variable est de'pendante du syste`me: il ne faudrait pas ... ; .br ; ;** System dependant (defvar *temporary-files-dir* (concat "/tmp/" (gensym))) ; On utilise le package des rectangles: (de {HP7221}:display-init (*plotter*) (let ((colors ({Plotter}:nb-colors *plotter*)) (list '(bleu noir vert rouge)) (name)) (when (= 0 colors) (prinflush "Number of colors (4 or 8) ") (until (or (eq (setq colors (read)) 4) (eq colors 8))) ({Plotter}:nb-colors *plotter* colors)) (when (= 8 colors) (setq list (mcons violet dore brun citron list))) (while list (setq name (concat *temporary-files-dir* (car list))) (oconsq Plotter files *plotter* (omakeq PlotterFile color (nextl list) name name chan (openo name) empty t)))) (output nil)) ; La recopie du fichier et le controle de flux de'pendent du syste`me ; .br ; ;** System dependant (de {HP7221}:display-end (*plotter*) ({HP7221}:close) ({Plotter}:curchan *plotter* (outchan)) ({HP7221}:on) (flush) (let ((files ({Plotter}:files *plotter*)) (file)) (while files (unless ({PlotterFile}:empty (setq file (nextl files))) ; on rouvre le fichier en lecture ; et on l'imprime sur la tty (comline (catenate "stty start \ stop \;cat " ({PlotterFile}:name file) ";stty start \ stop \"))))) ({Plotter}:curchan *plotter* (outchan)) ({HP7221}:off) (flush) (terpri) (print "PPlot termine") ; une sucette a qui comprendra pourquoi! ({Plotter}:files *plotter* nil) 'Done) (de {HP7221}:display-frame (*plotter* rect color) ({HP7221}:change-color color) ({HP7221}:frame ({Rect}:xorg rect) ({Rect}:yorg rect) ({Rect}:width rect) ({Rect}:height rect))) (de {HP7221}:display-box (*plotter* rect color) ({HP7221}:change-color color) ({HP7221}:rect ({Rect}:xorg rect) ({Rect}:yorg rect) ({Rect}:width rect) ({Rect}:height rect))) (de {HP7221}:display-vector (*plotter* rect color) ({HP7221}:change-color color) ({HP7221}:vector ({Rect}:xorg rect) ({Rect}:yorg rect) ({Rect}:width rect) ({Rect}:height rect))) (de {HP7221}:display-text (*plotter* rect ltext angle color) (let ((xdim ({Rect}:width rect)) (ydim ({Rect}:height rect))) (unless (or (<= xdim 0) (<= ydim 0) (null ltext)) ({HP7221}:change-color color) ({HP7221}:plot-text ({Rect}:xorg rect) ({Rect}:yorg rect) xdim ydim ltext (cassq angle '((0 . 0) (1 . 3) (2 . 2) (3 . 1))))))) ; Permet l'e'criture dans le fichier approprie' (de {HP7221}:change-color (color) (let ((files ({Plotter}:files *plotter*)) (file)) (while files (if (eq ({PlotterFile}:color (car files)) color) (setq file (nextl files)) (nextl files))) (unless file ({HP7221}:error "Not a color" color)) ({Plotter}:curchan *plotter* ({PlotterFile}:chan file)) (when ({PlotterFile}:empty file) ({HP7221}:select-pen color) ({PlotterFile}:empty file nil)))) ; ferme tous les fichiers ouverts en e'criture (de {HP7221}:close () (let ((files ({Plotter}:files *plotter*))) (while files (close ({PlotterFile}:chan (nextl files))))) (output nil)) ; .Section "COLORIX, COLORY & Co" (deftclass {OutputDevice}:Screen) ; .SSection "Colory, soit encore l'ancien Colorix" ; ATTENTION: CETTE PARTIE DE CODE N'A JAMAIS ETE TESTEE (deftclass {OutputDevice}:Colory) ; Une instance de Colory (defvar *colory* (omakeq Colory)) (de {Colory}:color (color) (cassq '((bleu . 11) (noir . 4095) (vert . 176) (rouge . 2816) (violet . #.(- 4095 176)) (dore . 4032) (brun . 4095) (citron . 4032) (blanc . 0)))) (de {Colory}:display-init (device) (COLORIX 10 0) (repeat 1000 nil) (COLORIX 6 0) (COLYREM 0 0 255 255 255) (COLYFLUSH 0 0 255 255 255)) (de {Colory}:display-end (device)) (de {Colory}:display-frame (device rect color) (COLSHAPE ({Rect}:xorg rect) ({Rect}:yorg rect) ({Rect}:width rect) ({Rect}:height rect) ({Colory}:color color))) (de {Colory}:display-box (device rect color) (COLBOX ({Rect}:xorg rect) ({Rect}:yorg rect) ({Rect}:width rect) ({Rect}:height rect) ({Colory}:color color))) (de {Colory}:display-vector (device rect color) ({Colory}:vector ({Rect}:xorg rect) ({Rect}:yorg rect) ({Rect}:width rect) ({Rect}:height rect) ({Colory}:color color))) (de {Colory}:vector (xmin ymin width height color) (cond ((<= width 1) (COLSHAPE xmin ymin 1 height)) ((<= height 1) (COLSHAPE xmin ymin width 1)) (t ({Colory}:vector xmin ymin (div width 2) (div height 2) color) ({Colory}:vector (+ xmin (div width 2)) (+ ymin (div width 2)) (- width (div width 2)) (- height (div height 2)) color)))) (de {Colory}:display-text (device rect lines angle color) ({Colory}:text ({Rect}:xorg rect) ({Rect}:yorg rect) ({Rect}:width rect) ({Rect}:height rect) lines ({Colory}:color color))) (de {Colory}:text (x y width height liste color) (let ((maxlength 0) ; width max des lignes (margeg) ; marge a` gauche (margeh)) ; marge au dessus du texte ; on calcule la longueur maximale des lignes (let ((liste liste)) (while liste (setq maxlength (max (plength (nextl liste)) maxlength)))) (setq margeg (div (- width (* 10 maxlength)) 2) margeh (div (- height (* 11 (length liste))) 2)) (when (and (> margeg 0) (> margeh 0)) (incr x margeg) (while liste (COLTEXT (nextl liste) x (incr y margeh) color 1)))))