Lesson 5
User input & System variables

Most programs require some information from the user.  AutoLISP includes a set of functions designed to get user input (see "4 - User input" in the Catalog of Function Definitions).  These functions are sometimes called get-functions because they all begin with "get...".  This lesson illustrates several of these functions as well as the initget function, which controls the allowable input for the get-functions.  It also covers system variables.

The get-functions

All of the get-functions pause for user input.  They can also display a prompt to tell the user what type of information to enter.  Their ability to wait for input sets them apart from other AutoLISP functions.  The other functions execute completely without any further user input.  When you typed the various expressions from the previous practice sessions, they executed completely, their result was displayed, then the AutoCAD command prompt reappeared, at which time AutoCAD waits for your next command.  But the get-functions pause for user input before returning any result.

The getint function

The getint function pauses for the user to enter an integer.  If you enter  (getint)  at the AutoCAD command prompt, it pauses until you enter an integer, then returns that integer.  If you enter something other than an integer, getint responds with an appropriate error message.  For example, if you enter the letters "seven,"  or the floating point real 5.5, getint would display the error message "Requires and integer value" and then prompt you to "Try again".   There is one other thing the getint function will accept:  you can simply press 'Enter' without typing an integer (this is known as a "null response").  When you give a null response to getint, it returns  nil.

Recommendation:  You should experiment with getint at the command prompt.  It is well worth your time with this function, as with all functions, to try out various forms and various input in order to "get to know" the functions.  Also, it is very helpful to you if, as you learn the various functions, you learn not only the name and the syntax, but also exactly what the function will and will not accept, and exactly what the function returns (including what the function returns when you give a null response).

Suppose you are writing a program to make some calculations for a chain drive.  At a certain place in the program you will use the getint function to get two integers from the user:  the number of teeth on the small and large sprockets.  You will need to include a prompt in each getint expression, and you will need to save the value that the user enters by surrounding the getint expression with a setq expression.  It would look something like this in your program.

      (setq teeth1 (getint "\nNumber of teeth on small sprocket: "))
      (setq teeth2 (getint "\nNumber of teeth on large sprocket: "))

Although the prompt is optional, without it the user would not know which number to enter first.  And without the setq function the number would be lost.

Also notice the following:

The getreal function

The getreal function pauses for the user to enter a real (floating point decimal) number.  You will use getreal more often than getint, as the sample programs in the previous lessons illustrate.  Nevertheless, both are important.  At times a program need a real, at other times it needs an integer.

The getreal function works just like the getint function with these two exceptions:


The getpoint and getcorner functions

The getpoint function pauses for the user to locate a point.  The point can be located with the mouse, or from the keyboard.  The user can use the usual osnap modes, or the program can enable a particular osnap mode for the user.  Getpoint will take a point argument, or a string argument (a prompt), or both and would usually be surrounded by a setq expression.  Below is an example of getpoint with a string argument as a prompt.

      (setq p1 (getpoint "\nLocation of first point: "))

The getpoint function returns a list of three reals, which are the X, Y, and Z coordinates of the point.  Even if the user enters only the X and Y coordinates at the keyboard (for example "4,2"), getpoint adds the Z coordinate and returns the list (4.0 2.0 0.0).  If the elevation is currently set (with the ELEV command) at something other than zero, and only two points are indicated (when picking by mouse or entering two coordinates at the keyboard), then getpoint adopts the current elevation as the Z coordinate.

When a point argument is added, as shown below, that point is used as the anchor for a rubber-band cursor as the user moves the mouse away from the anchor point.  The point argument can be placed before or after the string argument (most programmers put it before).

      (setq p2 (getpoint p1 "\nLocation of second point: "))

This use of an anchor (or "base") point was used in the mslot sample program in Lesson 1 (line 10).

The getcorner function is very similar to getpoint.  The main difference is that it requires the point argument, and it uses that point as the anchor for a rectangular rubber-band cursor rather than a straight line rubber-band cursor.

To enable a particular osnap mode so that the mode is displayed dynamically as the user moves the cursor around the screen, use a sequence like this:

      (setvar "osmode" 1)           ; 1 enables endpoint
      (setq p7 (getpoint "\nPick point: "))
      (setvar "osmode" 0)           ; 0 disables all running osnap modes

The getstring function

The getstring function pauses for the user to enter a string, up to 132 characters.  It takes a string argument (a prompt), a non-nil argument (to allow spaces), or both.  For example:

      (getstring "\nEnter color: ")

would accept a single word (no spaces) and return that word as a string.  If you tried to enter a space, the space would function as an 'Enter' just like it usually does.  In contrast,

      (getstring 1 "\nEnter description: ")

would accept a phrase including spaces.  The phrase must be entered with the 'Enter' key rather than the space bar.  The use of the number 1 as the non-nil argument is better than using T as you will often see recommended, because T can be accidentally set to nil, but 1 cannot.  As with getpoint, either order will work, but most programmers place the non-nil argument before the prompt.

The initget function with an integer argument

The initget function takes an integer or string argument, or both, which place limitations on the responses allowed for the next get-function.  (String arguments are discussed in a later lesson.)  For example, in the following sequence the initget function with the integer 4 initializes the getreal function so that the user cannot enter a negative number.

      (initget 4)
      (setq wid (getreal "\nEnter width: "))

If the user enters a negative number, a prompt appears indicating that the number must be positive and the user is told to try again.

The integers are bitwise, which means that they are best understood when you think of the binary equivalents of the integers.  Below are the first five integers with their binary equivalents, for illustration.  When the first column of the binary number (counting from the right) is flagged (has a 1), null response is disallowed.  When the second column is flagged, no zeros are allowed.  When the third column is flagged, no negative numbers are allowed.
 

Decimal Binary Meaning
1 0001 no null response
2 0010 no zeros
3 0011 no zeros and no null response
4 0100 no negative numbers
5 0101 no negative numbers and no null response

See initget under "4 - User input" for a complete list of numbers and their meaning.

The above discussion pertains to the use of initget with the getreal function.  Initget works similarly with getint and getdist, but there are some differences when you use initget with the other get-functions.  There is a helpful chart of the various get-functions and how initget values effect them in the AutoCAD R14 Customization Guide, under "initget."

Using initget is very important to your program because it filters out bogus input and thus keeps the program from crashing.  Just one simple scenario will make the point.  Suppose you are getting a number from the user which you plan to use later in the program as a divisor.  You do not want the user to enter a zero, since that would cause the program to crash and return a "divide by zero" error message.  Using initget with an argument of 2 (or any number which in binary flags the second column) will keep the user from entering a zero.

Practice session

Practice entering each of the get-functions described above, without prompts, with prompts, with additional arguments where appropriate, and with initget.  Notice not only what works and what does not work, and not only the data type returned, but also what is returned for a null response.

System variables, getvar & setvar

AutoCAD uses over 200 system variables to store information about the drawing and the drawing environment.  You will find all the system variables listed in Appendix B of the AutoCAD R14 Command Reference.  This appendix also lists the data type of each variable and where it is stored.

Most of these variables are set in the normal course of creating and editing a drawing.  For example, when you hit function key F7 (or click on "GRID" in the status bar) to turn the grid on or off, its new state is recorded in system variable "gridmode."  And when you change the size of the pickbox used to select entities, its new size is recorded in system variable "pickbox."  Many of these system variables are saved with the drawing, so the settings will be the same the next time you edit the drawing.  Others, in order to be consistent from one drawing to the next, are saved in the Windows registry.

AutoLISP has two functions devoted to retrieving and setting system variables: getvar and setvar.  You can retrieve the current value of any system variable with the getvar function.  You can set most system variables to a new value with the setvar function (some system variables are read-only and cannot be changed with setvar).

The syntax of the setvar function is simple.  It takes one argument, the name of the system variable as a string (enclosed in quotation marks).  For example

Notice that the getvar function returns different variable settings in different data types, depending on the particular system variable.  For example, "orthomode" returns an integer, while "limmax" returns a 2D point (a list of two reals).

The syntax of the setvar function is also simple.  The first argument is the name of the system variable as a string.  The second argument is the value to be assigned to that system variable, submitted in the same form that getvar would retrieve it.  Thus if you are setting "orthomode," you would submit an integer, but if you are setting "limmax," you would submit a 2D point.  For example,

Not only must the data type be appropriate, but the value must be in the proper range.  For example, you cannot set the system variable "filletrad" to a negative number.

There are several other data types which are listed in the practice session below.

Another practice session

Experiment with several system variables.  For example:

Experiment with several other system variables that use various data types, such as:
0/1 switch
"gridmode" - grid off or on
"snapmode" - snap off or on
"orthomode" - ortho off or on
"dimaso" - associative dimensioning off or on
Bitwise integer  (1, 2, 4, 8, 16, 32, etc.)
"osmode" - osnap modes, 0 = none, 1 = endpoint, 2 = midpoint, etc.
Integer
"pickbox" - size of pickbox in pixels
"lunits" - linear units, 1 = scientific, 2 = decimal, etc.
"luprec" - linear unit precision
"auprec" - angular unit precision
Percentage
"cursorsize" - size of the cursor as a percentage of viewport width
"pdsize" - size of point display (negative values)
Real
"filletrad" - fillet radius
"textsize" - height of text
"dimscale" - overall dimensioning scale
2D point
"gridunit" - X and Y grid spacing
"limmax" - upper right corner of limits
3D point
"lastpoint" - last point entered (addressed with "@")
"insbase" - drawing insertion base point
String
"clayer" - current layer
"textstyle" - name of current text style
"insname" - block name to appear as default in the INSERT command


Sample program, table

Designers often need to include tables in their drawings.  Tables can be used to list revisions, bolt circle offsets, parametric dimensions, and many other things.  The table program illustrates most of the functions discussed in this lesson and produces a table similar to the one shown here.
 

TABLE HEADING HERE
     
     
     
     
     
     

The user determines these aspects of the table:

We try to keep these sample programs simple so they will illustrate the lesson at hand and avoid too many extras that would cause confusion.  This is especially true for this table program.  A more advanced program would allow for columns of different widths and perhaps rows of different heights, might attach the table to the title block or a certain "corner" in the drawing, might automatically generate line numbers, etc.

There is another aspect of the program which, because it has been kept simple, might cause some confusion.  In section 50 the program takes the simplest approach possible to detecting whether the current text style has a variable or fixed height.  (Several functions used in this section are not explained until later lessons).  In the last line of section 50, the program sets the text height at one-half the row height, which is a reasonable height for the header as well as for any text placed in the table later.  But whether or not that text height is applied to the header depends on the drawing's current text style.  If the current text style has a variable height (if the height for the current style is set to zero), then the program's setting for the text height is used.  But if the current text style has a fixed height, then the program uses that fixed height. A more sophisticated program might create a new text style or give the user the option to alter the fixed height, or even change fonts for the header, etc.

Notice that variable sp serves several different roles in the program.  It holds different starting points for each of the vertical lines (section 30), then for each of the horizontal lines (section 40), then for the middle point of the text (section 50).  Variable len also holds two different values (the length of vertical lines, then the length of horizontal lines).  And variable rowhei is reset (see third line in section 50) if the current text style has a fixed height.  (The table has already been drawn at this point, so this does not change the height of the rows in the table.  It merely allows the text to be spaced a reasonable distance above the table even if the current fixed text height is much smaller or larger that what would be appropriate for text inside the table.)

Notice also that this program captures the current settings of two system variables, blipmode and osmode (section 10).  Then blipmode is turned on before picking the upper left corner of the table (section 20) then turned off before drawing all the lines (section 30).  Osmode (osnap mode) is turned off before the lines are drawn.  This is a precaution, in view of the possibility that, after the table is drawn, it might overlap existing geometry.  (This situation could cause lines to be drawn incorrectly if a running osnap mode were enabled while the program was drawing the lines.)  Both system variables are then reset to their original settings at the end of the program (section 60).

One final note.  In an AutoLISP program, the parenthesis that closes a loop or other long expression usually occupies a whole line by itself.  This is done so that the parenthesis can line up directly below its matching opening parenthesis and is a good format when you are first learning AutoLISP.  But it is also a waste of "vertical space" when you are editing the program.  In order to get more of the code on screen at one time, the closing parenthesis can be moved from its usual location to the end of the previous line.  This is illustrated below at the end of sections 30, 40, and 50.

------ marker ------ beginning of working program ------ try it out ------

;|  TABLE
    Copyright © 1998 Ronald W. Leigh
    Draws a table with any number of
    equal spaced columns and rows
Variables:
colwid  Column width
cols    Number of columns
head    Heading
len     Length of hor. then ver. lines in table
obm     Old blipmode
oom     Old osnap mode
rowhei  Row height
rows    Number of rows
sp      Start pt. for ver. lines, hor. lines, text
ts      Current text style
tshei   Height of current text style
ulc     Upper left corner of table                |;

;10====PROGRAM SETUP

(defun c:table (/ colwid cols head len obm oom
                  rowhei rows sp ts tshei ulc)
(setq obm (getvar "blipmode") oom (getvar "osmode"))
(graphscr)

;20====GET TABLE LOCATION, COLUMNS & ROWS, HEADING

(setvar "blipmode" 1)
(setvar "osmode" 0)
(initget 1)
(setq ulc (getpoint "\nUpper left corner of table: "))
(initget 7)
(setq cols (getint "\nNumber of columns: "))
(initget 7)
(setq colwid (getreal "\nWidth of each column: "))
(initget 7)
(setq rows (getint "\nNumber of rows: "))
(initget 7)
(setq rowhei (getreal "\nHeight of each row: "))
(setq head (getstring 1 "\nHeading: "))

;30====DRAW VERTICAL LINES

(setvar "blipmode" 0)
(setq sp ulc len (* rows rowhei))
(repeat (1+ cols)
  (command ".line" sp (polar sp (* 1.5 pi) len) "")
  (setq sp (polar sp 0 colwid)))

;40====DRAW HORIZONTAL LINES

(setq sp ulc len (* cols colwid))
(repeat (1+ rows)
  (command ".line" sp (polar sp 0 len) "")
  (setq sp (polar sp (* 1.5 pi) rowhei)))

;50====DRAW TEXT

(setq ts (getvar "textstyle"))
(setq tshei (cdr (assoc 40 (tblsearch "style" ts))))
(if (> tshei 0) (setq rowhei (* 2 tshei)))
(setq sp (polar ulc 0 (/ len 2)))
(setq sp (polar sp (* 0.5 pi) (/ rowhei 2)))
(if (> tshei 0)
  (command ".text" "M" sp 0 head)
  (command ".text" "M" sp (/ rowhei 2) 0 head))

;60====RESET

(setvar "blipmode" obm)
(setvar "osmode" oom)
(princ)
)

-------- marker -------- end of working program -------- try it out --------
 

HOME


Copyright © 1988, 1998 Ronald W. Leigh