In this post, we look at the most powerful method available to “non-programmers” for customizing BricsCAD — the LISP programming language. In this post, learn the first steps needed to write a LISP routine of your own.

For a full overview of LISP commands for BricsCAD, you can view the official, BricsCAD LISP Developer Guide.


The following topics are covered in this post:


WHY WRITE A PROGRAM?

If you are like many CAD users, you are busy creating drawings and you have no time to learn how to write software programs. No doubt, you may be wondering, “Why bother learning a programming language?” In some ways, it’s like being back again in school. Sitting in the classroom sometimes seems like a waste of time.

But the things you learn now make life easier later. Learning some LISP programming now means you’ll feel really good whipping off a few lines of code to let LISP perform tedious tasks for you. The nice thing about LISP is that you can program it on the fly. And you can use it for really simple but tedious tasks.

Here’s the example we’ll use for this tutorial:

The Id Command

BricsCAD has the Id command. When you pick a point on the screen, Id reports the 3D x,y,z- coordinates of the point. Problem is, Id reports the value in the command prompt area, like this:

: id
Select a point to identify coordinates: (Pick a point.)
X = 8.9227 Y = 6.5907 Z = 0.0000

Wouldn’t it be great if you could change Id so that it places the coordinates in the drawing, next to the pick point? That would let you label x,y-coordinates and z-elevations over a site plan. With LISP, you can.

THE PLAN OF ATTACK

Before you write any LISP code, you need to figure out how you’re going to get those x,y,z-coordinates off the command prompt area and into the drawing. Recognize that there are two parts to solving the problem:

Part 1. Obtain the coordinates from the drawing, probably by picking a point.
Part 2. Place the coordinates as text in the drawing.

Obtaining the Coordinates

LISP provides several ways to get the coordinates of a picked point. Browsing through the LISP Programming Language Reference, you learn you could:

  • Use the Id command with the command function, as in (command “ID”).
  • Use the LastPoint system variable with the getvar function, as in (getvar “lastpoint”).
  • Use the getpoint function, as in (getpoint “Pick a point: “)

It would be a useful lesson to use each of the three and then see what happens. By experimenting, you make mistakes and then learn from the mistakes.

  1. Start BricsCAD, load a drawing, and switch to the Prompt History window with F2. At the ‘:’ prompt, enter:

    : (commandID“)

    Here you are executing a BricsCAD command (Id) from within a LISP routine. The command function lets
    you use any BricsCAD command in LISP. The BricsCAD command is in quotation marks “ID” because the command is a string (programmer-talk for “text”). Just as before, BricsCAD prompts you for the point.

  2. In response to the LISP routine’s prompt, pick a point:

    Select a point to identify coordinates: (Pick a point.)
    X = 8.9227 Y = 6.5907 Z = 0.0000

  3. Unknown to you, BricsCAD always stores the x,y,z-coordinates of the last-picked point in a system variable called LastPoint. So, you should copy the coordinates from LastPoint to a variable of your own making. You need to do this because the coordinates in LastPoint are overwritten with the next use of a command that makes use of a picked point.
    Recall from in this chapter that the setq function stores values in variables. Make use of it now. At the ‘:’ prompt, enter:

    : (setq xyz (getvar LastPoint“))
    (8.9227 6.5907 0.0000)

    • Xyz is the name of the variable in which you store the x,y,z-coordinate.
    • Getvar is the name of the LISP function that retrieves the value stored in a system variable.
    • And “LastPoint” is the name of the system variable; it is surrounded by quotation marks because it is a system variable name (a string).

    After entering the LISP function, BricsCAD returns the value it stored in variable xyz, such as (8.9227 6.5907
    0.0000) — your result will be different. Notice how the coordinates are surrounded by parenthesis. This is
    called a list, for which LISP is famous (indeed, LISP is short for “list processing”). Spaces separate the numbers, which are the x, y, and z-coordinates, respectively:

    x 8.9227
    y 6.5907
    z 0.0000

    BricsCAD always stores the values in the order of x, y, and z. You will never find the z- coordinate first or the x-coordinate last.

So, we’ve now solved the first problem in one manner. We obtained the coordinates from the drawing and then stored them in a variable. We did mention a third LISP function we could use, getpoint. Programmers prefer getpoint because it is more efficient than the Id-LastPoint combo we used above.

Type the following to see that it works exactly the same, the difference being that we provide the prompt text (“Point: ”):

: (setq xyz (getpoint “Point: “))
Point: (Pick a point.)
(8.9227 6.5907 0.0000)

As before, we use the setq function to store the value of the coordinates in variable xyz. The getpoint function waits for you to pick a point on the screen. The “Point: “ is called a prompt, which tells the user what the program is expecting the user to do. We could just as easily have written anything, like:

: (setq xyz (getpoint “Press the mouse button: “))
Press the mouse button: (Pick a point.)
(8.9227 6.5907 0.0000)

Or, we could have no prompt at all, as follows:

: (setq xyz (getpoint))
(Pick a point.)
(8.9227 6.5907 0.0000)

That’s right. No prompt. Just a silent BricsCAD waiting patiently for the right thing to happen … and the user puzzled at why nothing is happening. A lack of communication, you might say. That’s why prompts are important.

We’ve now seen a couple of approaches that solve the same problem in different ways. With the x,y,z-coordinates safely stored in a variable, let’s tackle the second problem.

PLACING THE TEXT

To place text in the drawing, we can use only the command function in conjunction with the Text command. I suppose the MText command might work, but for one line of text, the Text command is excellent. The Text command is, however, trickier than the Id command. It has a minimum of four prompts that your LISP routine must answer:

: text
Text: Style/Align/Fit/Center/Middle/Right/Justify/<Start point>:
Height of text <2>:
Rotation angle of text <0>:
Text:

Start point: a pair of numbers, specifically an x,y-coordinate.
Height of text: a number to make the text legible.
Rotation angle of text: a number, probably 0 degrees.
Text: the string, in our case the x,y,z-coordinates.

Let’s construct a LISP function for placing the x,y,z-coordinates as text:

(command “text” xyz 200 0 xyz)

(command is the command function.
“text” is the BricsCAD Text command being executed.
xyz variable stores the starting point for the text.
200 is the height of the text. Change this number to something convenient for your drawings.
0 is the rotation angle of the text.
xyz means you’re lucky: the Text command accepts numbers as text.
) and remember: one closing parenthesis for every opening parenthesis.

Try this out at the ‘:’ prompt:

: (command “text” xyz 200 0 xyz)
Text: Style/Align/Fit/Center/Middle/Right/Justify/:
Height of text: 200
Rotation angle of text: 0
Text: 2958.348773815669,5740.821183398367
:

BricsCAD runs through the Text command, inserting the responses for its prompts, then placing the coordinates as text. We’ve solved the second part of the problem.

PUTTING IT TOGETHER

Let’s put together the two solutions to your problem:

(setq xyz (getpoint “Pick point: “))
(command “text” xyz 200 0 xyz)

There you have it: a full-fledged LISP program. Well, not quite. It’s a pain to retype those two lines each time you want to label a point. In the next section, you find out how to save the code as a .lsp file on disk. You’ll also dress up the code.

Adding to the Simple LISP Program

What you have now is the algorithm — the core of every computer program that performs the actual work. What is lacking is most of a user interface — the part that makes it easier for any user to employ the program.

All you have for a user interface is part of the first line that prompts, “Select point to identify coordinates: ”. There’s a lot of user interface problems with this little program. How many can you think of? Here’s a list of problems I came up with:

  • It’s a pain to retype those two lines each time you want to label a point — you need to give the program a name …
  • … and you need to save it on disk so that you don’t need to retype the code with each new BricsCAD session…
  • … and, if you use this LISP program a lot, then you should have a way of having it load automatically.
  • The x,y,z-coordinates are printed to eight decimal places; for most users, that’s w-a-y too many.
  • You may want to control the layer that the text is placed on.
  • You may want a specific text style.
  • Certainly, you would like some control over the size and orientation of the text.
  • Here’s an orthogonal idea: store the x,y,z-coordinates to a file on disk — just in case you ever want to reuse the data.

CONQUERING FEATURE BLOAT

“Okay,” you may be thinking, “I can agree that these are mostly desirable improvements. Go right ahead, Mr. Grabowski: Show me how to add them in.”

But, wait a minute! When you’re not familiar with LISP, you may not realize how a user interface adds a tremendous amount of code, which mean more bugs and more debugging. (If you are familiar with programming, then you know how quickly a simple program fills up with feature-bloat.) While all those added features sound desirable, they may make the program less desirable. Can you image how irritated you’d get if you had to answer the questions about decimal places, text font, text size, text orientation, layer name, filename — each time you wanted to label a single point?

Take a second look at the wish list above. Check off features important to you, and then cross out those you could live without.

Wishlist Item #1: Naming the Program

To give the program a name, surround the code with the defun function, and give it a name, as follows:

(defun c:label ( / xyz)
(setq xyz (getpoint “Pick point: “))
(command “text” xyz 200 0 xyz)
)

Let’s take a look at what’s been added, piece by piece:

Defining the Function – defun

(defun defines the name of the function. In LISP, the terms function, program, and routine are used interchangeably (defun is short for “define function.”)

Naming the Function – C:

c:label is the name of the function. I decided to call this program “Label”; you can call it anything you like, so long as the name does not conflict with that of any built-in LISP function or other userdefined function. The c: prefix make this LISP routine appear like an BricsCAD command.

To run the Label program, all you need do is type “label” at the ‘:’ prompt, like this:

: label
Select a point to identify coordinates: (Pick a point.)

When the c: prefix is missing, however, then you have to run the program like a LISP function, complete with the parentheses, as follows:

: (label)
Select a point to identify coordinates: (Pick a point.)

Local and Global Variables – /

( / xyz ) declares the names of input and local variables; the slash separates the two:

Input variables — feed data to LISP routines; the names of input variables appear before the slash.
Local variables — used only within programs; the names of local variables appear after the slash

In this program, xyz is the name of the variable that is used strictly within the program. If variables are not declared local, they become global. The value of a global variable can be accessed by any LISP function loaded into BricsCAD.

The benefit to declaring variables as local is that BricsCAD automatically frees up the memory used by the variable when the LISP program ends; the drawback is that the value is lost, making debugging harder. For this reason, otherwise-local variables are kept global until the program is debugged.

And the ) closing parenthesis balances the opening parenthesis at the beginning of the program.

Wishlist Item #2: Saving the Program

By saving the program to a file on disk, you avoid retyping the code with each new BricsCAD session. You do this, as follows:

  1. Start a text editor (the Notepad supplied with Windows or Text Edit with Linux and Mac are good). Type the code shown:

    (defun c:label ( / xyz)

    (setq xyz (getpoint “Pick point: “))
    (command “text” xyz 200 0 xyz)

    )

    I indented the code in the middle to make it stand out from the defun line and the closing parenthesis. This is standard among programmers; the indents make it easier to read code. You can use a pair of spaces or the tab key because LISP doesn’t care.

  2. Save the file with the name label.lsp in BricsCAD’s folder.

Wishlist Item #3: Automatically Loading the Program

To load the program into BricsCAD, type the following:

: (load “label”)

If BricsCAD cannot find the LISP program, then you have to specify the path. Assuming you saved label.lsp in the \cad\support folder, you would enter: : (load “\\cad\\support\\label”)

Now try using the point labeling routine, as follows:

: label
Select a point to identify coordinates: (Pick a point.)

TIP BricsCAD provides a way to automatically load LISP programs. When BricsCAD starts up, it looks for a file called on_doc_load.lsp.lsp. BricsCAD automatically loads the names of LISP programs listed in the file.
Adding label.lsp to on_doc_load.lsp is easy. Open the on_doc_load.lsp file with a text editor (if the file does not exist, then start a new file called on_doc_load.lsp and store it in the \BricsCAD folder). Add the name of the program:(load “label.lsp”)Save the on_doc_load.lsp file. Start BricsCAD and it should load label automatically.——–

Adding label.lsp to on_doc_load.lsp is easy. Open the on_doc_load.lsp file with a text editor (if the file does not exist, then start a new file called acad.lsp and store it in the \BricsCAD folder). Add the name of the program:

(load “label.lsp”)

Save the on_doc_load.lsp file. Start BricsCAD and it should load label automatically.

Wishlist #4: Using Car and Cdr

The x,y,z-coordinates are printed to eight decimal places — that’s too many. There are two solutions.

One is to ask the user the number of decimal places, as shown by the following code fragment:

: (setq uprec (getint “Label precision: “))
Label precision: 1
1

Or steal the value stored in system variable LUPrec — the precision specified by the user through the Units command — under the (not necessarily true) assumption that the user wants consistent units. The code to do this is as follows:

(setq uprec (getvar “LUPREC”))

That was the easy part. The tough part is applying the precision to the x,y,z-coordinates, which takes three steps: (1) pick apart the coordinate triplet; (2) apply the precision factor; and (3) join together the coordinates. Here’s how:

  1. Open label.lsp in NotePad or other text editor. Remove / xyz from the code. This makes the variable “global,” so that you can check its value at BricsCAD’s ‘:’ prompt. The code should look like this:

    (defun c:label ( )

    (setq xyz (getpoint “Pick point: “))
    (command “text” xyz 200 0 xyz)

    )

  2. Save, and then load label.lsp into BricsCAD.
  3. Run label.lsp, picking any point on the screen. If you don’t see the coordinates printed on the screen, zoom to extents.
  4. At the ‘:’ prompt, enter the following:

    : !xyz
    (6.10049 8.14595 10.0)

    The exclamation mark forces BricsCAD to print the value of variable xyz, which holds the x,y,z-coordinates. Your results will differ, depending on where you picked.

  5. LISP has several functions for picking apart a list. Here you use the car and cdr functions, and combinations thereof. The car function extracts the first item (the x-coordinate) from a list. Try it now:

    : (car xyz)
    6.10049

  6. The cdr function is the complement to car. It removes the first item from the list and then gives you what’s leftover:

    : (cdr xyz)
    (8.14595 10.0)

  7. In addition to car and cdr, LISP allows me to combine the “a” and “d” in several ways to extract other items in the list. To extract the y-coordinate, use cadr, as follows:

    : (cadr xyz)
    8.14595

  8. And to extract the z-coordinate, use caddr, as follows:

    : (caddr xyz)
    8.14595

  9. I now have a way to extract the x-coordinate, the y-coordinate, and the z-coordinate from variable xyz. I’ll store them in their own variables, as follows:

    : (setq ptx (car xyz)
    Missing: 1) > pty (cadr xyz)
    Missing: 1) > ptz (caddr xyz)
    Missing: 1) > )

    You use variable PtX to store the x-coordinate, PtY for the y-coordinate, and so on. In addition, a form of LISP shorthand was used in the code above that allows you apply the setq function to several variables. Recall the reason for BricsCAD’s ‘Missing: 1) >’ prompt: it reminds you that a closing parenthesis is missing.

  10. Now that the three coordinates are separated, you can finally reduce the number of decimal places. There are a couple of ways to do this. Use the rtos function, because it does two things at once: (1) changes the number of decimal places to any number between 0 and 8; and (2) converts the real number into a string.
    Why a string? You’ll see later. For now, here is the rtos function at work:

    : (rtos ptx 2 uprec)
    “6.1”

    The rtos function uses three parameters: ptx, 2, and uprec.
    PtX Name of the variable holding the real number.
    2 Type of conversion, decimal in this case. The number 2 is based on system variable LUnits, which defines five modes of units:

    1. Scientific
    2. Decimal
    3. Engineering
    4. Architectural
    5. Fractional

    UPrec Name of the variable holding the precision (the code for that is at the beginning of this section). This varies, depending on the type of units. For example, a value of 2 for decimal means two decimal places; a 2 for architectural means quarter-inch.
    Assuming, then, that the precision in UPrec is 1, the rtos function in the code fragment above reduces 6.10049 to 6.1.

  11. Truncate and preserve the values of x, y, and z three times, as follows:

    : (setq ptx (rtos ptx 2 uprec)
    1> pty (rtos pty 2 uprec)
    1> ptz (rtos ptz 2 uprec)
    1> )

    Notice that you can set a variable equal to itself: PtX holds the new value of the x-coordinate after rtos gets finished processing the earlier value stored in PtX. Reusing a variable name like this helps conserve memory.

  12. With the coordinates truncated, you now have to string (pardon the pun) them together with the strcat function, short for string concatenation. Try it now:

    : (strcat ptx pty ptz)
    “6.18.110.0”

    That’s more like it!

  13. Back to the text editor. Add in the code you developed here, shown in boldface, and with LISP functions in purple:

    (defun c:label ( / xyz xyz1 uprec ptx pty ptz)

    (setq uprec (getint “Label precision: “))
    (setq xyz (getpoint “Pick point: “))
    (setq ptx (car xyz)
    pty (cadr xyz)
    ptz (caddr xyz)
    )
    (setq ptx (rtos ptx 2 uprec)
    pty (rtos pty 2 uprec)
    ptz (rtos ptz 2 uprec)
    )
    (setq xyz1 (strcat ptx “, ” pty “, ” ptz))
    (command “text” xyz 200 0 xyz1)

    (

  14. Notice that all variables are local. Notice, too, the change to variable xyz in the last couple of lines: you don’t want the text placed at the rounded-off coordinates, so use xyz1 as the variable holding the text string.
  15. Finally, you should add comments to your code to remind you what it does when you look at the code several months from now. Semicolons indicate the start of comments:

    ; Label.Lsp labels a picked point with its x,y,z-coordinates.
    ; by Ralph Grabowski, 25 February, 1996.
    (defun c:label ( / xyz xyz1 uprec ptx pty ptz)

    ; Ask user for the number of decimal places:
    (setq uprec (getint “Label precision: “))
    ; Ask the user to pick a point in the drawing:
    (setq xyz (getpoint “Pick point: “))
    ; Separate 3D point into individual x,y,z-values:
    (setq ptx (car xyz)
    pty (cadr xyz)
    ptz (caddr xyz)
    )
    ; Truncate values:
    (setq ptx (rtos ptx 2 uprec)
    pty (rtos pty 2 uprec)
    ptz (rtos ptz 2 uprec)
    )
    ; Recombine individual values into a 3D point:
    (setq xyz1 (strcat ptx “, ” pty “, ” ptz))
    ; Place text:
    (command “text” xyz 200 0 xyz1)

    )

  16. Save the file as label.lsp, then load the LISP routine into BricsCAD with:

    : (loadlabel“)
    “C:LABEL”

  17. Run the routine, and respond to the prompts: ”

    : label
    Label precision: 1
    Pick point: (Pick a point.)
    text Justify…/<Start point>:
    Height of text <200.0000>: 200
    Rotation angle of text <0>: 0
    Text: 5012.3, 773.2, 0.0
    :

Saving Data to Files

In the previous tutorial, we began to worry about user interface enhancements. What started out as two lines of code has now bulged out into 23. In this tutorial, we learn how to fight feature bloat (more later) and add the ability to save data to a file.

A reader wrote me with this wish list item: “The LISP file comes in very handy with some of the programs I use, but I would like to be able to save the data collected on the x,y,z-coordinates in a text file.”

Saving the data to file is easily done with the open, write-line, and close functions. Let’s take a look at how to do this. Dealing with files in LISP is simpler than for most programming languages because LISP has very weak file access functions. All it can do is read and write ASCII files in sequential order; LISP cannot deal with binary files nor can it access data in random order.

THE THREE STEPS

There are three steps in writing data to a file:

Step 1. Open the file.
Step 2. Write the data to the file.
Step 3. Close the file.

Step 1: Open the File

LISP has the open function for opening files. The function lets you open files for one of three purposes: (1) read data from the file; (2) write data to the file; or (3) append data to the file. You must choose one of these at a time; LISP cannot do all three at once.

In all cases, LISP takes care of creating the file if it does not already exist. Reading data is easy enough to understand, but what’s the difference between “writing” and “appending” data?

  • When I ask BricsCAD to open a file to write, all existing data in that file is erased, and then the new data is added.
  • When I ask BricsCAD to open a file to append, the new data is added to the end of the existing data.

For our purpose, we want to keep adding data to the file, so choose append mode. The LISP code looks like this:

(setq FIL (open “xyzdata.txt” “a“))

Here you are setting something (through setq) equal to a variable named FIL. What is it? In pretty much all programming languages, we don’t deal with the filename directly, but instead, deal with a file descriptor. This is a name (some sequence of letters and numbers) to which the operating system assigns the filename. Now that you have the file descriptor stored in variable FIL, you work with FIL, not the filename, which I have decided to call xyzdata.txt.

The final “a” tells LISP you want to open xyzdata.txt for appending data. The options for the open function are:

“a” Appends data to end of file.

“w” Writes data to file (erase existing data).

“r” Reads data from file.

Step 2: Write Data to the File

To write data to files, use the write-line function. This function writes one line of data at a time.

(Another function, the write function, writes single characters to files.) The code looks like this:

(write-line xyz1 fil)

You cannot, however, just write raw data to the file because it would look like three decimal points and a lot of digits, like this:

8.15483.27520.0000

Most software is able to read data with commas separating numbers, like this:

8.1548, 3.2752, 0.0000

That includes spreadsheets, database programs, and even some word processing software. I tell these programs that when they read the data, they should consider the comma to be a separator and not a comma. In that way, the spreadsheet program places each number in its own cell. With each number in its own cell, I can manipulate the data. For this reason, you need code that formats the data.

Fortunately, you’ve done that already. Last tutorial, you used the strcat function along with the cdr, cadr, and caddr functions to separate the x, y, and z components of the coordinate triplet. So you can reuse the code, which looks like this:

(setq ptx (car xyz)
pty (cadr xyz)
ptz (caddr xyz)
)
(setq xyz1 (strcat ptx “, ” pty “, ” ptz))

The strcat function places the commas between the coordinate values.

Step 3: Close the File

Finally, for good housekeeping purposes, close the file. BricsCAD will automatically close the file for you if you forget, but a good programmers clean up after themselves. Closing the file is as simple as:

(close fil)

PUTTING IT TOGETHER

Add the code for opening, formatting, writing, and closing to the lable.lsp program:

(defun c:label ( / xyz xyz1 uprec ptx pty ptz)

(setq uprec (getint “Label precision: “))
(setq xyz (getpoint “Pick point: “))
(setq ptx (car xyz)   pty (cadr xyz)
ptz (caddr xyz)  )
; Format the x,y,z coordinates:
(setq ptx (rtos ptx 2 uprec)
pty (rtos pty 2 uprec)
ptz (rtos ptz 2 uprec))
; Add commas between the three coordinates:
(setq xyz1 (strcat ptx “, “ pty “, “ ptz))
; Write coordinates to the drawing:
(command “text” xyz 200 0 xyz1)
; Open the data file for appending:
(setq fil (open “xyzdata.txt” “a”))
; Write the line of data to the file:
(write-line xyz1 fil)
; Close the file:
(close fil)

)

Using a text editor, such as Notepad, make the additions to your copy of lable.lsp. Load it into BricsCAD with the load function:

: (load “label”)

And run the program by entering Label at the ‘:’ prompt:

: label
Label precision: 4
Pick point: (Pick a point.)

As you pick points on the screen, the routine labels the picked points, but also writes the 3D point data to file. After a while, this is what the data file looks something like this:

8.1548, 3.2752, 0.0000
7.0856, 4.4883, 0.0000
6.4295, 5.6528, 0.0000
5.5303, 6.7688, 0.0000
5.4331, 8.3215, 0.0000

Wishlist #5: Layers

Let’s take a moment to revisit the wishlist. One wishlist item is to control the layer on which the text is placed. There are two ways to approach this wishlist item:

  • The no-code method is to set the layer before starting the LISP function.
  • The LISP-code version is to ask the user for the name of the layer, then use the setvar function to set system variable CLayer (much easier than using the Layer command), as follows:

    (setq lname (getstring “Label layer: “))
    (setvar “CLAYER” lname)

    Add those two line before the line with the “Pick point” prompt.

Wishlist #6: Text Style

To specify the text style, there are the same two methods. The no-code method is to simply set the text style before starting the routine. Otherwise, you can write LISP code similar to set the style with the setvar command, as follows:

(setq tsname (getstring “Label text style: “))
(setvar “TEXTSTYLE” tsname)

Once again, add those two line before the line with the “Pick point” prompt.

By now, you may be noticing that your program is starting to look big. This is called “feature bloat.” More features, especially in the area of the user interface, makes software grow far beyond the size of its basic algorithm.

What’s next?

To conclude LISP section chapter, I’ll give you 7 tips to help you out when you write your LISP functions.


Download BricsCAD free for 30-days

Start Using BricsCAD Today

Permanent or subscription licenses that work in all languages, in all regions.


  1. Introduction
  2. 55 Tips for BricsCAD Users
  3. Settings
  4. Changing the Environment
  5. Custom User Interface
  6. Introduction to the Customize Dialog Box
  7. Customize the Menu Bar & Context Menus
  8. Toolbars and Button Icons
  9. Writing Macros and Diesel Code
  10. Ribbon Tabs and Panels
  11. Keystroke Shortcuts, Aliases & Shell Commands
  12. Mouse, Double-click & Tablet Buttons
  13. Absolutely Everything You Need to Know About The Quad
  14. Rollover Properties
  15. Workspaces and the User Interface
  16. Designing Tool & Structure Panels
  17. Creating Simple & Complex Linetypes
  18. Patterning Hatches
  19. Decoding Shapes & Fonts
  20. Coding with Field Text
  21. Writing Scripts
  22. Programming with LISP (Introduction)
  23. LISP Functions
  24. Writing a Simple LISP Program