home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1988
/
04
/
porter
/
porter.ls2
< prev
next >
Wrap
Text File
|
1979-12-31
|
7KB
|
208 lines
STRUCTURED PROGRAMMING LISTING TWO APRIL ISSUE
IMPLEMENTATION MODULE LineDwg;
(* Implements LineDrawing module defined by N. Wirth in *)
(* "Programming in Modula-2." This module assumes EGA *)
(* monitor in 640 x 350 color graphics mode. *)
(* Uses virtual coordinates, where origin is at lower *)
(* left corner of screen area, size is 800 x 600. *)
(* Adapted by K. Porter for DDJ, April 1988 issue *)
(* ---------------------------------------------------- *)
FROM SYSTEM IMPORT REGISTERS, INT;
FROM Strings IMPORT Length;
CONST VW = 800.0; (* virtual width of screen *)
VH = 600.0; (* virtual height *)
RW = 640.0; (* real device width, EGA screen *)
RH = 350.0; (* device height *)
EGA = 16; (* EGA 640 x 350 color mode *)
(* Variables local to this module *)
VAR reg : REGISTERS;
xf, yf : REAL;
color : INTEGER;
(* --------------LOCAL PROCEDURES ------------------------- *)
PROCEDURE writePixel (c, x, y : INTEGER);
(* write pixel of color c at device x, y *)
BEGIN
reg.AH := 12;
CASE c OF (* map color indicator to EGA palette *)
0 : reg.AL := 15| (* white *)
1 : reg.AL := 7| (* light gray *)
2 : reg.AL := 8| (* dark gray *)
3 : reg.AL := 0 (* black *)
END; (* of CASE *)
reg.BX := 0;
reg.CX := x;
reg.DX := y;
INT (16, reg);
color := c; (* set prevailing color *)
END writePixel;
(* ------------------------ *)
PROCEDURE devX (x : INTEGER) : INTEGER;
(* translate x to device x *)
BEGIN
RETURN TRUNC (xf * FLOAT (x));
END devX;
(* ------------------------ *)
PROCEDURE devY (y : INTEGER) : INTEGER;
(* translate y to device y *)
BEGIN
RETURN TRUNC (RH - (yf * FLOAT (y)));
END devY;
(* ------------------ VISIBLE PROCEDURES -------------------- *)
PROCEDURE dot (c : CARDINAL; x, y : INTEGER);
(* Place a dot of color c at coordinate x, y *)
BEGIN
writePixel (c, devX (x), devY (y));
END dot;
(* ------------------------ *)
PROCEDURE line (d, n : CARDINAL);
(* Draw a line of length n in direction d
(angle = 45 * d degrees) *)
VAR xdir, ydir : INTEGER; (* x and y directions given d *)
distance : CARDINAL;
BEGIN
CASE d OF
0 : xdir := 1; ydir := 0| (* right *)
1 : xdir := 1; ydir := 1|
2 : xdir := 0; ydir := 1| (* up *)
3 : xdir := -1; ydir := 1|
4 : xdir := -1; ydir := 0| (* left *)
5 : xdir := -1; ydir := -1|
6 : xdir := 0; ydir := -1| (* down *)
7 : xdir := 1; ydir := -1
END; (* of CASE *)
FOR distance := 1 TO n DO
Px := Px + xdir; (* advance the pen *)
Py := Py + ydir;
dot (color, Px, Py); (* draw in prevailing color *)
END;
END line;
(* ------------------------ *)
PROCEDURE paint (c : CARDINAL; x, y, w, h : INTEGER);
(* Paint the rectangular area at x, y of width w and
height h in color c, where 0 = white,
1 = light gray, 2 = dark gray, 3 = black *)
VAR cy, prevY, dy : INTEGER;
BEGIN
prevY := 0;
color := c; (* set new prevailing color *)
FOR cy := y TO y+h DO
dy := devY (cy); (* get current device y *)
IF dy <> prevY THEN (* if new scan line, draw *)
Px := x; Py := cy;
line (0, w);
prevY := dy; (* remember where last line drawn *)
END
END
END paint;
(* ------------------------ *)
PROCEDURE copyArea (sx, sy, dx, dy, dw, dh : INTEGER);
(* Copy rectangular area at sx, sy into rectangle
at dx, dy of width dw and height dh *)
VAR c, x, y, ix, iy, nx, ny, tx, ty : INTEGER;
BEGIN
ix := devX (sx); iy := devY (sy); (* source dev coords *)
nx := devX (sx+dw); ny := devY (sy+dh); (* ending coords *)
tx := devX (dx); ty := devY (dy); (* target coords *)
FOR y := ny TO iy DO (* go top to bottom *)
FOR x := ix TO nx DO
reg.AH := 13; (* read pixel *)
reg.BX := 0;
reg.CX := x;
reg.DX := y;
INT (16, reg); (* get pixel color into al *)
reg.AH := 12; (* write pixel to dest *)
reg.CX := tx + x - ix;
reg.DX := ty + y - iy;
INT (16, reg);
END
END
END copyArea;
(* ------------------------ *)
PROCEDURE clear; (* Clear the screen *)
(* Also places display into EGA graphics mode *)
BEGIN
reg.AH := 0;
reg.AL := EGA; (* EGA 640 x 350 *)
INT (16, reg);
color := 0; (* reset default color to white *)
END clear;
(* ------------------------ *)
PROCEDURE Write (ch : CHAR); (* Write ch at pen's position *)
VAR cc, cr : INTEGER; (* Char col and row *)
BEGIN
cc := devX (Px) DIV 8; (* Derive char pos from pen *)
cr := devY (Py) DIV 14;
reg.AH := 2; (* Set text cursor position *)
reg.BX := 0;
reg.DX := (cr * 256) + cc;
INT (16, reg);
reg.AX := 2560 + ORD (ch); (* Write char via ROM BIOS *)
reg.BX := 7; (* Light gray text only *)
reg.CX := 1;
INT (16, reg);
Px := Px + CharWidth; (* advance by char virtual width *)
END Write;
(* ------------------------ *)
PROCEDURE WriteString (s : ARRAY OF CHAR);
VAR i : CARDINAL;
BEGIN
FOR i := 0 TO Length (s) DO
Write (s[i]);
END
END WriteString;
(* ---------------- INITIALIZATION ------------------------ *)
BEGIN
Px := TRUNC (VW / 2.0); (* Virtual screen center *)
Py := TRUNC (VH / 2.0);
mode := replace;
width := TRUNC (VW); (* Virtual screen size *)
height := TRUNC (VH);
CharWidth := 10; (* Char sizes in virtual units *)
CharHeight := 24;
xf := RW / VW; (* x translation factor *)
yf := RH / VH; (* y translation factor *)
color := 0; (* white is default color *)
END LineDwg.