This chapter describes the programming language of MUIbase, including all available functions. This chapter, however, is not intended as a general guide about programming. You should be familiar with the basics about programming and should already have written some small programs.
To enter a program for a project, open the program editor by selecting menu item `Program - Edit'. This will open the `Edit program' window containing:
The program editor is an asynchronous requester. You can leave the window open and still work with the rest of the application. You can close the editor at any time by clicking into its window close button. If you have done changes since the last successful compilation then a safety requester pops-up asking for confirmation to close the window.
You can also compile a project's program without opening the program editor by choosing menu item `Program - Compile'. This can be useful if you e.g. do changes to an external include file and want to incorporate these changes in the project's program.
MUIbase programs are pre-processed similar to a C compiler preprocessing a C source file. This section describes how to use the preprocessing directives.
All directives start with a hash symbol # which should be the first character on a line. Space or tab characters can appear after the initial #.
#define
name string
Defines a new symbol with the given name and contents. The symbol string can be any text including spaces and ends at the end of line. If string does not fit on one line you can use further lines by using a backslash character \ at the end of each line (except for the last one). If the symbol name does occur in the remaining source code then it will be replaced by the contents of string.
Example: `(PRINTF "X is %i" X)' prints `X is 1' (Occurances of name in strings are not altered.)
The replacement of defined symbols is done syntactically which means that you can replace symbols with any text, e.g. you can define your own syntax like in the following example:
#define BEGIN ( #define END ) BEGIN defun test () ... END
The replacement string of a definition may contain another symbol that
has been defined with the #define
directive to allow nested definitions.
However there is an upper limit of 16 nested definitions.
See also #undef, #ifdef, #ifndef.
#undef
name
Removes the definition of symbol name. If name has not been defined, nothing happens.
See also #define, #ifdef, #ifndef.
#include
filename
Reads in the contents of filename (a string surrounded with double quotes) at this location. MUIbase searches in the current directory and in the directory specified in the preferences (see section Program include directory) for loading the file. The file contents are processed by the compiler as if they were part of the current source code.
An external file may include one or more other external files. However
there is an limit of 16 nested #include
directives. To protect files from
including them more than once, you can use conditional compilation.
Be careful when moving source code to external files! Debugging and tracking down errors is much harder for external files. Move only well tested and project independent code to external files.
#if
const-expr
If the given constant expression results to non-NIL then the text up to
the matching #else
, #elif
, or #endif
is used for compilation,
otherwise (the expression results to NIL) the text up to the matching #else
,
#elif
, or #endif
is discarded for compilation.
Currently you can only use TRUE and NIL as constant expressions.
See also #ifdef, #ifndef, #elif, #else, #endif.
#ifdef
name
If the given symbol has been defined with a #define
directive then the
text up to the matching #else
, #elif
, or #endif
is used for compilation,
otherwise it is discarded.
See also #if, #ifndef, #elif, #else, #endif.
#ifndef
name
If the given symbol has not been defined with a #define
directive then the
text up to the matching #else
, #elif
, or #endif
is used for compilation,
otherwise it is discarded.
See also #if, #ifdef, #elif, #else, #endif.
#elif
const-expr
Any number of #elif
directives may appear between an #if
,
#ifdef
, or #ifndef
directive and a matching #else
or
#endif
directive. The lines following the #elif
directive
are used for compilation only if all of the following
conditions hold:
If the above conditions hold then subsequent #elif
and #else
directives are
ignored up to the matching #endif
.
See also #if, #ifdef, #ifndef, #else, #endif.
#else
This inverts the sense of the conditional directive otherwise in effect.
If the preceding conditional would indicate that lines are to be included,
then lines between the #else
and the matching #endif
are ignored. If the
preceding conditional indicates that lines would be ignored, subsequent
lines are included for compilation.
Conditional directives and corresponding
#else
directives can be nested. However there is a maximum nesting count
limit of 16 nested conditional directives
See also #if, #ifdef, #ifndef, #elif, #endif.
#endif
Ends a section of lines begun by one of the conditional directives #if
,
#ifdef
, or #ifndef
. Each such directive must have a matching #endif
.
See also #if, #ifdef, #ifndef, #elif, #else.
MUIbase uses a programming language with a lisp-like syntax. Indeed several
constructs and functions have been adopted from standard lisp.
However, MUIbase is not fully compatible to standard lisp.
Many functions are missing (e.g. destructive commands) and the meaning of
some commands is different (e.g. the return
command).
The advantage of a lisp-like language is that you can program in both, a functional and an imperative way. Functional languages are getting quite popular in mathematical applications. The basic concept in functional languages is the use of expressions. Functions are defined in a mathematical way and recursion is used heavily.
Imperative programming languages (e.g. C, Pascal, Modula) use an imperative description on how to compute things. Here, the state is the basic concept (e.g. variables) and a program computes its output by going from one state to another (e.g. by assigning values to variables).
Lisp combines both techniques and therefore you can choose in which way you want to implement things. Use the one which is more appropriate for the specific problem or which you like more.
A lisp expression is either a constant, a variable, or
a function application.
For calling functions, lisp uses a prefix notation.
The function and its arguments are surrounded by parenthesis.
For example, to add two values a
and b
, you write
(+ a b)
All expressions return a value, e.g. in the above example the
sum of a
and b
returned.
Expressions can be nested, that is, you can place an expression
as a sub-expression into another one.
Function evaluation is done by using a call-by-value scheme, this means that the arguments are evaluated first before a function is called.
If not stated otherwise, all functions are strict, that is,
all arguments of a function are evaluated before the function is called.
Some functions, however, are non-strict, e.g. IF
, AND
and
OR
. These functions may not evaluate all arguments.
MUIbase knows three kinds of programs. The first one is the project program kind. In a program of this kind you can define functions and global variables. The functions can be used as trigger functions for attributes. You define a project program in the program editor (see section Program editor).
The second kind is the query program kind. For this kind you can enter expressions only. An expression is allowed to contain global variables and calls to functions that are defined in the project program. However, you cannot define new global variables or functions in a query program. Query programs are entered in the query editor (see section Query editor).
The third kind of programs are filter expressions. Here you can only enter expressions that contain calls to pre-defined MUIbase functions. Not all pre-defined functions are available, only those that don't have a side effect, e.g. you cannot use a function that writes data to a file. Filter expressions are entered in the change filter requester (see section Changing filters).
In a MUIbase program you can define symbols like functions and local or global variables. The names of these symbols must follow the following conventions:
To access tables and attributes in a MUIbase program, you have to specify a path to them. A path is a dot separated list of components where each component is the name of a table or an attribute.
Paths can either be relative or absolute. Absolute paths are specified with a table name as the first component, followed by a list of attributes that lead to the final attribute you want to access. E.g. the absolute path `Person.Name' accesses the `Name' attribute in the current record of table `Person', or the absolute path `Person.Father.Name' accesses the `Name' attribute in the record referenced by the `Father' field (a reference attribute to table `Person').
Relative paths already have a current table to which they are relative. For example in a filter expression the current table is the table for which you write the filter expression. The relative path for an attribute in the current table is simply the attribute name itself. For attributes that are not directly accessible from the current table but indirectly via a reference attribute, the same rules as for absolute paths apply.
It is not always clear if a specified path is a relative or an absolute one, e.g. suppose you are writing a filter expression for a table `Foo' that has an attribute `Bar' and there also exists a table `Bar'. Now entering `Bar' would be ambiguous, what is meant, the table or the attribute? Therefore all paths are first treated as relative ones. If no attribute is found for the specified path than the path is treated as global. In our example the attribute would be preferred.
But now, what if you want to access the table in the above example? Therefore the path must be given absolute. To indicate that a path is global you have to insert two colons in front of the path. In our example you would have to type `::Bar' for accessing the table.
To give you a better understanding of paths and their semantics, consider in our example that the `Bar' attribute in the `Foo' table is a reference to the `Bar' table, and the `Bar' table has an attribute `Name'. Now you can access the `Name' attribute by typing `Bar.Name' or `::Bar.Name'. Both expressions have a different meaning. `::Bar.Name' means to take the current record of table `Bar' and return the value of the `Name' attribute of this record, whereas `Bar.Name' takes the current record of table `Foo', extracts the record reference of the `Bar' field and uses this record for getting the value of the `Name' attribute.
To make a more complete example, consider that table `Bar' has two records. One that contains `Mats' and one that contains `Steffen' in the `Name' field. The first record should be the current one. Furthermore table `Foo' has one record (the current one) whose `Bar' field refers to the second record of table `Bar'. Now `::Bar.Name' results to `Mats' and `Bar.Name' to `Steffen'.
The programming language of MUIbase knows of the following data types:
Type Description Bool all expressions. Non-NIL expressions are treated as TRUE. Integer long integer, 32 bit, choice values are automatically converted to integers Real double, 64 bit String strings of arbitrary length Memo like strings but line oriented format Date date values Time time values Record pointer to a record File file descriptor for reading/writing List list of items, NIL is empty list.
All programming types support the NIL value.
The programming language of MUIbase can handle constant expressions which can be entered depending on the type of the expression:
Type Description Integer Integer constants in the range of -2147483648 to 2147483647 can be specified as usual. Real Floating point constants in the range of -3.59e308 to 3.59e308 can be specified as usual, in scientific or non-scientific format. If you omit the decimal point then the number may not be treated as a real number but as an integer instead. String String constants are any character strings surrounded by double quotes, e.g. "sample string". Within the double quotes you can enter any characters except control characters or new lines. However there are special escape codes for entering such characters: \n new line (nl) \t horizontal tabulator (ht) \v vertical tabulator (vt) \b backspace (bs) \r carriage return (cr) \f form feed (ff) \\ backslash character itself \" double quote \e escape code 033 \nnn character with octal code nnn \xnn character with hex code nn Memo There are no constant values, just use a constant string instead. Date Constant date values can be specified in one of the formats `DD.MM.YYYY', `MM/DD/YYYY', or `YYYY-MM-DD', where `DD', `MM' and `YYYY' are standing for two and four digit values representing the day, month and year of the date respectively. Time Constant time values can be entered in the format `HH:MM:SS', where `HH' is a two digit value in the range of 0 to 23 representing the hours, `MM' a two digit value in the range of 0 to 59 representing the minutes, and `SS' a two digit value in the range of 0 to 59 representing the seconds.
For some other pre-defined constant values, see section Pre-defined constants.
In the remainder of this chapter, you will find the description of all commands and functions available for programming MUIbase. The following syntax is used for describing the commands:
This section lists commands for defining functions and global variables. The commands are only available for project programs.
DEFUN
defines a function with the specified name, a list of arguments
that are passed to the function, and a list of expressions to evaluate.
(DEFUN
name(
varlist)
expr ...)
The name of a function must start with a lowercase character, followed by further characters, digits or underscore characters (see section Name conventions).
The parameters varlist specifies the arguments of the function:
varlist: var1 ...
where var1 ... are the names for the arguments. The names must follow the same rules as the function name.
It is also possible to add type specifiers to the arguments (see section Type specifiers).
The function executes the expressions expr, ... one by one and returns the value of the last expression. The function may call further functions including itself. A self defined function can be called like calling a pre-defined function.
For example to count the number of elements of a list, you can define the following function:
(DEFUN len (l) (IF (= l NIL) 0 (+ 1 (len (REST l))) ) )
Functions defined with DEFUN
are listed in the pop-up list-views
of table and attribute requesters (see section Creating tables and section Creating attributes).
This command is only available for project programs.
DEFUN*
is the star version of DEFUN
and has the same
effect as DEFUN
(see section DEFUN). The only difference is that functions
defined with DEFUN*
are not listed in the pop-up list-views
when creating or changing tables and attributes.
However, it is still possible to enter the function name in the corresponding
string fields.
This command is only available for project programs.
(DEFVAR
var [expr])
Defines a global variable with initial value of expr or NIL if expr is missing. The name of the variables must start with a lowercase letter followed by further letters, digits or underscore characters (see section Name conventions).
You can also add a type specifier to the variable name (see section Type specifiers).
DEFVAR
is only available for project programs.
All DEFVAR
commands should be placed on top of all function definitions.
Example: `(DEFVAR x 42)' defines a global variable `x' with value 42.
There are some pre-defined variables in MUIbase (see section Pre-defined variables).
This section lists functions for program control, e.g. functions for defining local variables, loop functions, conditional program execution, loop control functions and more.
To evaluate several expressions one by another the PROGN
construction can be used.
(
[expr ...])
executes expr ... one by one.
Returns the result of the last expression (or NIL if no expression has been specified).
In Lisp this construct is known as (PROGN
[expr ...])
.
Example: `(1 2 3 4)' results to 4.
See also PROG1.
Another way, besides the PROGN
function, to evaluate several expressions
one by another is the PROG1
expression.
(PROG1
[expr ...])
executes expr ... and returns the value of the first expression (or NIL if no expression has been specified).
Example: `(PROG1 1 2 3 4)' results to 1.
See also PROGN.
LET
defines a new block of local variables.
This is useful, e.g., for defining local variables of a function.
The syntax is
(LET (
varlist)
expr ...)
where varlist is a list of local variables.
varlist: varspec ...
varspec:(
var expr)
| var
Here var is the name of the variable and must start with a lowercase character, followed by further characters, digits or underscore characters (see section Name conventions).
In the case of a (
var expr)
specification,
the new variable is initialized with the given expression.
In the other case the new variable is set to NIL.
It is also possible to add type specifiers to the variables. (see section Type specifiers).
After initializing all variables the list of expressions expr ... are evaluated and the value of the last one is returned.
For example, the following LET
expression
(LET ((x 0) y (z (+ x 1))) (+ x z) )
results to 1.
See also DOTIMES, DOLIST, DO, DEFVAR.
The SETQ
function sets values to variables, attributes and tables.
(SETQ
lvalue1 expr ...)
Sets lvalue1 to the value of expr. The dots indicate
assignments for further lvalues. An lvalue is either a variable,
an attribute in a table, or a table.
In case of a variable, the variable must have been previously
defined (e.g. by a LET
expression).
Setting the value of a table means setting its program or
gui record pointer: `(SETQ
Table expr)
'
sets the program record pointer of Table to the
value of expr, `(SETQ
Table* expr)
'
sets the gui record pointer of it and updates the display.
For more information about program and gui record pointers, see section Tables.
SETQ
returns the value of the last expression.
Example: `(SETQ a 1 b 2)' assigns 1 to the variable `a', 2 to the variable `b' and returns 2.
See also SETQ*, LET, DEFVAR, Tables, section Semantics of expressions.
SETQ*
is the star version of SETQ
(see section SETQ)
and has similar effects. The difference is that when assigning
a value to an attribute, SETQ*
calls the trigger function of
that attribute (see section Attribute trigger)
instead of directly assigning the value.
In case no trigger function has been specified for an attribute,
SETQ*
behaves like SETQ
and simply assigns the value
to the attribute.
Example: `(SETQ* Table.Attr 0)' calls the trigger function of `Table.Attr' with an argument of 0.
Warning: With this function it is possible to write endless loops, e.g.
if you have defined a trigger function for an attribute and this function
calls SETQ*
to set a value to itself.
FUNCALL
is used to call a function.
(FUNCALL
fun-expr [expr ...])
Calls the function fun-expr with the given arguments. The expression fun-expr can be any expression whose value is a pre-defined or user-defined function, e.g. a variable holding the function to call. If the number of arguments is not correct, an error message is generated.
FUNCALL
returns the return value of the function call
or NIL if fun-expr is NIL.
For more information about functional expressions, see section Functional parameters.
IF
is a conditional operator.
(IF
expr1 expr2 [expr3])
The expression expr1 is tested. If it results to non-NIL then the value of expr2 is returned else the value of expr3 (or NIL if not present) is returned.
This function is not strict, that is, only one expression of expr2 or expr3 will be evaluated.
CASE
is similar to the switch
statement in the C language.
(CASE
expr [case ...])
Here expr is the selection expression and case ... are pairs consisting of:
case:(
value [expr ...])
where value is a single expression or a list of expressions and expr ... are the expressions to be executed if one of the case expression matches.
The CASE
expression first evaluates expr.
Then each case pair is checked whether it (or one of the expressions in the list)
matches the evaluated expression.
If a matching case expression is found then the corresponding expressions
are executed and the value of the last expression is returned.
If no case matches, NIL is returned.
Example: `(CASE 1 ((2 3 4) 1) (1 2))' returns 2.
COND
is, like IF
, a conditional operator.
(COND
[(
test-expr [expr ...])
...])
COND
test the first expression of each list one by one.
For the first one that does not result to NIL,
the corresponding expressions expr ... are evaluated
and the value of the last expression is returned.
If all tested expressions result to NIL then NIL is returned.
(COND ((> 1 2) "1 > 2") ((= 1 2) "1 = 2") ((< 1 2) "1 < 2") )
results to "1 < 2".
For simple loops the DOTIMES
command can be used.
(DOTIMES (
name int-expr [result-expr ...])
[loop-expr ...])
Here name is the name of a new variable which will be used in the loop. The name must start with a lowercase character, followed by further characters, digits or underscore characters (see section Name conventions).
The number of times the loop is executed is given in int-expr. In result-expr ... expressions can be specified that are executed after terminating the loop. In loop-expr you specify the body of the loop, that is, the expressions that are evaluated in each loop run.
Before executing the loop, DOTIMES
computes the value of int-expr
to determine the number of times the loop gets executed.
Here int-expr is evaluated only once at the start of the loop
and must result to an integer value.
Then DOTIMES
sets the loop variable to the values of 0 to int-expr-1
one by one for each loop run. First, the variable is initialized with zero
and checked if it is already greater or equal to the value of expr.
If int-expr is negative or NIL or if the variable is greater or equal to the value of
expr then the loop is terminated and the result expressions are evaluated.
Otherwise the loop expressions are evaluated and the variable is incremented
by one. Then the execution returns to the termination test and, possibly,
does further loop runs.
The DOTIMES
expression returns the value of the last result expression
or NIL if no result expression has been given.
(DOTIMES (i 50 i) (PRINT i))
Prints the numbers from 0 to 49 and returns the value 50.
See also DOLIST, DO, FOR ALL, LET.
For loops through lists the DOLIST
expression can be used.
(DOLIST (
name list-expr [result-expr ...])
[loop-expr ...])
Here name is the name of a new variable which will be used in the loop. The name must start with a lowercase character, followed by further characters, digits or underscore characters (see section Name conventions).
In list-expr you specify the list over which the loop should be executed, result-expr ... are expressions which are evaluated after terminating the loop, end loop-expr ... build the body of the loop.
Before executing the loop, DOLIST
computes the value of list-expr.
This expression is evaluated only once at the start of the loop and must result
to a list value.
Then DOTIMES
sets the loop variable to the nodes of the list one by one
for each loop run.
First the loop variable is initialized to the first node of the list.
If the list is already empty (NIL) then the loop is terminated and the
result expressions are evaluated.
Otherwise the loop expressions are
evaluated and the variable is set to the next node of the list.
Then the execution returns to the termination test and, possibly, does further
loop runs.
The DOLIST
expression returns the value of the last result expression
or NIL if no result expression has been given.
(DOLIST (i (SELECT * FROM Accounts)) (PRINT i))
Prints all records of table `Accounts' and returns NIL.
See also DOTIMES, DO, FOR ALL, LET.
With the DO
expression arbitrary loops can be programmed.
(DO (
[binding ...]) (
term-expr [result-expr ...])
[loop-expr ...])
where binding ... are the variable bindings, each of which is either:
(
name init [step])
where name is a name for the new variable, init is the initial
value of the variable, and step is a step expression.
Furthermore, term-expr is the termination test expression, result-expr ... are the result expressions (the default is nil) and loop-expr ... build the body of the loop.
The DO
loop first initializes all local variables with the init
expressions, then tests the termination expression. If it results to TRUE,
the loop is terminated and the result expressions are evaluated. The value
of the last result expression is returned.
Otherwise the body of the loop (
loopexpr ...)
is executed
and each variable is updated by the value of its step expression.
Then the execution returns to test the terminating expression and so on.
(DO ((i 0 (+ i 1))) ((>= i 5) i) (PRINT i))
Prints the values 0, 1, 2, 3 and 4 and returns the value 5.
Of course this is a quite complicated way to build a simple FOR loop.
Therefore a simpler version exists, the DOTIMES
expression.
See also DOTIMES, DOLIST, FOR ALL, LET.
The FOR ALL expression is used to loop over a list of records.
(FOR ALL
table-list [WHERE
where-expr] [ORDER BY
order-list]DO
expr ...)
Here table-list is a comma-separated list of tables, where-expr an expression to test each set of records, order-list a comma-separated list of expressions by which the record sets are ordered, and expr ... are the expressions that are executed for each record set.
FOR ALL
first generates a list of all record sets for which the loop body should
be executed. This is done like in the SELECT
expression.
Please see section SELECT, for more information about how this list is generated.
For each element of this list the loop body expr ... is executed.
For example, summing up an attribute of a table can be done in the following way:
(SETQ sum 0) (FOR ALL Accounts DO (SETQ sum (+ sum Accounts.Amount)) )
The FOR ALL
expression returns NIL.
See also SELECT, DOTIMES, DOLIST, DO.
NEXT
can be used for controlling DOTIMES
,
DOLIST
, DO
and FOR ALL
loops.
Calling NEXT
in the body of a loop will jump to the next loop iteration.
This can be used for skipping non-interesting loop runs, like e.g. in
the following example:
(FOR ALL Table DO (IF not-interested-in-the-current-record (NEXT)) ... )
See also EXIT, DOTIMES, DOLIST, DO, FOR ALL.
EXIT
can be used to terminate a loop.
(EXIT
[expr ...])
EXIT
within a loop body will terminate the loop,
execute the optional expressions expr ..., and return the
value of the last expression (or NIL in case of no expression)
as the return value of the loop.
Possible return expressions of the loop as for example in
(DOTIMES (x 10 ret-expr ...) ...)
are not executed.
You may use the EXIT
function for example to end a FOR ALL
loop
when you found the record you are interested in:
(FOR ALL Table DO (IF interested-in-the-current-record (EXIT Table)) ... )
See also NEXT, RETURN, HALT, DOTIMES, DOLIST, DO, FOR ALL.
Within a function definition you can return to
the caller by using the RETURN
command.
(RETURN
[expr ...])
terminates the function, executes the optional expressions expr ..., and returns the value of the last expression (or NIL in case of no expression).
(DEFUN find-record (name) (FOR ALL Table DO (IF (= Name name) (RETURN Table)) ) )
The example searches a record whose Name attribute matches the given name. The function returns the first record found or NIL in case of no record found.
HALT
can be used to terminate program execution.
(HALT)
stops program execution silently.
For aborting program execution with an error message
the ERROR
function can be used.
(ERROR
fmt [arg ...])
stops program execution and pops up a requester with an error message.
The error message is generated from fmt and the optional arguments
arg ... like in the SPRINTF
function (see section SPRINTF).
For each type a predicate is defined that returns TRUE if the supplied expression is of the specified type and NIL otherwise. The predicates are:
Predicate Description(STRP
expr)
TRUE if expr is of type string, NIL otherwise.(MEMOP
expr)
TRUE if expr is of type memo, NIL otherwise.(INTP
expr)
TRUE if expr is of type integer, NIL otherwise.(REALP
expr)
TRUE if expr is of type real, NIL otherwise.(DATEP
expr)
TRUE if expr is of type date, NIL otherwise.(TIMEP
expr)
TRUE if expr is of type time, NIL otherwise.(NULLP
expr)
TRUE if expr is NIL (an empty list), NIL otherwise.(CONSP
expr)
TRUE if expr is a non-empty list, NIL otherwise.(LISTP
expr)
TRUE if expr is a list (may be NIL), NIL otherwise.(RECP
table expr)
TRUE if expr is a record pointer of the given table. If expr is NIL then TRUE is returned (initial record). If table is NIL then a check is done whether expr is a record pointer of any table.
This section lists functions for converting values from one type to another one.
STR
can be used to convert an expression into a string representation.
(STR
expr)
converts expr into a string representation. The type of expr determines the conversion:
Type Return string String The string itself. Memo The whole memo text in one string. Integer String representation of integer value. Real String representation of real value. If expr is an attribute then the number decimals specified for this attribute are used, otherwise 2 decimals are used. Choice Label string of the choice attribute. Date String representation of date value. Time String representation of time value. Bool The string "TRUE" NIL User defined nil string if expr is an attribute, the string "NIL" otherwise. Record String representation of record number. Others String representation of internal address pointer.
MEMO
can be used to convert an expression into a memo.
(MEMO
expr)
converts expr into a memo representation.
It treats the expression like the STR
function
(see section STR) but returns a memo text instead of a string.
See also STR.
INT
is used to convert an expression into an integer.
(INT
expr)
converts expr into an integer value. Possible conversions are:
Type Return value String If the whole string represents an integer value then the string is converted into an integer. Leading and following spaces are ignored. If it does not represent an integer value, NIL is returned. Memo Same as for string. Integer The value itself. Real If the value lies within the integer range than the real value is rounded and returned, otherwise NIL is returned. Choice The internal number (starting with 0) of the current label. Date Number of days since 01.01.0000. Time Number of seconds since 00:00:00. Record Record number. NIL NIL Others An error message is generated and program execution is aborted.
REAL
is used to convert an expression into a value of type real.
(REAL
expr)
converts expr into a real.
It treats the expression like the INT
function
(see section INT) but returns a value of type real instead of an integer.
See also INT.
DATE
is used to convert an expression into a date (with your best girl friend :-).
(DATE
expr)
converts the given expression into a date (only one date guys, needs two good girl friends for getting more dates!) Possible conversions are:
Type Return value String If the whole string represents a date value then the string is converted into a date value. Leading and following spaces are ignored. If it does not represent a date value, NIL is returned. Memo Same as for string. Integer A date value is generated where the given integer represents the number of days since 01.01.0000. If the integer value is too great (date value would be greater than 31.12.9999) or negative then NIL is returned. Real Same as for integer. Date The value itself. NIL NIL others An error message is generated and program execution is aborted.
TIME
is used to convert an expression into a time value.
(TIME
expr)
converts the given expression into a time value. Possible conversions are:
Type Return value String If the whole string represents a time value then the string is converted into a time value. Leading and following spaces are ignored. If it does not represent a time value, NIL is returned. Memo Same as for string. Integer A time value is generated where the given integer represents the number of seconds since 00:00:00. The integer value is taken modulo the number of seconds per day, e.g. `(TIME 86400)' results to 00:00:00. Real Same as for integer. Time The value itself. NIL NIL others An error message is generated and program execution is aborted.
This section lists boolean operators.
AND
checks if all of its arguments are TRUE.
(AND
[expr ...])
checks expr ... one by another until one expression evaluates to NIL. If all expressions evaluate to non-NIL then the value of the last expression is returned. Otherwise NIL is returned.
This function is non-strict which means that arguments of AND
may not be evaluated, e.g. in `(AND NIL (+ 1 2))' the expression
`(+ 1 2)' is not evaluated since a NIL value has already been processed,
however in `(AND (+ 1 2) NIL)' the expression `(+ 1 2)' gets evaluated.
OR
checks if all of its arguments are NIL.
(OR
[expr ...])
checks expr ... one by another until one expression evaluates to non-NIL. Returns the value of the first non-NIL expression or NIL if all expressions evaluate to NIL.
This function is non-strict which means that arguments of OR
may not be evaluated, e.g. in `(OR TRUE (+ 1 2))' the expression
`(+ 1 2)' is not evaluated since a non-NIL value (here `TRUE')
has already been processed, however in `(OR (+ 1 2) TRUE)'
the expression `(+ 1 2)' gets evaluated.
NOT
is used to invert the value of a boolean expression.
(NOT
expr)
results to TRUE if expr is NIL, NIL otherwise.
For comparing two values in a MUIbase program, use
(
op expr1 expr2)
where op is in {=
, <>
, <
, >
, >=
,
<=
, =*
, <>*
, <*
, >*
, >=*
, <=*
}.
The star is used for special comparison (strings are compared case
insensitive, records are compared by using the order defined by the user).
The following table shows all rules for comparing two values in a MUIbase program.
Type Order relation Integer NIL < MIN_INT < ... < -1 < 0 < 1 < ... < MAX_INT Real NIL < -HUGE_VAL < ... < -1.0 < 0.0 < 1.0 < ... < HUGE_VAL String: NIL < "" < "Z" < "a" < "aa" < "b" < ... (case sensitive) NIL <* "" <* "a" <* "AA" <* "b" < ... (case insensitive) Memo: same as string Date NIL < 1.1.0000 < ... < 31.12.9999 Time NIL < 00:00:00 < ... < 23:59:59 Bool NIL < TRUE Record: NIL < any_record (records itself are not comparable with <) NIL <* rec1 <* rec2 (order specified by user)
See also LIKE.
Here, some mathematical functions are listed.
For adding values, use
(+
expr ...)
Returns the sum of the arguments expr .... If any argument value is NIL then the result is NIL. If the values are of type real or integer then a real (or integer) value is the result.
You may also add strings or memos. In this case the result is the concatenation of the strings/memos.
If expr is of type date and the rest of the arguments are integers/reals then the sum of integers/reals are interpreted as a number of days and added to expr. If the resulting date is out of range (smaller than 1.1.0000 or greater than 31.12.9999) then NIL is the result.
If expr is of type time and the rest of the arguments are integers/reals then the sum of integers/reals are interpreted as a number of seconds and added to expr. However the rest of the arguments can also consist of expressions of type time. The resulting time value is computed modulo 24:00:00.
Expression Value (+ 1 2 3) 6 (+ 5 1.0) 6.0 (+ "Hello" " " "world!") "Hello world!" (+ 28.11.1968 +365 -28 -9) 22.10.1969 (+ 07:30:00 3600) 08:30:00 (+ 03:00:00 23:59:59) 02:59:59
See also Subtracting values, 1+, Multiplying values, CONCAT, CONCAT2.
For subtracting values, use
(-
expr1 expr2 ...)
Subtracts the sum of expr2 ... from expr1. Here the same rules apply as for adding values (see section Adding values), except that strings and memos can't be subtracted.
(-
expr)
has a special meaning, it returns the
negative value of expr (integer or real), e.g.
`(- (+ 1 2))' results to -3.
See also Adding values, 1-.
1+
increases an integer or real expression by one.
(1+
expr)
Returns the value of expr (integer or real) plus one. If expr is NIL then NIL is returned.
See also Adding values, 1-.
1-
decreases an integer or real expression by one.
(1-
expr)
Returns the value of expr (integer or real) minus one. If expr is NIL then NIL is returned.
See also Subtracting values, 1+.
For multiplying integer/real values, use
(*
expr ...)
Returns the multiplication of the integer/real values expr .... If all arguments are integers then an integer is returned, otherwise the result is a value of type real.
See also Adding values, Dividing values.
For dividing integer/real values, use
(/
expr1 [expr2 ...])
Divides expr1 by the multiplication of the rest of the arguments. Returns a real value. On division by zero, NIL is returned.
See also Multiplying values, DIV, MOD.
DIV
is used for integer division.
(DIV
int1 int2)
Returns the integer division of int1 with int2. For example, `(DIV 5 3)' results to 1.
See also Dividing values, MOD.
MOD
is used for modulo calculation.
(MOD
int1 int2)
Returns int1 modulo int2. For example, `(MOD 5 3)' results to 2.
See also DIV.
MAX
returns the argument that has the largest value.
(MAX
expr ...)
Returns the maximum value of the arguments expr ... (all integers or reals). If one of the expressions is NIL then NIL is returned.
See also MIN.
MIN
returns the argument that has the smallest value.
(MIN
expr ...)
Returns the minimum value of the arguments expr ... (all integers or reals). If one of the expressions is NIL then NIL is returned.
See also MAX.
ABS
computes the absolute value of an expression.
(ABS
expr)
Returns the absolute value of expr (integer or real). If expr is NIL then NIL is returned.
TRUNC
truncates decimals of a real value.
(TRUNC
real)
Returns the largest integer (as a real number) not greater than the specified real number. If real is NIL then NIL is returned.
Examples: `(TRUNC 26.1)' results to 26, `(TRUNC -1.2)' results to -2.
See also ROUND.
ROUND
rounds a real value.
(ROUND
real digits)
Returns the specified real number rounded to digits decimal digits. If real or digits are NIL then NIL is returned.
Examples: `(ROUND 70.70859 2)' results to 70.71, `(ROUND 392.36 -1)' results to 392.0.
See also TRUNC.
RANDOM
can be used to generate random numbers.
(RANDOM
expr)
Returns a random number. On the first call the random number generator
is initialized with a value generated from the current time.
RANDOM
generates a random number in the range of
0 ... expr, excluding the value of expr itself.
The type of expr (integer or real) is the return type.
If expr is NIL then NIL is returned.
Example Meaning (RANDOM 10) returns a value from 0 to 9, (RANDOM 10.0) returns a value from 0.0 to 9.99999...
This section deals with functions useful for strings.
LEN
computes the length of a string.
(LEN
str)
Returns the length of the given string or NIL if str is NIL.
See also WORDS, LINES, MAXLEN.
LEFTSTR
extracts a sub string out of a string.
(LEFTSTR
str len)
Returns the left part of the given string with at most len characters. If str or len are NIL or if len is negative then NIL is returned.
Example: `(LEFTSTR "Hello world!" 5)' results to "Hello".
See also RIGHTSTR, MIDSTR, WORD, LINE.
RIGHTSTR
extracts a sub string out of a string.
(RIGHTSTR
str len)
Returns the right part of the given string with at most len characters. If str or len are NIL or if len is negative then NIL is returned.
Example: `(RIGHTSTR "Hello world!" 6)' results to "world!".
See also LEFTSTR, MIDSTR, WORD, LINE.
MIDSTR
extracts a sub string out of a string.
(MIDSTR
str pos len)
Returns a part of the given string with at most len characters. If len is NIL then the number of returning characters is not restricted. The sub string starts at the pos-th position (starting with zero). If str or len are NIL or if len is negative then NIL is returned. If pos is out of range, that is, negative or greater than the string length, NIL is returned.
Example: `(MIDSTR "Hello world!" 3 5)' results to "lo wo".
See also LEFTSTR, RIGHTSTR, WORD, LINE, SETMIDSTR, INSMIDSTR.
SETMIDSTR
replaces a sub string in a string.
(SETMIDSTR
str index set)
Returns a copy of string str where the sub string starting at index is overwritten with string set. The length of the returned string is greater or equal to the length of str. If one of the arguments is NIL or if index is out of range then NIL is returned.
Example: `(SETMIDSTR "Hello world!" 6 "Melanie!")' results to "Hello Melanie!".
See also INSMIDSTR, REPLACESTR.
INSMIDSTR
is used to insert a sub string into a string.
(INSMIDSTR
str index insert)
Returns a copy of string str where the string insert has been inserted at the given index. If one of the arguments is NIL or if index is out of range then NIL is returned.
Example: `(INSMIDSTR "Hello world!" 6 "MUIbase-")' results to "Hello MUIbase-world!".
See also SETMIDSTR, REPLACESTR.
INDEXSTR
searches a string for the occurrence of a sub string.
(INDEXSTR
str substr)
Searches for the occurrence of substr in str. String comparison is done case-sensitive. Returns the index (starting with 0) of the sub string in str or NIL if the sub string is not present. If one of the arguments is NIL then NIL is returned.
Example: `(INDEXSTR "Hello world!" "world")' returns 6.
See also INDEXSTR*, INDEXBRK, INDEXBRK*.
INDEXSTR*
has the same effect as INDEXSTR
(see section INDEXSTR)
except that string comparison is done case-insensitive.
See also INDEXSTR, INDEXBRK, INDEXBRK*.
INDEXBRK
is used to search for a character in a string.
(INDEXBRK
str brkstr)
Searches for the occurrence of a character from brkstr in str. String comparison is done case-sensitive. Returns the index (starting with 0) of the first character found in str or NIL if no character is found. If one of the arguments is NIL then NIL is returned.
Example: `(INDEXBRK "Hello world!" "aeiou")' returns 1.
See also INDEXBRK*, INDEXSTR, INDEXSTR*.
INDEXBRK*
has the same effect as INDEXBRK
(see section INDEXBRK)
except that string comparison is done case-insensitive.
See also INDEXBRK, INDEXSTR, INDEXSTR*.
REPLACESTR
replaces sub strings by other strings.
(REPLACESTR
str substr replacestr)
Replaces all occurrences of substr in str by replacestr. If any of the strings are NIL or substr is empty then NIL is returned.
Example: `(REPLACESTR "From Freiburg to San Francisco" "Fr" "X")' results to "Xom Xeiburg to San Xancisco".
See also SETMIDSTR, INSMIDSTR, REMCHARS.
REMCHARS
removes characters from a string.
(REMCHARS
str chars-to-remove)
Returns a copy of str where all characters of chars-to-remove are removed from. If str or chars-to-remove are NIL then NIL is returned.
Example: `(REMCHARS your-string " \t\n")' removes all spaces, tabs and newline characters from your-string.
See also REPLACESTR, TRIMSTR.
TRIMSTR
removes leading and trailing spaces from a string.
(TRIMSTR
str)
Returns a copy of str where all leading and trailing spaces have been removed.
Example: (TRIMSTR " I wrecked Selma's bike. ")
results to
"I wrecked Selma's bike.".
See also REMCHARS.
WORD
returns a word of a string.
(WORD
str num)
Returns the num-th word (starting with zero) of the given string. Words in a string are non-empty sub strings separated by space-like characters (e.g. space, tab or newline characters).
If str or num are NIL, or if num is out of range, that is, less than zero or greater or equal to the number of words, then NIL is returned.
Example: `(WORD "Therefore, I lend Selma my bike." 3)' results to "Selma".
See also WORDS, LINE, LEFTSTR, RIGHTSTR, MIDSTR.
WORDS
counts the number of words in a string.
(WORDS
str)
Returns the number of words of the given string or NIL if str is NIL. Words are sub strings separated by space-like characters (e.g. space, tab, or newline characters).
Example: `(WORDS "Actually, it wasn't really my bike.")' results to 6.
CONCAT
concatenates strings.
(CONCAT
[str ...])
Returns the concatenation of the given list of strings where space characters have been inserted between the strings. If one of the strings is NIL, or the list is empty, then NIL is returned.
Example: `(CONCAT "I" "thought" "it" "was" "an "abandoned" "bike.")' results to "I thought it was an abandoned bike.".
See also CONCAT2, Adding values, SPRINTF.
CONCAT2
concatenates strings.
(CONCAT2
insert [str ...])
Returns the concatenation of the given list of strings. The strings will be separated with the given insert string. If insert is NIL, one of the strings is NIL, or the list is empty, then NIL is returned.
Example: `(CONCAT2 "! " "But" "it" "wasn't!")' results to "But! it! wasn't!".
See also CONCAT, Adding values, SPRINTF.
UPPER
converts a string to upper case.
(UPPER
str)
Returns a copy of the given string where all characters are converted to upper case. If str is NIL then NIL is returned.
Example: `(UPPER "Selma found a letter attached to my bike.")' results to "SELMA FOUND A LETTER ATTACHED TO MY BIKE.".
See also LOWER.
LOWER
converts a string to lower case.
(LOWER
str)
Returns a copy of the given string where all characters are converted to lower case. If str is NIL then NIL is returned.
Example: `(LOWER "The letter was from Silke.")' results to "the letter was from silke.".
See also UPPER.
ASC
converts a character to its ASCII code.
(ASC str)
Returns the ASCII code of the first character of str. If str is empty, 0 is returned. If str is NIL, NIL is returned.
Example: (ASC "A")
results to 65.
CHR
converts an ASCII code to a character.
(CHR
int)
Returns a string containing the character with ASCII code int. If int is 0, an empty string is returned. If int is NIL or not in the range of ASCII characters (0..255) then NIL is returned.
Example: `(CHR 67)' results to "C".
LIKE
compares strings.
(LIKE
str1 str2)
Returns TRUE if str1 matches str2, NIL otherwise. The string str2 may contain the joker characters '?' and '*' where '?' matches exactly one character and '*' matches a string of any length. String comparison is done case insensitive.
Example: `(LIKE "Silke has been in France for one year." "*France*")' results to TRUE.
See also Comparison functions.
SPRINTF
formats a string with various data.
(SPRINTF
fmt [expr ...])
SPRINTF
takes a series of arguments, converts them to strings,
and returns the formatted information as one string.
The string fmt determines exactly what gets written to
the return string and may contain two types of items: ordinary characters
which are always copied verbatim and conversion specifiers which direct
SPRINTF
to take arguments from its argument list and format them.
Conversion specifiers always begin with a `%' character.
Conversion specifiers always take the following form:
%
[flags][width][.
precision]type
where
SPRINTF
will be converting, such as string, integer, real, etc.
Note that all of the above fields are optional except for type. The following tables list the valid options for these fields.
SPRINTF
returns the formatted string or NIL in case fmt is NIL.
Call Result (SPRINTF "Hello") "Hello" (SPRINTF "%s" "Hello") "Hello" (SPRINTF "%10s" "Hello") " Hello" (SPRINTF "%-10.10s" "Hello") "Hello " (SPRINTF "%010.3s" "Hello") " Hel" (SPRINTF "%-5.3b" TRUE) "TRU " (SPRINTF "%i" 3) "3" (SPRINTF "%03i" 3) "003" (SPRINTF "% 0+- 5.3i" 3) " 003 " (SPRINTF "%f" 12) "12.00" (SPRINTF "%10e 12.0) " 1.20e+1" (SPRINTF "%+-10.4f" 12.0) "+12.0000 " (SPRINTF "%10.5t" 12:30:00) " 12:30" (SPRINTF "%d" 28.11.1968) "28.11.1968" (SPRINTF "He%s %5.5s!" "llo" "world champion ship") "Hello world!"
See also PRINTF, STR, Adding values, CONCAT, CONCAT2.
This section deals with functions useful for memos.
LINE
extracts a line in a memo.
(LINE
memo num)
Returns the num-th line (starting with zero) of the given memo. The line string will not have a terminating newline character. If memo or num are NIL or if num is out of range, that is, less than zero or greater or equal to the number of lines, then NIL is returned.
LINES
returns the number of lines in a memo.
(LINES
memo)
Returns the number of lines of the given memo or NIL if memo is NIL.
MEMOTOLIST
converts a memo to a list of strings.
(MEMOTOLIST
memo)
Converts the given memo to a list. If memo is NIL then NIL is returned, otherwise a list is generated where each element contains one line of the memo.
Example: `(MEMOTOLIST "My insurance\npays for\nthe wrecked bike.")' results to ( "My insurance" "pays for" "the wrecked bike." ).
See also LISTTOMEMO.
LISTTOMEMO
converts a list to a memo.
(LISTTOMEMO
list)
Converts the given list to a memo. If list is NIL then NIL is returned, otherwise a memo is generated where each line consists of the string representation of the corresponding list element.
Example: `(LISTTOMEMO (LIST "Silke" "lends me" "'my' bike" "till" 01.09.1998)' results to: "Silke\nlends me\n'my' bike\ntill\n01.09.1998".
See also MEMOTOLIST.
FILLMEMO
fills in a memo with the results of expressions.
(FILLMEMO
memo)
Creates a copy of the given memo where all substrings of the form `$(expr)' are replaced by their results after evaluation.
Example: `(FILLMEMO "(+ 1 1) is $(+ 1 1).")' results to "(+ 1 1) is 2."
Please use only small expressions in the memo as debugging and tracking down errors is not easy here.
See also FORMATMEMO, INDENTMEMO.
FORMATMEMO
formats a memo.
(FORMATMEMO
memo width fill)
Formats memo to a memo with lines not longer than width characters. If fill is non-NIL then spaces are used to pad the lines up to exactly width characters. The memo is processed section-wise. A section starts at the first non-white-space character. The line holding this character and all following lines up to the first line whose first character is a white-space are counted to this section. The whole section is then formated word-wise, that is, as many words are put in one line as there is space for.
See also FILLMEMO, INDENTMEMO.
INDENTMEMO
indents a memo by putting spaces to the left.
(INDENTMEMO
memo indent)
Returns a copy of the given memo where each line is indented by indent space characters. If memo or indent is NIL then NIL is returned. If indent is negative, a value of 0 is used.
See also FILLMEMO, FORMATMEMO.
This section lists functions for processing lists.
CONS
builds a pair of expressions.
(CONS
elem list)
Constructs a new list. The first element of the new list is elem, the rest are the elements of list (which should be a list or NIL). The list list is not copied, only a pointer is used to reference it!
Example: `(CONS 1 (CONS 2 NIL))' results to ( 1 2 ).
The elements of a list can be of any type, e.g. it's also possible to have
a list of lists (e.g. see section SELECT).
The CONS
constructor can also be used to build pairs of elements, e.g.
`(CONS 1 2)' is the pair with the two integers 1 and 2.
LIST
generates a list out of its arguments.
(LIST
[elem ...])
takes the arguments elem ... and generates a list of it.
This is equivalent to calling (CONS
elem (CONS
... NIL))
.
Note that NIL alone stands for an empty list.
LENGTH
determines the length of a list.
(LENGTH
list)
returns the length of the given list.
Example: `(LENGTH (LIST "a" 2 42 3))' results to 4.
See also LIST.
FIRST
extracts the first element in a list.
(FIRST
list)
returns the first element of the given list. If list is empty (NIL) then NIL is returned.
See also REST, LAST, NTH, CONS.
REST
returns the sub-list after the first element of a list.
(REST
list)
returns the rest of the given list (the list without the first element). If list is empty (NIL) then NIL is returned.
Example: `(REST (LIST 1 2 3))' results to ( 2 3 ).
LAST
extracts the last element in a list.
(LAST
list)
Returns the last element of the given list or NIL if list is NIL.
NTH
extracts the n-th element of a list.
(NTH
n list)
Returns the n-th element of the given list (starting with 0) or NIL if the element doesn't exist.
APPEND
concatenates lists.
(APPEND
[list ...])
returns the concatenation of list ....
Example: `(APPEND (list 1 2) (list 3 4) (list 5))' results to ( 1 2 3 4 5 ).
See also LIST.
REVERSE
reverses a list.
(REVERSE
list)
returns the reverse list.
Example: `(REVERSE (list 1 2 3))' results to ( 3 2 1 ).
MAPFIRST
applies a function to all list elements.
(MAPFIRST
func list [...])
Builds a list whose elements are the result of the specified function called with the arguments of the given list elements one by one. The length of the returned list is as long as the length of the longest specified list. If one of the specified lists is too short then the list is padded with NIL elements.
Expression Value (MAPFIRST 1+ (LIST 1 2 3)) ( 2 3 4 ) (MAPFIRST + (LIST 1 2 3) (LIST 2 3)) ( 3 5 NIL )
SORTLIST
sorts the elements of a list.
(SORTLIST
func list)
Returns a copy of the specified list that has been sorted using the function func for ordering. The order function must take two arguments one for each element and return an integer value less than zero if the first element is smaller than the second one, a value greater then zero if the first element is greater than the second one, and a value of zero if the two elements are equal.
Example for a string comparing function usable for sorting:
(DEFUN cmp_str (x y) (COND ((< x y) -1) ((> x y) 1) (TRUE 0) ) )
Now you can sort a list by calling:
(SORTLIST cmp_str (LIST "hi" "fine" "great" "ok"))
which results to ( "fine" "great" "hi" "ok" ).
See also SORTLISTGT, MAPFIRST.
SORTLIST
sorts the elements of a list.
(SORTLISTGT
gtfunc list)
Like SORTLIST
but here you specify an order function that returns a value
not equal to NIL if the first element is greater then the second one, and NIL
otherwise.
Example: `(SORTLISTGT > (LIST "hi" "fine" "great" "ok"))' result to ( "fine" "great" "hi" "ok" ).
For requesting information from the user, the following functions can be used.
ASKFILE
prompts the user for entering a filename.
(ASKFILE
title oktext default savemode)
Pops up a file-requester for entering a filename. The window title can be set in title, the text of the `Ok' button in oktext, and the initial filename in default. You may specify NIL for one of them to use default values. The last argument savemode (bool) allows setting the file-requester to a save mode. This mode should be used when asking for a filename to write something to.
ASKFILE
returns the entered filename as string or NIL in case the user
canceled the requester.
ASKDIR
prompts the user for entering a directory name.
(ASKDIR
title oktext default savemode)
Pops up a file-requester for entering a directory name. The arguments are
used in the same way as in ASKFILE
(see section ASKFILE).
ASKDIR
returns the entered directory
name as string or NIL in case the user canceled the requester.
ASKSTR
prompts the user for entering a string.
(ASKSTR
title oktext default maxlen)
Pops up a requester asking for a string to enter. The window title, the text of the `Ok' button, and the initial value can be set in title, oktext, and default respectively (strings or NIL for default values), maxlen determines the maximum characters the user can enter.
ASKSTR
returns the entered string or NIL in case the user canceled.
See also ASKFILE, ASKDIR, ASKCHOICESTR, ASKINT.
ASKINT
prompts the user for entering an integer value.
(ASKINT
title oktext default min max)
Pops up a requester asking for an integer to enter. The window title and the text of the `Ok' button can be specified in title and oktext (strings or NIL for default values). In default you pass the initial integer value or NIL to start with an empty editing field. In min and max you can set the integer range. Entered values outside this range are not accepted by the requester. Use NIL for default min and max values.
ASKINT
returns the entered integer or NIL if the user canceled the requester.
See also ASKSTR.
ASKCHOICE
prompts the user to select one item out of many items.
(ASKCHOICE
title oktext choices default)
Pops up a requester allowing the user to choose one item out of many items. You can set the window title and the text of the `Ok' button in title and oktext (strings or NIL for default values). In choices you specify a list of choices from which the user can choose one. The list items can be any expressions that can be converted to strings. The initial choice value can be set in default which must be an integer index into the choice list (starting with index 0 for the first item). Use NIL for no initial choice.
ASKCHOICE
returns the index of the chosen item or NIL if the user canceled
the requester.
(LET ((items (LIST "First Entry" 2 3.14 "Last entry")) index) (SETQ index (ASKCHOICE "Choose one item" "Ok" items NIL)) (IF index (PRINTF "User chose item num %i with contents <%s>\n" index (STR (NTH index items)) ) ) )
See also ASKCHOICESTR, ASKOPTIONS.
ASKCHOICESTR
prompts the user for entering a string value offering
several pre-defined ones.
(ASKCHOICESTR
title oktext strings default)
Pops up a requester allowing the user to choose one string out of many strings or to enter any other string in a separate string field. You can set the window title and the text of the `Ok' button in title and oktext (strings or NIL for default values). In strings you specify a list of strings from which the user can choose one. The initial value of the string field can be set in default (string or NIL for an empty string field).
ASKCHOICESTR
returns the chosen string or NIL if the user canceled the
requester.
(LET ((strings (LIST "Claudia" "Mats" "Ralphie")) likebest) (SETQ likebest (ASKCHOICESTR "Who do you like the best?" "Ok" strings "My collies!") ) (IF likebest (PRINTF "User chose <%s>\n" likebest)) )
See also ASKCHOICE, ASKOPTIONS.
ASKOPTIONS
prompts the user for selecting several items out of a list of items.
(ASKOPTIONS
title oktext options selected)
Pops up a requester allowing the user to select several options out of many options. You can set the window title and the text of the `Ok' button in title and oktext (strings or NIL for default values). In options you specify a list of options from which the user can select some. The list items can be any expressions that can be converted to strings. The initial selection state can be set in selected which must be a list of integers each specifying an index whose corresponding item in the options list should initially be selected. Use NIL for all items being unselected.
ASKOPTIONS
returns a list of integers each specifying the index of a selected
item, or NIL in case the user canceled or did not choose any item.
(LET ((options (LIST "Salva Mea" "Insomnia" "Don't leave" "7 days & 1 week")) (selected (LIST 0 1 3)) ) (SETQ selected (ASKOPTIONS "Select music titles" "Ok" options selected)) (IF selected ( (PRINTF "User has selected the following items:\n") (DOLIST (i selected) (PRINTF "\tnum: %i contents: <%s>\n" i (STR (NTH i options))) ) ) ) )
ASKBUTTON
prompts the user for pressing a button.
(ASKBUTTON
title text buttons canceltext)
Pops up a requester with the specified window title (string or NIL for a default title) and specified description text (string or NIL for no text). The function waits until the user presses one of the buttons specified in buttons (list of strings) or the `Cancel' button. The text of the cancel button can be set in canceltext. If you specify NIL here then a default text based on the number of buttons you specified is used.
ASKBUTTON
returns the number of the pressed button (starting with 0 for
the first (leftmost) button) or NIL if the user pressed the `Cancel' button.
(LET ((buttons (LIST "At home" "In bed" "In front of my Amiga")) index) (SETQ index (ASKBUTTON "Please answer:" "Where do you want to be tomorrow?" buttons "Don't know") ) (IF index (PRINTF "User chose: <%s>\n" (NTH index buttons)) ) ) (ASKBUTTON "Info" "You have been playing with your\nAmiga for five hours now.\nGo to bed!" NIL NIL )
See also ASKCHOICE.
ASKMULTI
prompts the user to enter various kinds of information.
(ASKMULTI
title oktext itemlist)
ASKMULTI
is a multi-purpose requester. It opens a window with the specified
title, a set of gui objects for editing data, and two buttons (`Ok' and `Cancel')
for terminating the requester. The text of the `Ok' button can be set in
oktext (string or NIL for default text). The set of gui objects are
specified in itemlist which is a list of items where each item has one
of the following forms:
(LIST
title"String"
initial [help])
for editing one line of text,(LIST
title"Memo"
initial [help])
for editing multi-line text,(LIST
title"Integer"
initial [help])
for editing an integer,(LIST
title"Real"
initial [help])
for editing a real,(LIST
title"Date"
initial [help])
for editing a date,(LIST
title"Time"
initial [help])
for editing a time,(LIST
title"Bool"
initial [help])
for a boolean field,(LIST
title"Choice"
initial(LIST
choice ...)
[help])
for a choice field.(LIST
title"ChoiceList"
initial(LIST
choice ...)
[help])
for selecting one item of a list.(LIST
title"Options"
initial(LIST
option ...)
[help])
for selecting several items of a list. non-list-expr for static text
The title (string or NIL for no title) will be displayed to the left of the gui object. If the initial value is NIL then a default value is used (e.g. an empty text field). For choice fields the initial value must be the index (starting with 0) for the initial active entry, for choice list fields the initial value may be NIL (no item is activated), and for options fields the initial value must be a list of integers representing the indices (starting with 0) of the items that are initially selected. The optional help field (string) can be used for giving more information to the user about the usage of the field.
ASKMULTI
returns a list of result values which the user
has edited and acknowledged by pressing the `Ok' button.
Each result value of a field has the same format as the one for
the initial value, e.g. for a choice list field the result value is
the index of the selected item (or NIL if no item has been
selected), or for an options field the result value is
a list of integers representing the indices of the selected items.
For static text a value of NIL is returned.
E.g. if you have specified a date field, a static text field, a choice field, an options field, and a string field with initial value "world", and the user has entered 11.11.1999, selected the choice entry with index number 2, selected the 3rd and 4th item in the options field, and left the string field untouched then the function returns the list ( 11.11.1999 NIL 2 ( 3 4 ) "world" ).
If the user cancels the requester, NIL is returned.
(ASKMULTI "Please edit:" NIL (LIST (LIST "N_ame" "String" "") (LIST "_Birthday" "Date" NIL) (LIST "_Sex" "Choice" 0 (LIST "male" "female")) (LIST "_Has car?" "Bool" NIL) (LIST "_Likes", "Options" (LIST 0 2) (LIST "Beer" "Wine" "Whisky" "Wodka" "Schnaps") )) )
Please see also the project `AskDemo.mb' for further examples.
This sections lists functions and variables for input and output (e.g. printing) of data.
FOPEN
opens a file for reading/writing.
(FOPEN
filename mode)
Opens the file specified by filename (string). The mode parameter (string) controls the access mode. Use `"w"' to open a file for writing, `"a"' to append to a file, and `"r"' for reading from a file. You may also use other flags (or combination of flags) like `"r+"' for reading and writing. There is no check done that tests if you have specified a valid flag string. However if the file can't be opened, NIL is returned.
FOPEN
returns a file handle on success. On failure NIL is returned.
If filename or mode are NIL then NIL is returned.
Example: `(FOPEN "PRT:" "w")' opens and returns a file handle to the printer.
See also FCLOSE, stdout, FFLUSH.
FCLOSE
closes a file.
(FCLOSE
file)
Closes the given file. Returns 0 on success, NIL if an error has occurred. If file is NIL then 0 is returned (no error). After closing a file accessing the file handle is an illegal operation and results in aborting program execution with an error message.
The global variable stdout
holds the file handle
to MUIbase's standard output file.
The output filename can be set in menu item `Program - Output file'.
You may use `PRT:' here for sending the output to your printer,
or `CON:////Output/CLOSE/WAIT' for printing into a console window.
On the first access of this variable (either directly, e.g. by calling `(FPRINTF stdout ...)', or indirectly, e.g. by calling `(PRINTF ...)', this file is opened. The file is not pre-opened on program execution. This avoids opening the file when no output is generated, e.g. when you simply want to do some calculations and change some record contents.
If MUIbase can't open the program output file then execution is aborted and an error message is generated.
PRINT
converts an expression to a string and prints it.
)
Converts the value of elem to a readable string and prints it to stdout
.
This function mainly exists for debug purposes.
PRINTF
prints a formatted string.
(PRINTF
format [expr ...])
Formats a string using the given format string and arguments and prints it
to stdout
.
Formatting is done like in SPRINTF
(see section SPRINTF).
PRINTF
returns the number of output characters or NIL on failure.
If format is NIL then NIL is returned.
Example: `(PRINTF "%i days and %i week" 7 1)' prints the string
"7 days and 1 week" to stdout
and returns 17.
See also PRINT, FPRINTF, stdout.
FPRINTF
prints a formatted string to a file.
(FPRINTF
file format [expr ...])
Formats a string using the given format string and arguments and prints it
to the specified file.
Formatting is done like in SPRINTF
(see section SPRINTF).
FPRINTF
returns the number of output characters or NIL on failure.
If file is NIL then FPRINTF
still returns the number of
potentially written characters but no output is actually written.
If format is NIL then NIL is returned.
FERROR
checks if an file I/O error has occurred.
(FERROR
file)
returns TRUE if an error for the given file has occurred, NIL otherwise.
FGETCHAR
reads a character from a file.
(FGETCHAR
file)
Returns the next character from the given file as a string or NIL if file is NIL, end of file has been reached, or an error has happened. If the next character is a null character, an empty string is returned.
See also FGETCHARS, FGETSTR, FPUTCHAR.
FGETCHARS
reads characters from a file.
(FGETCHARS
num file)
returns a string containing the next num characters from the given file. If end of file has been reached before reading num characters or if a null character has been read then only these characters are returned. If num or file are NIL, num is negative, end of file has been reached before reading the first character, or a read error has happened then NIL is returned.
FGETSTR
reads a string from a file.
(FGETSTR
file)
returns the next line of the given file as a string or NIL if file is NIL, end of file has been reached, or an error happened. The end of a line is detected if either a newline character or a null character is read, or if end of file is detected. In either case the string does not contain any newline characters.
See also FGETCHAR, FGETCHARS, FGETMEMO, FPUTSTR.
FGETMEMO
reads a memo from a file.
(FGETMEMO
file)
returns a memo that contains the contents of the given file up to the next null character or up to the end of file. If file is NIL, end of file has been reached before reading any characters, or an error occurred then NIL is returned.
FPUTCHAR
writes a character to a file.
(FPUTCHAR
str file)
Writes the first character of str to the given file. If str is empty, a null character is written, if str or file are NIL, nothing happens. Returns str or NIL in case an output error occurred.
FPUTSTR
writes a string to a file.
(FPUTSTR
str file)
Prints str together with a newline character to the given file. If str or file are NIL, nothing happens. Returns str or NIL in case an output error occurred.
See also FPUTCHAR, FPUTMEMO, FGETSTR.
FPUTMEMO
writes a memo to a file.
(FPUTMEMO
memo file)
Prints memo to the given file. If memo or file are NIL, nothing happens. Returns memo or NIL in case an output error occurred.
FFLUSH
flushes pending data to a file.
(FFLUSH
file)
Flushes all pending output for the given file. Returns 0 on success, NIL if an error occurred. If file is NIL then 0 is returned (no error).
This section lists functions that deal with records.
NEW
allocates a new record for a table.
(NEW
table init)
Allocates a new record in the given table. The parameter init specifies the record which should be used for initializing the new record. A value of NIL stands for the initial record.
NEW
returns a record pointer to the new record.
The NEW
function has the side effect of setting the
program record pointer of the given table (see section Tables)
to the new record.
Example: `(NEW table NIL)' allocates a new record in the given table and initializes it with the initial record.
See also NEW*, DELETE, Tables.
NEW*
is the star version of NEW
(see section NEW).
(NEW*
table init)
NEW*
checks if you have specified a `New' trigger
function for the given table (see section New trigger).
If so then this trigger function is called for allocating
the record and its result is returned.
The init parameter can be used to specify a record with
which the new record should be initialized (use NIL for the
initial record).
If no trigger function has been specified, the function behaves like
the NEW
function.
Warning: With this function it is possible to write endless loops, e.g.
if you have defined a `New' trigger function for a table
and this function calls NEW*
to allocate the record.
DELETE
deletes a record in a table.
(DELETE
table requester)
Deletes the current program record of the given table after an optional delete requester. The first argument specifies the table for which the current program record should be deleted, the second argument is a boolean expression. If it is NIL then the record is deleted silently, if it is not NIL then the state of preferences menu item `Record delete requester' is checked. If it is not set, the record is deleted silently, otherwise the standard delete requester appears asking for confirmation. If the users cancels the delete operation then the record will not be deleted.
The return code of the DELETE
function
reflects the selected action. If it returns TRUE then
the record has been deleted, otherwise (the user
has canceled the operation) NIL is returned.
On deletion, DELETE
sets the program record pointer
(see section Tables) of the specified table to NIL.
Example: `(DELETE table NIL)' deletes the current record in the given table silently.
See also DELETE*, DELETEALL, NEW, Tables.
DELETE*
is the star version of DELETE
(see section DELETE).
(DELETE*
table requester)
DELETE*
checks if you have specified a `Delete' trigger
function for the given table (see section Delete trigger).
If so then this trigger function is called for deleting
the record and its result is returned.
The requester parameter can be used to specify
if the trigger function should pop up a confirmation requester
before deleting the record.
If no trigger function has been specified, the function behaves like
the DELETE
function.
Warning: With this function it is possible to write endless loops, e.g.
if you have defined a `Delete' trigger function for a table
and this function calls DELETE*
to delete the record.
See also DELETE, DELETEALL, NEW*.
DELETEALL
deletes all records of a table.
(DELETEALL
table[*
])
Deletes all records of the specified table. If you add a star behind the table name then only those records that match the current filter of the table are deleted. There is no saftey requester before deleting the records.
DELETEALL
returns TRUE on successful deletion of all records,
otherwise NIL is returned. If table is NIL then NIL is returned.
Example: `(DELETEALL table*)' deletes all records in the given table that match the filter of the table.
GETMATCHFILTER
returns the match-filter state of a record.
(GETMATCHFILTER
rec)
Returns TRUE if the specified record matches the filter of its table, NIL otherwise. If the filter of the table is currently not active then TRUE is returned. If rec is NIL (the initial record) then NIL is returned.
See also SETMATCHFILTER.
SETMATCHFILTER
sets the match-filter state of a record.
(SETMATCHFILTER
rec on)
Changes the match-filter state of the specified record
to the value of on.
SETMATCHFILTER
returns the new match-filter state of the given record.
The new state may be different from the expected one because setting the
match-filter state to NIL does only work when the filter of the corresponding
table is currently active, otherwise TRUE is returned.
Calling SETMATCHFILTER
with a value of NIL for rec
(the initial record) will always return NIL.
See also GETMATCHFILTER.
RECNUM
returns the record number of a record.
(RECNUM
record)
Returns the record number of the given record. Please note that the numbering for records is different than e.g. for lists. For lists, strings and others the counting begins with zero, however for records it begins with 1 for the first record. The number 0 is reserved for the initial record. This seems to be inconsistent with the rest of the MUIbase programming functions, but it does really makes sense here as the record numbers are also used in the window display.
COPYREC
copies records.
(COPYREC
rec source)
Copies the contents of record source to record rec. If source is NIL then rec is set to the values of the initial record. If rec is NIL then an error message is generated.
COPYREC
returns rec.
See also NEW.
This section lists functions that work on attributes of a table.
ATTRNAME
returns the name of an attribute.
(ATTRNAME
attr)
Returns a string containing the name of the specified attribute.
See also TABLENAME
MAXLEN
returns the maximum size of a string attribute.
(MAXLEN
string-attr)
Returns the maximum number of characters that the given string attribute can hold.
See also LEN.
GETLABELS
returns all labels of a choice or string attribute.
(GETLABELS
attr)
Returns the labels of the given choice or string attribute. In case of a choice attribute, the labels you entered in the attribute requester (see section Type specific settings) are returned, in case of a string attribute, the labels you entered for the list-view pop-up (see section Attribute object editor) are returned.
The labels are returned in one single string and are separated by newline characters.
For example, consider you have a choice attribute with the labels
`Car', `House', and `Oil'.
Then calling GETLABELS
on that attribute will result to
the string "Car\nHouse\nOil".
Note: you can easily convert the result string to a list by
calling MEMOTOLIST
(see section MEMOTOLIST) on the result string.
See also SETLABELS.
SETLABELS
is used to set the labels of a string attribute.
(SETLABELS
attr str)
Sets the labels of the string attribute attr to the labels listed in the str argument. The str argument consists of lines each of which holds one label. The labels replace the ones you have entered for the pop-up list-view in the attribute object editor (see section Attribute object editor).
SETLABELS
returns the value of its str argument.
Example: `(SETLABELS Table.String "My house\nis\nyour house")' sets the list-view labels of the specifies string attribute to `My house', `is', and `your house'.
Note: you can easily convert a list of labels to the required string format by calling section LISTTOMEMO on the list.
See also GETLABELS.
TABLENAME
returns the name of a table.
(TABLENAME
table)
Returns a string containing the name of the specified table.
See also ATTRNAME
GETORDERSTR
returns the record order of a table.
(GETORDERSTR
table)
Returns the current order expression of the given table. The returned string contains the attribute names used for ordering separated by spaces. Each attribute name is prepended by a `+' or a `-' sign indicating ascending or descending order. An empty string means no ordering.
Consider a table `Person' which is ordered by the Attributes `Name' (ascending), `Town' (ascending), and `Birthday' (descending). Then `(ORDERSTR Person)' will result to the string "+Name +Town -Birthday".
See also SETORDERSTR.
SETORDERSTR
sets the record order of a table.
(SETORDERSTR
table order)
Sets the order of the given table to the attributes in the order string. The order string must contain the attribute names used for ordering separated by any number of spaces, tabs or newlines. Each attribute name may be prepended by a `+' or a `-' sign indicating ascending or descending order. If you omit this sign then ascending ordering is assumed.
SETORDERSTR
returns TRUE if it has been able to set the new order,
NIL otherwise, e.g. if an unknown attribute has been specified
or the type of the attribute is not allowed for ordering.
If you specify NIL for the order argument then nothing
happens and NIL is returned.
Note: For building the order string you should not directly write the
attribute names into the string because when you change
an attribute name then the order string will not be updated.
Better use the ATTRNAME
function (see section ATTRNAME)
to copy the attribute's name into the order string.
Consider a table `Person' with the attributes `Name', `Town', and `Birthday'. Then `(SETORDERSTR Person (SPRINTF "+%s" (ATTRNAME Person.Name)))' will set the order of table `Person' using `Name' as (ascending) order attribute.
See also GETORDERSTR.
GETFILTERACTIVE
returns the filter state of a table.
(GETFILTERACTIVE
table)
Returns TRUE if the filter of the specified table is currently activated and NIL otherwise.
See also SETFILTERACTIVE, GETFILTERSTR, GETMATCHFILTER.
SETFILTERACTIVE
sets the filter state of a table.
(SETFILTERACTIVE
table bool)
Sets the filter state of the specified table. If bool is non-NIL then the filter is activated, otherwise it is deactivated.
SETFILTERACTIVE
returns the new state of the filter.
The new state may not be the expected one in case you activate
the filter but an error condition occurs and the filter can't be
activated.
However deactivating the filter always succeeds.
See also GETFILTERACTIVE, SETFILTERSTR, SETMATCHFILTER.
GETFILTERSTR
returns the record filter expression of a table.
(GETFILTERSTR
table)
Returns the record filter expression of the specified table as a string. An empty string means that no filter expression has been set for this table.
See also SETFILTERSTR, GETFILTERACTIVE, GETMATCHFILTER.
SETFILTERSTR
sets the record filter expression of a table.
(SETFILTERSTR
table filter-str)
Sets the record filter expression of the specified table to the expression in the filter-str argument. If the filter of the given table is currently active then the new filter expression is directly applied to all records and the match-filter state of all records are recomputed.
SETFILTERSTR
returns TRUE if it has been able to compile
the given filter string expression, otherwise NIL is returned.
Note that you only get the result of the compilation.
If the filter of the given table is currently active and
recomputing all match-filter states of the corresponding
records fails then you will not notice that from the result
of this function.
The recommended way to set a new filter expression is
like follows:
(SETFILTERACTIVE Table NIL) ; always succeeds. (IF (NOT (SETFILTERSTR Table filter-string)) (ERROR "Can't set filter string for %s!" (TABLENAME Table)) ) (IF (NOT (SETFILTERACTIVE Table TRUE)) (ERROR "Can't activate filter for %s!" (TABLENAME Table)) )
If SETFILTERSTR
is called with a value of NIL for
the filter-str argument then nothing happens and NIL is returned.
Example: `(SETFILTERSTR Table "(> Value 0.0)")'.
See also GETFILTERSTR, SETFILTERACTIVE, SETMATCHFILTER.
RECORDS
returns the number of records in a table.
(RECORDS
table)
Returns the number of records in the given table. You may append a star to the table name for counting the number of records that match the filter of the table.
RECORD
returns a record pointer for a given record number.
(RECORD
table num)
Returns the record pointer to the num-th record in the given table or NIL if a record with this number doesn't exist. You may add a star to the table name to get the num-th record that matches the record filter of the table.
Please note that record numbers start with 1 and record number 0 is used for the initial record.
SELECT
extracts and returns various data from records.
(SELECT
[DISTINCT
] exprlistFROM
tablelist [WHERE
where-expr] [ORDER BY
orderlist])
where exprlist is either a simple star `*' or a list of expressions with optional titles separated by commas:
exprlist:*
| expr"title",
...
and tablelist is a list of table names:
tablelist: table[*
] [ident
],
...
For each table in the table list you can specify an identifier. This can be very useful if a table occurs more than once in the table list (see example of comparing ages below). If you add a star to a table then only the records matching the currently defined filter of that table will be examined.
The orderlist has the following syntax:
orderlist: expr [ASC
|DESC
],
...
where expr, ... can be arbitrary expressions or field numbers.
For example `(SELECT Name FROM ... ORDER BY 1)'
will sort the result by the `Name' attribute.
You may specify ASC
or DESC
for an
ascending or descending order.
If none of them are present then an ascending order is assumed.
The select-from-where query builds the (mathematical) cross product of all tables in the table list (it examines all sets of records in table, ...) and checks the where-expression (if any). If the where-expression results to TRUE (or there is no where-expression) then a list is build whose elements are calculated by the expression list in the select-part. If you have specified a single star for the expression list then the list contains the values of all attributes belonging to tables in the table list (except virtual attributes and buttons).
The result of the query is a list of lists. The first list entry contains the title strings, the remaining ones contain the values of the from-list in the matching records.
See section Query examples for some examples using the SELECT
function.
See also FOR ALL.
This section describes functions for manipulating gui elements.
SETCURSOR
sets the cursor on a gui element.
(SETCURSOR
attr-or-table)
Sets the cursor on the given attribute or table gui object. The function also opens the window where the attribute/table resides in if the window was not open.
SETCURSOR
returns TRUE if everything went ok
(window could be opened) or NIL on failure.
GETDISABLED
returns the disabled state of an attribute.
(GETDISABLED
attr)
Returns the disabled state of the specified attribute in the current record.
See also SETDISABLED, GETWINDOWDISABLED.
SETDISABLED
sets the disabled state of an attribute.
(SETDISABLED
attr bool)
Sets the disabled state of the specified attribute in the current record to the value of bool. Returns the new value of the disabled state.
See also GETDISABLED, SETWINDOWDISABLED.
GETWINDOWDISABLED
returns the disabled state of a window.
(GETWINDOWDISABLED
attr-or-table)
Returns the state of the disabled flag of the window in which the specified attribute or table resides. If the attribute of table resides in the root window then NIL is returned.
See also SETWINDOWDISABLED, GETWINDOWOPEN, GETDISABLED.
SETWINDOWDISABLED
sets the disabled state of a window.
(SETWINDOWDISABLED
attr-or-table disabled)
Sets the state of the disabled flag of the window button in which the specified attribute or table resides to the value of disabled. If you disable a window, the window is closed and the corresponding window button is disabled. You can't disable the root window of a project.
SETWINDOWDISABLED
returns the new state of the window's
disabled flag.
See also GETWINDOWDISABLED, SETWINDOWOPEN, SETDISABLED.
GETWINDOWOPEN
returns the open state of a window.
(GETWINDOWOPEN
attr-or-table)
Returns the open state of the window where the given attribute/table resides.
See also SETWINDOWOPEN, GETWINDOWDISABLED.
SETWINDOWOPEN
opens and closes a window.
(SETWINDOWOPEN
attr-or-table open)
Opens or closes the window in which the given attribute/table resides. If open is non-NIL then the window is opened, otherwise it is closed. You cannot close the root window of a project.
SETWINDOWOPEN
returns the new open state of the window.
See also GETWINDOWOPEN, SETWINDOWDISABLED.
This section lists functions dealing with projects.
PROJECTNAME
returns the project name.
(PROJECTNAME)
PROJECTNAME
returns the name of the current project as a string
or NIL if no name has been defined yet.
See also CHANGES.
CHANGES
returns the number of changes in the current
project.
(CHANGES)
Returns an integer containing the number of changes since the last save operation of the current project.
See also PROJECTNAME.
This section lists functions accessing the operating system.
EDIT
launches the external editor.
(EDIT
filename)
Starts the external editor for editing the specified file.
The external editor can be set in menu item
`Preferences - External editor' (see section External editor).
EDIT
starts the external editor asynchronously, that is,
the function returns to the caller immediately.
EDIT
returns TRUE if it was successful in starting the editor,
else it returns NIL.
EDIT*
is the star version of EDIT
and has the same
effect as EDIT
(see section EDIT).
The only difference is that EDIT*
starts the external editor
synchronously and waits until the user exits the editor.
VIEW
launches the external viewer.
(VIEW
filename)
Starts the external viewer for displaying the specified file.
The external viewer can be set in menu item
`Preferences - External viewer' (see section External viewer).
VIEW
starts the external viewer asynchronously, that is,
the function returns to the caller immediately.
VIEW
returns TRUE if it was successful in starting the viewer,
else it returns NIL.
VIEW*
is the star version of VIEW
and has the same
effect as VIEW
(see section VIEW).
The only difference is that VIEW*
starts the external viewer
synchronously and waits until the user exits the viewer.
SYSTEM
calls an external program.
(SYSTEM
fmt [arg ...])
Calls an external program. The command line to call the program is
generated from fmt and the optional arguments like in
the SPRINTF
function (see section SPRINTF).
SYSTEM
waits until the called program exits.
If you don't want SYSTEM
to wait then use a command
line that starts the program in the background.
SYSTEM
returns TRUE on success and NIL on failure, e.g. when the
command line could not be executed or the called command returned an
error code.
Example: `(SYSTEM "run %s %s" "clock" "digital")' launches the system's clock in digital mode.
See also EDIT, EDIT*, VIEW, VIEW*.
STAT
examines a filename.
(STAT
filename)
Examines if the specified filename exists in the file system.
STAT
returns NIL if the filename could not be found,
0 if the filename exists and is a directory, and an integer
value greater than 0 if the filename exists and is a regular file.
TACKON
creates a pathname.
(TACKON
dirname filename)
Joines dirname and filename to a pathname.
TACKON
knows how to deal with colons and slashes in
dirname. It returns the pathname as a string or NIL if
dirname or filename is NIL.
Example: `(TACKON "Sys:System" "CLI")' results to "Sys:System/CLI".
FILENAME
extracts the filename part of a path name.
(FILENAME
path)
Extracts the last component of the given path name.
There is no check whether path actually refers to a file,
thus it is also possible to use FILENAME
to
get the name of a sub-directory.
FILENAME
returns its result as a string or NIL if
path is NIL.
Example: `(FILENAME "Sys:System/CLI")' results to "CLI".
DIRNAME
extracts the directory part of a path name.
(DIRNAME
path)
Extracts the directory part of the given path name.
There is no check whether path actually refers to a file,
thus it is also possible to use DIRNAME
to
get the name of a parent directory.
DIRNAME
returns its result as a string or NIL if
path is NIL.
Example: `(DIRNAME "Sys:System/CLI")' results to "Sys:System".
TODAY
returns the current date.
(TODAY)
Returns the current date as a date value.
See also NOW.
NOW
returns the current time.
(NOW)
Returns the current time as a time value.
See also TODAY.
MESSAGE
displays a message to the user.
(MESSAGE
fmt [arg ...])
Sets the window title of the pause/abort window (if it is open).
The title string is generated from fmt and the optional arguments
like in the SPRINTF
function (see section SPRINTF).
MESSAGE
returns the formatted title string.
Example: `(MESSAGE "6 * 7 = %i" (* 6 7))'.
GC
forces garbage collection.
(GC)
Forces garbage collection and returns NIL. Normally garbage collection is done automatically from time to time.
MUIbase knows some pre-defined global variables.
In the current version there exists only one global variable: stdout
(see section stdout).
The following pre-defined constants can be used in any expression for programming.
Name Type Value Comment -------------------------------------------------------------------------NIL
any NILTRUE
bool TRUERESET
string "\33c"NORMAL
string "\33[0m"ITON
string "\33[3m"ITOFF
string "\33[23m"ULON
string "\33[4m"ULOFF
string "\33[24m"BFON
string "\33[1m"BFOFF
string "\33[22m"ELITEON
string "\33[2w"ELITEOFF
string "\33[1w"CONDON
string "\33[4w"CONDOFF
string "\33[3w"WIDEON
string "\33[6w"WIDEOFF
string "\33[5w"NLQON
string "\33[2\"z"NLQOFF
string "\33[1\"z"INT_MAX
integer 2147483647 Maximum integer valueINT_MIN
integer -2147483648 Minimum integer valueHUGE_VAL
real 1.797693e+308 Largest absolute real valuePI
real 3.14159265359OSVER
integer <OS version>OSREV
integer <OS revision>MBVER
integer <MUIbase version>MBREV
integer <MUIbase revision>LANGUAGE
string depends Default language.
See section Constants, for more information about constants.
For defining your own constants, use the #define
preprocessing directive (see section #define).
You can pass a function as an argument to another function. This is useful for defining functions of higher order, e.g. for sorting or mapping a list.
To call a function that has been passed in an argument you have
to use the FUNCALL
function (see section FUNCALL).
(DEFUN map (l fun) # arguments: list and function (LET (res) # local variable res, initialized with NIL (DOLIST (i l) # for all items one by one (SETQ res (CONS (FUNCALL fun i) res) # apply function and ) # build new list ) (REVERSE res) # we need to reverse the new list ) )
You can now use the map function for example to increment all items of a list of integers:
`(map (LIST 1 2 3 4) 1+)' results to ( 2 3 4 5 ).
It is possible to specify the type of a local variable by adding a type specifier behind the name. The following type specifiers exist:
Specifier Description :INT for integers :REAL for reals :STR for strings :MEMO for memos :DATE for dates :TIME for times :LIST for lists :FILE for file handles :FUNC for functions of any type :table for record pointers to table
The type specifier appends the variable name as in the following example:
(LET (x:INT (y:REAL 0.0) z) ...)
The example defines three new variables `x', `y' and `z', where `x' is of type integer and initialized with NIL, `y' is of type real and initialized with 0.0, and `z' is an untyped variable initialized with NIL.
The advantage of the type specifiers is that the compiler can detect more type errors, e.g. if you have a function:
(DEFUN foo (x:INT) ...)
and call it with `(foo "bar")' then the compiler generates an error message. However, if you call `foo' with an untyped value, e.g. `(foo (FIRST list))' then no error checking can be done at compile time because the type of `(FIRST list)' is unknown.
For reasons of speed no type checking is currently done at run time. It could be implemented but then would add a little overhead which is not really necessary as the wrong type will result in a type error sooner or later anyway.
Type specifiers for record pointers have another useful feature. If you tag a variable as a record pointer to a table then you can access all attributes of this table by using the variable name instead of the table name in the attribute path. E.g. if you have a table `Foo' with an attribute `Bar', and you define a variable `foo' as:
(LET (foo:Foo)
then you can print the `Bar' attribute of the third record by using:
(SETQ foo (RECORD Foo 3)) (PRINT foo.Bar)
Note that in a select-from-where expression, variables defined in the from list automatically have a type of record pointer to the corresponding table.
The semantics of expressions are very important for understanding what a program does. This section lists the semantics depending on syntactical expressions.
(
func [expr ...])
AND
, OR
and IF
.
These functions may not evaluate all expressions.
For more information about non-strict functions, see section Lisp syntax,
section AND, section OR, and section IF.
(
[expr ...])
()
evaluates to NIL.
LET
(see section LET).
For automatic execution of MUIbase programs you can specify trigger functions for projects, tables and attributes which are called in specific cases. This section lists all available trigger possibilities.
After opening a project, MUIbase searches the project's program
for a function called onOpen
.
If such a function exists then this function is called without
any arguments.
(DEFUN onOpen () (ASKBUTTON NIL "Thank you for opening me!" NIL NIL) )
See also onClose, onChange, demo `Trigger.mb'.
Before closing a project, MUIbase searches the project's program
for a function called onClose
.
If such a function exists then this function is called without
any arguments. In the current version the result of the
trigger function is ignored and the project is closed regardless
of its return value.
If you do changes to the project in the onClose
function
then MUIbase will ask you for saving the project first before
it is actually closed. If you use menu item `Project - Save & Close'
for closing the project, the trigger function is called before
saving the project, thus the changes are saved automatically.
(DEFUN onClose () (ASKBUTTON NIL "Good bye!" NIL NIL) )
See also onOpen, onChange, demo `Trigger.mb'.
Whenever the user makes changes to a project or after saving a project,
MUIbase searches the project's program for a function called
onChange
.
If such a function exists then this function is called without
any arguments. This can be used to count the changes a user
does to a project.
(DEFUN onChange () (SETQ Control.NumChanges (CHANGES)) )
In the above example `Control.NumChanges' could be a virtual attribute somewhere in an `exactly-one-record' table for displaying the project's number of changes.
See also onOpen, onClose, demo `Trigger.mb'.
When the user wants to allocate a new record by selecting one of the menu items `New record' or `Duplicate record' and the `New' trigger of that table has been set to a MUIbase program function then this trigger function is executed. The `New' trigger function can be set in the table requester (see section Creating tables).
The trigger function receives NIL or a record pointer as the first
and only argument. NIL means that the user wants to allocate a
new record, a record pointer means that the user wants to duplicate
this record. If the trigger function has more than one argument
then these are initialized with NIL. The trigger function should
allocate the new record by calling the NEW
function (see section NEW).
The result returned by the trigger function will be examined.
If it returns a record pointer then this record will be displayed.
The `New' trigger is also called when a MUIbase program calls
the NEW*
function (see section NEW*).
(DEFUN newRecord (init) (PROG1 ; for returning the result of NEW (NEW Table init) ... ) )
See also NEW*, Delete trigger.
When the user wants to delete a record by selecting menu item `Delete record' and the `Delete' trigger of that table has been set to a MUIbase program function then this trigger function is executed. The `Delete' trigger function can be set in the table requester (see section Creating tables).
The trigger function receives a boolean argument as its only argument.
If the argument is non-NIL then the function should ask the user
if he really wants to delete the record. If so, the function should
call DELETE
(see section DELETE) for deleting the record.
The `Delete' trigger is also called when a MUIbase program calls
the DELETE*
function (see section DELETE*).
(DEFUN deleteRecord (requester) (DELETE Table requester) )
See also DELETE*, New trigger.
In the attribute requester (see section Creating attributes) you can define a trigger function that is called whenever the user wants to change the attribute contents.
If you have defined such a trigger function for an attribute and
the user changes the value of that attribute then
the record contents are not automatically updated with the new value.
Instead the value is passed to the trigger function as first argument.
The trigger function can now check the value and may refuse it.
To store the value in the record you have to use the SETQ
function.
The trigger function should return the result of the SETQ
call or the old value of the attribute if it decides to refuse
the new one.
The trigger function is also called when a MUIbase program calls
the SETQ*
function (see section SETQ*) for setting a value
to the attribute.
(DEFUN setAmount (amount) (IF some-expression (SETQ Table.Amount amount) (ASKBUTTON NIL "Invalid value!" NIL NIL) ) Table.Amount ; return current value )
See also SETQ*
In MUIbase virtual attributes are special attributes that calculate their value on the fly whenever it is needed. E.g. if you go to another record by clicking on one of the arrow buttons in a table's panel bar and a virtual attribute in that table has its `Immediate' flag (see section Attribute object editor) set then the value of that attribute is computed and displayed. For computing the value the attribute's `Compute' trigger function is called. This trigger function can be specified in the attribute requester (see section Type specific settings). The return value of this function defines the value of the virtual attribute. If you don't specify a `Compute' trigger function for a virtual attribute then the attribute's value is NIL.
You can also trigger the calculation of a virtual attribute by simply accessing it in an MUIbase program, so e.g. if you have a button that should compute the value of the virtual attribute, you only need to specify a function for the button like the following one:
(DEFUN buttonHook () virtual-attr )
You can also set a virtual attribute to any value by using
the SETQ
function:
(SETQ virtual-attr expr)
However if you access the virtual attribute after the SETQ
call
then the value of the virtual attribute is recomputed.
There is no caching of the value of a virtual attribute because it's not easy to know when the value has to be recomputed and when not. So you should access virtual attributes rarely and cache the value in local variables for further use yourself.
For an example on how to use virtual attributes please check the `Movie.mb' demo.
See also Virtual attributes, demo `Movie.db'.
Go to the first, previous, next, last section, table of contents.