Chapter 5 -- Input / Output Routines


Input Routines

Function Key Routines

With the routines in this section you control the clearing, setting, and display of function key labels, which DataCAD saves in an internal record.

The function keys are numbered from 1 to 20. (F1) through (F10) are numbered 1 through 10. The Shifted (or Alted) function keys (S1) through (S10) are numbered 11 through 20.

fnkeyconv

FUNCTION fnkeyconv (key : integer) : integer;

fnkeyconv takes a key returned from an input routine and converts it to an ordinal function

key number in the range 1 to 20, or returns -1 when the key is not a function key.

For instance, when a user presses (F3), getchar returns the constant f3. fnkeyconv returns 3 when passed f3. The constants returned representing the function keys are not in numerical order, whereas the numbers returned by fnkeyconv are.

fnkeyconv (S7) returns 17

fnkeyconv (Esc) returns -1

fnkeyconv (F10) returns 10

To read any function key between (F1) and (S3), you can use the following code:

getchar (key);

key := fnkeyconv (key);

IF (1 <= key) AND (key <= 13) THEN

...

lblmsg

PROCEDURE lblmsg (key : integer; str : string);

lblmsg sets the message that appears when a function key is pressed. The parameters are similar to lblset, but the string may be up to 60 characters in length.

lblset

PROCEDURE lblset (key : integer; str : string);

lblset sets the string str to the internal label associated with the label number key. This procedure does not cause anything on the display to change. Although the string passed to lblset can be any length, only the first eight characters appear. When the string is shorter than eight characters, it is padded on the right with spaces.

lblsett

PROCEDURE lblsett (key : integer; str : string;toggle : boolean);

lblsett is similar to lblset, but takes the additional parameter, toggle. When toggle is true, an asterisk is inserted in front of str before str is assigned to the function key. When toggle is false, a space is inserted before str.

lblsinit

PROCEDURE lblsinit;

This procedure clears DataCAD's internal record of the function key labels. Use it first prior to setting up a menu. Note that this procedure does NOT clear the function keys that are displayed. To do that, use lblsinit followed by lblson.

lblson

PROCEDURE lblson;

lblson takes the current internal function key labels and displays them on the monitor. The current labels are overwritten.

Mouse / Keyboard Routines

The following routines access the mouse and keyboard. They allow you to use the default DataCAD menus for certain functions.

answer

FUNCTION answer (i :integer) : boolean;

Use answer to ask the user a yes/no type of question.

* Depending on the value of i, different responses are expected. When i=0, the choices are Yes/No. When i=1, the options are Continue/Stop. The last recognized value is i=2, which is On/Off.

* The function return value is true when the user picks the first option, false when the user picks the second option.

You can use answer as in the example below:

wrtmsg ('Are you sure?');

IF answer (0) THEN

doit;

END;

dgetang

FUNCTION dgetang (and : IN OUT real; key OUT : integer) : integer;

dgetang is used to enter an angle while the macro handles the use of function keys. dgetang is similar to both getang and getpoint.

* The return value is either res_normal or res_escape. The return value and use of the parameter key are the same as in getpoint. When you call dgetang, the default angle menu does not appear; however, the current angle style still applies.

done := false;

and := pi;

REPEAT

lblsinit;

lblset ( 1, '25 Degr');

lblset (20, 'Exit');

lblson;

wrtlvl ('test');

wrtmsg ('Enter angle for widgets: ');

result := dgetang (ang, key);

IF result = res_escape THEN

IF key = f1 THEN

and := radians (25.0);

result := res_normal;

{ get out of loop }

ELSIF key = s0 THEN

done := true;

END;

END;

UNTIL done OR (result = res_normal);

IF NOT done THEN

{ do processing here }

...

One useful feature of all of the dget functions is the ability to use (S10) as an Exit key.

dgetdis

FUNCTION dgetdis (dis : IN OUT real; key : OUT integer) : integer;

Use dgetdis to enter a distance while the macro handles the use of the function keys. dgetdis is similar to getdis and dgetang.

* The return value is either res_normal or res_escape. The return value and use of the parameter key are the same as in getpoint.

dgetint

FUNCTION dgetint (int : IN OUT integer; key : OUT integer) : integer;

dgetint is similar to dgetang and dgetdis, but the user enters an integer.

* The return value is either res_normal or res_escape. The return value and use of the parameter key are the same as in getpoint.

dgetrl

FUNCTION dgetrl (rl : IN OUT real; key : OUT integer) : integer;

dgetrl is used to enter real numbers (decimal numbers) while the macro handles the use of the function keys.

* The return value is either res_normal or res_escape. The return value and use of the parameter key are the same as in getpoint.

dgetstr

FUNCTION dgetstr (str : IN OUT string; len : integer; key : OUT integer) : integer;

dgetstr reads a string from the keyboard, while the macro handles the function keys.

* The parameter str must be initialized.

* The parameter len is the maximum allowable length of the string. len can be less than or equal to (but not greater than) the maximum length of str.

* The return value is either res_normal or res_escape. The return value and use of the parameter key are the same as in getpoint.

fgetlayr

FUNCTION fgetlyr (offset : IN OUT integer; key : IN OUT integer; lyr : IN OUT layer) : integer; BUILTIN 226;

fgetlayr works like getlyr except that a valid selection need not be made to exit this function.

* Initialize offset to zero. This returns the number of times scrolled forward into layer selections. When the function return value is res_escape, key returns which key was pressed. lyr is the layer selected when the function return value is res_normal. lyr should be initialized to a valid value before calling the routine. The return values are the same as in the routine getpointp.

getang

PROCEDURE getang (ang : IN OUT real);

getang reads an angle from the keyboard.

* It displays the default angle menu, and allows the user to use the function keys or type the angle from the keyboard. The angle is expressed in radians, using the DataCAD angle convention, regardless of the currently selected type of angle display. Notice that the parameter ang is an IN OUT parameter; and must be initialized before calling getang. The current value of ang displays as a default when getang is called.

getchar

PROCEDURE getchar (key : OUT integer);

getchar reads characters from the keyboard. As discussed in the "Introduction" chapter, the DataCAD keyboard returns an escape code when you press certain keys. Of particular interest are the codes that function keys return. The rest of the escape codes (such as the arrow keys, (Home), etc.) are handled within DataCAD.

The escape codes returned by the function keys are represented by the built-in constants f0 through f9 for the function keys, and the constants s0 through s9 for shifted function keys.

NOTE: Function keys always return their respective keycodes even when nothing appears on them.

getclr

PROCEDURE getclr (clr : IN OUT integer);

getclr reads a color from the keyboard. It displays the color menu and asks the user to select from it. getclr returns the color selected. clr should be initialized before calling getclr.

getdis

PROCEDURE getdis (dis : IN OUT real);

getdis reads a distance from the user. It displays the default distance menu and then accepts input from either the function keys or the keyboard.

* The parameter dis is in DataCAD drawing units. The function keys and input strings depend on the currently-selected scale type, but the variable is always in the same units. The parameter must be initialized first since it is an IN OUT parameter and used for the default.

getesc

PROCEDURE getesc (key : OUT integer);

getesc reads in a function key from the user. Use this procedure when the user's only option is to select a function key, and has nothing to point to. This procedure is used in DataCAD's Edit and Utility menus. The user can enter walls when getesc is called.

An example piece of code that lets the user select from two different options or toggle a variable is:

done := false;

REPEAT

lblsinit;

lblset ( 1, 'Method 1');

lblset ( 2, 'Method 2');

lblsett ( 3, 'Fast', fast);

lblset (20, 'Exit');

lblson;

wrtlvl ('Widgets');

wrtmsg ('Enter widget options.');

getesc (key);

IF key = f1 THEN

doMethod1;

ELSIF key = f2 THEN

doMethod2;

ELSIF key = f3 THEN

fast := NOT fast;

ELSIF key = s0 THEN

done :=true;

END;

UNTIL done;

getflname

FUNCTION getflname (fname, path : IN OUT string; ext : string; entire : OUT string; addext : boolean) : boolean;

getflname reads a filename from the user. You can scroll through the existing filenames which appear on the function keys, select a filename, or type the filename (and path if necessary).

* fname is an IN OUT variable that is the eight character filename being read. On input it is the default filename, on exit it is the user-selected filename. fname is only the eight character filename without the extension or path.

* path is the path where the file is located. It is this path that the default files are listed from. The user can change the path, and upon exit path may change from its input value.

* ext is the file extension of files to list; it includes the dot. Therefore, .dc3 (not dc3) is used to read in a drawing name.

* entire is the entire name, including the path, of the file that was read in. This may be a relative or absolute filename. addext is true when entire includes the extension ext, otherwise it is not.

* getflname returns true when the user enters a filename or selects one from the function keys. false is returned when the user selects exit, (S10). getflname does not check to see if a file exists, it merely reads in a filename.

getint

PROCEDURE getint (i : IN OUT integer);

getint is used to read an integer from the keyboard. The default integer menu appears and the user can type the number or use the function keys.

* When getint returns to the macro, the parameter i contains the value that was entered. Because this parameter is an IN OUT parameter it must be initialized before being passed to getint.

getlyr

PROCEDURE getlyr (lyr : OUT layer);

getlyr reads a layer from the keyboard. Input by function key or by typing the name of a layer. You can scroll through the default layers which appear on the function keys.

NOTE: Exit, (S0), does not work in getlyr, see "fgetlyr".

getmode

FUNCTION getmode (action : string; mode : IN OUT mode_type; key : integer) : integer;

getmode is the function that implements the entity, group, area, fence, selection set user interface.

* action is the verb that determines what to do to selected entities, for example, action might be move at a Move menu.

* mode is the variable that reads the user-selected entities. This is explained in greater depth in a following section.

For example:

done := false;

REPEAT

lblsinit;

lblset ( 7, 'Undo');

lblset ( 8, 'Partial');

lblset (10, 'Clr Undo');

{ lblson should NOT be used here }

wrtlvl ('Erase');

result := getmode ('erase', move, key);

IF result = res_escape THEN

IF key = f7 THEN

undo;

ELSIF key = f8 THEN

partial;

ELSIF key = f0 THEN

clrUndo;

ELSIF key = s0 THEN

done := true;

END;

ELSIF result = res_normal THEN

{ note this loop is the same if the user picked

entity, group, area, or selection set }

addr := ent_first (mode);

WHILE ent_get (ent, addr) DO

addr := ent_next (end, mode);

deleteIt (ent);

END;

END;

UNTIL done;

There are several important points to note about the above example:

* When setting the labels, do not use (F1) through (F6) or (S0). These are used by getmode for the entity, group, area, fence, selection set, layer search, and exit keys.

* Do not call lblson before calling getmode. getmode does this itself, and if you call it, the functions keys blink.

* The return value and the parameter key are used as in getpoint. When the user correctly selects entities, res_normal returns. When res_normal is returned, mode reads the selected entities out of the database.

* If one of the function keys (F7) to (S9) are pressed, res_escape returns and the appropriate value is returned in key.

getpoint

FUNCTION getpoint (pt : OUT point; key OUT integer) : integer;

getpoint is used for reading the current cursor position using the mouse or keyboard.

When a valid point is entered, getpoint returns res_normal. When an escape code is read from the keyboard getpoint returns res_escape. The escape code is returned in the variable key.key determines which function key was pressed. getpoint returns when any of the following happen:

* The left mouse button is pressed (a point is entered).

* The middle mouse button is pressed and a point is snapped to.

* The right mouse button is pressed. Pressing the right mouse button is ALWAYS the same as pressing (S10), regardless of where the cursor is pointing or what is assigned to (S10).

* The user enters a point with (Spacebar).

* A function key is pressed.

See getchar for more information.

getrll

PROCEDURE getrll (rl : IN OUT real);

getrll reads a real number from the keyboard.

The default real numbers (decimal numbers) appear on the function keys. The user types a number or uses the appropriate function key.

* The parameter rl must be initialized before calling getrll.

getstr

PROCEDURE getstr (str : IN OUT string; len : integer);

getstr reads a string from the keyboard. Since there is no default string menu, the function keys are not used by this procedure.

* The parameter str must be initialized.

* The parameter len is the maximum allowable length of the string. len can be less than or equal to (but not greater than) the maximum length of str.

globalesc

PROCEDURE globalesc (key : IN integer);

globalesc handles keyboard toggles, keyboard interrupts, and user-defined keyboard macros. Ordinarily, these toggles and interrupts are handled automatically by input routines which take a keystroke as input. During a call to getpoint or getmode, when a key is pressed which is not trapped by the routine itself, the key is implicitly passed on to globalesc for further processing.

For example, if the user presses the forward slash key, the implicit call to globalesc presents the WindowIn menu. globalesc determines what action to take, if any, and executes the action corresponding to the keystroke if any is required.

These calls to globalesc are automatic and implicit to all DCAL input routines except getchar and getpointp. getchar always returns the integer key code of the key pressed no matter what key it may be. All Alt, Control, Function, and high-bit keys are returned by getchar; however, no processing is done on the key code by globalesc. When the user enters the forward slash key as input, the WindowIn menu does not appear unless the DCAL program tests the input for "/" and correspondingly calls menuwindowin.

getpointp gives you the option of whether or not to automatically process keys through globalesc.

* If the doesc toggle passed to getpointp is false when getpointp is called, globalesc is not called automatically and key is handled the same as in a call to getchar. In this case, getpointp has a return value of res_escape, and key contains the key code of the pressed key. You can then examine the value of key prior to passing it to globalesc. Thus you can determine what action the user intends prior to calling globalesc in your program.

This command is useful with keyforceexit to clean up before forced, or early termination of a macro occurs, for example:

...

iores := getpointp (pnt, key, vmode_all, false);

IF iores = res_normal THEN

{ process point }

ELSIF iores = res_escape THEN

{ process key }

IF key = f1 THEN

{ do your action }

...

ELSIF keyforceexit THEN

{ do cleanup before termination }

globalesc (key);

ELSE

globalesc (key);

END;

globalesc (key);

END;

...

NOTE: getchar and getpointp always trap the key combination (Ctrl)-(C). This is the only key combination that can never be trapped from within a DCAL macro. When (Ctrl)-(C) is pressed, the macro immediately stops executing under all conditions. See getpointp, getchar, and keyforceexit.

Reading from the Database

Use the routines in this section to read entities from the DataCAD database. With these routines you can examine the drawing file. The routines are flexible enough read the same information in several ways.

The entities that read the database use a variable of type mode_type. This variable controls the type of entity that is being read and where in the database the current search is occurring.

draw_mode

FUNCTION draw_mode (mode : IN OUT mode_type; clear, dobrk, todl : IN boolean; drmode : IN integer) : integer;

draw_mode draws a collection of entities described by the mode variable mode.

* mode must be initialized by either the procedure mode_init or mode_init1, or be a return value from the procedure getmode. draw_mode gives you complete control over how to draw the entities using any of four parameters.

* clear is a Boolean flag which, when true, indicates to clear the screen prior to drawing the collection of entities. When clear is false, the screen is not cleared first. dobrk is a Boolean flag which, if true, indicates to DataCAD that the (Del) and (End) keys should be monitored. When dobrk is true, and either the (Del) or (End) keys are pressed, redrawing the data is interrupted. When dobrk is false, (Del) and (End) are ignored and the data is drawn to completion.

* todl is a Boolean flag which, when true, indicates to draw_mode that the hardware display list (if applicable) should be appended to during the screen refresh. When todl is false, the data is refreshed on the screen only and not appended to the display list. The display list is dependent on your graphics card and driver. drmode may take on one of three constant values: drmode_white, drmode_flip, or drmode_black. See ent_draw.

* The return value from draw_mode indicates the status of the break keys. When the toggle dobrk is false, draw_mode returns 0. When dobrk is true, draw_mode may return -1, 0, or 1. A return value of 0 indicates that draw_mode executed to completion and neither (Del) nor (End) was pressed. A return value of -1 indicates that (Del) was pressed and drawing was interrupted. A return value of 1 indicates that (End) was pressed and drawing was interrupted. With this information, draw_mode may be placed in a loop, and (Del) and (End) monitored accordingly.

ent_first

FUNCTION ent_first (mode : IN OUT mode_type) : entaddr;

ent_first returns the address of the first entity that mode specifies.

* When mode is set to read from the current layer (lyr_curr), ent_first returns the address of the first entity on the current layer. When no entities are specified by mode, ent_first returns nil.

ent_get

FUNCTION ent_get (ent : OUT entity; adr : entaddr) : boolean;

ent_get reads the entity located at address adr from the database and returns true when an entity is read from that location. false returns when the address is nil or if DataCAD is unable to read an entity from that address.

The following loop is used to read the

database:

{ first, set the mode variable up }

mode_init (mode);

mode_ss (mode, 10);

{ this part of the loop is INVARIANT with respect to the mode. No matter how many entities you are reading, be it one or all, the following piece of code is THE SAME }

addr := ent_first (mode);

WHILE ent_get (ent, addr) DO

{ do something to the entity here }

{ if the entity is deleted, call

ent_next before it is deleted }

addr := ent_next (ent, mode);

END;

ent_near

FUNCTION ent_near (ent : OUT entity; x, y : real; mode : IN OUT mode_type; errmsg : boolean) : boolean;

ent_near is used to search the database for the entity that is nearest to the point (x, y).

* When no entity is within the miss distance of the point (x, y), false returns.

* When an entity is found, ent is set to that entity and ent_near returns true.

* The database is searched according to the variable mode, which must be initialized before calling ent_near.

* When errmsg is true, an error message prints if no entities are found within the current miss distance. When errmsg is false, no error message prints. The value of errmsg does not affect the value that is returned by ent_near.

The following code example finds the nearest entity that is a line or arc on any layer that is turned on:

mode_init (mode);

mode_lyr (mode, lyr_on);

mode_enttype (mode, entlin);

mode_enttype (mode, entarc);

IF ent_near (ent, x, y, mode, true) THEN

ent_draw (ent, drmode_flip);

pause (0.1);

ent_draw (ent, drmode_flip);

END;

ent_next

FUNCTION ent_next (ent : IN OUT entity; mode : IN OUT mode_type) : entaddr;

ent_next returns the address of the next entity specified by mode.

The entity parameter to ent_next is the last entity read from the database with mode. See also ent_get.

ent_setunused

PROCEDURE ent_setunused (ent : IN OUT entity; ignore : boolean);

ent_setunused marks or unmarks an entity as being unused when the database is read by mode_ignore. An entity should always be marked as unused and then immediately marked as used after the database is read.

* When ignore is true, ent is ignored. When ignore is false, the entity is read even if mode_ignore reads the database.

The following code is used to find the two nearest entities to a given point.

mode_init (mode);

IF ent_near (ent1, x, y, mode, true) THEN

mode_init (mode);

mode_ignore (mode);

{ do not read ent1 during this scan }

ent_setunused (ent1, true);

b = ent_near (ent2, x, y, mode,true);

{ reset ent1 as able to be read }

ent_setunused (ent1, false);

IF b THEN

{ look at the two entities }

END;

END;

extents_mode

PROCEDURE extents_mode (mode : IN OUT mode_type; min, max : OUT point);

extents_mode calculates the x, y, and z extents of any collection of entities described by the mode variable mode.

* mode must be initialized by either the procedure mode_init or mode_init1, or be a return value from the procedure getmode. Any valid mode may be used.

* min and max describe the opposite corners of the smallest three-dimensional box which contains the extents of the data. min and max are the minimum and maximum extents of this box.

mode_1lyr

PROCEDURE mode_1lyr (mode : IN OUT mode_type; lyr : layer);

mode_1lyr instructs DataCAD to read the entities from only one layer, which is specified by the parameter lyr.

To set a mode variable to read all entities from the layer that a particular entity is on, use:

mode_init (mode);

mode_1lyr (mode, ent.lyr);

mode_atr

PROCEDURE mode_atr (mode : IN OUT mode_type; aname: string);

mode_atr sets the mode variable to return all entries in the drawing with an attribute attached named aname.

mode_box

PROCEDURE mode_box (mode : IN OUT mode_type; x1, y1, x2, y2 : real);

When mode_box is called, mode reads only entities that are completely inside the box specified by (x1, y1), (x2, y2). DataCAD automatically determines which corners of the box are given, so the coordinates do not have to be in any particular order.

mode_enttype

PROCEDURE mode_enttype (mode : IN OUT mode_type; enttype : integer);

By default, a mode variable returns all entities on a given layer or combination of layers. By calling mode_enttype once or more times, you can control which types of entities are read.

For example, the following code changes all lines and circles on the current layer to red.

mode_init (mode);

mode_enttype (mode, entlin);

mode_enttype (mode, entcrc);

addr := ent_first (mode);

WHILE ent_get (ent, addr) THEN

addr := ent_next (ent, mode);

ent_draw (ent, drmode_black);

ent.color := clrred;

ent_update (ent);

ent_draw (ent, drmode_white);

END;

mode_fence

PROCEDURE mode_fence (mode : IN OUT mode_type; pnts : IN pntarr; npnt : IN integer);

mode_fence is similar to mode_box, but is used to specify entities that are inside a polygonal fence.

* The array of points is pnts.

* The number of points is given by npnt.

mode_group

PROCEDURE mode_group (mode : IN OUT mode_type; ent : IN OUT entity);

mode_group specifies that a group (linked collection of entities) is to be read.

* ent is any entity that is in the group. The first entity read will not necessarily be ent, but ent will be one of the entities read.

mode_ignore

PROCEDURE mode_ignore (mode : IN OUT mode_type);

mode_ignore sets mode to ignore any entities in the database that have been marked unused by ent_setunused. This is useful for snapping to a point and finding the next nearest entity.

See "ent_setunused" for an example.

mode_init

PROCEDURE mode_init (mode : IN OUT mode_type);

mode_init must be called to initialize the mode variable.

* This procedure should be called before the mode variable is used. The default setting of the mode variable is to read all entities from the current layer.

mode_init1

PROCEDURE mode_init1 (mode : IN OUT mode_type);

mode_init1 is similar to mode_init, except the layer search type is set to the value currently being used by DataCAD. That is, when Layer Search is on in DataCAD, an automatic mode_lyr (mode, lyr_on) is performed, otherwise a mode_lyr (mode, lyr_curr) is performed on the mode variable.

mode_lyr

PROCEDURE mode_lyr (mode : IN OUT mode_type; lyr : integer);

mode_lyr sets the mode variable to read from layers in one of three ways, depending upon the value of lyr:

* When lyr is lyr_curr, entities are read from the current layer only.

* When lyr is equal to lyr_on, entities are read from all layers that are on.

* When lyr is equal to lyr_all, entities are read from the entire database.

mode_ss

PROCEDURE mode_ss (mode : IN OUT mode_type; ssnum : integer);

mode_ss sets mode to read from the database those entities that are in selection set number ssnum.

mode_sym

PROCEDURE mode_sym (mode : IN OUT mode_type; sym : IN OUT symbol);

mode_sym reads the entities that are in a symbol. The entities read from a symbol are read only.

NOTE: Do not attempt to change the entities with ent_update.

Additional Input Routines

The declarations for the routines in this section are not built-into the DCAL compiler, but require the inclusion of the file _input.inc.

The routines in this section are used to enter

data or objects in more complex ways than by using getpoint alone. These routines complement the functions getpoint and getmode. They are similar in operation, but significantly increase the functionality of a macro's user interface. See also getpolyline.

getarc

FUNCTION getarc (msg : IN string; init : IN OUT boolean; center : OUT point; radius, bang, eang : OUT real; key : OUT integer) : integer;

getarc allows the user to input an arc using

one of seven different methods with a single call to a DCAL routine. This is the same function used throughout DC-Modeler for entering circular shapes such a cylinders and domes. getarc automatically handles dragging as required, clockwise/ counterclockwise toggling for two-point arc entry, changing of input modes, and the effects of changing the current color upon the input sequence.

* init is a Boolean flag indicating whether getarc should initialize itself or not. Since getarc is reentrant, init should be set to true prior to the capture of each new arc. init immediately sets to false after the first invocation of getarc and uses this fact to determine whether or not any particular call to getarc is reentrant or not.

* msg is the message with which getarc prompts the user during the input sequence. It is the string which follows the prompt, "Enter ... point of ".

* getarc returns res_normal when a valid arc is entered. When res_normal returns, the description of the arc is contained in the fields center, radius, bang and eang. center is the center point of the arc. The z-coordinate of center is the value of Z-Base upon exit from the routine. radius is the radius of the arc. bang and eang are the beginning and ending angles of the arc respectively. begang and endang have been properly normalized prior to exit. Normalized angles are always positive, and bang is always smaller than eang.

* When a function key is pressed, res_escape returns. In this case, key should be processed the same as it would with a call to getpoint and contains the keycode of the function key pressed. getarc uses function keys (Fl) through (F8), and (S0). The calling routine may use the remaining function keys. As with getmode, you need only execute lblsinit; lblson is performed automatically by getarc.

The following example acts as a template for the use of getarc:

VAR

key : integer;

result : integer;

done: boolean;

center : point;

radius : real;

bang: real;

eang: real;

...

init := true;

REPEAT

...

result := getarc ('Enter arc.', init, center, radius, bang,

eang, key);

IF result = res_escape THEN

IF key = s0 THEN

done := true;

END;

ELSIF result = res_normal THEN

{ A valid arc has been captured and is described by

center, radius, bang, and eang. }

END;

UNTIL done;

getpointp

FUNCTION getpointp (pnt : OUT point; key : OUT integer; vmode : IN integer; doesc : IN boolean) : integer;

getpointp is used in place of the function getpoint when you want to explicitly control the viewing projection or to trap any calls to globalesc. The rest of getpointp operation is identical to that of getpoint.

* getpointp returns an integer value equal to either res_normal or res_escape. When a valid point is entered the return value is res_normal.

* pnt contains the point entered in world coordinates.

* When one of the function keys is pressed, the return value is res_escape. When a keyboard interrupt is pressed doesc is false. In this case, key contains the value of the function key which was pressed ((Fl) thru (F0) or (Sl) thru (S0)), or the keycode of the key pressed.

* vmode may be one of the constants vmode_orth, vmode_para, vmode_pers, or vmode_oblq indicating that the allowable viewing projection for the call to getpointp is orthographic, parallel, perspective, or oblique, respectively. When the current viewing projection does not correspond to this projection, the screen automatically refreshes in the most current view in the appropriate projection. Effectively, getpointp executes a call to view_checkmode prior to allowing input.

* vmode may be set to either of the constants vmode_edit or vmode_all. vmode_edit indicates that either an orthographic or a parallel projection is allowable. When editing in three dimensions, you can use either of these two projections for many input and editing operations. When the current projection is either orthographic or parallel, no action is taken. If the current projection is not either of these, then the most recent view in these two projections is used. vmode_all indicates that any viewing projection is allowable.

* doesc is a flag which indicates whether or not getpoint should handle keyboard interrupts automatically. When doesc is true, keyboard interrupts are handled from within getpointp just as they are with getpoint. When doesc is false, keyboard interrupts are passed back to the calling macro. In this case, key contains the key code of the key which would normally be passed to the procedure globalesc. You can examine the value of this key and take action accordingly, or pass the key explicitly to the procedure globalesc. The following example calls getpointp allowing only for orthographic or parallel projections. Handling of globalesc by getpointp is disabled. When (Esc) is pressed, a message prints and no further action is taken. Otherwise, control is explicitly passed to globalesc.

CONST

esc = 27;

VAR

key : integer;

result : integer;

curs: point;

done: boolean;

...

result := getpointp (curs, key, vmode_edit, false);

IF result = res_escape THEN

IF key = s0 THEN

{ Exit control loop. }

done := true;

ELSIF key = esc THEN

wrterr ('ESC pressed. No action taken.');

{ Do nothing. }

ELSE

{ Call globalesc explicitly. }

globalesc (key);

END;

ELSIF result = res_normal THEN

{ Process input here the same as when using getpoint. }

END;

getpoly

FUNCTION getpoly (msg : IN string; init : IN OUT boolean; pnt : IN OUT polyarr; npnt : IN OUT integer; key : OUT integer) : integer;

getpoly allows the user to input a polygon by a single call to a DCAL routine. Since polygons have a wide variety of uses, getpoly simplifies and standardizes a user interface for polygon input.

getpoly automatically handles dragging as required, partial drawing of the polygon when the screen is refreshed or the current color changed, and going backwards through the input process at the user's request.

* init is a Boolean flag indicating whether or not getpoly should initialize itself. Since getpoly is reentrant, set init to true prior to the capture of each new polygon. init immediately sets to false after the first invocation of getpoly and uses this fact to determine whether any particular call to getpoly is reentrant or not. msg is a string which is concatenated to the end of the input request, "Enter the ... point of the ", by getpoly.

* getpoly returns res_normal when a valid polygon is entered. When res_normal is returned, the variable pnt contains the array of vertices for the polygon. The z- coordinates of the polygon are set to Z-Base, and may not all be the same depending upon whether the user changed Z-Base during the operation. npnt is the number of vertices the polygon contains. When a function key is pressed or the user selects (Cancel), res_escape returns. In this case, key should be processed identically to a call to getpoint and contains the keycode of the function key pressed. getpoly uses function keys (S7), (S8), and (S0). The calling routine may use the remaining function keys. As is the case with the function getmode, you need only execute lblsinit; lblson is executed automatically by getpoly. The following example acts as a template for the use of getpoly:

VAR

key : integer;

result : integer;

done: boolean;

pnt : polyarr;

npnt: polyarr;

...

init := true;

REPEAT

...

lblsinit;

result : = getpoly ( ' to enter ', init , pnt , npnt , key);

IF result = res_escape THEN

IF key = s 0 THEN

done := true;

END;

ELSIF result = res_normal THEN

{ A polygon has been captured. pnt and npnt contain

the description of the polygon. }

END;

UNTIL done;

inputat

PROCEDURE inputat ( col, row : IN integer );

inputat controls the screen location of input for the functions dgetstr, dgetint, dgetrl, dgetdis, and dgetang.

Ordinarily, these input functions operate only on the message line (the bottom line of the screen) and the location of input is at the end of the last issued wrtmsg procedure. inputat makes it possible to obtain input using these functions at any location on the screen. col is the column (in characters) in which the input field begins. row is the row in which the input field exists. Currently, col must be an integer between l and 80 inclusively, and row must be an integer between 1 and 25 inclusively.

inputat can create formlike input screens when used with the procedure printstr, and the input functions described above.

In the following example, dgetstr is called, but input is directed towards the center of the screen using inputat:

VAR

str : str80;

key : integer;

result : integer;

...

str := '';

printstr ( 'Enter distance: ', 15, 10, clrblue, 0, false);

inputAt (31, 10);

result : = dgetstr ( str, len, key);

IF result = res_normal THEN

{Input string captured. }

ELSIF result = res_escape THEN

{ Function key pressed. }

END;

inputwhere

PROCEDURE inputwhere ( col, row : OUT integer );

inputwhere returns the current input location

which is used during the next call to dgetstr, dgetdis, etc.

See "inputat".

keyforceexit

FUNCTION keyforceexit (key : IN integer) : boolean;

keyforceexit determines when a keyboard

interrupt should cause control to pass out of the calling macro to some other point in the program.

keyforceexit is used with getpointp. When

getpointp is called with doesc set to false, the key passed back to the calling macro may be examined using keyforceexit. keyforceexit returns true when (;) is pressed. Pressing (;) exits the user from the current process and passes control to the main Edit menu.

Knowing when a macro is to be exited, allows

the calling macro to clean up prior to releasing control. If you drew temporary data on the screen, keyforceexit allows you to know if the data should be undrawn before passing control to globalesc and subsequently out of the macro.

keyforceexit does not return true when the user

presses (Ctrl)-(C). When (Ctrl)-(C) is pressed, the macro immediately stops executing under all conditions.

Dragging Routines

The declarations for the routines in this

section are not built into the DCAL compiler,

but require the inclusion of the file _drag.inc.

The following routines may optionally be used

during input operations which use the functions getpoint and getpointp to drag an object on the screen. Many of DataCAD's standard editing functions either drag existing data as it is being manipulated, or drag a shape which is representative of the operation being performed. The routines described here provide for much of this functionality from within a DCAL macro.

* All coordinates (points) are in absolute world coordinates unless specified otherwise.

* Some of the dragging routines provide for defining the location of the cursor relative to the geometry of the dragged shape independently so that relative world coordinates may be used.

* All of the dragging routines take a color parameter. The color parameter should be specified using one of the 15 predefined constants for DataCAD's standard colors. Alternatively, the color may be specified with the built-in variable linecolor so that the current line color is used. Note that linecolor varies on a layer by layer basis.

* Many of the dragging routines also take an ortho parameter. This parameter is a Boolean flag which indicates whether or not the dragging routine should consider orthographic snapping. When the ortho parameter is true, orthographic snapping is enabled only if the user enabled orthographic snapping via the O keyboard interrupt. When the ortho parameter is false, orthographic snapping is not enabled regardless of whether the user enabled orthogaphic snapping via the O keyboard interrupt or not.

drag2pt

PROCEDURE drag2pt (ptl, pt2 : IN point; ortho: IN boolean; clr: IN integer);

drag2pt drags two lines with the cursor.

drag2pt is used in DataCAD's standard user interface by the

*Fence function for selecting entities during an editing operation.

* One line extends from ptl to the cursor and the other line extends from pt2 to the cursor. ptl and pt2 are defined in absolute world coordinates.

* clr is the color of the lines.

* ortho indicates when dragging is sensitive to the orthographic keyboard interrupt.

dragbar

PROCEDURE dragbar (pt : IN point; lftofs, rhtofs, pntofs, curofs : IN real; ortho : IN boolean; clr : IN integer);

dragbar drags a rectangle by fixing one end of the rectangle and moving the other end of the rectangle with the cursor.

* pt is the point about which the rectangle is rotated. The dimensions of the rectangle are defined using offsets relative to the point pt and the cursor.

* pntofs is the distance between pt and the end of the bar nearest pt. When pntofs is zero, the end of the bar coincides with pt.

* curofs is the distance between the cursor and the end of the bar nearest the cursor. When the end of the bar coincides with the cursor, curofs is zero.

* lftofs is the distance from a line extending from pt to the cursor to the left side of the rectangle. rhtofs is the distance from a line extending from pt to the cursor to the right side of the rectangle.

* clr is the color of the polygon; and ortho indicates when dragging is sensitive to the Orthographic keyboard interrupt.

dragboxmove

PROCEDURE dragboxmove (pt, min, max : IN point; clr : IN integer);

dragboxmove drags a rectangular box whose sides are parallel with the x and y axes of the screen. dragboxmove is used in DataCAD's standard user interface by the Move/Drag function when the number of entities to drag exceeds Maxlines.

* min and max are the lower left and upper right corners of the box respectively.

* pt is a point in the same coordinate system as min and max and describes the location of the cursor for dragging the box. When the coordinates of pt are identical to min, for example, the box is dragged by its lower left corner.

* clr is the color of the box.

dragcrc3

PROCEDURE dragcrc3 (ptl, pt2 : IN point; doline, ortho : IN boolean; clr : IN integer);

dragcrc3 drags a circle defined by three points. dragcrc3 is used in DataCAD's standard user interface by the Curves/3Pt Circ function.

* Two of the points are specified by ptl and pt2; the third point is defined by the location of the cursor. ptl and pt2 are defined in absolute world coordinates. When doline is true, a line is drawn extending from ptl to pt2. When doline is false, this line is not drawn.

* clr is the color of the circle.

* ortho indicates when dragging is sensitive to the Orthographic keyboard interrupt.

dragdia

PROCEDURE dragdia (pt : IN point; doline, ortho: IN boolean; clr: IN integer );

dragdia drags a circle by extending a line across its diameter. dragdia is used in DataCAD's standard user interface by the Curves/Dia Circ function.

* pt is the point from which to drag the line. The circle passes through the point pt and the cursor. When doline is true, a line is drawn from pt to the cursor bisecting the circle. When doline is false, this line is not drawn.

* clr is the color of the circle.

* ortho indicates whether dragging is sensitive to the Orthographic keyboard interrupt.

dragmodemove

PROCEDURE dragmodemove (mode : IN OUT mode_type; pt : IN point);

dragmodemove drags any collection of entities which exist in the drawing database. dragmodemove is used in DataCAD's standard user interface in the Move/Drag function.

* mode is a mode_type variable which must be initialized and set using one or more of the mode routines. The definition of the mode variable is important to the performance of dragmodemove; some modes scan the database more efficiently than others. Set mode using the procedure mode_ss. Modes which are defined as selection sets are one of the more efficient ways to read the database, and result in maximum efficiency of dragmodemove. Adversely, modes defined using mode_fence or mode_box are more computationally intensive and result in poorer dragging performance by dragmodemove. Because dragging is dependent upon the speed and performance of each particular computer system, it's not a good idea to specify a mode which refers to too many entities in the database. Certain entities such as mesh surfaces and surfaces of revolution may require the generation of many line segments, seriously degrading the performance of dragmodemove. When specifying mode, use care as to how the mode variable is defined as well as the type of entities to which mode refers.

* pt is a point in world coordinates which represents the location of the cursor relative to the data represented by the mode variable.

dragmoderot

PROCEDURE dragmoderot (mode : IN OUT mode_type; cent, ofs, ref : IN point);

dragmoderot drags a collection of entities which exist in the drawing database by rotating them about a point.

* mode is a mode_type variable which must be initialized and set using one or more of the mode routines.

* cent is a point in absolute world coordinates which defines the center of rotation relative to the entities in the database described by the mode variable.

* ofs is a relative offset from cent describing a point to which the center of rotation maps. The entities are rotated about a point which is computed by adding the offset ofs to the point cent.

* ref is a point in absolute world coordinates about which the cursor rotates and which is used as a reference point for calculating the rotation angle of the collection of entities. cent, ofs, and ref may be identical in some applications. For example, if you rotated a collection of entities about a specified point named pt, cent and ref would be set equal to pt, and the coordinates of ofs would be set to zero.

Refer to "dragmodemove" regarding the specification of the mode_type variable. These notes apply equally to procedure dragmoderot. dragmoderot is not currently used in DataCAD's standard user interface but is provided for use by DCAL applications.

dragply

PROCEDURE dragply (pnt : IN pntarr; startidx, endidx : IN integer; ref : IN point; close, ortho : IN boolean; clr : IN integer);

dragply drags a polygon of arbitrary shape containing up to 36 vertices.

* pnt is a variable of type pntarr and contains the vertices of the polygon. The actual values of the z-coordinates of the polygon are not critical since dragging is a two- dimensional operation, but they must be initialized to valid real numbers.

* startidx and endidx are the starting and ending indices of the polygon respectively. startidx is typically equal to 1, but does not have to be.

* ref is a point in world coordinates which indicates the location of the cursor relative to the points contained in array of vertices pnt. l When the polygon is closed, close is true. When the beginning and ending vertices of the polygon are not joined, close is false.

* clr is the color of the polygon.

* ortho indicates when dragging is sensitive to the Orthographic keyboard interrupt. dragply is used in DataCAD's standard user interface when inserting symbols with the

*DynmRot toggle turned off.

dragplyrot

PROCEDURE dragplyrot (pnt : IN pntarr; startidx, endidx : IN integer; cent, ofs, ref : IN point; close, ortho, doline : IN boolean; clr : IN integer);

dragplyrot drags a polygon of arbitrary shape containing up to 36 vertices by rotating the polygon about a point.

* pnt is a variable of type pntarr and contains the vertices of the polygon. The actual value of the z-coordinates of the polygon is not critical since dragging is a two-dimensional operation, but they must be initialized to valid real numbers.

* startIdx and endIdx are the starting and ending indices of the polygon respectively. startIdx is typically equal to 1, but does not have to be.

* cent is a point relative to the coordinates of the polygon about which the polygon rotates.

* ofs is the relative distance between cent and the point in world coordinates to which cent maps, and about which the polygon rotates.

* ref is a point in absolute world coordinates about which the cursor rotates and is used as a reference for calculating the rotation angle of the polygon. Cent, ofs, and ref may be identical in some applications. If you rotate a polygon which currently exists in the database about its first vertex, cent and ref equal the coordinates of the first vertex of the polygon, and the coordinates of ofs are set to zero.

* When doline is true, a line is drawn between the point ref and the cursor. When doline is false, this line is not drawn. clr is the color of the polygon.

* ortho indicates when dragging is sensitive to the Orthographic keyboard interrupt. dragplyrot is used in DataCAD's standard user interface when inserting symbols with the

*DynmRot toggle turned on.

dragrad

PROCEDURE dragrad (pt : IN point; doline, ortho : IN boolean; clr : IN integer);

dragradis drags a circle by extending a line from the center point of the circle to a point on the circle's circumference.

* pt is the center point of the circle; and the circle passes through the cursor.

* When doline is true, a line is drawn extending from the center of the circle to the cursor. When doline is false, this line is not drawn.

* clr is the color of the circle.

* ortho indicates when dragging is sensitive to the Orthographic keyboard interrupt. dragRad is used in DataCAD's standard user interface by the Curves/Rad Circ function.

Output Routines

Display Routines Use the routines in this section to write to the DataCAD command line area, to control the screen mode, and to control which parts of the drawing appear in the drawing viewport.

currwndw

PROCEDURE currwndw (lowleft, upright : IN OUT point);

This procedure sets lowleft and upright to be the lower left and upper right corners, respectively, of the current window. The two points are in world coordinates.

drawcursor

PROCEDURE drawcursor (pt : point);

drawcursor is used for debugging.

It draws a cursor at the given world coordinates using drmode_flip, so that calling drawcursor twice with the same point restores the screen to its original state.

extents

PROCEDURE extents (min, max : OUT point; recalc : IN boolean);

extents calculates the extents of the current drawing. extents returns a set of values that reflect only the layers which are currently turned on.

* min is a point which contains the x, y, and z- coordinates of the lower left corner of the bounding box. max is a point which contains the x, y, and z-coordinates of the upper right corner of the bounding box.

* When the flag recalc is true, the extents of the drawing are recalculated by examining each entity, and updating the extents which are saved with each layer prior to calculating the overall extents of those layers which are turned on. When the flag recalc is false, these calculations are not made, and the extents stored with each layer are assumed to be correct. DataCAD constantly updates the extents of each layer when entities are added to the drawing database, or during editing operations which cause the extents of a layer to become larger. When an editing or erase operation causes the extents of a layer to become smaller, the extents stored for each layer may not correctly reflect the actual extents of the entities on those layers. In this case, recalculation of the drawing extents is required to correctly update the extents for each layer.

grafmode

PROCEDURE grafmode;

grafmode sets the display into graphics mode.

The display is confusing, however, until redrawall is called.

pixsize

FUNCTION pixsize : real;

pixSize returns the size, in world coordinates, of a pixel at the current display scale.

popview

PROCEDURE popview;

popview pops a view off DataCAD's internal stack of 2D views. This is identical to pressing (P).

printstr

PROCEDURE printstr (str : string; col, row, color, cursor : integer; inverse : boolean);

printstr draws a string anywhere on the screen in graphics mode. This is the same procedure that is used internally to write all of the function keys and messages.

* str is the string to be written.

* col and row are the character coordinates of the position where the string is written. col is in the range 1 to 80 and row is in the range 1 to 25, with (1, 1) being the upper left of the screen.

* color is the color in which the string appears.

* cursor is the position in the string where the inverse cursor appears. When cursor is zero no cursor appears in the string (the typical case). Not all display drivers support a cursor in the string.

* When inverse is true, the string is in inverse video. See also "inputat" in this chapter.

pushview

PROCEDURE pushview;

pushview pushes the current view onto DataCAD's internal stack of 2D views. This is the procedure DataCAD calls before it performs windowin.

redraw

PROCEDURE redraw;

redraw is like regen, but on boards with a display list, the drawing is redrawn from the display list and not from the database. On cards without a display list, redraw is the same as regen, that is, the drawing is redrawn from the database. In general, when you want to redraw the drawing, call redraw.

redrawall

PROCEDURE redrawall;

redrawall redraws everything on the graphics screen after clearing the screen, including the messages, function keys, and the drawing.

regen

PROCEDURE regen;

regen redraws the entire drawing (all layers that are on) from the database. On boards with a display list, this is equivalent to the (U) key. On other boards, this is the same as the (Esc) key.

textmode

PROCEDURE textmode;

textmode sets the graphic display into text mode. Any of the input routines with the exception of getpoint (and its derivatives) work while in text mode.

toview

PROCEDURE toview (num : integer);

toview switches to one of DataCAD's ten saved views.

* num must be between 1 and 10 inclusively.

vwptclear

PROCEDURE vwptclear;

vwptclear erases the portion of the screen where the drawing appears. When the template viewport is on, the screen is not cleared.

windowin

PROCEDURE windowin (lowleft, upright : point);

windowin zooms as close as possible to the two points passed to it using the available scales.

The points are in world coordinates.

* lowleft and upright can be any two diagonally opposite corners of the new window.

wrterr

PROCEDURE wrterr (str : string);

wrterr writes its argument on the error line of the monitor, overwriting any previous error message. The error line is the second line from the bottom of the screen.

wrtltype

PROCEDURE wrtltype;

wrtLtype updates the line type descriptor at the lower left corner of the screen. Changing the value of the built-in variable linetype does not automatically update this descriptor; wrtltype must be called explicitly to perform this function.

wrtlvl

PROCEDURE wrtlvl (str : string);

wrtlvl writes out str as the current program level. This is the eight-character string on the bottom line next to the message string.

* When str is more than eight characters long, only the first eight characters are used. When str is less than eight characters long, it is padded on the right with blanks. The previous level string is overwritten.

wrtlyr

PROCEDURE wrtlyr;

wrtlyr writes out the name of the current layer in the lower left corner of the screen. On a color monitor, the layer name appears in the current color.

wrtmsg

PROCEDURE wrtmsg (str : string);

wrtmsg writes its argument on the bottom line of the display, overwriting the previous message.

Use this procedure to write prompts to the screen for input routines:

wrtmsg ('Enter number of divs: ');

getint (divs);

getout := false;

REPEAT

wrtlvl ('Stairs');

wrtmsg ('Point to center.');

result := getpoint (cent, key);

IF result = res_escape THEN

IF key = s0 THEN

getout := true;

END;

END;

UNTIL (result = res_normal) OR

getout;

wrtscl

PROCEDURE wrtscl;

wrtscl writes out the current scale in the lower left corner of the monitor.

wrtss

PROCEDURE wrtss;

wrtss updates the selection set indicator in the lower left hand corner of the screen to indicate the currently active selection set and whether or not selection set appending is active. wrtss is typically used immediately after a call to a selection set routine.

See "Selection Set Routines" for more information.

wrtstat

PROCEDURE wrtstat;

wrtstat updates the SWOTHLUD status indicator at the lower left corner of the screen.

Changing the value of one of the built-in variables such as ortho snapping, or walls on/off does not automatically update this indicator; wrtstat must be called explicitly to do this.

Plotting Routines

The declarations for the routines in this section are not built-into the DCAL compiler, but require the inclusion of the file_plot.inc.

The following routines invoke DataCAD's plotting system from within a DCAL macro. The plotting interface to DCAL is extremely flexible without compromising the performance or usability of the system. In fact, the plotting system available through DataCAD is a subset of the plotting system available through DCAL.

plot_close

PROCEDURE plot_close; (plot : IN OUT plot_type);

plot_close closes the plotting subsystem.

* plot must be the same variable passed to plot_open.

plot_mode

PROCEDURE plot_mode (plot : IN OUT plot_type; mode : IN OUT mode_type; multipen : IN boolean; pensort : IN boolean; colors : IN boolean; vwptMin : IN point; vwptMax : IN point; wndwMin : IN point; wndwMax : IN point; center : IN point; ang : IN real);

plot_mode does the actual plotting of entity data to the plotter or file. plot_mode may be called multiple times between calls to plot_open and plot_close.

* plot is the variable initialized by plot_open. The entities to plot are determined by mode, just as in any reading of the database.

* multipen controls whether or not a multiple pen plot is being performed.

* pensort controls the sorting by pen option.

* colors controls whether or not a color plot is being performed.

* vwptmin and vwptmax control the area on the plotter where the plotted output appears. Only the x and y coordinates of these points are used; however, z-coordinates should be initialized to a real value.

* wndwmin and wndwmax are the world coordinates that are plotted into the area defined by vwptmin and vwptmax (again, only the x and y values are used). Notice that the ratio of x and y values in vwptmin and vwptmax does not have to match the ratio of x and y values in wndwmin and wndwmax, but typically you want the ratios to be the same.

* center is the center of rotation for a rotated plot. center should always be initialized to some value, even when no rotation is specified. center is specified in world coordinates (that is, relative to wndwmin and wndwmax).

* ang is the angle of rotation for a rotated plot.

plot_open

FUNCTION plot_open

(penwidth : IN integer;

penspeed : IN integer;

maxx : IN real;

maxy : IN real;

tofile : IN boolean;

fname : IN string;

plot : IN OUT plot_type)

: integer;

plot_open opens the plotting subsystem. It must be called before a plot is started.

* penwidth is the pen width (in plotter units) DataCAD uses to plot multiple weight lines.

* penspeed is the pen speed DataCAD passes to the plotter driver. Not all plotter drivers support pen speeds; the units are plotter defined. When in doubt, pass the built-in variable pltpenspeed to plot_open.

* maxx and maxy are the sizes, in world coordinates, of the paper in the plotter.

* tofile is true when the plotter output is going to a file, and false when output is sent to the plotter.

* fname is only used when tofile is true, and is the name of the plot file where the plotter data is sent.

* The variable plot is initialized by plot_open and used in plot_close and plot_mode. The return value is zero if successful and non- zero if unable to open the plotter.

File Routines

Use the routines in the following section to manipulate DOS files. See the "File I/O Routines" section for reading and writing files. Any routines that return integers use the DOS file error constants described in the "Constants" chapter.

File Manipulation Routines

chdir

FUNCTION chdir (path : string) : integer;

chdir changes the current directory to path.

This procedure should NEVER be called, but is included for completeness .

file_copy

FUNCTION file_copy (oldname, newname : string) : integer;

file_copy copies a file from one location to another.

* newname can be in the same directory as oldname as long as the filename is different.

file_del

FUNCTION file_del (fname : string) : integer;

file_del deletes a file.

* fname is the pathname of a unique file (no wild cards). The return value is the DOS return code.

file_exist

FUNCTION file_exist (fname : string) : boolean;

file_exist checks for existence of a file.

* file_exist returns true when the file fname exists, false when it does not.

file_find

FUNCTION file_find (str : OUT string; attr : OUT integer; buf : IN OUT dosbuf) : boolean;

file_find searches for files specified in the

previous call to file_pattern.

* The name of the file found (without the name of the path) is returned in str, and its attribute is returned in attr. For example, the following example of code:

file_pattern ('c:/mtec/*.exe', 0, buf');

WHILE file_find (str, attr, buf) DO

wrterr (str);

END;

could produce the output:

DCAD.EXE

CONFIG.EXE

CONVTPL.EXE

file_pattern

PROCEDURE file_pattern (pat : string; attr : integer; buf : IN OUT dosbuf);

file_pattern is used with file_find to search directories for given files.

* file_pattern initializes the variable buf for use by file_find.

* attr is the file attribute to search for; for normal files, this number is zero. For more information on file attributes, see your DOS Reference Manual.

file_ren

FUNCTION file_ren (oldname, newname : string) : integer;

file_ren renames a file from oldname to newname. This function can also be used to move files from one directory to another, as long as they remain on the same disk drive.

For example:

iores := file_ren ('c:/dcad/abc.def', 'c:/abc.def');

moves the file abc.def to the root directory, as long as the return code is fl_ok.

mkdir

FUNCTION mkdir (path : string) : integer;

mkdir creates (makes) directories. Similar to the DOS mkdir command, mkdir can create only one directory at a time.

For example, when c:/dcad does not exist,

iores := mkdir (c:/dcad/dwg);

fails.

rmdir

FUNCTION rmdir (path : string) : integer;

rmdir is used to remove directories. Similar to the DOS keyboard command rmdir, the directory being removed must be empty.

File I/O Routines

The functions presented in this section allow DCAL macros to read or write to files or devices. All functions in this section (with the exception of f_eof) return one of the file i/o constants, described in the "Constants" chapter. An operation with no errors returns fl_ok. Once an error occurs in a file, no further operations are performed on that file, and all subsequent calls to any of the file i/o functions return the same error number.

DCAL understands two types of files: text files and binary (or data) files. Specify the file type in the f_open or f_create function calls. You can use the routines that read and write strings, reals, integers, and characters with either text files or data files. For text files, these routines convert the arguments to and from strings. For data files, the parameter is written to the file as a data item (not converted to a string).

f_close

FUNCTION f_close (fl : IN OUT file) : integer;

f_close closes the file fl.

f_close must be called before leaving the macro to ensure that the RAM buffer is flushed to the disk and the file handle is released.

f_create

FUNCTION f_create (fl : OUT file; fname : string; text : boolean) : integer;

f_create creates a file with the name fname.

* When the file is a text file, text is true, otherwise text is false. The file is opened for writing (fmode_write).

f_eof

FUNCTION f_eof (fl : IN OUT file) : boolean;

f_eof returns true when the current state of file fl is the end of file; otherwise, it returns false.

f_open

FUNCTION f_open (fl : OUT file; fname : string; text : boolean; mode : integer) : integer;

f_open opens an existing file or device.

* The name of the file (including the path) is given by fname.

* The file variable fl is initialized to read, write, or read and write the file depending on whether mode is fmode_read, fmode_write, or fmode_read_write, respectively.

* When text is true, the file is opened as a text file, and mode must be fmode_read. When text is false, the file is opened as a data file.

f_rdchar

FUNCTION f_rdchar (fl : IN OUT file; ch : OUT char) : integer;

f_rdchar reads a character from the specified file.

f_rdint

FUNCTION f_rdint (fl : IN OUT file; i : OUT integer) : integer;

f_rdint reads an integer from the file fl.

In a text file, an integer is specified as a string. This function skips leading white space, and converts the string that follows to an integer. In a data file, two bytes are read from the file and put in the variable i.

f_rdln

FUNCTION f_rdln (fl : IN OUT file) : integer;

This function reads past the next new line sequence. This function is important when you read a text file for strings.

The first call to f_rdstr returns the first line (string) of the file. The next call to f_rdstr returns a string of zero length, because the file is sitting at the new line mark, which terminates a string. To advance to the next line, call f_rdln between the calls to f_rdstr. This call is only valid for text files, and returns an error when used on a data file.

f_rdreal

FUNCTION f_rdreal (fl : IN OUT file; rl : OUT real) : integer;

This function reads a real from the file fl.

f_rdstr

FUNCTION f_rdstr (fl : IN OUT file; str : OUT string) : integer;

This function reads a string from the file fl. The string is terminated by either reaching the maximum length of the file or by hitting a new line character.

See the discussion of f_rdln.

f_seek

FUNCTION f_seek (fl : IN OUT file; recnum : integer) : integer;

f_seek can only be used on data files.

* f_seek positions the file pointer to the recnum record of file fl, based on the record length set for that file in f_setrec. Record numbers start at 0. For example, to seek to the fourth record of a file, write:

iores := f_seek (fl, 3);

This positions the pointer for the file at the 18th byte of the file fl. f_seek and f_setrec allow a programmer to build and read a random access data file.

f_setrec

FUNCTION f_setrec (fl : IN OUT file; len : integer) : integer;

f_setrec sets the record length of a file in bytes. This record length is used only in the function f_seek.

* The parameter fl must be a data file.

f_setrec must be called after f_open or f_create. If f_setrec is not called, the record length is assumed to be one byte. The function sizeof is useful with this function.

For example, if every record of a data file consisted of two fields, one a real and the other an integer, you might write:

iores := f_setrec (fl,

sizeof (0.0) + sizeof (0));

This sets the record size to 6 bytes. Because this number may change in future versions of DCAL and DataCAD, it is a good idea to use sizeof and f_setrec.

f_wrchar

FUNCTION f_wrchar (fl : IN OUT file; ch : char) : integer;

This function writes a single character to the file.

f_wrln

FUNCTION f_wrln (fl : IN OUT file) : integer;

f_wrln writes a new line to the file. This tells the file to start a new line at the current position.

f_wrint

FUNCTION f_wrint (fl : IN OUT file; int : integer) : integer;

This function writes an integer to the file.

integer is converted to a string first when using a text file. Notice that the integer is not padded on either side with spaces, so you may want to write leading or trailing spaces (or both) to the file using f_wrstr or f_wrchar.

f_wrreal

FUNCTION f_wrreal (fl : IN OUT file; rl : real) : integer;

f_wrreal is similar to f_wrint, except that it writes out a real instead of an integer. The real number is converted to a string before writing to the file when fl is a text file.

f_wrstr

FUNCTION f_wrstr (fl : IN OUT file; str : string) : integer;

f_wrstr writes a string to the file fl. The string is not padded with spaces or new line characters.



Thank you for printing this page. Please feel free to contact us for further assistance. You can call our sales department at +1 (800) 394-2231, Monday through Friday from 8:00 a.m. to 5:00 p.m. Eastern time or send an e-mail message to info@datacad.com.