Regions with CLR
Volume Number: 2
Issue Number: 2
Column Tag: Basic School
Basic Does Regions (with CLR!) 
By Dave Kelly, General Dynamics Corp., MacTutor Editorial Board
Hello! This month we will explore the Macintosh Quickdraw routines with a trip
into the world of regions. This may be a review for some of you that program in other
languages such as Pascal or C as this subject has been covered quite well in past issues
of MacTutor (See Vol. 1 No. 3 "Quickdraw does Regions" or Vol 1 No. 4 "Ports O' Call in
Quickdraw"). Until recently it has been impossible to meaningfully talk about regions
from MSBASIC. Wth the Clear Lake Research (CLR) Libraries available it is now
possible to give BASIC equal time with the other languages when referring to
Quickdraw. Quickdraw routines are called from BASIC in much the same method used in
Pascal or other languages. In fact, we recommend that you review the Pascal columns
referred to above as they have information which may pertain to any language, not just
Pascal. The same is true for this column when discussing calls to Quickdraw or other
routines used by all languages.
Fig. 1 Screen dump of our regions program
First a bit of a review for those that are not familiar with Quickdraw regions and
associated calls. We have available to us via the CLR Libraries [Note: These libraries
are available from the MacTutor mail order store for $50 for both the libraries and
the speech routines. -Ed.], over 20 statements involving regions. These are found
listed with their functions on page 14 of the CLR manual or you may refer to Chapter 4
of Macintoshâ„¢ Revealed, Volume One by Chernicoff and published by Hayden Press.
Instead of going into a detailed study of Quickdraw I refer you to the previous issues of
MacTutor mentioned above. (Back issues are available through the MacTutor Store).
A few things to remember when working with Quickdraw: The horizontal
coordinates increase from left to right and the vertical coordinates increase from top to
bottom. You may want to think of a region as an area on the screen with a set of points
inside the region and a set of points outside. A point in the region cannot be both inside
and outside the region. It should also be noted that a graphic point is located to the
'right' and 'below' its corresponding mathematical coordinate.
The Region/Clip Demo program (note: requires CLR Libraries) will set up a
region and by using the GetClip and SetClip statements (CLR) we can specify the region
which we want the text (or graphics) to be drawn to. In this way, only drawing that
occurs within the region will show up on the screen. Any drawing outside the region
will not show up. This could be useful when you want to draw in a particular part of the
screen without disturbing the contents of another part of the screen. The demo program
first opens up the appropriate library:
LIBRARY"ToolLib
Remember to include the disk volume name if necessary. I would advise you to
use the Statement Mover program to move the libraries that you use over to the BASIC
program file so they will always follow the program no matter what disk you put it on.
Next we set up some of the array variables used by the program and associated
library routines. If the variable is undeclared the libraries cannot work. Also be sure
to dimension the arrays properly. For example, if the pattern%() array below were
dimensioned to 0 instead of three, the routine SetRect would go ahead and try to store 4
variables, but would only be able to find one. The results could be unpredictable. Save
your work before running your program in case there might be any misteaks (ha, ha).
The SetRect command sets the left, top, right, and bottom coordinates of the array equal
to the indicated values respectively.
DIM R%(3),OvalR%(3),fontinfo%(3),pattern%(3)
x1%=50:y1%=20:x2%=450:y2%=200
SetRect R%(0),x1%,y1%,x2%,y2%
SetRect pattern%(0),&HAA,&HAA,&HAA,&HAA
SetRect pattern%(0),&HAA,&HAA,&HAA,&HAA
The window is opened and the background is set to the background pattern defined
in the pattern%() array. The screen is cleared so that the background pattern will be
redrawn. The pattern%() array is cleared with SetRect and the background pattern
cleared so that subsequent CLS statements will clear the screen to white. Note that the
CLS command only clears within the clipping region. When a BASIC window is opened
up the clipping region defaults to the window size.
WINDOW 1,"",(2,30)-(508,275),4
CALL BACKPAT (VARPTR(pattern%(0)))
CLS
SetRect pattern%(0),0,0,0,0
CALL BACKPAT(VARPTR(pattern%(0)))
Another CLR Library statement allows us to determine the size of the currently
selected font. The program sets the TEXTSIZE to 9 and then calls the getfontinfo routine.
The font info is returned in the array fontinfo%(). The variable fontinfo%(0) returns
the ascent, fontinfo%(1) returns the descent, fontinfo%(2) returns the maximum
character width, and fontinfo%(3) returns the vertical distance between the descent
line and the ascent line below it. The program needed to know the total spacing for each
line of text which is given by the sum of the ascent, descent, and the vertical distance
between the descent line and the ascent line below it. Note that a call to getfontinfo
would be useful for programs trying to determine the number of lines of text to print
per page (or screen) when using various sizes and styles of fonts.
CALL TEXTSIZE(9)
getfontinfo fontinfo%(0)
fh%=fontinfo%(0)+fontinfo%(1)
Next the region handle variables are defined and the clipping region represented
by the screen is stored away so it may be restored again later. If the OldReg! handle
were not saved in this way, the last clipping region would be used the next time printing
to the window. To define a new region, execute a NewRgn command. This allocates space
for the new region and the region is initialized to the empty region. GetClip sets the
region with the handle indicated (in this case OldReg! is the handle) to the current clip
region.
handle!=0
OldReg!=0
NewRgn OldReg!
getclip OldReg!
We now define the region which we want to use as our clipping region. First we
initialize the region with NewRgn with handle! . Next we may define the contents of the
region. A series of graphics statements will make up the region we wish to create. We
open the region with OpenRgn and follow it with whatever graphics commands we desire
such as FRAMEOVAL, FRAMERECT, LINE, and others. Note that arcs cannot form part of
the region definition. The end of the definition is indicated with the CloseRgn handle!
statement where handle! is the handle! of the region being defined. Next the clipping
region is set to the region with handle! with the statement Setclip handle! . All points
either printed or drawn outside the region will not be shown. Only those points inside
the region may be seen when printing is done inside the region.
NewRgn handle!
FRAMEOVAL VARPTR(R%(0))
CloseRgn handle!
Setclip handle!
The next several statements of the program print text in the region which has
been set as the clipping region. Note that CLR has provided us with the Drawtext text$
statement to drawtext much faster than with the BASIC PRINT statement. To use
drawtext you must move the quickdraw pen to the desired pixel position and issue the
drawtext statement. It is harder to use that the BASIC printing statements but the speed
difference makes it worth using when speed counts.
There are other statements which may be used with regions. One region may be
subtracted from another with DiffRgn or use XorRgn or UnionRgn to combine regions.
These and other commands will be left for future MacTutor columns. The program uses
the framergn command to draw a border around the edge of the region. The current
pensize is used for the border line.
CALL PENSIZE (2,2)
framergn handle!
Now for a word of caution: If your program should crash for some reason before
your region is disposed of, you should be prepared to manually type in the disposeRgn
statement and appropriate handle or handles for the regions used. Remember to dispose
of all regions before quiting your program as the space for the regions has been
allocated and will not be returned unless the regions have been disposed of. Otherwise,
you may find yourself wondering why you are running out of room on the heap. The
statement is:
disposergn handle!
A few words on the CLR Libraries clipping statements: The CLR Libraries
manual mentions a statement named ClipRect which is supposed to set the clipping
region to a rectangle. The ClipRect routine is not included on my ToolLib file. No need
to panic yet, however, because the same command can be reconstructed with a
combination of region calls and clipping calls. One solution is to use the following
sequence to do a ClipRect (set the clipping region to a rectangle):
DIM rect%(3)
handle!=0
SetRect rect%(0),x1%,y1%,x2%,y2%
NewRgn handle!
FRAMERECT ( VARPTR(Rect%(0))
CloseRgn handle!
Setclip handle!
You may also use SetRectRgn or RectRgn to set a region equal to a rectangle. The
statement syntax is:
SetRectRgn hand!,left%,top%,right%,bottom%
The region with handle hand! is set equal to the rectangle with coordinates
left%,top%,right%, and bottom%.
RectRgn hand!, rect%(0)
The region specified by the handle hand! is set equal to the rectangle rect%. A
region is not created by this, but must have been previously defined with NewRgn.
You may use either of these two statements in place of the OpenRgn and CloseRgn
sequence above as desired.
Use GetClip to set a region to the current clipping region and SetClip to set the
clipping region to a different region. You may want to use SetClip to switch back and
forth between different clipping regions.
Have any interesting programs you have created after experimenting with
clipping regions? Feel free to share them with others by sending them in to MacTutor.
'Region/Clip Demo
'by Dave Kelly
'MacTutor ©1986
LIBRARY"ToolLib
DIM R%(3),OvalR%(3),fontinfo%(3),pattern%(3)
x1%=50:y1%=20:x2%=450:y2%=200
SetRect R%(0),x1%,y1%,x2%,y2%
SetRect pattern%(0),&HAA,&HAA,&HAA,&HAA
WINDOW 1,"",(2,30)-(508,275),4
CALL BACKPAT (VARPTR(pattern%(0)))
CLS
SetRect pattern%(0),0,0,0,0
CALL BACKPAT(VARPTR(pattern%(0)))
CALL TEXTSIZE(9)
getfontinfo fontinfo%(0)
fh%=fontinfo%(0)+fontinfo%(1)
handle!=0
OldReg!=0
NewRgn OldReg!
getclip OldReg!
NewRgn handle!
FRAMEOVAL VARPTR(R%(0))
CloseRgn handle!
Setclip handle!
CALL MOVETO(x1%,y1%)
FOR i=1 TO 18
CALL MOVETO (x1%,y1%+i*fh%)
FOR j=1 TO 6
drawtext "Read Mac Tutor!
NEXT j
NEXT i
CALL PENSIZE (2,2)
framergn handle!
disposergn handle!
dh%=50:dy%=25
x1%=x1%+dh%:y1%=y1%+dy%
x2%=x2%-dh%:y2%=y2%-dy%
SetRect R%(0),x1%,y1%,x2%,y2%
NewRgn handle!
FRAMEOVAL VARPTR(R%(0))
CloseRgn handle!
Setclip handle!
CLS
CALL MOVETO(x1%,y1%)
FOR i=1 TO 18
CALL MOVETO (x1%,y1%+i*fh%)
FOR j= 1 TO 6
drawtext "It's Grrrreat!
NEXT j
NEXT i
framergn handle!
disposergn handle!
Setclip OldReg!
disposergn OldReg!
LIBRARY CLOSE
END