DEFINITION MODULE DMWindIO;
(*******************************************************************
Module DMWindIO ('Dialog Machine' DM_V3.0)
Copyright (c) 1985-2006 by Andreas Fischlin, Alex Itten and
ETH Zurich.
Purpose Provides routines for window related input and
output on behalf of a 'Dialog Machine' program.
Remarks Method: This module supports mouse input, (object
selection, dragging), scrolling (clicking the
mouse within particular regions of the scrollbar)
text output (pen positioning with cardinal
numbers), pixel graphics (pen positioning with
integer numbers), turtle graphics, and graphics
output via so-called user coordinates (pen
positioning with real numbers) within windows as
managed by module DMWindows.
There exists in fact just one pen while
making output within the working area of a
window. The various coordinate systems
(see below) are provided just for the
application programmer's convenience.
This module belongs to the 'Dialog Machine'.
Programming
o Design
Andreas Fischlin 16/12/1985
o Implementation
Andreas Fischlin 16/12/1985
Alex Itten 22/12/1986
ETH Zurich
Systems Ecology
CHN E 35.1
Universitaetstrasse 16
8092 Zurich
SWITZERLAND
URLs:
<mailto:RAMSES@env.ethz.ch>
<http://www.sysecol.ethz.ch>
<http://www.sysecol.ethz.ch/SimSoftware/RAMSES>
Last revision of definition: 27/04/1993 AF
*******************************************************************)
FROM DMWindows IMPORT Window, RectArea, RestoreProc;
FROM SYSTEM IMPORT BYTE, ADDRESS;
(***********************************************)
(*##### Object selection and dragging #####*)
(***********************************************)
(* Notes:
The following procedures work only in the current front
window.
A double click is defined as a click which has occurred
within a certain time span elapsed since the last time the
mouse button has been released (can be adjusted by
the user via the control panel). A double click always
implies a single mouse click. Note that every click,
in particular also the first click of a double click,
will result in an user event. This means that in case
of a double click DMMaster will call the installed
MouseHandler for a WindowContent event twice, i.e.
first for the first click, second for the succeeding
second click (the double click). Routines testing for
a single mouse click will always return TRUE for the
first, those testing the double click will return TRUE
only at the second click. Hence your application must
always treat the double click in a way which implies a
preceeding single mouse click. E.g. treat an object as
selected and invert it upon first click always and if
the next click is a double click (it comes quickly
enough and approximately at the same location (within
±3 pixels)) open the currently selected object.
In case you support double clicks and dragging you
should always call the procedure Drag as soon you have
detected a single mouse click. Whether you have
actually dragged can be found out by setting a «has
been dragged» flag in the afterDragP procedure, which
will be never called in case the user has not actually
dragged. The Dialog Machine detects the intent of the
user to drag by observing the mouse movements and
assumes that the user did not drag if he releases
the mouse button still within ±3 pixels of the vicinity
of the last mouse click.
*)
TYPE
MouseModifiers = (ordinary, (*mouse button only*)
cmded, (*Command key pressed also*)
opted, (*Option key pressed also*)
shifted, (*Shift key pressed also*)
capsLock, (*Caps Lock key pressed also*)
controlled); (*Control key pressed also*)
ClickKind = SET OF MouseModifiers;
DragProc = PROCEDURE (INTEGER, INTEGER);
PROCEDURE PointClicked(x,y: INTEGER; maxDist: INTEGER): BOOLEAN;
(*
Tests whether the mouse has been clicked within distance
maxDist from point (x,y) in cartesian (pixel) coordinates of
the currently active window. This procedure returns true only
once; it will return false after having reported true until
the event occurs anew. Implementation restriction: maxDist
must be < 256!
*)
PROCEDURE RectClicked(rect: RectArea): BOOLEAN;
(*
Tests whether the mouse has been clicked within the rectangle
rect with lower left corner at (rect.x,rect.y), width rect.w,
and height rect.h in cartesian (pixel) coordinates of the
currently active window. This procedure returns true only
once; it will return false after having reported true until
the event occurs anew.
*)
PROCEDURE PointDoubleClicked(x,y: INTEGER; maxDist: INTEGER): BOOLEAN;
(*
Tests whether the mouse has been clicked twice in short
sequence (actual time determined by desk accesory "Control
Panel") within distance maxDist from point (x,y) in cartesian
(pixel) coordinates of the currently active window. This
procedure returns true only once; it will return false after
having reported true until the event occurs anew.
Implementation restriction: maxDist must be < 256!
*)
PROCEDURE RectDoubleClicked(rect: RectArea): BOOLEAN;
(*
Tests whether the mouse has been clicked twice in short
sequence (actual time determined by desk accesory "Control
Panel") within the rectangle rect with lower left corner at
(rect.x,rect.y), width rect.w, and height rect.h in cartesian
(pixel) coordinates of the currently active window. This
procedure returns true only once; it will return false after
having reported true until the event occurs anew.
*)
PROCEDURE GetLastClick(VAR x,y: INTEGER;
VAR click: ClickKind): BOOLEAN;
(*
Get position of last single click within currently active
window content in cartesian (pixel) coordinates. The
variable click indicates whether a modifying key (e.g. shift,
option, or command) has been pressed simultaneously with the
double click. This procedure returns correct values only
once; it will destroy this information and can return correct
values only if the mouse is clicked again. NOTE: This
procedure returns TRUE only if the last click was not a
double click, i.e. was either the first click of a double
click or any other single click.
*)
PROCEDURE GetLastDoubleClick(VAR x,y: INTEGER;
VAR click: ClickKind): BOOLEAN;
(*
Get position of last double click (shortly after and in
vicinity of previous click) within currently active window
content in cartesian (pixel) coordinates. The variable click
indicates whether a modifying key (e.g. shift, option, or
command) has been pressed simultaneously with the double
click. This procedure returns correct values only once; it
will destroy this information and can return correct values
only if the mouse is clicked again. NOTE: This procedure returns
TRUE only if the last click was really a double click, i.e. was
the second click of a double click.
*)
PROCEDURE GetCurMousePos(VAR x,y: INTEGER);
(*
Get current mouse position in cartesian (pixel) coordinates
of the current output window (Note: This procedure does not
return the coordinates where the mouse has been clicked, but
where it is right now! Hence, a typical usage is from within
a drag procedure.
*)
PROCEDURE GetLastMouseClick(VAR x,y: INTEGER;
VAR click: ClickKind);
(*
Get position of last mouse click within currently active
window content in cartesian (pixel) coordinates. The
variable click indicates whether a modifying key (e.g. shift,
option, or command) has been pressed simultaneously with the
mouse click. NOTE: This procedure returns correct values
many times and will not destroy this information unless the
mouse is clicked again and it assigns values always
regardless whether the click is the second click of a double
click or not (compare above with GetLastClick and
GetLastDoubleClick).
*)
PROCEDURE DoTillMButReleased(p: PROC);
(*
Execute procedure p as long as the mouse button is not
released
*)
PROCEDURE Drag(duringDragP,afterDragP: DragProc);
(*
Calls during dragging repeatedly procedure duringDragP (draws
typically the outline of the object to be dragged once
relative to the coordinates (x,y) representing a mouse
position) till the mouse button is released. Attempts to call
procedure SetMode within the drag procedure are ignored since
module DMWindows also uses this procedure to erase the object
at the old position if the mouse is still moved. Releasing
the mouse button indicates the end of the dragging process,
which results in a single call to the procedure afterDragP.
Actual parameters are the coordinates x and y of the point,
where the button has been released. Procedure afterDragP
typically removes object at old position and draws object
fully at the new location. Attempts to drag the object
outside of window u fail, i.e. the object is jumping back at
its old position.
*)
(***************************)
(*##### Scrolling #####*)
(***************************)
(*
If you have created a window which contains scrollbars using
the procedure DMWindows.CreateWindow, the scrollbars will
initially be inactive. You must first define the actual content
size of your document by means of the procedure SetContSize.
Then you must assign a scrolling procedure to define how the
Dialog Machine should handle a scrolling event. You may choose
between the auto scroll mechanism offered by the Dialog Machine
and your own scrolling procedure.
The program structure of a module using the auto scroll mechanism
may look like this:
================ Example =================
MODULE MyModule;
FROM DMMaster IMPORT RunDialogMachine;
FROM DMWindows IMPORT Window, CreateWindow, WindowKind, ScrollBars,
RectArea, CloseAttr, ZoomAttr, WindowFrame,
WFFixPoint, NoBackground;
FROM DMWindIO IMPORT SetContSize, SetScrollStep, SetScrollProc,
AutoScrollProc;
VAR
myWindow: Window;
PROCEDURE MyDrawing( w: Window );
BEGIN
(* your drawings here *)
END MyDrawing;
PROCEDURE MakeWindow;
VAR frame: WindowFrame; contentRect: RectArea;
BEGIN
WITH frame DO
x := 20; y := 20;
w := 200; h := 200;
END;
CreateWindow( myWindow, GrowOrShrinkOrDrag,
WithBothScrollBars, WithCloseBox, WithZoomBox,
bottomLeft, frame, "My Window", MyDrawing );
WITH contentRect DO
x := 0; y := 0; (* content rect should be larger *)
w := 300; h := 300; (* than window frame! *)
END;
SetContSize( myWindow, contentRect );
SetScrollStep( myWindow, 50, 10 );
SetScrollProc( myWindow, AutoScrollProc );
END MakeWindow;
BEGIN
NoBackground;
MakeWindow;
RunDialogMachine;
END MyModule.
Machine' eventually repeatedly during the scrolling done by
the user, i.e. only once if the user clicks in the page up or
down scroll bar region, only once if the user drags the
scroll box to a new location, and repeatedly after every
small scroll step in case the user presses the mouse button
in the scroll up or scroll down arrows. Usually this
procedure calls GetScrollBoxPos or GetScrollBoxChange and
then it adjusts and reconstructs the window content by
calling MoveOriginTo and drawing procedures or ScrollContent
and UpdateWindow.
*)
PROCEDURE SetContSize(u: Window; contentRect: RectArea);
(*
Defines the actual content size of your document. If your
document is larger than the window, the contentRect defines
the maximum area over which you can scroll. In this case the
scrollbars will become active otherwise they will become
inactive. The x coordinate of the contentRect belongs to the
left most position and x+w to the right most position of the
horizontal scrollbar. The y coordinate of the contentRect
belongs to the lowest position and y+h to the highest
position of the vertical scrollbar.
*)
PROCEDURE GetContSize(u: Window; VAR contentRect: RectArea);
PROCEDURE SetScrollStep(u: Window; xStep, yStep: INTEGER);
(*
Defines the minimum scroll distance by which the content of a
window will be scrolled if the user clicks the down or up
arrow of a scrollbar. If the user clicks into the page up or
page down area of a scrollbar (e.g. grey region), then the
scrolling distance is equal to the current window size minus
the size of one scroll step.
*)
PROCEDURE GetScrollStep(u: Window; VAR xStep, yStep: INTEGER);
PROCEDURE SetScrollBoxPos(u: Window; posX,posY: INTEGER);
PROCEDURE GetScrollBoxPos(u: Window; VAR posX,posY: INTEGER);
(*
These procedures set respectively return the current position
of the scroll boxes of the scrollbars relative to the defined
contentRect of your document.
*)
PROCEDURE GetScrollBoxChange(u: Window; VAR changeX,changeY: INTEGER);
(*
Returns the relative change of the scrollbox position since
the last calling of GetScrollBoxChange or GetScrollBoxPos.
*)
PROCEDURE AutoScrollProc(u: Window);
(*
Assign this procedure to your window, if you want to use the
auto scroll mechanism of the Dialog Machine. It scrolls the
current visible part of the window, moves the coordinate
system origin and calls the restore procedure of the window
for the regions which could not be filled automatically. If
the auto update mechanism is used together with this auto
scrolling mechanism, the whole information stored in the
offscreen bitmap is used to update the window. However, the
latter combination is not recommended, because the scrolling
may not always be handled consistently.
*)
PROCEDURE SetScrollProc(u: Window; scrollP: RestoreProc);
(*
Assigns a scroll procedure to the window u to handle
scrolling events. This procedure is called by the 'Dialog
Machine' eventually repeatedly during the scrolling done by
the user, i.e. only once if the user clicks in the page up or
down scroll bar region, only once if the user drags the
scroll box to a new location, and repeatedly after every
small scroll step in case the user presses the mouse button
in the scroll up or scroll down arrows. Usually this
procedure calls GetScrollBoxPos or GetScrollBoxChange and
then it adjusts and reconstructs the window content by
calling MoveOriginTo and drawing procedures or ScrollContent
and UpdateWindow.
*)
PROCEDURE GetScrollProc(u: Window; VAR scrollP: RestoreProc);
PROCEDURE ScrollContent(u: Window; dx,dy: INTEGER);
(*
Scrolls the content of the window u dx pixels to the right
and dy pixels upwards. This procedure doesn't change the
pixel coordinate system of the window u, it simply moves the
entire content of the window to different coordinates. The
space created by the scroll is erased and an update event is
generated for it.
CAUTION: If you use this procedure, any drawing operation
within a scroll procedure should be done by your update
procedure only, otherwise the update procedure will overwrite
your drawings right after it handled the scroll event.
Call UpdateWindow afterwards to handle the update event and
to fill the empty space generated by this procedure. Note:
This procedure may be clipped to a clipping rectangle in
order to scroll only the content of this rectangle (see
SetClipping).
*)
PROCEDURE MoveOriginTo(u: Window; x0,y0: INTEGER);
(*
Moves origin to point (x0,y0) defined in old, i.e. current
cartesian (pixel) coordinates (default origin is lower left
corner of current WindowFrame).
*)
(********************************)
(*##### General Output #####*)
(********************************)
VAR
WindowIODone: BOOLEAN;
(*indicates success of an input/output routine*)
PROCEDURE SelectForOutput(u: Window);
(*switches all subsequent output related actions to window u*)
PROCEDURE CurrentOutputWindow(): Window;
(*returns current output window*)
TYPE
PaintMode = (replace, paint, invert, erase);
(*
replace : Destination := Source
paint : Destination := Destination OR Source
invert : Destination := Destination XOR Source
erase : Destination := Destination AND NOT Source
(1 = black and 0 = white )
*)
Hue = [0..359]; (* = degrees. See HSV model below *)
GreyContent = (light, lightGrey, grey, darkGrey, dark);
Saturation = [0..100]; (* percent *)
(*
According to the Hue-Saturation-Value (HSV) color model by
Ivan Dum. see Fundamentals of interactive Computer Graphics
p. 613 ff. On black-and-white displays (like the
Macintosh's), Hue, GreyContent and Saturation are not
supported. Any call of one of these color procedures has no
effect.
*)
Color = RECORD
hue: Hue;
greyContent: GreyContent;
saturation: Saturation;
END;
PatLine = BYTE;
Pattern = ARRAY [0..7] OF PatLine;
VAR
pat: ARRAY [light..dark] OF Pattern;
(*
predefined patterns, which may be used to simulate the
GreyContent on an black-and-white display.
*)
black, white, red, green, blue, cyan, magenta, yellow : Color;
(*
these are 8 predefined colors, which may be used for
defining colors. These are READ ONLY VARIABLES! Don«t
change their values
*)
PROCEDURE SetMode(mode: PaintMode);
(*
Set one of the four modes for every output procedure e.g.
Dot, LineTo, MoveBy, Circle etc. and all text drawing
procedures in current output window
*)
PROCEDURE GetMode(VAR mode: PaintMode);
PROCEDURE SetBackground(c: Color; pat: Pattern);
(*
Set the color and the background pattern of any Window
background. On a black-and-white Display the parameter c has
no effect. The default background color is white and the
default background pattern is pat[light].
*)
PROCEDURE GetBackground(VAR c: Color; VAR pat: Pattern);
(*
Returns the current background color and pattern of the
current output window.
*)
PROCEDURE SetColor(c: Color);
(*
Set the color for all subsequent drawing in current output
window. On a black-and-white display this procedure has no
effect. The default color is black.
*)
PROCEDURE GetColor(VAR c: Color);
(* Returns the current color of the current output window. *)
PROCEDURE SetPattern(p: Pattern);
(*
Set the current pen pattern to p. This pattern will be used
by all line drawing routines e.g. LineTo, MoveBy, UCLineTo,
CloseAndFillPolygon and Circle if filled is FALSE. The
procedure Dot is not affected by this procedure.
*)
PROCEDURE GetPattern(VAR p: Pattern);
(*
Returns the current pattern of the current output window.
*)
(****************************************************************
Each window knows at least two reference systems: a grid with
cells of character size (determined by current font) and
cartesian coordinates with the origin at the lower left corner.
The cells of the character based grid are referenced by line
and column with the upper left corner being (1,1). The maximum
dimensions of the grid are determined by the current window
size. Attempts to write below the bottom of the window result
in the call of procedure EOWAction as previously assigned
(default EOWAction is ScrollUp by one line). The grid system
can only be referenced correctly with a non-proportional font
such as Monaco. Otherwise, i.e. if a proportional font is
used, cell coordinates just denote the position of the leftmost
character in the string. The cell into which the last character
drawn falls has to be determined by means of procedure
DMWindIO.GetPos. The width of a cell is constant and
corresponds to the average number of pixels a character of the
current font occupies. Hence, this grid can provide a rough
estimate to position strings within the window, and helps to
align text.
Each window possesses a current position for both reference
systems: The caret denotes the current cell in the character
grid, the pen is at the current graphic output point.
*****************************************************************)
PROCEDURE IdentifyPos(x,y: INTEGER; VAR line,col: CARDINAL);
(*
Identify line and column corresponding to the position (x,y).
Returns (0,0) if (x,y) outside window.
*)
PROCEDURE IdentifyPoint(line,col: CARDINAL; VAR x,y: INTEGER);
(*
Identify point (x,y) corresponding to lower left corner of
character position (line,col)
*)
PROCEDURE MaxCol(): CARDINAL; (*current maximum column*)
PROCEDURE MaxLn(): CARDINAL; (*current maximum line*)
PROCEDURE CellWidth(): INTEGER; (*current char cell width in pixels*)
PROCEDURE CellHeight(): INTEGER; (*current char cell height in pixels*)
PROCEDURE BackgroundWidth(): INTEGER; (*background width in pixels*)
PROCEDURE BackgroundHeight(): INTEGER; (*background height in pixels*)
PROCEDURE SetEOWAction(u: Window; action: PROC);
(*
Assign procedure action, which is to be called if an attempt
is made to make output beyond the bottom of the window (EOW =
End Of Window), e.g. calling DMWindIO.WriteString after a
DMWindIO.WriteLn has been called when the caret was on line
MaxLn(). The default action is ScrollContent(0,CellHeight()).
*)
PROCEDURE GetEOWAction(u: Window; VAR action: PROC);
PROCEDURE EraseContent;
PROCEDURE RedrawContent;
(*
Forces the redrawing of the whole content of the current
output window by means of it's current restore procedure.
*)
PROCEDURE SetClipping(cr: RectArea);
(*
Clips any drawing outside rectangle with lower left corner
(cr.x,cr.y), width cr.w, and height cr.h in current output
window
*)
PROCEDURE GetClipping(VAR cr: RectArea);
(* Returns current clipping rectangle *)
PROCEDURE RemoveClipping;
(*
Resets previously set clipping rectangle in current output
window
*)
(********************************)
(*##### Textual Output #####*)
(********************************)
TYPE
WindowFont = (Chicago, Monaco, Geneva, NewYork);
LaserFont = (Times, Helvetica, Courier, Symbol);
FontStyles = (bold, italic, underline);
FontStyle = SET OF FontStyles;
PROCEDURE SetWindowFont(wf: WindowFont; size: CARDINAL;
style: FontStyle);
PROCEDURE GetWindowFont(VAR wf: WindowFont; VAR size: CARDINAL;
VAR style: FontStyle);
PROCEDURE SetLaserFont(lf: LaserFont; size: CARDINAL;
style: FontStyle);
PROCEDURE GetLaserFont(VAR lf: LaserFont; VAR size: CARDINAL;
VAR style: FontStyle);
(* Returns current window or laser font and attributes *)
PROCEDURE SetPos(line,col: CARDINAL);
(* Upper left corner = (1,1) *)
PROCEDURE GetPos(VAR line,col: CARDINAL);
PROCEDURE ShowCaret(on: BOOLEAN);
(*
TRUE: a triangular caret is shown at current pen position. All
text routines moves the caret. These reoutines are: SetPos,
Write, WriteLn, WriteString and all number writing procedures.
FALSE: the caret will be hidden
*)
PROCEDURE Invert(on: BOOLEAN); (*true: write subsequent text inverted,
false: stop inverting text*)
PROCEDURE Write(ch: CHAR);
(*
Write at the current position the character ch.
ASCII BS (= 10C; back space a position), FF (= 14C; calls ClearWindow),
LF (= 12C; move down one line, same col), CR (= 15C; WriteLn),
CAN (= 30C; delete till end of line), EOL (= 36C; WriteLn), and
DEL (= 177C; backspace and delete last char) are interpreted.
*)
PROCEDURE WriteLn; (* = Write(EOL) *)
PROCEDURE WriteString(s: ARRAY OF CHAR);
PROCEDURE StringArea (s: ARRAY OF CHAR;
VAR a: RectArea; VAR baseLine,sepSpace: INTEGER);
(*
Returns for the given string s the area the letters will
occupy (a.h = ascent + descent) and the baseLine (= descent).
<------------------ a.w ---------------------->
-----------------------------------------------
| ^ |
| | sepSpace (left blank between lines) |
| v |
|-----------******----------------------------|
| * ^ |
CharHeigth | * * **** | |
| * * * | |
| * * * a.h |
|-----*-----******--baseLine--------------|---|
| * ^ | |
| * baseLine | | |
| * v v |
a.y > -**--------------------------------------------
^ a.x
The routine
assumes that the string s will be written at the current pen
location and returns these values as a.x and a.y (≈ lower,
left corner of the character cell). The value sepSpace
corresponds to the amount of pixels which are left blank
between lines of text (≈ Inside Macintosh leading). If you
wish to clear an area "around" the string, blank an area
which adds twice sepSpace, once above and once below the
string. Note that CharHeight returns a.h+sepSpace.
*)
PROCEDURE StringWidth (VAR s: ARRAY OF CHAR): INTEGER;
PROCEDURE WriteVarString(VAR s: ARRAY OF CHAR);
(*
To support output as efficiently as possible, above
procedures allow to pass strings as VAR parameters. Otherwise
WriteVarString is equivalent to WriteString and StringWidth
is similar to StringArea. However, in contrast to
StringArea, procedure StringWidth returns just the width of
the string s in pixels, instead of the whole, string
enclosing rectangle as returned by StringArea (see above).
Experience shows, that during writing in a proportional font,
the width is the most frequently required value; hence,
StringWidth may be sufficient and there are only rare cases
where StringArea is actually needed.
*)
PROCEDURE WriteCard(c,n: CARDINAL);
PROCEDURE WriteLongCard(lc: LONGCARD; n: CARDINAL);
PROCEDURE WriteInt(c: INTEGER; n: CARDINAL);
PROCEDURE WriteLongInt(li: LONGINT; n: CARDINAL);
(*
Write number with at least n character. Insert leading
blanks if necessary
*)
PROCEDURE WriteReal(r: REAL; n,dec: CARDINAL);
PROCEDURE WriteLongReal(lr: LONGREAL; n,dec: CARDINAL);
(*
Write real number with at least n characters and dec decimals.
Insert leading blanks if necessary
*)
PROCEDURE WriteRealSci(r: REAL; n,dec: CARDINAL);
PROCEDURE WriteLongRealSci(lr: LONGREAL; n,dec: CARDINAL);
(*
Write real number with at least n characters and dec decimals in
scientific notation. Insert leading blanks if necessary
*)
(*****************************************************************
NOTE: Not only do all write procedures move the caret position,
but also the pen position!
*****************************************************************)
(*********************************)
(*##### Graphics Output #####*)
(*********************************)
(*---------------------------------------*)
(*===== Pixel oriented graphics =====*)
(*---------------------------------------*)
(*
Origin is at lower left corner of window. Non visible Pen at
current output location. Cartesian coordinates in pixels.
*)
PROCEDURE SetPen(x,y: INTEGER); (*does not draw*)
PROCEDURE GetPen(VAR x,y: INTEGER); (*get current pen position*)
PROCEDURE SetBrushSize(width,height: INTEGER); (* affects all subsequent drawing *)
PROCEDURE GetBrushSize(VAR width,height: INTEGER);
(*
Draw subsequently lines with a brush of width and height (in
pixels) as specified. The brush is moved along the cordinate
system with its upper left corner positioned exactly at the
current pen position. The width and the height define the
number of pixels actually drawn to the right and below the
upper left corner. This means that drawing lines e.g. by
means of procedured LineTo will result in a movement of the
upper left corner of the brush along the line specified by
LineTo (see below) and painting during this movement every
pixel touched by the brush as given by its dimensions. The
default size DMWindIO uses is (1,1). See module DMPrinting
for hair line styles, which are only supported on PostScript
printers, since they can't be drawn on a screen with a brush
size < (1,1).
*)
PROCEDURE Dot(x,y: INTEGER);
PROCEDURE LineTo(x,y: INTEGER);
(*Draw line from current to new pen position (x,y)*)
PROCEDURE Circle(x,y: INTEGER; radius: CARDINAL; filled: BOOLEAN;
fillpat: Pattern);
(*
Draw circle with centre at position (x,y), radius radius, and
fill it with the pattern fillpat if filled = TRUE
*)
PROCEDURE Area(r: RectArea; pat: Pattern);
(*
Paint the rectangular area at x,y of width w and height h
with pattern pat
*)
PROCEDURE CopyArea(sourceArea: RectArea; destx,desty: INTEGER);
(*
copy rectangular area sourceArea into rectangle area at
(destx,desty)
*)
PROCEDURE MapArea(sourceArea,destArea: RectArea);
(*
Map rectangular source area at (sourceArea.x,sourceArea.y)
with width (sourceArea.w), and height (sourceArea.h) into
destination rectangle at (destArea.x,destArea.y) with width
destArea.w and height destArea.h. Note: sizes of source and
destination rectangles may be different, but in order to
obtain optimal results avoid overlapping.
*)
PROCEDURE DisplayPredefinedPicture(fileName: ARRAY OF CHAR;
pictureID: INTEGER; f: RectArea);
(*
Displays a predefined picture read from a Macintosh resource
of the type "PICT" with ID = pictureID contained in the
resource fork of the file fileName. In the case that the
fileName passed is empty, the default search strategy to find
the resource is followed. The picture is displayed within
the rectangle f. If the picture has been predefined to a
different size, the display is scaled to fit exactly the
enclosing rectangle f. If w and h of the RectArea are equal
to zero, then the picture will be drawn in its original size
at the position specified by x and y of RectArea.
*)
PROCEDURE GetPredefinedPictureFrame(fileName: ARRAY OF CHAR;
pictureID: INTEGER; VAR f: RectArea);
(*
Returns the rectangle in which the predefined picture has
been stored. This procedure is typically called before
calling DisplayPredefinedPicture when the picture's size is
needed for computations, e.g. when it shall be centered or
otherwise formatted.
*)
PROCEDURE StartPolygon;
PROCEDURE CloseAndFillPolygon(pat: Pattern);
(*
Allows the drawing of a polygon by multiple calls to LineTo,
MoveBy, or PlotTo between calling StartPolygon and
CloseAndFillPolygon in order to fill it with pattern pat
(Must not be nested and each StartPolygon must be matched
with a CloseAndFillPolygon)
*)
PROCEDURE DrawAndFillPoly ( nPoints : CARDINAL;
VAR x, y : ARRAY OF INTEGER;
VAR withEdge : ARRAY OF BOOLEAN;
VAR edgeColors: ARRAY OF Color;
isFilled : BOOLEAN;
fillColor : Color;
fillPattern : Pattern );
(*
In contrast to CloseAndFillPolygon which always fills and
draws a frame this procedure allows to define for each
individual edge the attributes, such as the drawing of a
connecting line (withEdge) between corners, and the color to
be used (edgeColors). Moreover it can be controlled whether
the polygon is filled or not (transparent polygon)
(isFilled). Finally if filled it is not only possible to
control the pattern (fillPattern) but also the color (fillColor)
*)
(*
The following objects provide means to use Macintosh QuickDraw
output routines via the coordinate systems supported by this
module. The technique is to convert a position defined relative
to a supported coordinate system into the coordinates used by
QuickDraw before passing the values to the QuickDraw routine.
Use this feature only with utmost care! Note: The routines are
supported only on the Macintosh version of the "Dialog Machine"
and their usage will defy the portability of the client. Note:
It remains the programmer's responsibility to ensure the
correct output to the update copy of a window in case the
automatic restore mechanism (AutoRestoreProc) is used: Any
output made directly with a QuickDraw routine has to be made a
second time after having called procedure SelectRestoreCopy.
*)
TYPE
QDVHSelect = (v,h); QDVHSelectR = [v..h];
QDPoint = RECORD
CASE :INTEGER OF
0: v,h: INTEGER;
| 1: vh: ARRAY QDVHSelectR OF INTEGER;
END(*CASE*);
END(*RECORD*);
QDRect = RECORD
CASE :INTEGER OF
0: top,left,bottom,right: INTEGER;
| 1: topLeft,botRight: QDPoint;
END(*CASE*);
END(*RECORD*);
PROCEDURE XYToQDPoint(x,y: INTEGER; VAR p: QDPoint);
(*Convert position (x,y) into a QuickDraw point*)
PROCEDURE RectAreaToQDRect(r: RectArea; VAR qdr: QDRect);
(*Convert rectangular area r into a QuickDraw rectangle*)
PROCEDURE SelectRestoreCopy(u: Window);
(*
Only to be used if Macintosh QuickDraw output routines are
accessed directly and the current output goes to a window
with automatic restoration (DMWindows.AutoRestoreProc). First
call SelectForOutput and your QuickDraw routine. Second call
this procedure and your QuickDraw routine a second time.
*)
PROCEDURE SetRestoreCopy(u: Window; rcp: ADDRESS);
(*
Use instead of CreateWindow or AssignRestoreProc with actual
argument AutoRestoreProc. rcp must be of type GraphPort or
CGraphPort and must have been allocated before this procedure
is called. Subsequently the auto restore mechanism may be
used in the usual way. This procedure is only provided to
support the work with ColorQuickDraw on newer Macintosh
machines like the Macintosh II, and should only be used by
programmers with good Inside Macintosh knowledge!!!!!!!!
*)
(*-------------------------------*)
(*===== Turtle graphics =====*)
(*-------------------------------*)
(*
Angles are given in degrees (right angle = 90°) in positive
direction. 0° points horizontally to the right.
*)
PROCEDURE Turn(angle: INTEGER); (*turn by angle*)
PROCEDURE TurnTo(angle: INTEGER); (*turn to absolute angle position*)
PROCEDURE MoveBy(distance: CARDINAL); (*move by distance pixels*)
(*-------------------------------------------*)
(*===== Drawing in user coordinates =====*)
(*-------------------------------------------*)
PROCEDURE ScaleUC(r: RectArea; xmin,xmax,ymin,ymax: REAL);
(*
Scale user coordinates (xmin,ymin) to lower left corner
(r.x,r.y) of pixel coordinates. (xmax,ymax) corresponds to
(r.x+r.w,r.y+r.h). It is recommended to avoid drawing in
user coordinates (UC) outside of the defined rectangle. Note,
that clipping can be accomplished by calling procedure
SetClipping with the same argument as used when calling
ScaleUC. There is a logical pen (UCPen) associated with the
user coordinates, although output is actually made by using
the pixel oriented pen.
ERRORS:
- If the two limits of each range are equal (xmin = xmax OR
ymin = ymax) then an error message will be displayed and
the user coordinate system won«t be changed. The default
user corrdinate system is equal the pixel oriented
coordinate system ( r.x = xmin = 0; r.y = ymin = 0; r.w =
xmax - xmin = windowFrame.w; r.h = ymax - ymin =
windowFrame.h)
*)
PROCEDURE GetUC(VAR r: RectArea; VAR xmin,xmax,ymin,ymax: REAL);
(*
Returns current rectangle and extrema mapped onto it of
the user coordinate system
*)
(*
Convert from user coordinates to cartesian coordinates in
pixels and vice versa
*)
PROCEDURE ConvertPointToUC(x,y: INTEGER; VAR xUC,yUC: REAL);
PROCEDURE ConvertUCToPoint(xUC,yUC: REAL; VAR x,y: INTEGER);
(*
Returns the pixel coordinates of a point, which is specified
by the user coordinates xUC and yUC.
ERRORS:
- If the calculated pixel coordinates are outside the
INTEGER range, an error message will be displayed; x and
y remain unchanged.
*)
PROCEDURE UCFrame; (*Draw a frame around the user coordinate system*)
PROCEDURE EraseUCFrame;
PROCEDURE EraseUCFrameContent;
PROCEDURE SetUCPen(xUC,yUC: REAL);
(*set pen in user coordinates*)
PROCEDURE GetUCPen(VAR xUC,yUC: REAL);
(*get current pen position in user coordinates*)
PROCEDURE UCDot(xUC,yUC: REAL);
PROCEDURE UCLineTo(xUC,yUC: REAL);
(*Draw a line from current to new pen position (xUC,yUC)*)
PROCEDURE DrawSym(sym: CHAR);
(*
Draw character sym with its centre at current pen position
(may also be used for drawing in pixel oriented coordinates)
*)
END DMWindIO.