Auto-Illustrator
Support FAQs

Technical Information for xeoObject Developers

See also the xeoObject Language Reference

Introduction

xeoObjects are small external files that describe the functionality of a plug-in or process that cannot be defined within the core Auto-Illustrator program. For this reason, xeoObjects are used for plug-ins, and also elsewhere in the application. The document is written with the assumption that you are writing a plug-in for Auto-Illustrator in xeoObject format. The content here may not be suitable for other xeoObject applications, whether for Auto-Illustrator or not.

What is a xeoObject?

A standard text file with a .xeo extention, written in a uniform language that is a perculiar hybrid of lingo and ASM, with C-style variable declarations. The language itself is very limited, with only a few operands, but this in conjunction with the flexible variable and handler style syntax, is enough to write reasonably complex plug-ins.

A xeoObject also contains instructions that tell the xeoObject runtime environment how to layout a dialog box. You can make simple interactive plug-ins in the manner. The contents of a dialog box are also limited (for example, you can only have up to 16 buttons in your dialog), but should prove sufficient.

Language Syntax

Handlers

You divide your code blocks of instructions (known as a handler), and give each handler a name. Certain handlers are called by the xeoObject runtime environment, for example, when your plug-in needs to be executed, or when a user has interacted with a control on your dialog. Other handlers you can call yourself from your own code, meaning you can split the functionality of your plug-in up into easy to maintain chunks.

The syntax to define a handler is the same as in Lingo or Applescript:

   on handlername
     code goes here
   end
If you want to call this handler from elsewhere in your xeoObject code, you can do so using the do keyword:
   do handlername
Certain handler names are fixed, and you should make sure you have defined handlers for these names:

on open
Called when your plug-in initialises when Auto-Illustrator first starts up. In this handler, you should use some code to tell Auto-Illustrator exactly what the plug-in name is:

   on open
     senddata Auto-Illustrator::Plugin::Name Joe's First Plug-In
   end
on launch
Called when your plug-in is launched by a user. A user has selected your plug-in from the menu, so you should now start the main functionality of your plugin (ie, producing new shapes, setting up the dialog box if needed, etc).

Variables

Variables are a bit quirky in xeoObjects, but they are flexible. To start with, you use C-style variable definitions to define your variables as one of three different data types:
   int    myIntegerVariable
   double myDoubleVariable
   string myStringVariable
Note that you can put these definitions anywhere in your xeoObject file - there are no such things as local or global variables - everything has the same scope, so you need to bear that in mind when creating your various handlers.

When you refer to your variables in your code, there are two ways of doing so. If you are referring to the variable, then you just provide it's name. You do this when you want to set variables, or do maths such as add and mul (multiply). For example:

   set myIntegerVariable 42
   add myIntegerVariable 10
   set myDoubleVariable  5.5
   mul myDoubleVariable  2
   set myStringVariable  Mary Had a Little Lamb
However, if in your code you wish to refer to the actual value of that variable, then you enclose the variable name in square braces:
   add myIntegerVariable [myDoubleVariable]
This is a very important distinction. In the example above, the value of myDoubleVariable (which, I believe, we set to 5.5 then multiplied by 2, so is 11) is added to myIntegerVariable, which was 52. So myIntegerVariable is now 63.

You dont need to typecast variables. If you try adding a number onto a string, the number variable is treated as a string. (Psst, you can add a string onto a number, so long as the string contains a number, but thats rarely necessary).

   add myStringVariable %20it cost%20
   add myStringVariable [myIntegerVariable]
   add myStringVariable %20dollars
The value of myStringVariable is now "Mary Had a Little Lamb it cost 63 dollars". Note that %20 was used to indicate a space. You need to do that sometimes because you dont use quotation marks with string constants (unlike other languages) and the xeoObject runtime environment removes surplus whitespace from your script before executing. Also, you cannot mix string constants with variable references, hence the need for three separate add statements in the above example.

Conditional statements

Naturally, there will be times when you only want to execute some code when some comparison of variables you are using matches your requirements. The if statement only executes the next line of code if the condition set out evaluates to true:
   if [myIntegerVariable] > 5
     set myIntegerVariable 0
Note, once again, the difference between the first and second reference to the variable called myIntegerVariable. The first is in square braces because we are comparing the value of that variable with the number 5. It would be very tempting to not include the square braces, but the xeoObject runtime environment wouldn't evaluate that if statement correctly because it wouldn't be comparing the value of the variable myIntegerVariable. The situation is comparable to that of using pointers in C or Pascal: you have to remember to dereference the variable if you actually want it's value. The difference here is that an un-dereferenced variable reference equals zero, not the actual pointer address as in other languages. But you really dont need to know that.

There are five different comparison evaluations:

    < for numeric less-than (ie, 5 < 6 is true)
   == for numeric equality (ie, 4 == 4 is true)
    > for numeric greater-than (ie, 7 > 5 is true)
   eq for string equality (ie, yes eq no is false)
   ne for string inequality (ie, sun ne moon is true)

If you want to execute more than one line of code, you need to split that code into a separate handler and call it like so:

   on launch
     if [myIntegerVariable] == 42
       do theMeaningOfLife
   end

   on theMeaningOfLife
     any amount of code goes here
     any amount of code goes here
     any amount of code goes here
   end
Another important thing to remember is that you can't nest if statements:
   on launch
     if [myIntegerVariable] == 42
       if [myDoubleVariable] > 10
         set myStringVariable Easy!
   end
This does not work! Why? Because if the first conditional comparison evaluates to false (ie, if myIntegerVariable does not equal 42) then the runtime environment skips the next line and stops at the set line, which is not actually what you intended! (indentation means nothing to the interpreter). Instead, you have to split nested if statements into separate handlers:
   on launch
     if [myIntegerVariable] == 4
        do checkDoubleValue
   end
   on checkDoubleValue
     if [myDoubleVariable] > 10
       set myStringVariable Easy!
   end
It's clumsy, but in this respect conditional statements in xeoObjects are more like ASM, because you have to think about the 'location' of the 'instruction pointer' (ie, the linenumber that is currently executing).

Loops

Luckily, loops in xeoObjects are much easier. They're just like BASIC FOR..NEXT loops, with a few minor changes to the syntax:
   for variableName firstValue lastValue stepIncrement
      whatever code goes here
   next
This example counts from 1 to 10, adding that number to the end of a string, and each time divides another variable in half.
   for myIntegerVariable 1 10 1
     add myStringVariable [myIntegerVariable]
     mul myDoubleVariable 0.5
   next
PS. Don't put a conditional if statement right before a next statement. That's really bad. I'm sure you can figure out why.

Also, watch out you dont get your lastValue or stepIncrement figures wrong - if you're counting from 1 to 10 but your stepIncrement is -1, you'll count 1, 0, -1, -2, -3 (etc) and you'll never ever reach 10! This will lock up your computer. Don't blame us.