From Cheap Tricks,
Dec '96 & Feb '97 Issues

Published By:
Shu Associates, Inc.
120 Trenton St., Melrose, MA 02176-3714
(781)662-0020 (FAX Same)
eshu@world.std.com

DCAL PRIMER



		An Introduction to Programming in DCAL
			   by Bill D'Amico

			   UniQue Software
			     12 Chapel St
			 Freeport, ME  04032
			 (207) 865-0107 Phone
			  (207) 865-6322 Fax
			70033,3072 (CompuServe)
                


		      To the Would-Be DCAL User:

My own personal involvement with DCAL dates back to February of 1988,
when DCAL was first released in a fully documented form by
Microtecture Corp of Charlottesville, VA.  Over the years that I have
used DCAL to write enhancement programs for DataCAD, I have found it
to be an extremely powerful and capable tool.  When it was released,
it was years ahead of its time with respect to what competing CAD
programs offered for enhancement programming languages.  Even today
it ranks, in my mind, as the crowning technical achievement of the
original authors of DataCAD - namely Eric Smith and David
Giesselman.  How they were able to write both an innovative,
progressive architectural CAD program such as DataCAD as well as an
entire programming language to enhance it is the stuff of mystery and
legend in the software business.

I have used DCAL to write four primary macros which are currently sold
by my company, UniQue Software: the BLOCKER Space Planning Macro,
TOUCHUP 3D Hatching Macro, DCSPRINT Utilities Macro, and the TPLLIB
Template Library Documentation Macro.  I have also written dozens of
other programs with DCAL that have solved specific problems for
DataCAD clients.

I wrote this document for CADKEY in February of 1993 and it was
published their 'Reference Point' newsletter for DataCAD users, which
no longer exists.  It is intended as an 'ice-breaker' for those
adventurous DataCAD users who would like to learn the basics of
programming in DCAL.

This document may be reproduced - in its entirety only - without
permission.  It is not to be sold for profit.  DCAL and DataCAD are
trademarks of CADKEY, Inc.

Bill D'Amico
September, 1994


---------------------------------------------------------------------
			    What is DCAL?
---------------------------------------------------------------------

DCAL stands for DataCAD Applications Language.  It is a programming
language which allows you to extend the capabilities of the DataCAD
program by writing 'macros' which can be accessed and run by users
from within DataCAD.  DCAL macros can be programmed to perform nearly
any drawing manipulation task.  Do not confuse DataCAD keyboard
macros -simple keystroke sequences for DataCAD to 'play back' - with
DCAL macros.

---------------------------------------------------------------------
			    Why Use DCAL?
---------------------------------------------------------------------

The basic reason you would write a macro
is to 'teach' DataCAD to do things that either it can't already do,
or that you feel are too difficult or repetitive to do using the
standard DataCAD drawing functions.  A good example of this concept
is CADKEY's 'CLIPIT' macro, which allows you to perform
'eraser-shield'-type cutting and copying of pieces of drawings.
Another is the new '3DSTAIR' macro, also from CADKEY, which will
automatically construct a wide variety of complex 3-dimensional stair
types based on the dimensions you give it.  If you have ever tried to
perform either of these tasks with standard, 'generic' DataCAD
commands, and then used the macros that were written specifically to
perform them, you would understand why macros are powerful additions
to DataCAD's feature set.  If you have never used a macro at all,
start simple: try the 'ARROW' macro, which will allow you to draw a
wide arrow of the width that you may specify from the menu.  The
macro can take your input and create the 7 lines needed to draw a 
wide arrow much quicker than you could by accurately drawing and
trimming the same 7 lines in DataCAD.

---------------------------------------------------------------------
			  Who Can Use DCAL?
---------------------------------------------------------------------

Make no mistake about it, DCAL is a powerful programming tool.  As
such, programming DataCAD effectively with DCAL requires both a
thorough knowledge of DataCAD from the user's point of view, as well
as at least a beginner's level of programming principles using a
language such as BASIC or, even better, PASCAL.  DCAL programming is
very PASCAL-like in structure and flow, so elementary concepts such
as functions, procedures, and variable types need to be firmly
grasped in order to write even the simplest of DCAL macros.

It is NOT the case that anyone who uses DataCAD - even a DataCAD
'guru' - can write DCAL macros.  It is also NOT the case that any
programmer can write good, easy-to-use DCAL macros.

We said DCAL is a powerful tool.  Most powerful tools that I know of
are also dangerous. DCAL is powerful because it can directly read and
write data in a DataCAD drawing file.  For this reason it is also
dangerous, because a DCAL macro can corrupt a DataCAD drawing file if
it is not carefully written.

If I haven't scared you off yet, let's get to it...

---------------------------------------------------------------------
		    Setting Up to Program in DCAL
---------------------------------------------------------------------

A few things must be done before you can program in DCAL.  First, you
must install the DCAL language programs themselves from the disks
supplied by CADKEY.  After that, I would recommend that you put the
directory you installed DCAL into (usually C:\DCAL) on your PATH 
statement in your AUTOEXEC.BAT file so that you can edit and write
programs in any directory and then compile and link them by just
typing the DCAL compile and link commands (discussed later).  That
way you can more easily separate your work into a number of
directories.  Your path statement in AUTOEXEC.BAT should be changed
to read something like:

		  PATH=C:\DOS;C:\;C:\WINDOWS;C:\DCAL

A final requirement for being able to program in DCAL (and, actually,
for changing your AUTOEXEC.BAT file above!) is that you must be able
to edit a text file using a good text editor like DOS 5.0's EDIT, or
to use your word processor to edit and save your program source files
as plain DOS text files.  No, I wouldn't recommend using EDLIN,
although I'm sure it's been done.

---------------------------------------------------------------------
		  Our First Example - 'Hello World'
---------------------------------------------------------------------

The typical example used to introduce a programming language is the
famous 'Hello World' example.  This is how many language tutorial
manuals start, by showing just about the simplest program anyone
would want to write.  The program will do nothing more than put the
message 'Hello World' on the DataCAD screen for the user to read, but
the steps required to do so will introduce us to the basics of how
any program in DCAL is written.

The 'Hello World' macro will simply display the words 'Hello World' on
the message line on the next to last line from the bottom of
DataCAD's prompt area underneath the drawing window. The following is
the 'HELLO' macro:

			PROGRAM hello;

			BEGIN

			wrterr('Hello World');

			END hello.


This tiny little DCAL program shows the basic structure of a program
file.  The program name is 'hello'.  Program execution begins at the
word 'BEGIN' and ends at the word 'END'.  The only line of actual
program code is the line 'wrterr('Hello World');'.  The wrterr
statement invokes the DCAL procedure 'wrterr', which is a built-in
DCAL subprogram that takes the string that you give it in the
parentheses (in this case 'Hello World') and displays it on what DCAL
calls the error line of the DataCAD display.  Note that program code
lines must always end in a semicolon.

To write this program, you will need to open up a file with a text
editor (again, DOS 5.0's EDIT command will do), type in the commands
you see here, then save the file with a '.DCS' (for DCAL Source)
extension.  We will call it 'HELLO.DCS'.  DCAL macro source files must
then be processed through two steps in order to convert them to an
executable DCAL macro file ('.DCX') for DataCAD to run. These steps
are called compiling and linking.  So our first step -compiling the 
HELLO.DCS file - is accomplished from the DOS command line by typing:

			      DCC HELLO

(DCC is the DCAL Compiler).  If there are no errors reported from the
compile step, a file 'HELLO.DCO' is created, which can then be linked
to form the 'HELLO.DCX' macro executable file by typing, again from
the DOS command line:

			      DCL HELLO;

(DCL is the DCAL Linker).  Note that you must include the semicolon. 
This is because DCAL's linker can link many source files into one
large macro file, so the semicolon on the command line tells the
linker that this is the last file (and in this simple case the only
one) that is needed to build the DCX macro executable file.

If there are no link errors reported, you should now have a HELLO.DCX
file that can be run from DatACAD's 'Macros' menu.  Just copy the
HELLO.DCX file to your 'macros' subdirectory (usually C:\MTEC\DCX),
run DataCAD, and pick 'HELLO' off of the Macros menu. You should get
the message 'Hello World' written on the 'error line' in the prompt
area at the bottom of the screen.

---------------------------------------------------------------------
		     Variables and Variable Types
---------------------------------------------------------------------

Now, the HELLO macro is so simple that it really shows us nothing of
the elementary concepts of DCAL mentioned above - procedures,
functions, and variable types.  So let us now consider the following
small DCAL macro program called 'EXAMPLE1', which introduces the
concept of variable types:

	PROGRAM example1;

	VAR
	  a : integer;
	  b : integer;
	  c : integer;
	  d : integer;
	  e : integer;
	  f : real;
	  g : real;
	  h : real;
	  s : string(80);
	  m : boolean;

	BEGIN

	a := 10
	b := 3
	c := a + b;
	d := a * b;
	e := a / b;

	f := 10.0;
	g := 3.0;
	h := f / g;
	
	s := 'Hello World';

	m := true;

	END example1;


The new 'VAR' section of the EXAMPLE1 macro declares the variables
that the program is going to use before they are ever used.  This is
a requirement of DCAL which some other languages - most notably
BASIC, do not have.  Any and all variables that are going to be used
in a program (or procedure or function, as we will see later) must
have their 'type' declared in a 'VAR' section before the program's
'BEGIN' statement.  Declaring a variable means indicating what type of
information that variable will hold.  Variable names can be up to 20
characters in length, and must start with a letter (a-z).  Upper and
lower case is ignored in all DCAL statements, so you can use them
interchangeably.  I prefer to keep DCAL statements that define program
sections and program flow, such as PROGRAM, IF, THEN, BEGIN, END,
PROCEDURE, etc. as all capitals, as it seems to make programs easier
to read.  You will see that most of the examples in the DCAL manual
are written that way.

Anyway, the EXAMPLE1 macro shows how variables are declared and used
in DCAL.  Variables a through e have been declared as integers, so
they can be assigned any value from -32767 to 32767, but only integer
values (no decimal point).  We assign a value of 10 and b a value of
3 with the first two program statements, then we illustrate addition,
multiplication, and division of integers with the next three.  The
':=' is called the assignment operator, as it is used to assign the 
value of the expression to its right to the variable on its left.  
So c will take on the value 13, and d will be 30. The value of e,
however, will be 3, NOT 3.3333333 as you would expect if you did 10/3
on your calculator.  This is because we declared that e can only hold
an integer value, so 10 / 3 will only yield the integer portion of
the result, which is, of course, 3.  So e will have a value of 3. 
Doing the same division operation using the variables f, g, and h
will result in h's value being set to 3.33333333.  Why?  Because f,
g, and h have been declared as real variables, which can have decimal
points and therefore fractional values.  Variable s is declared as a
string variable that can be up to 80 characters long.  We assign s
equal to the value 'Hello World'.  Integers, reals, and strings are
three of the more commonly used types, as is a 'boolean', which can
have the value of 'true' or 'false'.  The EXAMPLE1 macro assigns the
value of true to the variable m.  Chapter 8 - 'DCAL Built In Types'
in the DCAL manual goes into much more detail about these and other
variable types.  You can also define your own types in a TYPE section
of your program, but discussing the reasons for doing so at this
point would be getting ahead of ourselves.

DataCAD also has many variables already declared and built into DCAL,
all of which have to do with various drawing settings.  These are
outlined in Chapter 9 - 'DCAL Built In Variables' in the DCAL
manual.  As the user works in DataCAD and changes various drawing
settings, the values of these built in variables are what is actually
being changed.  For example, toggling on the 'LyrSrch' option on
DataCAD's menu changes the value of the built in boolean variable
lyrsearch to true.  Toggling it off changes lyrsearch to false.  The
DCAL macro can therefore find out if layer search is currently on
just by seeing if lyrsearch is set to true, as in the following
IF..THEN example:

	IF lyrsearch THEN
	  wrterr('Layer search is on');
	ELSE
	  wrterr('Layer search is off');
	END;

Here the 'IF' statement checks to see if the value of lyrsearch is
true.

Another example of a built in variable is linewidth, an integer
variable which holds the current setting of line weight:

	IF linewidth > 5 THEN
	  wrterr('Are you sure you want to draw with such a wide line?');
	END;

You can change the values of any and all of these built in variables
at any time inside your macro.  You can turn layer search off with:

	lyrsearch := false;

or, you can change the current line width with:
	lineweight := 2;


Variables types are one of the cornerstones of any programming
language.  You should familiarize yourself with DCAL's built in types
by looking over Chapter 8 in the DCAL manual, then look over the
built in variables in Chapter 9.  If you are very familiar with
DataCAD as a user, you should recognize most or all of the built in
variables in Chapter 9.

---------------------------------------------------------------------
		       Procedures and Functions
---------------------------------------------------------------------

Since good programming practice dictates that any program of any
significant size must be broken down into subprograms that interact
with one another, any serious programming language provides the
ability to do so.  DCAL is no exception.  DCAL provides two mechanisms
for creating such subprograms - calling them, like PASCAL,
'procedures' and 'functions'.  A procedure is like a little program
all itself.  Like the built in DCAL 'wrterr' procedure used in the
HELLO macro, you can write procedures that can be called upon to
perform a specific task and/or produce a result based on data that is
passed to it.  In the HELLO macro, we knew that we wanted to display 
a message on the screen, and we knew what the message was.  Since
wrterr knows how to do that, we simply 'called' the wrterr procedure
and gave it the message string that we wanted the user to see.  We
may not know exactly how wrterr accomplished this feat - but we don't
have to.  The important thing is that the job gets done.  A function
is identical to a procedure except that functions return a value of a
particular type.  That means that you must have a variable ready to 
receive the result of calling a function, for example:

			r := 4.0;
			s := sqrt(r);

Here r and s are both variables of type real.  The variable r is
assigned the value 4.0, then the square root function is asked to
operate on the value of r, and s is assigned that value, which will 
obviously be 2.0.

DCAL has some 500 built in procedures and functions - that is the bad
news for anyone who wants to try to learn DCAL and master them all. 
The good news is that you really can learn them as you go -as your
programs get more and more sophisticated - and that they do very 
sophisticated things for you that you would otherwise have to program
yourself.  Like the sqrt function and the wrterr procedure - you can
just 'call' them and let them do a lot of the work for you!

We will get into writing our own procedures and functions as we get
further into DCAL, but for now, our next example will just call a few
of DCAL's many built in procedures.

---------------------------------------------------------------------
		     'DataCAD, what time is it?'
---------------------------------------------------------------------

You have probably been working along in DataCAD and not been wearing
your watch and wished you could ask DataCAD to tell you the time. 
No?  Well, maybe you have wanted DataCAD to automatically place the
current time and/or date on your drawing for you?  Well, in either
case, you probably concluded that DataCAD simply can't tell time even
though you know that your computer can.  Actually, DataCAD can tell
time, it simply has no command on any menu for you to ask it to. This
is a perfect example of why a DCAL macro is useful - we can use DCAL
to have DataCAD perform a task - telling us the date and time - that
no standard DataCAD command will allow us to do.

DCAL contains a procedure called 'readclock' which will read the PC's
clock and assign values to integer variables that will allow us to
derive and display the date and time to the user.  In addition to the
'readclock' procedure, the DATETIME macro introduces two other new
procedure - 'strcat' and 'cvintst'.

The macro 'DATETIME' can be written as follows.

	PROGRAM datetime;

	#include '/dcal/inc/_misc.inc'

	VAR
		year, month, day, hours  : integer;
		minutes, seconds, hundredths : integer;
		tmp_str : str8;
		outstr  : str80;
		am_or_pm : string(2);

	BEGIN

	readclock(year, month, day, hours, minutes, seconds, hundredths);
	cvintst(month,outstr);
	strcat(outstr,'/');
	cvintst(day,tmp_str);
	strcat(outstr,tmp_str);
	strcat(outstr,'/');
	cvintst(year,tmp_str);
	strcat(outstr,tmp_str);
	strcat(outstr,' -- ');

	IF hours > 12 THEN
		cvintst(hours-12,tmp_str);
		am_or_pm := 'PM';
	ELSE
		cvintst(hours,tmp_str);
		am_or_pm := 'AM';
	END;
	strcat(outstr,tmp_str);
	strcat(outstr,':');
	cvintst(minutes,tmp_str);
	IF minutes < 10 THEN
		strcat(outstr,'0');
	END;
	strcat(outstr,tmp_str);
	strcat(outstr,am_or_pm);

	wrterr(outstr);

	END datetime.


The 'readclock' procedure in DCAL does the actual work of getting the
current date and time information from the computer down to the
hundredths of a second.  It stores that information in the variables
enclosed in the parentheses (hours, minutes, etc..). Each of these is
just an integer value which would look something like:

		2 19 1993 18 3

if we didn't pretty it up a bit, so we must use further program logic
to read and convert these numbers into a nice text string to display
the same information to human being using the system who would expect
it more in a form like: 

		2/19/1993 -- 6:03PM

Remember the wrterr procedure that we use to display a string to the
user?  It will only accept a single string or string variable for
display, so we must convert these integers into strings and put the
strings together to make one string before we ask wrterr to display
that string to the user.  This is done by combining sequences of the
cvintst procedure to convert each integer value into a string, and
the strcat procedure which takes a string and adds it to the end of
another string.  Both of these procedures are well documented in
Chapter 11 of the DCAL manual, so I will save space here and
recommend you go there for more information on them. I use the 8
character string variable tmp_str over and over as I convert each
integer of the date and time to a string because I am building the 80
character string variable outstr as I go along and I only need 
tmp_str as a temporary holding place for the string value of each
converted integer.  Note that I also add nice punctuation as I build
the outstr variable, because I want it to be nicely formatted for the
user to read.  I also throw in a little IF..THEN to decide if it is
'AM' or 'PM' to get our feet wet with conditional logic in DCAL.  If
it is afternoon, then I subtract 12 from military time (18 hours) to
get 6 hours and use that instead. I also set the value of the 2
character string variable am_or_pm appropriately while I'm at it,
because it will get added to the end of the string just before it is
displayed to the user in the last program statement, using our
now-familiar wrterr procedure.

The only other concept which is new in this example is the line:

	#include '/dcal/inc/_misc.inc'

This line is needed because the definition of the readclock procedure
is actually external to DCAL's compiler.  So we tell the compiler to
include the definitions that it finds in the file '_misc.inc' in
DCAL's include file directory because we want to use the readclock
procedure that is defined there.  I prefer to use forward slashes
instead of DOS's usual backslashes here, because backslashes are used
for another purpose in DCAL which we will get to later.

---------------------------------------------------------------------
			       Summary
---------------------------------------------------------------------

At its simplest level, DCAL can be used to teach DataCAD a few small
tricks that it will not already do for you, like this issue's example
program, which reports the current system date and time to you while
you are in DataCAD.  Like any powerful language, though, DCAL can do
much more.  It can build menus, ask for and respond to user input,
draw entities, erase entities, etc.  In fact, there is very little
that you can imagine that you would like DataCAD to do for you that
can't be done with a DCAL macro.  However, programming DataCAD
through DCAL is very different from and much more complex than simply
using DataCAD.  The goal of this column is to present the basics of
DCAL in gradually increasing complexity.  To do so, I will try to make
each macro sample program one that is both instructional and
functional.  If you have followed along and written, compiled, and
linked the DATETIME macro, you will have learned some DCAL basics and
also created a useful utility macro for yourself.

Notice that I never said DCAL programming was fast or easy.  Like all
programming, it takes careful attention and sometimes many steps to
teach a computer - or in this case DataCAD - to do something you
thought would be very easy, like telling you the date and time.

---------------------------------------------------------------------
                           END OF DCAL PRIMER 
---------------------------------------------------------------------

To go back to the Reprints Page

How to Subscribe

Shu Associates Inc.
120 Trenton St.
Melrose, MA 02176-3714
(781)662-0020 Tel & Fax

You can E-mail us by clicking here: eshu@world.std.com

Copyright © 1997, Shu Associates Inc.

URL: http://world.std.com/~eshu/cheap/dcalprmr.htm