| From Cheap Tricks,
Published By:
|
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 ---------------------------------------------------------------------
Shu Associates Inc.
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