SlickEdit Slick-C - Macro - Programming - Guide - Book

You are on page 1of 137

Slick-C Macro Programming

Guide

SlickEdit® Inc.
3000 Aerial Center Parkway, Suite 120
Morrisville, NC 27560 USA
www.slickedit.com
Information in this document is subject to change without notice and does not represent a
commitment on the part of SlickEdit Inc. The software described in this document is
protected by U.S. and international copyright laws and by other applicable laws, and may be
used or copied only in accordance with the terms of the license or nondisclosure agreement
that accompanies the software. It is against the law to copy the software on any medium
except as specifically allowed in the license or nondisclosure agreement. The licensee may
make one copy of the software for backup purposes. No part of this manual may be
reproduced or transmitted in any form or by any means, electronic or mechanical, including
photocopying, recording, or information storage and retrieval systems, for any purpose other
than the licensee's personal use, without the express written permission of SlickEdit Inc.

Copyright  1988-2003 SlickEdit Inc. All rights reserved.


Cover design copyright  by SlickEdit Inc.
Printed in the United States of America.

SlickEdit, Visual SlickEdit and Clipboard Inheritance are registered trademarks of SlickEdit
Inc. Context Tagging, DIFFzilla, Dynamic Difference Editing and SmartPaste are trademarks
of SlickEdit Inc. All other trademarks are the property of their respective owners. Protected
by U.S. Patent 5,710,926.

ISBN 0-9716563-8-X
Contents

Contents
Contents.............................................................................................................................. 1
Introduction ....................................................................................................................... 1
About This Guide ......................................................................................................... 1
Intended Audience................................................................................................ 1
Key Conventions .................................................................................................. 1
Additional Visual SlickEdit Documentation ................................................................ 2
Contacting SlickEdit Inc. ............................................................................................ 2
Slick-C Overview ............................................................................................................... 3
Some History ................................................................................................................ 3
A Recurring Theme .............................................................................................. 3
Recognizing Problems in C++ ............................................................................. 3
Why Slick-C ......................................................................................................... 4
Work Still to be Done............................................................................................ 5
Container Variable Sample Code ......................................................................... 5
Getting Started by Example ............................................................................................. 8
A Key Bindable Command .......................................................................................... 8
An Event Driven Dialog Box....................................................................................... 9
A Batch Macro ........................................................................................................... 10
Compiling and Loading Macros..................................................................................... 12
Language Constructs....................................................................................................... 13
Comments .................................................................................................................. 13
String Literals............................................................................................................. 13
Numeric Constants ..................................................................................................... 14
Defining Constants..................................................................................................... 15
Mathematical Operators............................................................................................. 16
Assignment Operator ................................................................................................. 19
Scoping and Declaring Variables............................................................................... 19
Simple Variables ................................................................................................ 20
Details About Variable Initializations ................................................................ 21
struct ................................................................................................................... 21
Differences from C++................................................................................. 22
union ................................................................................................................... 23
Anonymous Unions ............................................................................................ 24
Arrays ................................................................................................................. 24
Differences from C++................................................................................. 25
Hash Tables ........................................................................................................ 25
Pointers Variables............................................................................................... 26
Differences from C++................................................................................. 27
Pointers to Functions .......................................................................................... 27
Differences from C++ ................................................................................. 28
Type Casting .............................................................................................................. 28
Differences from C++................................................................................. 29

i
Contents

How Typeless Container Variables Work ................................................................. 29


The IF Statement........................................................................................................ 30
Statement Block ......................................................................................................... 31
Loops .......................................................................................................................... 31
Switch Statement ........................................................................................................ 33
Functions.................................................................................................................... 34
Defining a Procedure.......................................................................................... 34
Argument Declarations ....................................................................................... 34
Default Arguments ............................................................................................. 35
Defining a Command ......................................................................................... 36
name_info Attributes .......................................................................................... 38
Function Prototypes ............................................................................................ 40
What is a Built-in Function? .............................................................................. 40
Where Are the Functions? .................................................................................. 40
Differences Between Commands, Built-ins, and Procs ...................................... 41
defmain. Writing Slick-C Batch Files ....................................................................... 41
Preprocessing ............................................................................................................. 43
Pragma ....................................................................................................................... 44
Including Header Files ............................................................................................... 45
Defining Controls ....................................................................................................... 45
Defining Events and Event Tables............................................................................. 46
def primitive ....................................................................................................... 46
Event Driven Dialog Boxes ................................................................................ 48
Module Initializations ................................................................................................ 49
Debugging Macros ........................................................................................................... 51
Finding Procedures .................................................................................................... 51
Finding Runtime Errors ............................................................................................. 51
Creating Dialog Boxes with the Dialog Editor .............................................................. 52
Dialog Box Creation Overview .................................................................................. 52
Dialog Editor Summary ............................................................................................. 53
Creating a Form ......................................................................................................... 55
Adding Controls ......................................................................................................... 55
Adding Event Handlers .............................................................................................. 57
Loading and Running the Form ................................................................................. 57
Saving a Form .................................................................................................... 58
Adding a Cancel Button ............................................................................................. 58
Adding an OK Button and Closing a Dialog Box...................................................... 58
Displaying Dialog Boxes ........................................................................................... 59
Clipboard Inheritance ................................................................................................. 64
How Visual SlickEdit's File Open Dialog Box was Built .................................. 66
Dialog Box Inheritance Order.................................................................................... 67
Objects and Instances ...................................................................................................... 69
The Active Object ...................................................................................................... 69
The Active Form ........................................................................................................ 69
Instance Expressions .................................................................................................. 69
Using Functions as Methods ...................................................................................... 70

ii
Contents

Built-in Controls .............................................................................................................. 72


Label Control ............................................................................................................. 72
Spin Control ............................................................................................................... 72
Text Box Control ....................................................................................................... 73
Editor Control ............................................................................................................ 74
Frame Control ............................................................................................................ 74
Command Button Control .......................................................................................... 74
Radio Button Control ................................................................................................. 74
Check Box Control ..................................................................................................... 75
Combo Box Control ................................................................................................... 75
List Box Control ......................................................................................................... 78
Vscroll Bar Control .................................................................................................... 80
Hscroll Bar Control .................................................................................................... 81
Drive List Control ...................................................................................................... 81
File List Box Control ................................................................................................. 81
Directory List Box Control ........................................................................................ 82
Picture Box Control ................................................................................................... 83
Gauge Control ............................................................................................................. 83
Image Control ............................................................................................................ 84
Adding a Bitmap Command Button or Check Box ............................................ 84
Adding Dialog Box Retrieval .......................................................................................... 87
Menus ................................................................................................................................ 88
Menu Macro Programming ........................................................................................ 88
Creating and Editing Menu Resources ............................................................... 88
Defining a Menu Resource ................................................................................. 88
Predefined Attributes For Auto-Enabling Commands ....................................... 89
Macro Callbacks for Enabling Commands......................................................... 90
Putting a Menu Bar on a Form ........................................................................... 91
Displaying a Menu as a Pop-up .......................................................................... 91
Common Dialog Boxes .................................................................................................... 93
String Functions Overview ............................................................................................. 94
Search Functions Overview ............................................................................................ 97
Buffer Input/Output Functions .................................................................................... 100
Selection Functions Overview ....................................................................................... 101
Writing Selection Filters .......................................................................................... 101
Unicode and SBCS/DBCS Macro Programming........................................................ 103
DLL Interface ................................................................................................................ 106
Shelling Programs from a Slick-C Macro ................................................................... 107
Hooking Exit and Other Events ................................................................................... 108
Invoking a Macro When Visual SlickEdit is Invoked ............................................. 108
Invoking a Macro Before Visual SlickEdit Terminates........................................... 108
Command Line Interfaces ............................................................................................ 109
Command Line Arguments...................................................................................... 109
get_string Procedure ................................................................................................ 109
Single Argument Prompting with Support for Prompt Style ................................... 110
State File Caching.......................................................................................................... 111

iii
Contents

Error Handling and the RC Variable.......................................................................... 112


Typical Mistakes ............................................................................................................ 113
Interpreter Error Handling .......................................................................................... 114
Event Names ................................................................................................................... 115
Differences Between Slick-C and C++ ......................................................................... 118
Structures ................................................................................................................. 118
Arrays....................................................................................................................... 118
Hash Tables ...................................................................................................... 119
Assignment Statement ...................................................................................... 119
Comparison Operator ....................................................................................... 119
Preprocessing.................................................................................................... 119
switch Statement............................................................................................... 119
Labeled Loops .................................................................................................. 119
Variable Argument Functions .......................................................................... 120
Built-in Graphics Primitives............................................................................. 120
Clipboard Inheritance ....................................................................................... 120
End of Statement. Semicolon .......................................................................... 120
Type Checking ................................................................................................. 120
Capability Not Supported by Slick-C ............................................................... 121
Windows Structure........................................................................................................ 122
Converting SlickEdit 2.3/2.4 Macros and Configuration .......................................... 125
Index ............................................................................................................................... 127
Reader’s Comments ..................................................................................................... 131

iv
Introduction

Introduction
About This Guide
This Slick-C Macro Programming Guide describes the features of the Slick-C programming
language, developed by SlickEdit Inc. Slick-C will allow you to extend the Visual
®
SlickEdit code editor by writing macros. Visual SlickEdit is the most comprehensive and
flexible code editor you can use. This guide is a companion piece to several products: Visual
SlickEdit and Visual SlickEdit Plug-In for WebSphere Studio & Eclipse.

Intended Audience
This guide is intended for anyone who uses Visual SlickEdit and would like to extend the
Visual SlickEdit code editor to customize and extend it beyond the built-in customability
features.

NOTE: Any item in the guide or online help that refers to UNIX also applies to Linux.

Key Conventions
Commands are specified in the following format: ("Search", "Find"). This means you
activate the menu bar (press ALT), select the "Search" menu bar word, and select the "Find"
menu item. The following keying conventions are used throughout this guide:

Action Convention Example

Type input from the keyboard Input shown in boldface Type vs

Press a key on the keyboard Key shown in uppercase Press ESC

Click a button on the screen Button shown in quotation marks Click “Save”

Click left or right mouse but- L” or “R”precedes the word “button” Click Rbutton
tons

Press a key combination Keys in uppercase, linked by “+” CTRL+=

Optional value Value enclosed in braces {value}

Your specified value Value shown in italics filename

Slick-C Macro Programming Guide 1


Introduction

Additional Visual SlickEdit Documentation


The complete Visual SlickEdit documentation set includes:

• Visual SlickEdit
- Visual SlickEdit User Guide (PDF and hardcopy manual)
- Visual SlickEdit Installation Guide (PDF and hardcopy manual)
- Slick-C Macro Programming Guide (PDF and hardcopy manual)
- Individual Quick Reference Sheets (PDFs) for the following emulations:
Brief, CodeWarrior, CUA, Epsilon, GNU Emacs, ISPF, SlickEdit (Text
Mode), VI, and Visual C++

• Visual SlickEdit Plug-In for WebSphere Studio & Eclipse


- Visual SlickEdit Plug-In for WebSphere & Eclipse User & Installation Guide
(PDF and hardcopy manual)
- Slick-C Macro Programming Guide (PDF and hardcopy manual)
- Individual Quick Reference Sheets (PDFs) for the following emulations:
Brief, CodeWarrior, CUA, Epsilon, GNU Emacs, ISPF, SlickEdit (Text
Mode), VI, and Visual C++

• Visual SlickEdit - OEM Edition


- Visual SlickEdit - OEM Edition: OEM Guide (PDF and hardcopy manual)
- User and Installation Guides for either Visual SlickEdit or Visual SlickEdit
Plug-In for WebSphere Studio & Eclipse (PDF and hardcopy manual)
- Slick-C Macro Programming Guide (PDF and hardcopy manual)
- Individual Quick Reference Sheets (PDFs) for the following emulations:
Brief, CodeWarrior, CUA, Epsilon, GNU Emacs, ISPF, SlickEdit (Text
Mode), VI, and Visual C++

Contacting SlickEdit Inc.


Patches and Macros: www.slickedit.com/support

Product Support: +1 919.473.0070 *


support@slickedit.com

Sales: 800.934.3348
+1 919.473.0070
sales@slickedit.com
Fax +1 919.473.0080

* NOTE: A current Maintenance and Support contract is required for telephone support
past the 30-day warranty period.

2 Slick-C Macro Programming Guide


Slick-C Overview

Slick-C Overview
Some History
Why did Microsoft decide to use the BASIC language as the extension language for products
such as Word and Excel? Why is Hypercard based on an English-like grammar with
container variables? Why did database companies develop their own languages instead of
using C++?

The answer is simple. The C and C++ languages are incomplete, difficult to use, and allow
developers to create unintended consequences too easily. While software products have all
become easier to use, why hasn't C++, the most popular object-oriented language, followed
suit?

When considering the alternatives for extending a graphical version of Visual SlickEdit, it
was very clear that DLLs written in C/C++ should not be the primary means. Extending the
editor had to be easier to use, safe, and preferably more portable. This was the reason
SlickEdit created the Slick-C language.

A Recurring Theme
The easier to use programming languages always seem to add one or more of the features
below to overcome problems in C++:

• Provide safe string processing which requires no memory management.


• Provide a language with more built-in primitives for building dialog boxes and
building a graphical user interface.
• Remove requirement to allocate and keep track of memory.
• Reduce or remove the need for pointers.
• Reduce need for declarations.
• Provide container variables for more easily passing around different kinds of
data.

To date some of the valiant attempts include Java, Delphi, Visual Basic, and Tcl/Tk.

Recognizing Problems in C++


In order to create something much better than C++, you must first understand its problems:

• Insufficient built-in types. No boolean, string, or container type.


• Too much memory management, especially for objects.
• No primitives for dialog boxes or building a graphical user interface.
• Overuse of pointers due to lack of language constructs.
• Lots of declaration data required even for the simplest program.

Slick-C Macro Programming Guide 3


Slick-C Overview

• Grammar is very large and ambiguous.

Why Slick-C
Slick-C has addressed a number of important problems in C++. The strongest features in
Slick-C are listed below:

• Language syntax is C++ with few major deviations. Unlike Java, you can pass
any type by reference or value as you would expect in C++.

• Many built-in language and compiler/linker features for building graphical user
interfaces. Language supports graphical resources such as dialog box
templates, menu templates, and bitmaps. A control type is built-in so that
compiler/linker detect references to controls which don't exist on a dialog box.

• Typed and untyped variables. A major problem with existing highly typed
object oriented languages such as C++ and Java is that they can't provide users
with a good container type variable. This makes these languages unsuitable for
simple editor macros, database applications, or shell scripts which don't need
the speed or rigidness of a highly typed language. How many times have you
heard someone first learning C++ say that they want to define a container class?
Then they find out it can't be done in any useful manner. Slick-C is highly
typed, but also provides a very powerful container type. See container variable
code samples below.

• Better built-in types. Arrays in Slick-C dynamically grow without requiring the
user to allocate memory. Hash tables (sometimes called associative arrays)
dynamically grow and can be pre-initialized similar to an array. A hash table is
an array which can be indexed with a string. One array or hash table can be
assigned to another as long as the types are compatible. The string type is much
more integrated into the language. String constants are converted to numeric
types and boolean (1 or 0) types. The switch statement supports string
expressions. There are separate string operators so you can determine whether
a string or numeric operation will be performed without knowing the variable
types.

• Clipboard Inheritance provides inheritance specifically for dialog boxes. This


feature allows you to copy parts of existing dialog boxes to the clipboard, paste
them elsewhere, and the original code still runs. New code can be attached to
the new controls without affecting the original controls. New code can be
added to the original controls to affect both instances of the controls; this is, of
course, inheritance. Creating inheritance for parts of dialog boxes is very
natural because the Slick-C language has been designed for this feature.

4 Slick-C Macro Programming Guide


Slick-C Overview

Work Still to be Done


Slick-C is not finished. What we have is the ground work for a powerful general purpose
programming language. To complete that language, it would need the following:

• C++ style classes. Like Java, classes in Slick-C will not require a delete to free
objects.

• Support for enum.

• Speed and size improvements for typed variables. Currently Slick-C has been
optimized for typeless container variables and strings. String concatenation is 5
times faster than Java. Integer arithmetic is 3 times slower than Java. Floating
point performance is much worse but can easily be optimized. Some of the
poor performance is due to the fact that Slick-C does 32 DIGIT integer and
floating point arithmetic. 64 bit longs and smaller floating point numbers
would really be big enough.

• Support for char and short types for conserving memory.

• Support for template classes. Container variables are sometimes a more


powerful mechanism (See sample code below) for accomplishing much of what
is done with template classes. However, users will likely want the speed and
additional type checking of template classes and many of us are already used to
template classes.

• instanceof operator like Java. This primitive is very important because it can
tell if a variable is an instance of a particular class which may be in the
inheritance chain. Currently, Slick-C has a _varformat() method, but it can't be
enhanced to traverse an inheritance chain.

• C++ code generation. That is, the ability to convert Slick-C code into source
code which can be compiled by any C++ compiler.

Container Variable Sample Code


These examples show what can be done in a language which truly supports typed variables
and untyped container variables.

Here is how to define a set of stack routines in Slick-C which support any type of element.

void stacknew(typeless &stack)


{
stack._makeempty(); // Destroy current contents of stack.
stack[0]=0; // Make an array and use first element as top count.
}
void stackpush(typeless &stack, typeless &value)
{

Slick-C Macro Programming Guide 5


Slick-C Overview

stack[++stack[0]]=value;
}
typeless stackpop(typeless &stack)
{
if (stack[0]<=0) return('');
// Make a copy of the element.
result=stack[stack[0]--];
// Free space allocated by value and delete array element. _deleteel is a
// built-in method which operates on arrays and hash tables.
stack._deleteel(stack[0]+1);
return(result);
}
defmain()
{
// The above routines can handle variables of any type, including string
constants.
struct RECORD {
int i;
_str s;
};
// You can't make a limit on the number of elements in an array.
// We will add support for initially allocating a specific number of elements.
RECORD arecord[];
arecord[0].i=4;arecord[0].s="element 0";
RECORD symboltable:[]; // Declare a hash table/associative array
symboltable:["name1"].i=1;symboltable:["name1"].s="element 0";
stacknew(stack);
stackpush(stack,arecord); // Push an array onto the stack
stackpush(stack,symboltable); // Push a hash table/associative array onto the
same stack
stackpush(stack,"string"); // Push a string constant onto the same stack
}

This example illustrates how a container variable can access structure members as an array.
This cannot be implemented elegantly in any other language.

/*
Read lines of a file which contains tab delimited data into an
array of structures. Each line represents an array structure element.
The tab delimited data on each line represents fields in the structure.
We will assume the file contains valid data for filling this structure.
*/
int ReadTable(_str filename,typeless (&table)[])
{
// Use an editor buffer to open and cache the file. Data is read
// in blocks from the file only. We don't need this much power, but
// Slick-C needs a few more non-editor file I/O functions.
status=_open_temp_view(filename,temp_view_id,orig_view_id);
if (status) return(status);
top();up(); // Place cursor on line 0 before first line of file.
for (j=0;;++j) {
if (down()) break;
get_line(line);
if (line:=="") continue;
rest=line;
p= &table[j]; //Make p point to this structure element.
// Here we access structure members as an array of elements
p->[0]="";

6 Slick-C Macro Programming Guide


Slick-C Overview

// Note that loop supports fields which are strings of length 0


for (i=0;;++i) {
if (rest:=="" && i) break;
// Parse is similar to REXX. We unable to come up with a function syntax
// that we were satisfied with so with went with a REXX style syntax.
// Place text up to but not included tab character into value variable.
// Place tab character and rest of data in rest variable.
parse rest with value "\t" +0 rest;
if (substr(rest,1,1):=="\t") {
rest=substr(rest,2);
}
p->[i]=value;
}
}
_delete_temp_view(temp_view_id);
activate_view(orig_view_id);
return(0);
}
struct TABLE_ENTRY{
_str name;
int value;
};
// defmain is the main entry pointer for a Slick-C batch/script macro
defmain()
{
TABLE_ENTRY table[];
// Table file should exist
// NOTE: (TABLE_ENTRY []) is type compatible with (typeless [])
status=ReadTable("table",table);
if (status) {
_message_box("Failed to read table file");
return(1);
}
_message_box("First record: name=":+table[0].name:+" value=":+table[0].value);
}

Slick-C Macro Programming Guide 7


Getting Started by Example

Getting Started by Example


There are three basic ways to extend Visual SlickEdit using Slick-C. You may either write a
key bindable command, an event driven dialog box, or a batch macro.

A Key Bindable Command


A key bindable command is the most common way to extend the editor. Command macros
may be bound to keys or invoked from a menu. When you use macro recording, Slick-C
source code is created for a key bindable command. You may edit the source code for a
recorded macro by using the list_macros command ("Macro", "List Macros...", Select a
macro and press the Edit button).

Open a new file called "test.e" (invoke the File Open menu item and type "test.e") and insert
the following lines:

_command hello()
{
message("Hello World");
}

Invoke the load command (F12 or "Macro", "Load Module...") to compile and load your
macro. You have now defined a new command called hello which may be bound to a key or
invoked from the Visual SlickEdit command line. Press Esc to place the cursor on the
command line, type "hello" and press Enter. You should see the message "Hello World" in
the message area.

Here's how you can bind your hello command to Alt+5:

• Invoke the Bind Command to Key dialog box ("Tools", “Configuration”, "Key
Bindings...").

• Type "hello" in the text box.

• Click the "Add Key or Mouse Click..." button

• Press Alt+5.

• Press Esc or click on the Quit button to close the dialog box. The editor will prompt
you to save the configuration when you exit. Newly loaded macro modules require
the state file to be saved.

8 Slick-C Macro Programming Guide


Getting Started by Example

An Event Driven Dialog Box


Event driven forms are ideal for creating dialog boxes. After creating the dialog box, the
show command may be used to display the dialog box from the command line or from a
menu item. To display a dialog box from a key binding you must write a key bindable
command which uses the show command to display the dialog box.

Perform the following steps to create a simple event driven dialog box:

• Create a new form ("Macro", "New Form").

• Double click on the command button bitmap in the dialog editor Properties dialog
box (above the check box bitmap which is a square box with an X in it).

• Double click on the text box bitmap in the dialog editor Properties dialog box (the
one with the letters "ab" in it). If you can't see the dialog editor Properties dialog
box, invoke the Properties menu item ("Window", "Properties") to make it visible.

• Move the command button or the text box so they do not overlap. Click on the
object with the left mouse button, hold it, and drag to move the object.

• Double click on the command button that appears on the form (not the bitmap in the
dialog editor Properties dialog box). The Select An Event dialog box should appear
with "lbutton_up" displayed in the combo box. Press Enter to select the event.

• You should be prompted with an Open dialog box for a new file which is to contain
the source code for this dialog box. Type "form1.e" and press Enter.

NOTE: If at any point you can't see the dialog editor Properties dialog box, invoke the
Properties menu item ("Window", "Properties") to make it visible.

After the performing the above steps, you should see a file called "form1.e" with the
following lines of code:

#include "slick.sh"

defeventtab form1
ctlcommand1.lbutton_up()
{

If you don't see the above code, probably because you already have a "form1.e" file. If this is
the case, modify the "form1.e" file to contains the lines of code above.

Modify the above code to add the statement (ctltext1.p_text="Hello World";) as shown
below.

Slick-C Macro Programming Guide 9


Getting Started by Example

Example (we have added some comments you don't need):

#include "slick.sh"

// Define an event table for the dialog box window.


defeventtab form1;

// Since this is the first event handler defined for this control
// and the name of this control does not match the last
// defined event table,
// the Slick-C translator automatically defines
// the event
// table form1.ctlcommand1 and defines the lbutton_up
// event handler within this
// new event table
ctlcommand1.lbutton_up()
{
// Set the p_text property of the text box control
ctltext1.p_text="Hello World";
}

Invoke the run_selected command ("Macro", "Load and Run Form") to load the code, load
the dialog box, and display the dialog box. Click the "ctlcommand1" button to display "Hello
World" in the text box. To close the Form1 dialog box, double click on the system menu (not
all UNIX window managers close windows when you double click on the system menu) or
press Ctrl+Shift+Space (in the running version of form1; not the edited copy). You can press
Ctrl+Shift+Space while any dialog box is running in order to edit it (including the Properties
dialog box).

You can display this dialog box from the command line by typing "show form1". To display
the dialog box modally enter "show -modal form1" on the command line. The show
command provides many powerful options. The editor will prompt you to save the
configuration when you exit. Dialog box templates and compiled macros are stored in the
state file ("vslick.sta" or "vslick.stu" under UNIX).

The example code below illustrates how to write a command which displays a dialog box.
This is useful for binding a command to a key which displays a dialog box.

#include "slick.sh"
_command run_form1()
{
// The -modal option disables other windows while the dialog box
// is displayed.
show("-modal form1");
}

A Batch Macro
Batch macros are useful for trying out Slick-C primitives and are easier to share between
multiple users. Batch macros may not be bound to a key; however, you can execute a batch
macro from the command line or a menu item.

10 Slick-C Macro Programming Guide


Getting Started by Example

Open a new file called "hello.e" (invoke the File Open menu item and type "hello.e") and
insert the following lines:

defmain()
{
message("Hello World");
}

You have now defined a new batch macro called hello which may be invoked from the Visual
SlickEdit command line. Save your macro and press Esc to place the cursor on the command
line. Type "hello" and press Enter. You should see the message "Hello World" in the
message area. Batch programs must be saved before they are executed in order for the macro
to get compiled. Visual SlickEdit automatically compiles batch programs if no
corresponding pcode file exists (hello.ex in this example), or the date of the source file is
newer than the pcode file.

Slick-C Macro Programming Guide 11


Compiling and Loading Macros

Compiling and Loading Macros


The two commands st and load ("Macro", "Load Module...") are provided for compiling
Slick-C modules from within the editor. The st command translates the module specified
into binary code called pcode. When no module is specified, the current buffer is translated.
The load command (F12 or "Macro", "Load Module...") will translate the module specified if
necessary (MAKE), and load the resulting pcode. When no module is specified, the current
buffer is saved if necessary, translated, and loaded. If a module is loaded which has already
been loaded, it is replaced. Both the commands invoke the external program "vstw.exe"
(UNIX: vstw) to translate the source module into pcode. DO NOT use the load command on
batch programs. After doing so you will no longer be able to execute the batch program until
you use the unload command ("Macro", "Unload Module...").

A module which was loaded with the load command may be unloaded with the unload
command ("Macro", "Unload Module..."). However, Visual SlickEdit's symbol table (called
the names table) will still contain the names of globally scoped variables, procedures, and
commands until you save the configuration. The configuration is automatically saved when
you exit the editor. You can invoke the save_config command from the Visual SlickEdit
command line to save the configuration at any time.

12 Slick-C Macro Programming Guide


Language Constructs

Language Constructs
Comments
Slick-C supports both C++ comment styles. Two forward slashes (//) declares the rest of the
line to be a comment. The two characters '/*' open a comment and '*/' closes a comment.
Unlike C++, comments may be nested.

Example:

i=1; // this is a comment

/* this is a /* nested */ comment */

String Literals
Strings may be in single or double quotes. Double quoted strings are identical to C++. A
backslash followed by a character has special meaning as follows:

\a Bell character (7)


\b Backspace character (8)
\f Form feed character (12)
\n New line character (10)
\r Carriage return (13)
\t Tab character (9)
\v Visual character (11)
\? Question mark character
\' Single quote character
\" Double quote character
\\ Backslash character
\xhh Hexadecimal character code
\ooo Octal character code

If single quotes are used, two single quotes consecutively represents one single quote
character. If double quotes are used, a backslash followed by a double quote represents one
double quote character. The operator ":==" used in the example below compares two strings
for exact equality. The Slick-C language does have a operator "==". However, this operator
will strip leading and trailing spaces and tabs from both operands (see “Mathematical
Operators” on page 16 for a list of operators).

Example:

"abc":=='abc'
"Can't find file":=='Can''t find file'
"\t":==_chr(9)

Slick-C Macro Programming Guide 13


Language Constructs

A backslash (not inside quotes) followed by a character or a number has the special meaning
as shown below. However, using this feature is not recommended because it is not C++
compliant. This features remains only for backward compatibility.

\a Bell character
\b Backspace character (8)
\f Form feed character(12)
\n New line
\r Carriage return
\t Tab
\v Visual character (11)
\xdd Hexadecimal character code dd
\ddd Decimal character code ddd

Quoted strings adjacent to escape sequences are read (lexed) as one string. No concatenation
is performed.

Example:

\n:==\10
\r:==\xd
\r:==\x0d
"\r\n":==\r\n
"1"\50 + "1"\49:== "23" // 12 + 11=="23", not 1:+(2+1):+1=="131"

Numeric Constants
The Slick-C language supports floating point numbers and hexadecimal numbers. The
mantissa is limited to 32 digits and the exponent is limited to 9 digits. When precision is lost,
the result is rounded. Overflow and underflow are detected. Floating point numbers have the
following syntax:

[+|-] digits [.][digits][E[+|-]digits]

OR

[+|-] [.][digits][E[+|-]digits]

The leading sign may have blanks before and after.

Hexadecimal numbers are defined in the same way as the C language, as follows:

0x hexdigits

14 Slick-C Macro Programming Guide


Language Constructs

Example:

4
" + 4e2"
4e2
" -4E-2"
-4E-2
0xff

Defining Constants
Slick-C has full support for #define textual replacements like C/C++. #define can be used
for defining constants or in-line functions.

This syntax for defining a textual replacement is:

#define name[(param1,param2,...)] value

Use a backslash at the end of a line to indicate that the value text continues to the next line.
Any occurrence of name is replaced with the text value before the source is compiled.

WARNING: When value represents a constant expression, you should place parentheses
around it to make sure there is not a problem with operator precedence.

Example:

#define MAXLINES15
#define MAXLINESP1 (MAXLINES+1)
#define max(a,b) ( ( (a) >= (b) ) ? (a) : (b) )
#define min(a,b) ( ( (a) <= (b) )\
? (a) : (b) )

defmain()
{
x=4;
y=7;
a=max(x,y);
}

Now that Slick-C has full support for #define replacement macros you should not use the
current const primitive. The Slick-C const primitive is more like Pascal than C++ and will
confuse C/C++ programmers.

The variable name is not prefixed with a type name, the expression must be a constant, and
the comma is optional. The syntax for declaring a constant is:

Slick-C Macro Programming Guide 15


Language Constructs

const
variable = constant_expression [',']
variable = constant_expression [',']
....

The comma is used to declare more than one constant on the same line. Constants may be
used in mathematical expressions.

Example:

const
LONG_CONST = "line 1" :+
"line 2" :+
"line 3"
DOS_INT = 0x21

Mathematical Operators
Slick-C uses the operator precedence of C. An expression can have the following unary
operators:

!e1 Logical NOT. Result is 1 if e1 evaluates to 0. Otherwise result is 0.


~e1 Bitwise complement.
-e1 Negation.
+e1 No change.
++v1 Increments the variable v1 and returns the result.
v1++ Returns the value of v1 and then increments the variable v1.
--v1 Decrements the variable v1 and returns the result.
v1-- Returns the value of v1 and then decrements the variable v1.

The binary and ternary operators for the Slick-C language are listed below from lowest to
highest precedence.

Operator Description

= Assign right operand to left operand.


+= Add left operand to right operand and assign to left operand.
-= Subtract right operand from left operand and assign to left oper-
and.
/= Divide left operand by right operand and assign to left operand.
*= Multiply left operand with right operand and assign to left oper-
and.
|= Bitwise OR left operand with right operand and assign to left
operand.

16 Slick-C Macro Programming Guide


Language Constructs

Operator Description

^= Bitwise XOR left operand with right operand and assign to left
operand.
&= Bitwise AND left operand with right operand and assign to left
operand.
e1?e2:e3 If expression e1 is TRUE (not the string '0'), expression e2 is
returned. Otherwise, expression e3 is returned.
&& Logical AND. If left hand expression is false, right hand expres-
sion is not evaluated.
|| Logical OR. If left hand expression is true, right hand expression
is not evaluated.
| Bitwise OR.
^ Bitwise XOR.
& Bitwise AND.
== Equal. Performs a numeric or string comparison depending on the
operands. This function is NOT identical to the C strcmp function
(see :== operator below).
NOTE: If both operands are numbers, a numeric comparison is per-
formed. Otherwise a string comparison is performed. In any case,
leading and trailing spaces and tabs are stripped before the com-
parison is performed.
> Greater than. Performs a numeric or string comparison depending
on the operands. See note under == operator.
>= Greater than or equal. Performs a numeric or string comparison
depending on the operands. See note under == operator.
< Less than. Performs a numeric or string comparison depending on
the operands. See note under == operator.
<= Less than or equal. Performs a numeric or string comparison
depending on the operands. See note under == operator.
!= Not equal. Performs a numeric or string comparison depending on
the operands. See note under == operator.
:== Exactly equal. Always performs string comparison. This is
equivalent to the C expression (strcmp(a,b)==0).
:!= Not exactly equal. Always performs string comparison.
:<= Exactly less than or equal. Always performs string comparison.

Slick-C Macro Programming Guide 17


Language Constructs

Operator Description

:< Exactly less than. Always performs string comparison.


:>= Exactly greater than or equal. Always performs string compari-
son.
:> Exactly greater than. Always performs string comparison.
:+ Concatenation.
<< Bitwise shift left.
>> Bitwise shift right.
+ Addition.
- Subtraction.
/ Division with possible floating point result.
Intdiv Division with integer result.
* Multiplication.
% Remainder.

In addition to the operators above there is also implied concatenation. When there is no
binary operator between two unary expressions, concatenation is automatically performed.

All numeric operators, except bitwise operators, support floating point numbers. Bitwise
operators support 32 bit integers for all platforms. In the future, bitwise operators will
support 32 bit int and 64 bit long for all platforms. There are two sets of comparison
operators. The operators <, >, =, !=, <=, and >= perform a numeric comparison if both string
expressions are valid numbers. The operators :<, :>, :==, :!=, :<=, and :>= always perform a
string comparison. Select the appropriate comparison operator for performing a string or
numeric comparison.

NOTE: Expressions may extend across line boundaries if the line ends in a binary
operator or if the line ends with a backslash.

18 Slick-C Macro Programming Guide


Language Constructs

Example:

(1.0==1) == 1
(1e2==100) == 1
(1e2:==100) == 0
(" abc "=="abc") == 1
(" abc ":=="abc") == 0
(" abc ":!="abc") == 1
(" 1 "==1) == 1
(" 1 ":==1) == 0
("abc":<"def") == 1
1 2 :=="12"
1 ( 2) :=="12"
pow(4,2) ==16
5%2 ==1
5/2 ==2
5/2.0 ==2.5
5 intdiv 2.0 ==2
5&2 ==0
5|2 ==7
(10<7) ==0
(10:<7) ==1

Assignment Operator
The simple assignment statement has the syntax:

variable=expression;

Example:

i=1;
i=i+1;

Assignment statements may be cascaded (x=y=z). Assignment statements within if


statements are not allowed. The compiler flags assignments within if statements as an error.

Scoping and Declaring Variables


A variable or identifier may contain any of the characters "A-Za-z$_0-9" and must start with
one of the characters "A-Za-z_$". The Slick-C language supports global, static (module),
and local scope variables. Global variables may be accessed by any module. The scope of a
static variable is limited to the module it is defined in. The scope of a local variable is
limited to the function it is defined in.

Variables are declared just like in C++; however, there are the following differences:

• Classes are not supported.

• void is only allowed as the returned type of a function.

Slick-C Macro Programming Guide 19


Language Constructs

• char, short, and float types are not yet available. All numeric types are signed.
The current Slick-C numeric types are int, long, and double.

• Slick-C has a built-in string type _str.

• Arrays, while declared similarly, cannot have a size limit. Arrays elements are
always dynamically allocated.

• Slick-C provides a :[] hash table operator which is similar to the array operator []
except that you index hash tables with a string type.

• There is no sizeof operator. Since the Slick-C interpreter currently stores all types
as container variables, the sizeof operator has no meaning.

• Only global or static variables can be initialized with the "=" operator.

• static structure members are not supported.

Rather than show you the complex BNF syntax for declaring variables, we will break up
declarations into categories. If you don't already know the C language, a book on the C
language would help you learn more about Slick-C.

Simple Variables
“Simple variable” means a variable which is not an array, hash table, structure, or function
pointer.

The syntax for defining a simple variable is:

[static] TypeName variable1[=expression1] , variable2[=expression2] ...;

Where TypeName may be any of the following:

boolean Use this for variables which only take on the value 0 or 1 and are
typically used with the boolean operators &&, ||, and !. You can
also use the new keywords "true" and "false".
int 32 bit signed integer.
long 32 DIGIT signed integer. In the future this will be a 64 bit
signed integer. Same as older keyword bigint. Currently this
type supports a 32 DIGIT number.
double 32 DIGIT mantissa and 32 bit signed exponent. Same as older
keyword bigfloat.
_str String. Same as older keyword bigstring.
typeless Container variable. You can assign a typeless variable anything.
Even an array of “whatever”, or hash table of “whatever”.
StructName See "struct" below.

20 Slick-C Macro Programming Guide


Language Constructs

UnionName See "union" below.

The comma is used to declare more than one variable of the same type. Local variables do
NOT have to be defined. Using a variable not already defined as global or constant declares
the variable to be a local typeless variable. However, you may declare variables within the
scope of a function to ensure that the variable will be local even if the name has been
declared elsewhere as a global or constant.

Examples:

// Declare a global integer


intgi=1;
//Declare a module scope integer
static intsi=2+4;
//Declare some global string variables
_strgstring1="Value1", gstring2="Value2";
//Declare a global large floating point variable
doublegd=1.4;
//Declare a global typeless variable
typelessgt="xyz";

defmain()
{
_str s; // Declare a local string variable
t=gi; // Copy gi into local container variable t.
message("t="t);
}

Details About Variable Initializations


Global and static numeric variables, which include boolean, int, long, and double, are
initialized to 0 when no user-specified value is given. Local variables of any type are not
initialized.

Global and static variables declared as typeless or _str are initialized with "" (a zero length
string) when no user-specified initialization value is given.

Examples:

boolean globalboolean=true;
int globalint;
double globaldouble;

defmain()
{
// will see "globalboolean=1 globalint=0 globaldouble=0"
message("boolean="globalboolean" "globalint" "globaldouble);
}

struct
Structures are typically used to logically group data. For example, a record in a database
might have a name, address, and phone number. This can be logically grouped into a

Slick-C Macro Programming Guide 21


Language Constructs

structure to make easier for you to remember what data needs to be filled in for a complete
record. Structures also can have the added effect of reducing the number of global variables.
There is no sizeof operator like in C++. Since the Slick-C interpreter currently stores all
types as container variables, the sizeof operator has no meaning.

The syntax for defining a structure is:

[static] struct [StructName ] {


member-variable-decl1;
member-variable-decl2;
...
} [variable1[={e1,e2, ...}] , variable2[={e1,e2, ...}], ...];

The struct declaration gives you the choice of defining your own type called StructName
and/or to declare one or more variables. The syntax of member-variable-decls is identical to
declaring other variables except that static structure members are not supported.

The syntax for accessing a member of a struct variable is:

variable.member-name

Differences from C++

• Space for structure elements is allocated when you access the element.

• Structure data is not continuous. This is obvious for string, array, and hash table
member variables which contain variable size data. However, even other types are
sometimes stored elsewhere. In the future, after a few changes are made, the way
Slick-C lays out memory will be documented.

• There is not a sizeof function which tells you the size of a structure in bytes.

Examples:

struct PHONERECORD { // Define a type called PHONERECORD


_str Name;
_str PhoneNumber;
} gPhoneRecord; // Declare a variable of that type.
PHONERECORD gPR={// Declare a variable of type PHONERECORD.
"Steve","555-1346"
};
PHONERECORD gRecordArray[]; // See arrays below
struct PHONERECORD2 { // Define a type called PHONERECORD2
_str Name;
_str PhoneNumber;
_str FaxNumber;
};

defmain()

22 Slick-C Macro Programming Guide


Language Constructs

{
messageNwait("Name="gPR.Name" PhoneNumber="gPR.PhoneNumber);
t=gPR; // Copy phone record data into a local container variable
//Container variables can access structure elements as an array.
messageNwait("Name="t[0]" PhoneNumber="t[1]);
}

union
Unions are typically used in place of a struct in the case where you have mutually exclusive
member variables. In this case, a union will require less memory than a struct. Memory is
only allocated for one member variable at a time.

The syntax for defining a structure is:

[static] union [UnionName ] {


member-variable-decl1;
member-variable-decl2;
...
} [variable1[={e1}] , variable2[={e1}], ...];

The union declaration gives you the choice of defining your own type called UnionName
and/or to declare one or more variables. The syntax of member-variable-decls is identical to
declaring other variables except that static union members are not supported.

The syntax for accessing a member of a union variable is:

variable.member-name

Examples:

union {
int i;
_str s;
double d;
}gu={1}; // Type checking here is with first member variable.

#define KIND_INT 1
#define KIND_STRING 2
#define KIND_DOUBLE 3
defmain()
{
struct {
int kind;
// Here we are nesting a union inside a struct.
// This union only requires space for one of these
// members at a time.
union {
int i;
_str s;
double d;
}u;

Slick-C Macro Programming Guide 23


Language Constructs

} x;

x.kind=KIND_INT;x.u.i=1;
...
switch (x.kind) {
case KIND_INT:
messageNwait("x.u.i="x.u.i);
break;
case KIND_STRING:
messageNwait("x.u.s="x.u.s);
break;
case KIND_DOUBLE:
messageNwait("x.u.d="x.u.d);
break;
}
}

Anonymous Unions
An anonymous union is a union member variable which has no name. This saves you from
having to type the union member variable name.

Example:

defmain()
{
struct {
int kind;
union {
int i;
_str s;
double d;
}; // No name for this union member variable
} x;
x.kind=1;x.i=1;
}

Arrays
Array variables are excellent for keeping track of a list of items. If you want to prompt a user
to select from an array of strings, use the _sellist_form (see online help).

The syntax for defining an array variable is:

[static] TypeName variable1[][={e1,e2, ...}] , variable2[][={e1,e2, ...}] ...;

The first element of an array starts at 0. Use more than one set of [] for multi-dimensional
arrays. Notice that you do not define the maximum number of elements in the array, because
array elements are allocated when you access them. The maximum number of elements that
may be placed in an array is about 2 billion. Your machine will likely run out of memory
before this limit is ever reached.

24 Slick-C Macro Programming Guide


Language Constructs

Use the _length() method to determine the number of elements in an array. The syntax for
using this method is variable._length().

The following statements will empty an array:

array._makeempty(); // Empty the array


array=null; // Empty the array. Same as above.

Differences from C++

• Space for array elements is allocated when you index into the array.

• You cannot use pointer variables to traverse array elements.

• You cannot limit the number of elements that the array may contain.

• Specifying an array variable WITHOUT the [] operator does not return a pointer to
the first element. Instead it refers to the entire array. This allows you to copy one
array to another or define a function which returns a copy of an array.

• There is not a sizeof function which tells you the size of the array in bytes. There is
a _length method which tells you the number of elements in the array.

Examples:

intgai[]={1, 7, 12};
intgaai[][]={{1},{1,2},{1,2,3}}; //two dimensional array
_strgastring1[]={"Value1", "Value2"};
typelessgat[]={"String", 1, 2.4};

defmain()
{
t=gai; // Copy all the array elements into a local container
variable
t[t._length()]=45; // Add another array element.
for (i=0;i<t._length();++i ) {
messageNwait("t["i"]="t[i]);
}
#if 0
// This C style pointer loop is not supported.
p= &array[0];pend= &array[2];
for (;p<pend;++p){ // If p and pend were declared as pointers,
} // compiler would not allow < or ++.
#endif
}

Hash Tables
Slick-C provides a :[] hash table operator which is similar to the array operator [] except that
you index hash tables with a string type. The syntax for defining a hash table variable is:

Slick-C Macro Programming Guide 25


Language Constructs

[static] TypeName variable1:[]


[={s1=>e1, s2=>e2, ...] , variable2:[][={s1=>e1,s2=>e2, ...] ...;

Examples:

#include "slick.sh"
int ghi:[]={"Symbol1"=>1,"Symbol2"=>2,"Symbol3"=>3};
int ghai:[][]={"Symbol1"=>{1},"Symbol2"=>{1,2},"Symbol3"=>{1,2,3}};
_str ghstring:[]={"Symbol1"=>"Value1", "Symbol1"=>"Value2"};

defmain()
{
messageNwait("ghi:['Symbol1']="ghi:["Symbol1"]);

// Copy all the hash table elements into a local container variable
t=ghi;
t:["Symbol4"]=4; // Add another hash table element.

// The loop below illustrates how you can traverse the elements
// in a hash table without knowing the string indexes.
typeless i;
boolean doModify;
doModify=false;
for (i._makeempty();;) {
t._nextel(i);
if (i._isempty()) break;
if (doModify) {
t._el(i)=4; // Modify element
} else {
messageNwait("i="i" value="t._el(i));
}
}
}

Pointers Variables
Pointer variables in C++ are usually considered to be a bad thing. Due to limits in the C++
language, pointers sometimes get over used. However, pointers are what make C++ a
"Systems" programming language. You can write your own memory management routines,
interface with hardware, and get that extra ounce of speed. Currently you cannot use pointers
in Slick-C to perform these types of low level functions. Unlike C++, Slick-C pointers
variables do not support arithmetic operations such as ‘<’, ‘>’, ’+’, and ‘-‘. Only the
operators ‘==’ , ’!=’, and ‘!’ are allowed. Pointers were added to Slick-C because we felt that
there are a few programming tasks which are more easily solved by pointers. If you access
an invalid pointer, Visual SlickEdit will not crash; however, your Slick-C macro will stop
running.

WARNING: When a module is reloaded, static variable addresses change. Make sure
you reinitialize global pointer variables which point to static (module scope) variables.

[static] TypeName *variable1[=&v1] , *variable2[=&v2] ...;

26 Slick-C Macro Programming Guide


Language Constructs

The unary & operator is used to return the address of a variable. The unary * operator is used
to pick up a pointer. However, you need to use the operator -> (ex. p->member-variable) to
access members of a pointer to a structure. See example below.

Differences from C++

• Space for array elements is allocated when you index into the array.

• You can't use pointer variables to traverse array elements.

• You can't limit the number of elements that the array may contain.

• There is not a sizeof function which tells you the size of the array in bytes. There is
a _length method which tells you the number of elements in the array.

Example:

intgi=1;
int*gpi=&gi;
defmain()
{
// Print out what gpi pointers to.
messageNwait("*gpi="(*gpi));
*gpi=2; // Change value of gi
messageNwait("get 2 here gi="gi);

struct {
int x,y;
} st,*pst;
st.x=1;st.y=2;
pst=&st;
messageNwait("pst->x="pst->x" pst->y="pst->y);
// This works too, but using -> is easier
messageNwait("(*pst).x="(*pst).x" (*pst).y="(*pst).y);
}

Pointers to Functions
Function pointer variables are useful for arguments to sort functions or for lookup tables
which contain a particular function to call. If you access an invalid function pointer, Visual
SlickEdit will not crash;. however, your Slick-C macro will stop running.

WARNING: When a module is reloaded, static function addresses change. Make sure
you reinitialize global function pointer variables which point to static (module scope)
functions.

[static] TypeName (*variable1)([ArgDecl1, ArgDecl2,...]){=function_name};

Where ArgDecl has the almost the same syntax as a variable declarations except static is not
supported and the "&" operator is used to specify call by reference parameters. Call by

Slick-C Macro Programming Guide 27


Language Constructs

reference array and hash table parameters require parentheses around the & and id. See
“Argument Declarations” on page 34.

The syntax for calling a pointer to function variable is:

(*pfn)([e1, e2,...])

Differences from C++

Only one syntax is currently supported for making a call with a pointer to a function variable.
The pfn(p1,p2,...) syntax is not supported. This limitation is necessary for container variables
because the compiler does not know the type of the variable. However, support will be added
for the other syntax for typed pointers to functions.

Examples:

void proc(_str a)
{
messageNwait("a="a);
}
defmain()
{
// Assign a pointer to a function to the container variable "t"
t=proc;
(*t)("First call");
// Declare a local pointer to function variable
void (*gpfn)(_str a);
gpfn=proc;
(*gpfn)("Second call");
}

Type Casting
Slick-C enforces strict type checking on typed non-container variables. There are times
when you need to convert one type to another to prevent the compiler from “complaining”.
Type casting helps tell the compiler you know what you are doing. In addition, type casting
can change the value of an expression.

The syntax for converting one type to another is as follows:

(VarDeclWithoutName) expression

Where VarDeclWithoutName is identical to a variable declaration without the variable name


except that the static keyword is not allowed.

Some casts are not allowed because they would require unrealistic assumptions by the
compiler. For example, you can't cast a struct type to another struct type.

28 Slick-C Macro Programming Guide


Language Constructs

Differences from C++

• Currently Slick-C only supports the less ambiguous C style type casting. Support
for the new C++ type casting syntax TypeName(variable) may be added in the
future. The argument is between having an elegant less ambiguous grammar or
conforming to C++ so there is nothing new to learn.

• Because Slick-C does not allow low level manipulation of memory, you can't do
things like type cast an "int *" to a "long *".

Examples:

defmain()
{
int i;
double d;
d=1.2;
i=(int)d; // i gets the value 1, NOT 1.2

typeless t;
t=1.2;
i=t; // Here i gets 1.2 BUT
// IN THE FUTURE this will NOT be the case because it
// will be physically impossible to store a float in a 32 bit int.

boolean b;
b= i!=0; // Can't use cast here.
i=(int)b; // Need cast here.
}

How Typeless Container Variables Work


Container variables are declared with the typeless keyword or are declared by an assignment
to an undefined variable. Slick-C has additional string operators so that the compiler always
knows whether to perform a string or numeric operation. The '+' operator always means add
two numbers, and the concatenation operator ":+" always means concatenate two strings.
The compiler performs (double) floating point arithmetic on container variables. Currently,
there is only a very small difference in speed between arithmetic operations on integer type
variables and container variables because, the Slick-C language has been optimized for string
and container operations. In the future, there will be design changes to optimize binary types
like integers. See “Mathematical Operators” on page 16 for a complete list of operators.

The container variable can store the contents of ANY typed variable. This is easy for the
interpreter since all typed variables are stored as container variables. At run-time, the
interpreter must check the current type of the container variable (and sometimes convert it) to
perform an operation.

Examples:

typeless t;

Slick-C Macro Programming Guide 29


Language Constructs

t=1; // Store an integer


// Convert the contents of the variable t to a
// floating pointer number (double type) and add 1.
// NOTE: The interpreter is smart and will only perform
// integer arithmetic here.
t=t+1;
// Since + always means addition, the compiler converts
// string constants to the smallest possible numeric type
t=t+"1";

// Declare string variable


_str s;
s=1; //Compiler will convert int to string
t=1.2;
// Must cast string type to int or compiler will complain.
t=(int)t+(int)s;
//Result is 2 and not 2.2 because of the cast of t
// to int.

//Destroy the integer and make an array.


//Also make the 0 element an integer.
t[0]=1;
t[1]=2; // Add another element;

t2=t; //Copy the array and all its elements

struct {
int x;
int y;
} st;
st.x=1;st.y=2;
t=st;
// Print out the elements of the structure
for (i=0;i<t._length();++i ) {
messageNwait("t["i"]="t[i]);
}

The IF Statement
The syntax for an if statement is:

if (expression ) statement
[else statement]

statement may be a C style statement block which contains multiple statements. See
“Statement Block” on page 31 for more information.

IMPORTANT: The value 0 for all types is false. All other values are true. Like C++,
Slick-C uses the value 0 for null pointers. For the string type, only a one byte length
string where the first character is an ASCII '0' is false. A 0 length string ("") is true when
used in a boolean expression.

Examples:

30 Slick-C Macro Programming Guide


Language Constructs

if (x<y) a=1;
if (x="a") {
y=1;
} else if (x="b") {
y=2;
} else if (x="c") {
y=3;
} else if (x="d") {
y=4;
}

Statement Block
A statement block is typically used to allow multiple statements within an if or loop
construct. However, it can also be used to declare a new local scope block. Syntax:

{
statement
statement
...
}

statement may declare local variables.

Example:

if (i<1) {
int x=1;
{
int x; // Can do the assignment here
x=3;
}
// The variable x will be 1 here and not 3.
}

Loops
The syntax for valid Slick-C language loops are:

[label:] while (condition_exp) statement


[label:] for ([b4e1 ,b4e2 ... ,b4e3]; [condition_exp] ; [cont_e1 ,cont_e2 ... ,cont_e3])
statement
[label:] do statement while ( condition_exp );

Slick-C Macro Programming Guide 31


Language Constructs

The while loop evaluates condition_exp first and then executes statement if condition_exp is
true (not the value 0), the statement will continue to be executed until condition_exp
becomes false (0) or a break statement is reached.

The C-style for loop is somewhat free form. The expressions before the first semicolon of
the for loop are executed before entering the loop. The condition_exp expression is checked
before entering the for loop as well. If condition_exp is true (not the value 0), the statement
is executed. The statement will continue to be executed until condition_exp becomes false
(0) or a break statement is reached. When the bottom of the for loop is reached, but before
condition_exp is checked again, the expressions after the second semicolon are executed.

The do loop executes statement first and then evaluates condition_exp. If expression is true
(not the value 0). The statement will continue to be executed until expression becomes false
(0) or a break statement is reached.

Loops may be exited with the break primitive. The continue primitive may be used to skip
to the top of a loop. Both of these primitives support an optional label argument (like Java).
If specified, the label must match the label of one of the loops you are currently in.

Using continue on a for loop causes the expressions after the second semicolon to be
executed before condition-_exp is checked. When continue is used on a do statement the
condition_exp is not checked and execution resumes at the top of the loop.

Example:

outerloop:
for(i=1;i<3;++i){
for (j=1;;++j) {
if (j==3) break outerloop; //Exit both loops
messageNwait("i="i);
}
}

for(i=1;i<10;++i){
messageNwait("i="i);
}
// The above for loop is equivalent to the loop below.
i=1;
for (;i<10;) {
messageNwait("i="i);
++i;
}

for(i=1;i<10;++i) messageNwait("i="i);

i=1;
while (i <10) ++i;

i=1;
do {
messageNwait("i="i);

32 Slick-C Macro Programming Guide


Language Constructs

} while (i<10);

status=search(":","@" /* No message option. */);


for(;;) {
if ( status ) {
break;
}
get_line(line);
messageNwait("found match line="line);
status=repeat_search();
}

Switch Statement
Slick-C supports the C switch statement. The Slick-C switch supports integers and string
types. The syntax of the switch statement is as follows:

switch (expression) {
[ case expression:
statements
]
[ case expression:
statements
]
...

[ default:
statements
]
}

The switch expression is evaluated and compared against all the case expressions. Once a
match is found, ALL statements below the case are executed, including those statements
found in the next case and the default, until a break statement is reached.

Example:

outerloop:
for (i=1;;++i) {
switch (i) {
case 1:
case 2:
messageNwait("i=1 or i=2");
break; // Done with these cases
case 3:
break outerloop;
}
}

Slick-C Macro Programming Guide 33


Language Constructs

Functions
We use the term “function” to mean something that can be called in some manner from the
macro language. Slick-C has three kinds of functions: procedures, commands, and built-ins.
The sections that follow describe each of these, and their differences.

Defining a Procedure
There are several differences between defining a procedure and defining a command with the
_command primitive. Unlike command functions, the scope of a procedure may be limited
to a module. Command functions may be invoked by typing the name on the Visual
SlickEdit command line, from a menu item definition, by using the execute function, or by
typing the name followed by arguments in parentheses in a Slick-C expression. Procedures
may only be called by the latter method and may not be bound to keys. A procedure name
must be a valid Slick-C identifier (same as C identifier). However, the name of a command
may be a keyword (not recommended), or a string constant containg a single character such
as "/" (Visual SlickEdit uses this to define a search command).

The syntax for defining a procedure is:

[static] [TypeName | void] id([ArgDecl1, ArgDecl2, ...])


{
statement
statement
...
}

Argument Declarations
The syntax for ArgDecls is the same as for declaring a variable except that the static keyword
may not be used. In addition, an & before the id declares a call by references parameter. Call
by reference array and hash table parameters require parentheses around the & and id. See
example below.

The last argument in the declaration list may be an ellipsis ('...' 3 dots) to indicate that the
function accepts more arguments of any type. Use the arg function to access these optional
arguments.

TypeName specifies the return type of the function. See “Where TypeName may be any of
the following:” on page 20. If TypeName or void is not specified, return statement checking
is relaxed. When the void type is used, a value cannot be specified to the return statement.
The return statement is used to specify the result of the function call and exit the function.

The optional static key word is used to limit the scope of a procedure to the module it is
defined in. By default, procedures are global and may be accessed by any module.

34 Slick-C Macro Programming Guide


Language Constructs

Procedures are called by specifying the name followed by comma delimited arguments, if
any, in parentheses.

Example:

// NOTE: The list, p1, and pfn parameters are call by reference
// parameters. Like C++, the list parameter requires parentheses
// around the & reference operator and the name because the []
// operator would otherwise be
// processed first. This avoids
// deviating much from C++ syntax.
//
// pfn is a reference to a pointer to a function.
boolean proc(int &p1,_str p2,_str (&list)[],int (*&pfn)(int))
{
return(true);
}

Default Arguments
The assignment operator has special meaning in an argument declaration. It defines a default
value
for an argument. The default value is used if the caller does not specify the parameter.
Default arguments should always be specified in the function definition but not in the
prototype. Unlike C++, default arguments in prototypes have no effect on the compiled code.

Example:

static int proc2()


{
return("before");
}
int proc(_str p1=proc2():+"after",int p2=2)
{
return(p1+p2);
}
defmain()
{
proc(); // Used defaults
proc("param1"); // Used the second default value
proc("param1",3);
proc(,3); -->This is not allowed
}

Procedures may have up to 15 arguments defined. The procedure may be called with more
arguments than defined by the procedure declaration. These "extra" arguments as well as the
arguments defined in the procedure declaration can be retrieved by the function arg.
Defining arguments with default values instead of using the arg function makes your code
more understandable. Calling the arg function with no parameters returns the number of

Slick-C Macro Programming Guide 35


Language Constructs

parameters the function was called with. The minimum number of arguments the procedure
may be called with is defined by the procedure heading.

The OLD SYNTAX for defining a procedure is:

[static] [type-name] id([ [var] id1, [var] id2, ... ])


{
statement
statement
...
}

The above syntax has the same meaning as the following new syntax:

[static] [type-name] id(typeless [&] id1, typeless [&] id2, ...])


{
statement
statement
...
}

The keyword var placed before the parameter declares the parameter to be a call by reference
parameter.

Defining a Command
The _command primitive is used to define a new command with argument completion.
Commands must be translated into pcode and loaded by the load command ("Macro", "Load
Module..."). A command may be invoked by typing its name on the Visual SlickEdit
command line, selecting it from a menu item definition, pressing a key, quoting its name in a
Slick-C function, or typing its name followed by arguments in parentheses in a Slick-C
expression. Command procedures always have the scope global and may be bound to a key
with the Bind Command to Key dialog box ("Tools", “Configuration”, "Key Bindings...").

The syntax for defining a command is:

_command [TypeName | void] name1[,name2 [,name3... ]( [ArgDecl1, ArgDecl2, ...] )


[name_info(const_exp)]
{
statements
}

TypeName specifies the return type of the command. See “Where TypeName may be any of
the following:” on page 20. If TypeName or void is not specified, return statement checking
is relaxed. When the void type is used, a value cannot be specified to the return statement.
The return statement is used to specify the result of the function call and exit the function. If

36 Slick-C Macro Programming Guide


Language Constructs

your command uses the arg function to access arguments, specify an ellipsis ("...") for the
last argument.

The syntax for ArgDecls is the same as for declaring a variable except that the static keyword
may not be used. In addition, an & before the id declares a call by references parameter. Call
by reference array and hash table parameters require parentheses around the & and id.
However, all typed or named arguments must have a default value.

The last argument in the declaration list may be an ellipsis ('...' 3 dots) to indicate that the
function accepts more arguments of any type. Use the arg function to access these optional
arguments.

The name of a command may be a valid Slick-C identifier, keyword (not recommended), or
string constant of length one such as "/" (Visual SlickEdit uses this to define a search
command).

Example:

//Allow command in read only mode


//Use ellipsis because this accesses arguments
_command int goto_line(...)
name_info(','VSARG2_READ_ONLY|VSARG2_REQUIRES_EDITORCTL)
{
param=arg(1);
if (param=="" || ! isinteger(param)) {
message('Please specify line number');
return(1);
}
p_line=param;
return(0);
}
_commmand void mycommand(_str filename="") name_info(FILE_ARG)
{
if (filename=="") {
_message_box("No filename specified");
}
message("filename="filename);
}

Commands get unnamed command line arguments by calling the arg function. When a
command is invoked from the command line, the expression arg(1) contains the rest of the
command line after the name with leading spaces removed. For example, invoking the edit
command "e file1 file2" calls the e command with "file1 file2" in arg(1). The parse built-in
is an excellent function for parsing a command line string (see online help for more
information on parse). When another macro calls a command, more than one argument
string may be passed. Calling the arg function with no parameters returns the number of
parameters the command or procedure was called with.

Slick-C Macro Programming Guide 37


Language Constructs

name_info Attributes
The optional constant expression const_exp is used for argument completion, restricting
when the command can be executed, and a few other options.

const_exp IS A SINGLE CONSTANT STRING EXPRESSION. A comma (‘,’) character in


the string indicates the end of an argument.

The first argument in const_exp indicates the type of word arguments the command accepts
and is used for argument completion purposes. For a list of already defined argument types,
look in the file "slick.sh" for constants that end in "_ARG". const_exp may contain one or
more of the _ARG constants. Separate each _ARG constant with a space. A asterisk ('*')
character may be appended to the end of a completion constant to indicate that one or more of
the arguments may be entered.

The second argument (after the quoted comma) specifies when the command should be
enabled/disabled, and a few other things. One or more of the following flags may be
specified and ORed together with the bitwise OR ('|') operator:

VSARG2_CMDLINE // Command supports the command line.


// VSARG2_CMDLINE allows a fundamental mode
// key binding to be inherited by the command line
VSARG2_MARK // ON_SELECT event should pass control on
// to this command and not deselect text first.
// Ignored if command does not require an editor control
VSARG2_QUOTE // Indicates that this command must be quoted when
// called during macro recording. Needed only if
// command name is an invalid identifier or
// keyword.
VSARG2_LASTKEY // Command requires last_event value to be set
// when called during macro recording.
VSARG2_MACRO // This is a recorded macro command. Used for completion.
VSARG2_TEXT_BOX // Command supports any text box control.
// VSARG2_TEXT_BOX allows a fundamental mode
// key binding to be inherited by a text box
VSARG2_NOEXIT_SCROLL // Do not exit scroll caused by using scroll bars.
// Ignored if command does not require an editor
control
VSARG2_EDITORCTL // Command allowed in editor control.
// VSARG2_EDITORCTL allows a fundamental mode
// key binding to be inherited by a non-MDI editor control
VSARG2_NOUNDOS // Do not automatically call _undo('s').
// Require macro to call _undo('s') to
// start a new level of undo.

VSARG2_READ_ONLY // Command allowed when editor control is in strict


// read only mode. Ignored if command does not require an
// editor control
VSARG2_ICON // Command allowed when editor control window is iconized
// Ignored if command does not require an editor control

VSARG2_REQUIRES_EDITORCTL // Command requires an editor control

38 Slick-C Macro Programming Guide


Language Constructs

VSARG2_REQUIRES_MDI_EDITORCTL // Command requires MDI editor control

VSARG2_REQUIRES_AB_SELECTION // Command requires selection in active


buffer
VSARG2_REQUIRES_BLOCK_SELECTION // Command requires block/column selection
// in any buffer
VSARG2_REQUIRES_CLIPBOARD // Command requires editorctl clipboard
VSARG2_REQUIRES_FILEMAN_MODE // Command requires active buffer to be
// in fileman mode
VSARG2_REQUIRES_TAGGING // Command requires <ext>_proc_search/find-tag
// support

VSARG2_REQUIRES_SELECTION // Command requires a selection in any buffer


VSARG2_REQUIRES_MDI // Command requires MDI interface may be because
// it opens a new file or uses _mdi object.
// Commands with this attribute are removed
// from pop-up menus which the MDI interface is
// not available (editor control OEMs).

Example:

#include "slick.sh"
// This command supports completion where the first argument
// is a filename and the second argument is an environment variable.
_command test1(...) name_info(FILE_ARG" "ENV_ARG)
{
parse arg(1) with file_name env_name;
message("file_name="file_name" env_name="env_name);
}
// This command is enabled only when the target is an editor control
// which has a selection.
_command void gui_enumerate()

name_info(','VSARG2_REQUIRES_EDITORCTL|VSARG2_REQUIRES_AB_SELECTION)
{
...
}
// This commmand supports completion on multiple filenames
_command e,edit(...)
name_info(FILE_ARG'*,'VSARG2_CMDLINE|VSARG2_REQUIRES_MDI)
{
...
}

The edit command allows any number of file name arguments to be given. When the user is
presented with a selection list of file names, many files may be selected with the Space Bar
key. If a asterisk ('*') is appended to the end of a completion constant, that command must
support a space delimited list of strings. Double quotes are placed around arguments with
embedded spaces.

The value of const_exp may be retrieved by the built-in function name_info.

Slick-C Macro Programming Guide 39


Language Constructs

Function Prototypes
Function prototypes are used to give the compiler type information about a function without
providing any code. Slick-C reduces the need for prototypes by performing some argument
checks at link time. When the linker finds an uninitialized variable error, it will recommend
that you add a function prototype to your source so the compiler can find your error. You
may need a function prototype if you want to use the function address in an expression.
Prototypes are not allowed for event functions.

The syntax for defining a function prototype is identical to defining a function except that a
semicolon (';') is placed after the closing parenthesis of the parameter list. Unlike C++,
default arguments in prototypes have no effect on the compiled code. No code or name_info
is given.

Example:

int proc(_str s,_str list[]); // Function prototype


int (*pfn)(_str s,_str list[])=proc; //Pointer to function
_command void command1(...); // Function prototype
_command void command1(...) { //Must have ... here to match prototype
// Use arg function here to get or set arguments.
}

What is a Built-in Function?


A built-in function is a function which was implemented in the interpreter and was not
written in the Slick-C language.

Where Are the Functions?


There are over 1200 documented functions and 200 properties.

There are two ways to find the function you are looking for. First, you can use the menu item
("Help", "Macro Functions by Category...") which shows you smaller lists of these functions
by category. Second, you can look at source code for existing commands we have already
written which you think will call functions similar to ones you need. For example, let’s say
you want to write a macro which gets the word at the cursor and does something with it. Try
to think of a command in Visual SlickEdit which operates on the current word. The
upcase_word command (Ctrl+Shift+U) uppercases the word at the cursor. If you don't know
the name of the command but you do know the key which invokes the command, use the
what_is command ("Help", "What is Key...") to find out the name of the command that gets
executed. Now that you have the name of the command, use the find_proc command
("Macro", "Find Slick-C Proc...") to bring up the macro source code. If you executed the
command "find_proc upcase_word", you will quickly see a procedure called cur_word
which looks like what you want. Place your cursor on any part of the cur_word procedure
and press the "?" button on the button bar.

40 Slick-C Macro Programming Guide


Language Constructs

Differences Between Commands, Built-ins, and Procs


• A command definition looks like a procedure that starts with the _command
primitive and has an optional name_info construct after the arguments. Built-ins
are not defined.

• Commands and built-ins always have the scope global. Procedures may have the
scope static (module) or global.

• Commands may be bound to keys. Built-ins and procedures may not.

• Commands may be invoked from the command line or the execute function. Built-
ins and procedures may not.

• Built-ins that do not return a value do not require parentheses when called (this will
change in the future). For example, the left built-in may be called by with left or
left(). You should always use parentheses so you don't have to remember which
function requires parentheses.

• A command may be given the same name as a built-in. However, this limits how
the command may be called within a macro (use the execute function). None of the
commands have the same name as a built-in so you can call any command just like
any other function.

• Only commands may be given non-alphanumeric single character names such as


+,=,!,@,#,$, etc. However, this limits how the command can be called within a
macro (place the command in quotes or use the execute function).

defmain. Writing Slick-C Batch Files


A batch macro contains a special function named defmain. Slick-C batch files have the
extension ".e". Batch macros may be invoked by typing the name (extension not required)
followed by arguments on the Visual SlickEdit command line, quoting the name in a macro,
or by using the execute function. If the batch macro needs to be recompiled (MAKE), the
Slick-C Translator is invoked before the batch macro is executed. DO NOT use the load
command to load a batch program because defmain will not be invoked and the module will
remain in memory. If you accidentally load a batch program, use the unload command to
unload it. When a batch program is executed, the defmain procedure is called after the
procedure definit is called (see “Module Initializations” on page 49).

The syntax of the defmain function is:

[TypeName | void] defmain()


{
statement
statement

Slick-C Macro Programming Guide 41


Language Constructs

...
}

TypeName specifies the return type of the function. See “Where TypeName may be any of
the following:” on page 20. If TypeName or void is not specified, return statement checking
is relaxed. When the void type is used, a value cannot be specified to the return statement.
The return value of defmain is placed in the predefined rc global variable. Beware, the
execute function only supports returning an int type. You will need to check the global rc
variable for other types.

The arg function is used to retrieve the command line arguments passed to the defmain
procedure. ALL command line arguments will be in arg(1). Use the parse statement to
easily parse multiple space delimited arguments.

Example:

defmain()
{
messageNwait("Arguments given: "arg(1));
parse arg(1) with word1 word2 .;
messageNwait("word1="word1" word2="word2);
return(0)
}

The example above displays the arguments given to the macro on the Visual SlickEdit
message line. If you define a procedure in a batch program, use the static keyword when
possible to conserve memory. Visual SlickEdit stores the names of global procedures and
variables in a names table.

Extending the editor with a batch macro has the advantage of conserving memory and
reducing the size of the state file. In addition, batch macros can more easily be shared
between multiple users. The editor keeps the batch macro loaded only while it is executing.
External batch macro names and arguments are not supported by completion. To provide
completion, you must define a command with the _command primitive and have it call the
external batch program. If you name the command the same name as the batch program
(without the extension), use the xcom command to bypass internal command searching.

There are two ways to invoke a Slick-C batch macro:

1. Enter the name of the module (extension not necessary) followed by arguments on
the Visual SlickEdit command line.

2. Enter "vs -p program" at the shell prompt, where program is the name of the batch
program and "vs" is the name of the editor. The "-p" option tells Visual SlickEdit to
terminate when the batch program completes. Alternatively, you may use the "-r"
option to have Visual SlickEdit remain resident after the batch program completes.

42 Slick-C Macro Programming Guide


Language Constructs

For any of the above methods, Visual SlickEdit will invoke the translator to compile the
source code file if the source code file exists and its date is later than the date of the pcode
(.ex) file.

Preprocessing
Preprocessing in Slick-C is indentical to C/C++ except that a #error directive has been
added. Preprocessing allows you to conditionally compile source code or define textual
replacements.

The syntax of the Slick-C language conditional if block is:

#if expression
[statements]
{#elif expression
[statements]}
[#else
[statements]]
#endif

There may be nothing more than space or tab characters preceding a '#'. Text on the same
line following #else or #endif is not allowed. Unlike in C, the expression specified MUST be
valid.

To display an error message and abort the compile, use the #error directive as shown below.

#error expression

Typically, preprocessing is used to help write macros which operate on multiple operating
systems or environments. The following constants are automatically defined by the Slick-C
translator.

__PCDOS__ Non-zero if current operating system is Windows. Use


machine() built-in function to determine at run-time which of
these operating systems you are running.
__UNIX__ Non-zero if current operating system is UNIX compatible.
__NT__ Non-zero if the current operating system is Microsoft NT
compatible.
__VERSION__ Version number of Visual SlickEdit.

The above identifiers have two underscore characters, one before and one after the alphabetic
name part.

In addition, you can use the Slick-C translator -d option to define a constant for use by
preprocessing. To test whether a constant has been defined, use the defined() function.

Slick-C Macro Programming Guide 43


Language Constructs

Example:

#if !defined(my_constant)
#define my_constant "default value"
#endif
#if __PCDOS__
name="c:\util\myprog"
#elif __UNIX__
name="/usr/bin/myprog"
#else
#error "Don't know what to do for this OS"
#endif

Pragma
#pragma is used to change various options during the course of a compile. Slick-C offers
the following options:

#pragma option(autodecl [, ( on | off ) ] )


Turns autodeclvars and autodeclctls on/off. If the second argument is not given,
value is restored to command line invocation value. Default is on. See
autoodeclvars and autodeclctls below
#pragma option(autodeclvars [, ( on | off ) ] )
Turns autodeclvars on/off. If the second argument is not given, value is restored to
command line invocation value. Default is on.
When on, compiler will attempt to automatically declare typeless variables when an
assignment is made.
#pragma option(autodeclctls [, ( on | off ) ] )
Turns autodeclctls on/off. If the second argument is not given, value is restored to
command line invocation value. Default is on.
When on, compiler will attempt to automatically declare control variables.
#pragma option(redeclvars [, ( on | off ) ] )
Turns redeclvars on/off. If the second argument is not given, value is restored to
command line invocation value. Default is off.
When on, any variable may be redeclared as a typeless variable. This is used to
generate code for variables without having the type information.
#pragma option(strictreturn [, ( on | off ) ] )
Turns strictreturn on/off. If the second argument is not given, value is restored to
command line invocation value. Default is on.
When on, and an explicit return type is given to a function, the compiler will flag an
error if a return statement is potentially missing.
#pragma option(strictellipsis [, ( on | off ) ] )
Turns strictellipsis on/off. If the second argument is not given, value is restored to
command line invocation value. Default is on.
When on, an ellipsis (... 3 dots) must be given as the last argument to a function or
prototype for type checking to succeed when calling function with extra arguments.
#pragma option(strictsemicolons [, ( on | off ) ] )
Turns strictsemicolons on/off. If the second argument is not given, value is restored
to command line invocation value. Default is off.

44 Slick-C Macro Programming Guide


Language Constructs

When on, semicolons must terminate all statements. We recommend using this
pragma so that smart editing features work better and some odd ball compilation
errors don’t occur.
#pragma option(strictparens [, ( on | off ) ] )
Turns strictparens on/off. If the second argument is not given, value is restored to
command line invocation value. Default is off.
When on, parenthesis must given on all built-in functions. We recommend using
this pragma since it makes the code a little more understandable.

NOTE: All #pragma options may be specified by command line compiler options. Run
vst.exe (UNIX: vst) with no arguments to view compiler options. You may use the VST
environment variable to specify compiler options for all your macros.

Including Header Files


The syntax of the include statement is:

#include string_constant

Includes the file specified by string_constant for compiling. If string_constant does not
specify a path, the Slick-C translator will look in the same directory of the main source file.
Otherwise, the path specified by string_constant is searched. If the file is not found, the
Slick-C translator will look for the include file in the directories specified by the
VSLICKINCLUDE and VSLICKPATH environment variables. Include files may be nested.

Defining Controls
Typically, you do not need to tell the compiler about a control you are referring to; however
there are a couple of cases in which you must declare a control. This can happen when the
compiler can't safely assume that you are referring to a control, or when the compiler is
confused about what dialog box the control you are accessing is on. The compiler needs to
tell the linker which dialog box is supposed to contain your control.

The syntax for declaring a control variable is:

[_nocheck] ObjectName ControlName;


OR
[_nocheck] _control ControlName;

Where ObjectName may be one of the following: _text_box, _combo_box, _image,


_picture_box, _command_button, _radio_button, _check_box, _label, _list_box,
_gauge, _spin, _vscroll, or _hscroll.

The _nocheck keyword tells the compiler not to check if the control exists on the current
dialog box.

Slick-C Macro Programming Guide 45


Language Constructs

Currently the "[_nocheck] ObjectName ControlName;" declaration is only allowed outside


the scope of a function. Support for local procedure scope will be added in the future. The
"_nocheck _control ControlName;" declaration already supports local procedure scope.

Example:

// Create a form with a command button named ctlcancel, and


// gauge named ctlgauge1. Set the cancel and default
// properties of the command button to true.
//
#include "slick.sh"
static boolean gcancel;
_command test()
{
// Need to tell compiler ctlgauge1 is a control because
// the form1_wid.ctlgauge1 is too ambiguous.
_control ctlgauge1;

// Show the form modeless so there is no modal wait


form1_wid=show("form1");
// Disable all forms except form1_wid
disabled_wid_list=_enable_non_modal_forms(0,form1_wid);
gcancel=0;
for (i=1;i<=100;++i) {
// Read mouse, key, and all other events until none are left or
// until the variable gcancel becomes true
process_events(gcancel);
if (gcancel) {
break;
}
// Do work here. Replace the delay below with the operation
// you want to do. The delay makes this example look more real.
delay(10);
form1_wid.ctlgauge1.p_value=i;
}
// Enable all forms that were disabled.
_enable_non_modal_forms(1,0,disabled_wid_list);
form1_wid._delete_window();
}
defeventtab form1;
ctlcancel.lbutton_up()
{
gcancel=1;
}

Defining Events and Event Tables


Event tables provide a mechanism for describing event/key bindings by source code, creating
event driven dialog boxes, and describing inheritance.

def primitive
The def primitive is used to bind a key sequence or event to a command or procedure and is
not typically used when creating event driven dialog boxes. The defeventtab primitive

46 Slick-C Macro Programming Guide


Language Constructs

selects the active event table that the def primitive sets the bindings to. If no defeventtab
declaration exists before the first def primitive the default_keys event table is used. The
default_keys event table defines the event handlers for Fundamental mode. The source code
representing the bindings is translated and then the event tables are loaded either by the load
command or by executing the module as a batch program. See “defmain. Writing Slick-C
Batch Files” on page 41 on for information on batch programs. Even though executing the
module as a batch program unloads the module when the defmain function terminates, the
event table changes remain present. This is because the command or procedure names and
the event tables are both maintained separately from the modules. The def primitive adds or
replaces the binding of an event table already in memory and may be used to unbind a key.

The syntax for defining a key is:

def {prefix_key} event [- event] [, event [- event]] ... = [command];

Command may be either a command (defined with _command) or global procedure. If


command is not specified, the existing event is unbound. The words prefix_key and event
above may be any valid event name. Some event names do not need to be enclosed in quotes.
However, you may want to always enclose them in quotes so you don't have to remember
which ones require quotes.

Example:

def "A-x"=safe_exit; // Note that "A-a" is different than "A-A"


// which requires the Alt and Shift keys to
// be pressed.
def "A-?"=help;
def "C-X" "b"=list_buffers;
def \0 - \255= nothing;

The defeventtab primitive is used to define a new event table. The syntax for defining a an
event table is:

defeventtab name;

name may contain a period ('.') character. The period is used to separate the form name from
the control name. The def primitive changes the binding of events of the last event table
defined. If no event table is defined, the default_keys event table is used.

Example:

defeventtab c_keys;
def " "=c_space;
def "ENTER"=c_enter;

Event tables are global in scope. When an event table is loaded by the load command or by
executing the module as a batch program, the new bindings will replace the event bindings of
the existing event table. If the event table specified by defeventtab does not exist, a new one
is created.

Slick-C Macro Programming Guide 47


Language Constructs

Event Driven Dialog Boxes


Event tables are also used to create event driven dialog boxes and inheritance. Much of the
event table definition code is automatically inserted by the dialog editor. However, once you
are more familiar with event tables, you will probably type in some event table definition
code yourself. If you are not famiar with some of the terminology used, you may want to
read the section Creating Dialog Boxes with the Dialog Editor first. To attach an event
table to a form (dialog box outer window) or form control, define an event table with the
same name (p_name property) as the form. Dot the form name with the control name if you
plan on specifying inheritance for an event table attached to a control.

defeventtab form_name[.control_name] [_inherit [etab_name]];

The _inherit primitive lets you link one event table to another. This makes it possible to
perform Clipboard Inheritance. If no name follows the _inherit keyword, the inheritance is
unlinked. You can add event handlers by using the def primitive or by defining an event
handler function as follows:

[ReturnType] ctl_name.event [- event] [, event [- event]] ...( [ArgDecl1, ArgDecl2,...])


{
statements
}

If ctl_name is the same name as the last event table form name (name before dot), the event
handler is attached to an event table named form_name. Otherwise, the event handler is
attached to an event table named form_name.ctl_name. The word event above may be any
valid event name. Some event names do not need to be enclosed in quotes. However, you
may want to always enclose the event names in quotes so you don't have to remember which
ones require quotes.

The syntax for ArgDecls is the same as for declaring a variable except that the static keyword
may not be used. In addition, an & before the id declares a call by references parameter. Call
by reference array and hash table parameters require parenthesis around the & and id.

Example (form with text box and OK button):

48 Slick-C Macro Programming Guide


Language Constructs

#include "slick.sh"

// Define an event table for the dialog box window.


defeventtab form1;

// Since this is the first event handler defined for this control
// and the name of this control does not match the last defined event, the
// table, the Slick-C translator automatically defines the event table
// form1.ctlcommand1 and defines the lbutton_up event handler within
// this new event table
void ctlcommand1.lbutton_up()
{
// Set the p_text property of the text box control
ctltext1.p_text="Hello World";
}

When the above code is loaded with the load command ("Macro", "Load Module..."), the
editor attaches the form1.ctlcommand1 event table to a control named ctlcommand1 on
form form1. A form1 event table is not created because no event handler for this event
table was defined. When you save the configuration ("Tools", "Configuration", "Save
Configuration..."), event tables that are not used are deleted.

Module Initializations
The Slick-C language provides two module initialization functions called definit and
defload. If present, the procedures definit and defload are called when a module is loaded.
definit is called before defload. Once the module is saved by the write_state command, the
definit procedure is invoked each time the editor is invoked. This gives your modules a
chance to perform initializations such as creating a temporary file, or allocating a selection,
or bookmark.

The syntax for defining the special functions definit and defload are:

definit()
{
statements
}
defload()
{
statements
}

The return value of these functions is always void. Therefore, you cannot specify an
argument to the return statement. For better performance, use the defload primitive instead
of the definit primitive when possible since the definit primitive forces a module to be
loaded when the editor is invoked.

Slick-C Macro Programming Guide 49


Language Constructs

When definit is called, the expression arg(1) indicates whether the module was loaded with
the load command or when the editor initialized. When a module is loaded, arg(1) returns
'L'. Otherwise arg(1) returns a null string ("").

The remainder of this section will present two useful examples of using definit.

Example:

int gmarkid= -1;


definit()
{
// If this is an editor invocation
if (arg(1)!="L") {
gmarkid=-1; // Indicate no mark is allocated.
}
}

There are two subtle points to this example when assuming that the gmarkid variable will be
used to contain an allocated mark id (also called selection handle). First, the variable
gmarkid is scoped as global and not static. This is because the mark needs to remain
allocated when this module is reloaded. When the module is reloaded, an unload of the
module occurs first and the _free_selection built-in is not called to free a mark already
allocated (there is no defunload primitive). Modules with static variables (module scope)
lose their value when reloaded. Second, the value of arg(1) is used to make sure that the
variable gmarkid is initialized only when the editor is invoked and not when the module is
loaded.

Use the example below as a template for creating a temporary buffer in the hidden window:

#include "slick.sh"
definit()
{
get_view_id(view_id);
activate_view(HIDDEN_VIEW_ID);
status=find_view(".bookmark");
if ( status ) {
/* Create a buffer and view in hidden window. */
status=load_files("+c +t");
if (status) {
// The nls function may be used for national language support
// in the future.
_message_box(nls('Could not create bookmark buffer'))
return;
}
p_buf_name=".bookmark";_delete_line();
p_buf_flags= THROW_AWAY_CHANGES|HIDE_BUFFER|KEEP_ON_QUIT;
}
// Note: ELSE case cannot empty bookmark buffer unless mark ids
// are freed. Might as well leave them.
get_view_id(bookmark_view_id);
activate_view(view_id);
}

50 Slick-C Macro Programming Guide


Debugging Macros

Debugging Macros
The Slick-C translator (vstw.exe UNIX: vstw) is fast, so that debug messages may be
inserted into your code and compiled quickly. Use the messageNwait (pronounced as
"message and wait") function to display a message and wait until a key is pressed. The
_message_box function may be used to display a dialog box with a message and wait until
you press Enter. Two helpful features are described in the following sections that will help
you debug and work on Slick-C macros.

These ".e" extension aliases can come in handy:

mmessageNwait("%\n: %\c");
mb_message_box("%\n: %\c");

Finding Procedures
The find_proc command ("Macro", "Find Slick-C Proc...") finds Slick-C source code or help
for a Slick-C tag name you specify. This is especially useful if you are browsing a macro and
you want to find out what a function does. You can find the procedure at the cursor by
pressing the Ctrl+Period key.

The syntax of the find_proc command is:

find_proc proc_name

Command Line Examples:

find_proc find_proc Finds the source code for find_proc.


find_proc cursor_up Finds the source code for cursor_up.
find_proc substr Displays help on substr built-in.

Finding Runtime Errors


When a Slick-C error occurs, a message box with a "Slick-C Error" title is displayed.
Usually the Slick-C Stack toolbar is displayed listing the call stack at the time of the error.
Double click in this toolbar to view source for a call stack entry. The find_error command
("Macro", "Find Slick-C Error") finds the last Slick-C interpreter run time error. The module
with the error is loaded and the cursor is placed on the line causing the error.

Slick-C Macro Programming Guide 51


Creating Dialog Boxes with the Dialog Editor

Creating Dialog Boxes with the Dialog


Editor
Dialog Box Creation Overview
Creating event driven dialog boxes in Slick-C is similar to Microsoft Visual Basic except that
the language has C++ style syntax and is more object oriented.

Here are some key differences between Slick-C and Visual Basic:

• When an event is sent to a control or dialog box, the object receiving the event
MUST be the active object (not necessarily the same as the system focus). This is a
major difference between Slick-C and Visual Basic. If a button control receives an
event and executes a statement like this, p_caption="New button caption", the
button's caption is changed and NOT the caption for the dialog box, which is what
Visual Basic would do.

• Built-in properties all start with the prefix "p_" to avoid these keywords from
conflicting with your own identifiers.

• A more general method of object instance referencing is used.

• Almost all properties that can be accessed at design-time may also be accessed at
run-time. For example, the p_name property for a control or dialog box may be set
after the dialog box is displayed.

• Event tables are used to group event handlers for controls. Event tables in Slick-C
are used in a similar fashion to classes in C++.

• Slick-C has sophisticated and powerful Dialog Box Inheritance Order. See
“Dialog Box Inheritance Order” on page 67 for more information.

• Parent, child, next, and previous (p_parent, p_child, p_next, p_prev) creation
order relationships are all maintained when dialog boxes are created.

• Event tables can be linked together. One event table can inherit the event handlers
of another event table. The event table links can be changed at run-time.

• The dialog editor allows event tables to be transferred through the clipboard.
Controls from the same or different dialog boxes may reference the same event
tables. There is no need for control arrays. See “Clipboard Inheritance” on
page 64 for more information.

52 Slick-C Macro Programming Guide


Creating Dialog Boxes with the Dialog Editor

• Functions may be used as methods which operate on an instance of an object.

Dialog Editor Summary


Press Ctrl+Shift+Space to edit a dialog box that is being run. If you accidentally press
Ctrl+Shift+Space when the Properties dialog box is active, you will be editing the Properties
dialog box. Double Click on the system menu to close the edited Properties form. Some
UNIX window managers do not close windows when you double click on the system menu.

Creating Controls
• Double click left mouse button on Properties dialog box control bitmap to create a
control in the center of the form.

• Click left mouse button on Properties dialog box control bitmap. Click left mouse
button on form, drag, and lift mouse button to create control the size of the dotted
rectangle.

Selecting Controls in Form


LButton If the control is not already selected, this deselects all
selected controls and selects the current control.

Shift+LButton Toggle selection of a control on/off.

LButton-ClickNDrag When you click and drag on the form, a dotted


rectangle is displayed. When you lift the left mouse
button, the controls within the rectangle are selected.

Deleting Controls
Select control(s). Press Backspace or Del key to delete the selected controls.

Setting Properties
• Select control(s). Click left mouse button on property in Properties list box. Type
new value in Properties combo box. Use combo box arrow or dots to assist in
entering a value. Press Enter when Properties list box is active, this sets the
property.

• Select control(s). (some properties) Double click the left mouse button on the
property in the Properties list box to go to the next value of the property. For color
and picture properties, a dialog box is displayed.

Aligning Controls
Select the control you want to align the other controls with. Select the other controls
with Shift+LButton. Double click the left mouse button on one of the properties x or y
to align the controls in the x or y direction. Press Enter on the value in the Properties
combo box.

Slick-C Macro Programming Guide 53


Creating Dialog Boxes with the Dialog Editor

Sizing Controls
• To size a single control, select the control and click and drag one of the selection
handles with the left mouse button.

• To size multiple controls, select the controls and set the width or height property.

• To size multiple controls, select the controls and press Shift+Left, Shift+Right,
Shift+Up, or Shift+Down arrow to move lower right corner of the selected controls
by one pixel.

Moving Controls
• Select control(s). Click and drag with the left mouse button on any of the selected
controls.

• Select control(s). Set the x or y property.

• Select control(s). Press Left, Right, Up, or Down arrow to move selected controls
by one pixel.

Miscellaneous Assignments While Form is Active


RButton Displays menu with various dialog editor commands.
Ctrl+Shift+Space Loads form and Slick-C code. Runs dialog box. If you
accidentally press Ctrl+Shift+Space when in the
Properties dialog box, you will be editing the
Properties dialog box. Double Click on the system
menu to close the edited Properties form. Some UNIX
window managers do not close windows when you
double click on the system menu.
Ctrl+S Loads form and saves into state file. Under UNIX, this
may just list source for the form that can be executed
the next time you invoke Visual SlickEdit.
Ctrl+L Loads form
Ctrl+C Copies selected controls.
Ctrl+V Pastes controls from the clipboard.
Ctrl+X Cuts selected controls.
Ctrl+A Selects all controls with same parent as the already
selected control(s).
Tab Deselects all controls and selects next control in tab
order (p_tab_index).
Shift+Tab Deselects all controls and selects previous control in
tab order.
LButton-Double-Click (on control) Displays Select an Event Function dialog
box for adding or modifying event handlers.

54 Slick-C Macro Programming Guide


Creating Dialog Boxes with the Dialog Editor

Miscellaneous Menu Items


System Box of form, Show Properties Display Properties dialog box.
Window menu, Properties Display Properties dialog box.
Window menu, Selected Form Display selected form (form being edited).
Macro menu, New Form Creates a new dialog box with a default
name.
Macro menu, Open Form Open existing dialog box or create new
dialog box.
Macro menu, Grid Sets the distances between the dots on edited
form.

The remainder of this section discusses various pieces of building a dialog box.

Creating a Form
The term form refers to the outer window of a dialog box. The objects within the dialog box
are called "controls". The term form also refers to the entire dialog box as well. A new form
can be created in one of two ways:

1. Use the New Form menu item ("Macro", "New Form").

OR

2. Use the Open Form menu item ("Macro", "Open Form...") and specify the name of
a form that does not already exist.

Adding Controls
("Window", "Properties..." or show_properties command)

Below is a picture of the Properties dialog box:

Slick-C Macro Programming Guide 55


Creating Dialog Boxes with the Dialog Editor

The bitmaps on the left of the Properties dialog box are used to create controls. There are
two ways to create a control. You can double click the left mouse button on the bitmap of the
control you want to create. This will place a new control in the middle of the selected form
(form1 for this sample session). However, with this method, you cannot create a control and
place it within another control. The Picture Box and Frame controls allow you to place
controls inside of them.

Here's another way to create a control. Perform these steps now to create a text box control
on form1:

• Single click on the text box bitmap so that it appears pressed in (like the arrow
bitmap above).

• Move your mouse so that it appears on top of the form, form1, you are editing. If
you can no longer see the form you are editing, use the Selected Form menu item
("Window", "Selected Form") to display it. Notice that the mouse pointer does not
look like a pointer any more. It should look like a large, thin plus sign. This
indicates that you are in creation mode.

56 Slick-C Macro Programming Guide


Creating Dialog Boxes with the Dialog Editor

• To create the text box control, click the left mouse button, and, while holding it
down, move the mouse pointer to the right to create a dotted rectangle. When you
release the mouse, the text box control will appear within the rectangle.

Adding Event Handlers


Set the form name and the control names ("name" property in Properties list box) before
adding code to the dialog box because these names will be referenced in the code. You should
prefix your control names with "ctl" so you can easily recognize them. To add an event
handler, perform the steps below:

• Double click on the control in the dialog box for which you want to add code (not
the bitmap in the Properties dialog box). The Select An Event dialog box should
appear.

• Choose an event and click OK.

• If this is the first event handler for this dialog box, you will be prompted with an
Open dialog box for a new file to contain the source code for this dialog box. Type
a unique filename. Usually this filename is derived from the name of the dialog
box you are creating (like "form1.e").

After performing the above steps, the dialog editor will insert an event function definition
into your source file and place your cursor in the function.

Loading and Running the Form


Invoke the run_selected command ("Macro", "Load and Run Form") to "run" the current
dialog box you are editing. This will load the code, load the dialog box, and run the dialog
box. The edited dialog box is not closed when you run it. To close the dialog box, double
click on the system menu (some UNIX window managers do not close windows when you
double click on the system menu) or press Ctrl+Shift+Space (in the running version of your
dialog box and not the edited copy). You can press Ctrl+Shift+Space when any dialog box is
running to edit it (this includes the Properties dialog box).

You can display your dialog box from the command line by typing "show <FormName>".
To display the dialog box modally enter "show -modal <FormName>" on the command line.
The show command provides many powerful options. For more information, see
“Displaying Dialog Boxes” on page 59. Dialog box templates and compiled macros are
stored in the state file ("vslick.sta" or "vslick.stu" under UNIX).

The example code below illustrates how to write a command which displays a dialog box.
This is useful for binding a command to a key which displays a dialog box.

Slick-C Macro Programming Guide 57


Creating Dialog Boxes with the Dialog Editor

#include "slick.sh"
_command void run_form1()
{
// The -modal option displays other windows while the dialog box
// is displayed.
show("-modal form1");
}

Saving a Form
Click on the form being edited and press Ctrl+S.

Adding a Cancel Button


Double click the left mouse button on the command button control. Set the "caption"
property to "Cancel" , set the "cancel" property to TRUE, and set the "name" property to "".
You can set the cancel property to TRUE by double clicking the left mouse button on the
cancel property in the Properties list box. As a rule of thumb, you should set the name
property of a control (never the form) to "" if you are not going to reference the control by
name because it wastes code space. Pressing the Cancel button (the command button with
the p_cancel property set to TRUE) when your dialog box is running will close the dialog
box even though you have not written any code. If you do add code to your cancel button,
you will need to close the dialog box yourself (p_active_form._delete_window();) .

Adding an OK Button and Closing a Dialog Box


• Create a command button control by double clicking on the command button
control in the Properties dialog box.

• Set the "caption" property to "OK", set the "default" property to TRUE, and set the
"name" property to "ctlok"

• Double click on the command button control in the dialog box for which you want
to add code (not the bitmap in the Properties dialog box). The Select An Event
dialog box should appear.

• Choose the lbutton_up event and click OK.

• If this is the first event handler for this dialog box, you will be prompted with an
Open dialog box for a new file to contain the source code for this dialog box. Type
a unique filename. Usually this filename is derived from the name of the dialog
box you are creating (like "form1.e").

After performing the above steps, the dialog editor will insert an event function definition
into your source file and place your cursor in the function. Add the code as shown below:

58 Slick-C Macro Programming Guide


Creating Dialog Boxes with the Dialog Editor

#include "slick.sh"

defeventtab form1
// Code for OK button.
ctlok.lbutton_up()
{
// Close the dialog box and return a value. The _delete_window
// function allows modal dialog boxes to return a value. For
// more information, see
// "Displaying Dialog Boxes" below. Each object
// in the dialog box will receive an on_destroy event.
// NOTE: If "" is a valid return value. Return 1 here and store
// your results in the global _param1 variable.
p_active_form._delete_window("return value");

// Statements after closing a dialog box are executed.


}

There are some subtle points about closing a dialog box. First, if a modal dialog box returns
a value, the value "" (zero length string) MUST be returned to indicate the dialog box has
been canceled. This convention is used so that when running a dialog box, you can press
Ctrl+Shift+Space to safely cancel and edit the dialog box. Second, you will need to use the
global container variables _param1.._param10 to return multiple strings. Alternately, you
can make an array or structure and place it in _param1. If you do place your string results in
the global variables _param1.._param10, make sure your dialog box returns 1 (or any value
other than "") to indicate that the dialog box was not canceled.

Displaying Dialog Boxes


The most common way to display a dialog box is with the show command. The show
command can be called in function style syntax from within a macro. It can also be invoked
from the command line or a menu item.

Command line call syntax:

show cmdline

Function call syntax:

show(cmdline [,arg1 [,arg2 ... [argN]]])

cmdline is a string in the format:


[option] form_name

option may be one of following:

-mdi Keep the form on top of the MDI Window.


-app Keep the form on top of the Visual SlickEdit Application
Window. This allows the MDI Window to be displayed on top
of the form.

Slick-C Macro Programming Guide 59


Creating Dialog Boxes with the Dialog Editor

-xy Restore the previous x, y position of the dialog box. If the old
position cannot be found, the dialog box is centered. When the
dialog box is closed, the x, y position is automatically saved (the
dialog manager calls _save_form_xy).
-hidden Do not make the form visible.
-modal Run the form modally. All other forms are disabled. Control
returns to the caller when the form window is deleted with
_delete_window.
-nocenter Do not center the form.
-new Normally, when a form is already displayed, the existing form is
given focus. This option allows for multiple instances of a form
to be displayed.
-reinit UNIX only. Ignored by other platforms. Causes
_delete_window function to make the form invisible instead of
deleting the form. The destroy events are dispatched even
though no windows are actually destroyed. Next time show is
called for the same dialog box, the invisible dialog box is made
visible, some properties are reinitialized, and the create events
are sent. Be careful when using this option. Not all dialog
boxes can use this option without minor modifications. The
form_parent() function will not work because the next time the
form is used, the parent is not changed to the new parent
specified.
-hideondel UNIX only. Same as -reinit option except no properties are
reinitialized when the invisible dialog box is shown again.

form_name specifies a form or menu resource. If it is an integer, it must be a valid index into
the names table of a form or menu. Otherwise, it should be the name of an existing form or
menu that can be found in the names table.

on_create and on_load Events


When a dialog box and all its objects are created, each object receives an on_create event.
The on_create event receives the arg1, arg2,...,argN arguments given to the show function.
After the on_create events are sent, the form receives an on_load event. You CANNOT set
the final focus in an on_create event. Use the _set_focus function during the on_load event
to set the initial focus to a control other than the control with lowest tab index (p_tab_index)
that is enabled and visible.

Return Value of Show


If the "-modal" option is given, the return value given to _delete_window is returned. "" is
returned if the dialog box is edited or destroyed during an on_create event. Use the global
variables _param1.._param10 to return more than one string value. Alternately, you can
make an array or structure and place it in _param1.

If the "-modal" option is not given, the form window id is returned if successful. Otherwise,
a negative error code is returned.

60 Slick-C Macro Programming Guide


Creating Dialog Boxes with the Dialog Editor

Example:

// This example requires that you create a form called form1 with a
// command button and load this file.
#include "slick.sh"
_command mytest()
{
result=show("-modal form1");
if (result=="") {
return(COMMAND_CANCELLED_RC);
}
message("_param1="_param1" _param2="_param2);
}

defeventtab form1
ctlcommand1.on_create()
{
// Global variable _param1.._param10 are defined in "slick.sh" to
// allow for multiple strings
// to be returned in separate variables. Alternatively, if the
// return strings do not contain spaces, you could concatenate
// them together with a space and use the parse built-in to easily
// separate them.
_param1="string1";
_param2="string2";
// Close the dialog box and indicate that the dialog box was not
// canceled. Each object in the dialog box will receive an
// on_destroy event.
p_active_form._delete_window(1);
}

Example:

// This example requires that you create a form called form1 with a
// command button and load this file.
#include "slick.sh"
_command void mytest()
{
show("-modal form1","param1 to on_create", "param2 to on_create");
}

defeventtab form1
ctlcommand1.on_create(_str arg1="", _str arg2="")
{
//arg1=arg(1); Could get the arguments with the arg built-in
//arg2=arg(2);
messageNwait("arg1="arg1" arg2="arg2);
}

Example:

#include "slick.sh"
defmain()
{
index=find_index("form1",oi2type(OI_FORM));
if (!index) {
messageNwait("form1 not found");

Slick-C Macro Programming Guide 61


Creating Dialog Boxes with the Dialog Editor

return(1);
}
// Can specify name table index instead of name
// When show is called without the "-modal" option, the
// positive window id (instance handle) of the form created
// is returned.
form_wid=show("-hidden -nocenter "index);
if (form_wid<0) {
return(1);
}
// Place the form at the top left corner of the display.
form_wid.p_x=form_wid.p_y=0;
// Make the form visible
form_wid.p_visible=1;
return(0);
}

Modal and Modeless Dialog Boxes


If you do not want the MDI Window or any other form to get focus when your dialog box is
displayed, specify the "-modal" option to the show command. When the "-modal" option is
given, other forms, including the MDI Window, are disabled (p_enabled=0) until the form is
closed. In addition, the _delete_window function can be used to return a value (see example
above).

Modeless Example:

#include "slick.sh"
defmain()
{
// When show is called without the "-modal" option, the positive
// window id (instance handle) of
// the form created is returned.
form_wid=show("-hidden -nocenter form1");
if (form_wid<0) {
return(1);
}
// Place the form at the top left corner of the display.
form_wid.p_x=form_wid.p_y=0;
// Make the form visible
form_wid.p_visible=1;
return(0);
}

Sometimes you need to display a status dialog box while doing some sort of processing. This
requires a modeless dialog box so control is returned to you. However, you still probably
want to disable all other dialog boxes including the MDI window while you do your
processing.

Advanced Modeless Example

#include "slick.sh"
static typeless gcancel;
_command void test()
{

62 Slick-C Macro Programming Guide


Creating Dialog Boxes with the Dialog Editor

// Show the form modeless so there is no modal wait


form1_wid=show("form1");
// Disable all forms by the one with p_window_id==form_wid. A
// space delimited string of disabled form window ids is returned.
disabled_wid_list=_enable_non_modal_forms(0,form_wid);
gcancel=0;
for (;;) {
// Read mouse, key, and all other events until non are left
// or until the variable gcancel becomes true.
process_events(gcancel);
if (gcancel) break;
// Do your processing here
}
// Enable the forms that were disabled.
enable_non_modal_forms(1,0,disabled_wid_list);
form1_wid._delete_window();
}
defeventtab form1;
ctlcancel.lbutton_up()
{
gcancel=1;
}

Dialog Box Parent Window


The parent window of a dialog box form has two uses. First, the dialog box will always
remain on top of the parent window. Use the show command and specify the "-app" option if
you want to allow a modeless dialog box to appear behind the MDI window. The "-mdi"
option of the show command can be used to make sure a dialog box stays on top of the MDI
window.

Command Line Examples:

show -app _calc_form


show -mdi -new _calc_form

Second, the parent window is used by some dialog boxes such as the Find, Replace, and
Spelling dialog boxes to determine which buffer to operate on. This allows these dialog
boxes to support the editor control. To do this, they call the _form_parent function during
an on_create event to get the window id of the window which contains the buffer to be
operated on. This does mean that these dialog boxes only support certain parent windows.
For example, the Find dialog box will not run correctly if the "-app" option of the show
command is used.

Remembering a Dialog Box Previous Position


By default, the show command centers the dialog box to the current form or MDI window.
Usually this is fine. However, sometimes it is helpful for a dialog box to reappear in the same
position it was in when the user closed the dialog box. To do this, specify the "-xy" option to
the show command. This adds the IS_SAVE_XY flag to the p_init_style property. When
the dialog box is closed, the x and y position of the dialog box is stored and later saved in the
auto restore file ("vrestore.slk" by default) when you exit the editor. The form is centered if
the old x,y position information cannot be found.

Slick-C Macro Programming Guide 63


Creating Dialog Boxes with the Dialog Editor

Clipboard Inheritance
Clipboard Inheritance (US patent No. 5,710,926) is a mechanism by which objects can be
transferred from one place to another via the clipboard in order to create new instances which
inherit the code of the original objects. Code for the new instances can be added, affecting
only the new instances, and code of the original instances can be modified, affecting both
instances. This is just another way to describe inheritance. The difference is that, with Slick-
C, the inheritance links are built for you in a very intuitive, natural way.

The most obvious flaw in Microsoft Visual Basic, Hypercard, and other high level user
interface building systems, is the loss of event handlers when you copy controls or dialog
boxes from one place to another via the clipboard.

A sample problem with some heavily commented source code will best demonstrate how the
Slick-C language works.

Assume you want to create a group of controls which are needed by Visual SlickEdit's File
Open dialog to allow the user to specify the various supported file formats. The file formats
Visual SlickEdit supports are:

• DOS. Each line is separated with a carriage return, followed by linefeed.

• Macintosh. Each line is separated with a carriage return only.

• UNIX. Each line is separated with a linefeed only.

• Record width. A user specified number of bytes placed in each line.

• A single user specified line separator character.

Here is a partial dialog box which can handle Visual SlickEdit's file formats:

And here is the code which drives this dialog box:

64 Slick-C Macro Programming Guide


Creating Dialog Boxes with the Dialog Editor

// The names of the controls do not need to be declared.

// The names of the radio button controls are ctlopendos, ctlopenmac, ctlopenunix,
// ctlopenauto

// The first text box is named ctlopenlinesep and the text box below it is named
// ctlopenwidth.

defeventtab form1;

// Define the lbutton_up event for the DOS radio button. This function will
// get called when any of the radio buttons get turned on. The event
// table automatically
// created here is called form1.ctlopendos.
ctlopendos.lbutton_up()
{
// Set the text displayed in both text boxes to nothing so the users
// knows that the radio button format has been chosen.
ctlopenlinesep.p_text='';
ctlopenwidth.p_text='';
}

static zap_radio_buttons()
{
ctlopendos.p_value=0;
ctlopenmac.p_value=0;
ctlopenunix.p_value=0;
ctlopenauto.p_value=0;
}

// Define the on_change event for the first text box. For a text box, the on_change
// event gets called when the users modifies the text in the text box.
// The event table
// automatically created here is form1.ctlopenlinesep.
ctlopenlinesep.on_change()
{
if (p_text!='') {
ctlopenwidth.p_text=''; // Clear out the other text boxes text.
zap_radio_buttons(); // Turn off all the radio buttons
}
}
// Define the on_change event for the second text box. The event table
// automatically created here is form1.ctlopenwidth.
ctlopenwidth.on_change()
{
if (p_text!='') {
ctlopenlinesep.p_text=''; // Clear out the other text boxes text.
zap_radio_buttons(); // Turn off all the radio buttons
}
}

Notice that only the first radio button ctlopendos has an event handler defined. The other
radio buttons just need to use the form1.ctlopendos event table. This can be accomplished
in the dialog editor in one of two ways. You can use Clipboard Inheritance or, if the radio
buttons are already created, you can just set the p_eventtab property of the other radio
buttons to form1.ctlopendos. To use Clipboard Inheritance you would simply write the
lbutton_up event code for the DOS radio button, copy the DOS radio button to the
clipboard, paste it back onto the dialog box within the frame, and set the p_caption property
for the new radio button to MAC. Either of these two methods can be used to propagate an
event table. When ctlopendos.lbutton_up() function gets called, it simply gets and sets the
properties of controls which obviously exist on this dialog box.

Slick-C Macro Programming Guide 65


Creating Dialog Boxes with the Dialog Editor

How Visual SlickEdit's File Open Dialog Box was Built


Clipboard Inheritance is a very powerful concept. If you take a close look at some of Visual
SlickEdit's complex dialog boxes, you will find out that there are massive amounts of
inheritance going on which was simply created by copying some controls to the clipboard,
and pasting them.

Below is a picture of Visual SlickEdit's ("fast" Windows 3.1 style) Open File dialog box:

The Open File dialog box has the form name _edit_form. This dialog box was actually
created by copying the _open_form dialog box (code links and all) to the clipboard, pasting
it, and then adding the "Find File..." button and the advanced controls. The _open_file form
can be thought of as the base File Open dialog box class. It is used for all other File Open,
and Save As operations except for opening files for editing which requires additional
controls. The inherited code from the base class File Open dialog required no changes except
for the OK button. For this, the OK button code was replaced with new code. The "Find
File..." displays a dialog box which has all the same advanced controls. The advanced
controls were taken from the Open File dialog box ("_edit_form") and all its related controls,
and copied them onto the Find File dialog box. The only additional code required was for
the OK button which was needed to return the results of the advanced options to the caller.

66 Slick-C Macro Programming Guide


Creating Dialog Boxes with the Dialog Editor

Visual SlickEdit's Find and Replace dialog boxes both allow searching across multiple files
and/or buffers. The controls for selecting files and buffers on these dialog boxes share the
same code. You might want to copy these controls onto your own dialog box to provide
multiple file and buffer processing for some other operation. In Visual SlickEdit 2.0, these
controls were pasted onto the Print dialog box.

It is important to note that while these examples did not require linking one event table to
another, the dialog editor recognizes when inheritance is required and will automatically link
event tables together. The statement below illustrates the syntax for linking one event table
to another.

defeventtab dlgbox2.textbox1 _inherit dlgbox1.textbox1

Dialog Box Inheritance Order


Each control in Slick-C has two properties called p_eventtab and p_eventtab2. The
p_eventtab property defines the user level 1 inheritance. User level 1 inheritance is intended
to allow you to modify the event handlers for one specific instance of a control without
affecting any other (except when Clipboard Inheritance is used). Like Microsoft Visual
Basic, you simply double click on the combo box when you want to add an event handler.
The dialog editor will automatically insert the necessary function declaration code so you
need only add statements within the function. Once you have written the event handler and
loaded the new code, the p_eventtab property displayed in the Properties list box will be
updated to reflect that you have defined a user level 1 event table. The p_eventtab2 property
defines the user level 2 inheritance. User level 2 inheritance is typically used to affect all
controls of a specific type. Normally, the dialog editor sets these properties for you when a
control is created. For example, when you create a combo box control with the dialog editor,
the p_eventtab2 property is automatically set to _ul2_combobx. The _ul2_combobx event
table defines the default processing used by every combo box. The user level 1 event
handler receives an on_change event (sent from the user level 2 code) when the text in the
combo box changes.

Visual SlickEdit uses a pre-defined inheritance order called the Dialog Box Inheritance
Order. When a control receives an event, the following search begins to determine which
event handler should get control:

1. IF and ONLY if the event we are searching is a key event, check the dialog box
frame's user level 1 inheritance.

2. Check current control's user level 1 inheritance.

3. Check current control's user level 2 inheritance.

4. Check automatic inheritance. Only the text box, combo box, and editor window
can have any automatic inheritance. This is how your emulation is supported in
these controls.

Slick-C Macro Programming Guide 67


Creating Dialog Boxes with the Dialog Editor

5. Check dialog box frame's user level 1 inheritance.

6. Check dialog box frame's user level 2 inheritance

7. Check dialog manager inheritance.

As soon as an event handler is found, the search stops and the event handler is executed.
Each inheritance level can have up to 20 linked event tables. This limit is only to avoid
infinite event table link loops. At run-time it is possible, but unusual, to change all
inheritance links and event tables for any object. The eventtab_inherit function can be used
to get or set an event table inheritance link.

Through trial and error, we found the above Dialog Box Inheritance Order to be the most
powerful. It allowed the dialog manager and all the default control event handling to be
written in Slick-C.

68 Slick-C Macro Programming Guide


Objects and Instances

Objects and Instances


Every object instance can be uniquely identified by a window id (also called instance
handle). Slick-C treats objects and windows the same. However, some objects, such as the
image control, have a window id but do not allocate an operating system resource known as a
window.

The Active Object


When an object receives an event, that object is the active object. More specifically, the
p_window_id property is set to the instance handle of that object. You can change the active
object by setting the p_window_id property to another object's window id. Accessing a
property without specifying a control name or instance handle accesses the property of the
active object and not the active form. This is significantly different than Microsoft Visual
Basic. For example, if a button control receives an event and executes a statement like
this, p_caption="New button caption", the button's caption is changed and NOT the
caption for the dialog box, which is what Visual Basic would do.

IMPORTANT: Changing the active object does NOT change the focus. Use the
_set_focus method to change the focus.

The Active Form


Slick-C has a p_active_form property which returns an instance handle to the current form.
The Slick-C interpreter actually does not keep track of what form is active. The active form
can be found rather quickly by traversing through the parents (p_parent) of the active object
until a form is reached.

Instance Expressions
The following examples illustrate common instance expressions:

ctltext1.p_text="test"; // Assuming ctltext1 has been declared


// globally or locally, lookup the
// ctltext1 control of the active form to get
// the window id, and set the
// p_text property.
x=_control ctltext1; // Put the window id of the "ctltext1" control
// of the active form in the variable x.
// The variable x does not have to
// be declared. There are cases where
// the _control keyword is not needed. It
// is better to always use
// it so you
// don't have to worry.
x.p_text="test"; // Set the p_text property of the
// object referenced by the

Slick-C Macro Programming Guide 69


Objects and Instances

// instance expression x.
(x+1-1).p_text="test"; // Same as previous statement. This
// shows that any valid Slick-C
// language expression may be
// used to get the window id.
x.(x+1-1).x.p_text="test";
// Same as the previous statement but wastes
// more code spaces. This shows that multiple
// periods ('.') may be used in an
// instance expressions.
form_wid=p_active_form; // Get the window id of the active form.
form_wid.ctltext1.p_text="test";
// Lookup ctltext1 as if the object
// referred to
// by the variable form_wid
// were the active object.
p_next.p_next.p_prev.p_prev.p_text="test";
// Waste some code space and access the p_text
// property of the active object.
p_window_id=_control ctltext1;
// Make the ctltext1 control the
// active object.
p_text="test"; // Access the p_text property of
// the active object.
_cmdline.p_text="test"; // _cmdline is a constant window id defined
// in "slick.sh". Set the command line p_text
// property to "test". Cool!!

Using Functions as Methods


A command or procedure may be called as a method without any additional declaration data.
The sample Slick-C source below illustrates this feature:

#include "slick.sh"
defmain()
{
// Call the tbupcase function as a method to operate on Visual
// Visual SlickEdit's command line. _cmdline is a constant instance
// handle defined in "slick.sh".
_cmdline.tbupcase();
}

// This function uppercases the text in a text box or combo box


// input field and has been written to operate on the current object.
tbupcase()
{
// The p_text property is used to get and set the contents of a
// text box or combo box input field
p_text=upcase(p_text);
}

Notice that tbupcase is not defined to be a method of a particular class. There are a
significant number of functions which can operate on any Visual SlickEdit object. This
feature also allows macros written in text mode Visual SlickEdit to be converted into Visual
SlickEdit macros and used as methods. Also, most functions in Visual SlickEdit are written
to operate on the current object which means you have access to a lot of methods. Using

70 Slick-C Macro Programming Guide


Objects and Instances

functions as methods is very useful when writing dialog box event handlers. The online help
indicates which functions can be used as methods for specific objects. If a function is called
and a statement within the function is not valid for the current object, the macro is stopped,
and a dialog box is displayed indicating the error. The find_error command ("Macro",
"Find Slick-C Error") may then be used to locate the source of the error. While using a
function as a method is useful, it lacks the ability to define two functions with the same name
which operate on different objects. This can be solved by allowing a class name (possibly
one of the built-in class names: _text_box, _combo_box etc.) when defining the function, like
in C++. This will be added to a future version of Visual SlickEdit.

Slick-C Macro Programming Guide 71


Built-in Controls

Built-in Controls
Label Control
The label control is used to display text in any font. Labels optionally may be aligned left,
aligned right, centered horizontally, centered vertically, or centered horizontally and
vertically. If you don't need to align the label, we recommend you should the p_auto_size
property to TRUE to ensure that the text inside the window fits. A common use of a label
control is to place it to the left of a text box to tell the user about what goes in the text box.
Select the Label control and use the up, down, left, and right arrow keys to help you center
the label to the text box.

For a complete list of label control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Spin Control
The most common use of a spin control is to increment or decrement a number displayed in a
text box (the text box usually appears to the left of the spin control). This can be performed
WITHOUT writing any code, simply by making the "tab_index" property of the text box one
less than the "tab_index" property of the spin control. You will get an error if there is no text
box with a tab index one less than the spin control, unless the "increment" property of the
spin control is set to zero. The easiest way to do this is to create the text box and then create
the spin control. You will want to turn off the "auto_size" property of the text box so you can
make the height of the text box larger than the font. Once you get the Spin control close to
the right edge of the text box, select the spin control and use the up, down, left, and right
arrow keys to help you center the Label to the spin control. The default increment is 1. You
can also use the spin control to increment/decrement the value in a gauge or scroll bar control
or increment/decrement a hexadecimal number displayed in a text box. In this case,
however, you must set the "increment" property of the spin control to zero and process the
on_spin_up and on_spin_down events yourself. The on_change event is called with a
reason set to CHANGE_NEW_FOCUS before an on_spin_up or on_spin_down event to
allow you to return the window id of the control you want to get focus, after spinning is
completed. Return an empty string ('') if you don't care.

Example:

#include "slick.sh"

// This example requires form name form1 with a text box and spin
// control. The spin control should be named ctlspin1 and the
// "increment" property should be zero. The tab index of the text
// box MUST be one less than the spin control. This code does not
// reference the name of the text box so that you can use Clipboard
// Inheritance(R) to create multiple working copies of a spin control
// capable of incrementing/decrementing the value in a text box control

72 Slick-C Macro Programming Guide


Built-in Controls

// without writing any new code.


defeventtab form1;
ctlspin1.on_change(reason)
{
if (reason==CHANGE_NEW_FOCUS) {
return(p_prev);
}
}
ctlspin1.on_spin_up()
{
new_dec_value=hex2dec(p_prev.p_text)+1;
p_prev.p_text=dec2hex(new_dec_value);
}
ctlspin1.on_spin_down()
{
new_dec_value=hex2dec(p_prev.p_text)-1;
p_prev.p_text=dec2hex(new_dec_value);
}

For a complete list of spin control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Text Box Control


The text box control allows the user to enter a single line of text. Use the editor control to
allow any number of lines to be entered. Text boxes support completion with the Space Bar
and question mark keys. Set the "completion" property of the text box if there is an existing
completion type which suits your needs. The FILE_ARG completion type is the most
common. It provides completion on file names. You can write new commands which
operate in all text boxes, edit windows, and editor controls.

Example:

#include "slick.sh"
_command void upcase_line()
name_info(","VSARG2_TEXT_BOX|VSARG2_REQUIRES_EDITORCTL)
{
init_command_op();
get_line(line);
replace_line(upcase(line));
retrieve_command_results();
}

Bind the upcase_line command above to Alt+F12. Notice that this command works in all
text boxes, edit windows, and editor controls. The key binding may not work in a text box if
you bind upcase_line to one of the CUA keys Alt+A..Alt+Z, Ctrl+X, Ctrl+C, or Ctrl+V. Use
the Redefine Common Keys dialog box ("Tools", "Configuration", "Redefine Common
Keys...") to allow all key bindings to be inherited into text box controls.

For a complete list of text box control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Slick-C Macro Programming Guide 73


Built-in Controls

Editor Control
The editor control allows a user to enter multiple lines. The editor control is used to view
clipboards, for the calculator, and for version control comments. Almost all your key
bindings for an MDI edit window will work in an editor control even if you have changed
your emulation. You can use macro recording to write a new command which works in an
edit window and editor control. Just check the "Allow in non-MDI editor control" check box
when you finish recording your macro.

For a complete list of editor control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Frame Control
The frame control is used to group a set of related controls. Often, radio buttons are placed
inside of a frame control to tell the dialog manager that only one of the radio buttons in the
group can be turned on at a time.

There are two ways to place a control inside a frame control:

• Click the left mouse button on the bitmap in the Properties dialog box of the control
you want to place inside the frame. Click and drag with the left mouse button
inside the frame control to create the control with the size of the rectangle
displayed.

• Copy or cut the control you want to place inside the frame to the clipboard. Select
the frame control and press Ctrl+V to paste the control inside the frame control.

For a complete list of frame control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Command Button Control


The command button control is most typically used to create an OK, Cancel, or Help button.

For a complete list of command button control properties, methods, and events, use the menu
item ("Help", "Macro Functions by Category").

Radio Button Control


Radio buttons must be grouped. Unlike check boxes, when one radio button is on, the other
radio buttons in the same group are off. Radio buttons are considered in the same group if
they have the same parent. Usually, radio buttons are grouped by placing them inside a
picture box or frame control. A picture box can have its "border_style" property set to
"BDS_NONE" to give the appearance that the picture box control does not exist.

74 Slick-C Macro Programming Guide


Built-in Controls

Use one of the following methods to place a radio button inside a frame or picture box:

• Click the left mouse button on the radio button bitmap in the Properties dialog box.
Click and drag with the left mouse button inside the frame or picture box control to
create the control with the size of the rectangle displayed.

• Copy or cut the radio button(s) you want to place inside the frame or picture box to
the clipboard. Select the frame or picture box and press Ctrl+V to paste the
control(s) inside it.

For a complete list of radio button control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Check Box Control


A check box is used for a true/false option. Check boxes may have the box part displayed to
the left or right of the caption.

For a complete list of check box control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Combo Box Control


A combo box is used in place of a text box for combo box retrieval, when only a fixed set of
responses is allowed, or when a common set of responses are known and a different response
may be typed in. Combo box retrieval is a mechanism by which the combo list box displays
the previous responses entered in the text box of the combo box. The combo box has three
styles ("style" property). Use the style which best suits your needs. The PSCBO_NOEDIT
style is used when only a fixed set of responses are allowed. Combo boxes support
completion with the Space Bar and question mark keys. Set the "completion" property of the
combo box if there is an existing completion type which suits your needs. The FILE_ARG
completion type is the most common. It provides completion on file names.

Example:

// This example illustrates combo box retrieval.


// This example requires a form named "form1", an OK button named
// "ok", and combo box named "ctlcombo1".
defeventtab form1;
ctlok.lbutton_up()
{
// When the OK button is pressed, you will want to save combo box
// retrieve information.
_append_retrieve(_control ctlcombo1,ctlcombo1.p_text);
}
ctlok.on_create()
{
// Fill in the combo box list
ctlcombo1._retrieve_list();

Slick-C Macro Programming Guide 75


Built-in Controls

A combo box consists of 4 controls: the root window, text box, picture box, and list box. The
properties and methods of the sub-controls may be accessed individually with the p_cb,
p_cb_text_box, p_cb_picture, p_cb_list_box instance handle properties. The
p_cb_picture property is only available when the control is displayed.

Example:

defeventtab form1;
ctlcombo1.on_create()
{
// To make the loop a little more efficient, activate the list
// box of the combo box control
p_window_id=p_cb_list_box;
for (i=1;i<=100;++i){
// Add an item to the active list box.
_lbadd_item("line="i);
}
// Activate the root window of the combo box.
p_window_id=p_cb;
}

Example:

#include "slick.sh"
defeventtab form1;
ctlcombo1.on_create()
{
// Show a picture which indicates that clicking on the picture
// box button displays a dialog box. _pic_cbdots is a global
// variable defined in "slick.sh" which is a handle to a picture.
p_cb_picture.p_picture=_pic_cbdots;
}
ctlcombo1.lbutton_down()
{
// Check if the left mouse button was pressed inside the picture
// box of the combo box
if (p_cb_active==p_cb_picture) {
result=show("-modal form2");
// process result here
return("");
}
// Skip user level 1 inheritance and execute the default event
// handler defined by user level 2 inheritance.
call_event(p_window_id,lbutton_down,2);
}

Example:

// This example requires a form named "form1", command button named


// "ok", a combo box named "ctlcombo1", and another command button
// named "ctlcommand1
#include "slick.sh"
defeventtab form1;
ctlok.lbutton_up()

76 Slick-C Macro Programming Guide


Built-in Controls

{
// Check if text in combo box text is valid. You might think you
// could use a non-editable style combo box. However, many users
// prefer typing in names using completion, to using the mouse to
// select an item out of a list box.
status=ctlcombo1._cbi_search("","$");
if (status) {
_message_box("Combo box contains invalid input");
return("");
}
// have valid input
}
ctlcommand1.lbutton_up()
{
// Add some items to the combo box list
ctlcombo1.p_cb_list_box._lbadd_item("Hello")
ctlcombo1.p_cb_list_box._lbadd_item("Open");
ctlcombo1.p_cb_list_box._lbadd_item("New");
// Make the correct item in the combo box list current so combo
// box retrieval works better. _cbi_search searches for p_text
// in the combo list box. The "$" specifies that an exact match
// should be found and not a prefix match.
status=ctlcombo1._cbi_search("","$");
if (!status) {
messageNwait("Found it!");
// Select the line in the combo box so that an up or down arrow
// selects the line above or below and not the current line.
ctlcombo1.p_cb_list_box._lbselect_line();
}
}

A combo box receives an on_change event with a reason argument under the following
circumstances:

reason Description

CHANGE_OTHER p_text property changed, probably because of typ-


ing.

CHANGE_CLINE p_text property changed because selected line in


list box changed and the list was visible.

CHANGE_CLINE_NOTVIS p_text property changed because a key was pressed


which scrolls the list (up, down, pgup, pgdown)
while the list was invisible.

CHANGE_CLINE_NOTVIS Same as CHANGE_CLINE_NOTVIS. Sent to user


2 level 2 inheritance only. User level 2 inheritance
will receive the CHANGE_CLINE_NOTVIS rea-
son as well if the user level 1 inheritance does not
catch the on_change event.

Slick-C Macro Programming Guide 77


Built-in Controls

The on_drop_down event is sent to a combo box with a reason argument. The reason
argument specifies one of the following conditions:

DROP_UP After combo list box is made invisible.


DROP_DOWN Before combo list box is made visible.
DROP_INIT Before retrieve next/previous. Used to initialize list
box before it is accessed.
DROP_UP_SELECTED Mouse released while on valid selection in list box and
list is visible

Example:

#include "slick.sh"
defeventtab form1;
ctlcombo1.on_drop_down(reason)
{
if (reason==DROP_INIT) {
if (p_user=="") {
p_user=1; // Indicate that the list box has been filled.
// Insert a lot of items
p_cb_list_box._insert_name_list(COMMAND_TYPE);
p_cb_list_box._lbsort();
p_cb_list_box._lbtop();
}
}
}

For a complete list of combo box control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

List Box Control


A list box is used to allow the user to choose from a fixed set of items. Multiple items from
the list may be selected at once by setting the "multi_select" property to MS_SIMPLE_LIST
or MS_EXTENDED (used by Open dialog box). A list box receives an on_change event,
with a reason argument set to CHANGE_SELECTED, when items are selected or deselected
because of a key press or mouse event. None of the _lb??? functions cause an on_change
event. Use the _find_longest_line() function to find the longest line in a list box.

Example:

// This example requires a form named "form1", a command button


// named "ok", and a list box named "ctllist1".
#include "slick.sh"
defeventtab form1;
ctllist1.on_change(reason)
{
// Check the reason value. In the future we may add more reason
// values for the list box.
if (reason==CHANGE_SELECTED) {
// IF any items in the list box is selected

78 Slick-C Macro Programming Guide


Built-in Controls

if (p_Nofselected) {
ctlok.p_enabled=1; // Enable the OK button
} else if(!ctlok.p_enabled){
ctlok.p_enabled=0; // Disable the OK button
}
}
}

Example:

//This example illustrates adding pictures to a list box.


#include "slick.sh"
#define PIC_LSPACE_Y 60 // Extra line spacing for list box.
#define PIC_LINDENT_X 60 // Indent before for list box bitmap.

defeventtab form1;
ctllist1.on_create()
{
// Add some extra line height.
p_pic_space_y=PIC_LSPACE_Y;
// _pic_??? arguments are global variables defined in "slick.sh"
// which are name table indexes to pictures. You can create and
// load your own pictures. All the bitmaps are shipped with the
// editor. Use the bitmap file "_drremov.bmp" as a template for
// creating your own bitmap for a list box. You can load your
// own bitmap files with the _update_picture function.
_lbadd_item("a:",PIC_LINDENT_X,_pic_drremov);
_lbadd_item("b:",PIC_LINDENT_X,_pic_drremov);
_lbadd_item("c:",PIC_LINDENT_X,_pic_drfixed);
// The p_picture property must be set to indicate that this list box
// is displaying pictures and to provide a scaling picture for
// the p_pic_point_scale property. The p_pic_point_scale property
// allows the picture to be resized for fonts larger or smaller than
// the value of the p_pic_point_scale point size. If
// p_pic_point_scale is 0, the picture is not scaled.
p_picture=picture;
p_pic_point_scale=8;
}

Example:

// This example illustrates how to resize a dialog box based on the


// longest item in a list box.
#include "slick.sh"
defeventtab form1;
ctllist1.on_create()
{
_lbadd_item("Line1");
_lbadd_item("This is a longer line2");
_lbadd_item("This is the longest item in the list box");
longest=_find_longest_line();

// Add on a little to account for the left and right borders of the
// list box. Have to convert client width because its in pixels.
list_width=longest+ p_width-_dx2lx(p_xyscale_mode,p_client_width);

form_wid=p_active_form;

Slick-C Macro Programming Guide 79


Built-in Controls

// Again we have to account for the left and right borders.


// Multiply p_x of list box by two to show equal amounts of
// spacing on each side of the list box.
form_width=2*p_x+ list_width+ form_wid.p_width-
_dx2lx(form_wid.p_xyscale_mode,form_wid.p_client_width);

p_width=list_width;
form_wid.p_width=form_width;

// Now make sure the whole dialog box can be seen on screen
form_wid._show_entire_form();
}

Example:

// This example illustrates how to disable a list box and make the
// items in the list box appear grayed.
#include "slick.sh"
defeventtab form1;
ctllist1.on_create()
{
_lbadd_item("item1");
_lbadd_item("item2");
p_no_select_color=1;
p_enabled=0;
p_forecolor=_rgb(80,80,80);
}

For a complete list of list box control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Vscroll Bar Control


A scroll bar control is typically used to allow the user to choose an integer that has a fixed
range or to display the completion status of a process. Set the "min", "max", "small_change",
and "large_change" properties to define the minimum integer value, maximum integer value,
increment/decrement which occurs when arrows are pressed, and increment/decrement
which occurs when you click left button between arrow and thumb box respectively.

The on_change event is sent after dragging the thumb box is completed. The p_value
property contains the new scroll position and will be in the range p_min..p_max.

The on_scroll event is sent while you click and drag the thumb box of a scroll bar.

Example:

#include "slick.sh"
defeventtab form1;
ctlvscroll1.on_scroll()
{
message("on_scroll p_value="p_value);
}

80 Slick-C Macro Programming Guide


Built-in Controls

ctlvscroll1.on_change()
{
message("on_change p_value="p_value);
}

For a complete list of scroll bar control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Hscroll Bar Control


See Vscroll Bar control above.

Drive List Control


The drive list is a combo box which allows selection of different disk drives. The Open
dialog box uses this control.

The drive list control receives an on_change event with a reason argument of
CHANGE_DRIVE when the drive is changed by selecting a different drive from the combo
list box.

Example:

#include "slick.sh"
defeventtab form1;
ctlcombo1.on_change(reason)
{
if (reason==CHANGE_DRIVE) {
message(
"Item selected from list. Current drive is now
"_dvldrive()
);
}
}

For a complete list of drive list control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

File List Box Control


The file list box control displays a list of files. Multiple files may be selected by setting the
"multi_select" property to MS_SIMPLE_LIST or MS_EXTENDED (used by Open dialog
box).

Slick-C Macro Programming Guide 81


Built-in Controls

A file list box receives an on_change event with a reason argument under the following
circumstances:

reason Description

CHANGE_SELECTED Occurs when items are selected or deselected


because of a key press or mouse event. None
of the _lb??? functions cause an on_change
event.

CHANGE_FILENAME _flfilename() function was called which


changed the file names listed.

Example

#include "slick.sh"
defeventtab form1;
ctlcommand1.lbutton_up()
{
ctllist1._flfilename("*.bat","c:\\");
}
ctllist1.on_change(reason)
{
if (reason==CHANGE_FILENAME) {
message("File list display directory "_flfilename());
}
}

For a complete list of file list box control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Directory List Box Control


The Directory list box control displays a list of directories.

A file list box receives an on_change event with a reason argument under the following
circumstances:

reason Description

CHANGE_SELECTED Occurs when items are selected or dese-


lected because of a key press or mouse
event. None of the _lb??? functions cause
an on_change event.

82 Slick-C Macro Programming Guide


Built-in Controls

reason Description

CHANGE_PATH _dlfilename() function was called which


changed the file names listed, the user dou-
ble clicked the left mouse button, or the user
pressed the Enter key.

Example:

// This example requires a form named "form1", a text box named


// "ctltext1", and a directory list box named "ctllist1".
#include "slick.sh"
defeventtab form1;
ctllist1.on_change(reason)
{
if (reason==CHANGE_PATH) {
// Set the text in the text box to current directory. Changing
// directories with the directory list box control changes the
// editor's current directory.
ctltext1.set_command(_dlpath(),1);
}
}

For a complete list of directory list box control properties, methods, and events, use the menu
item ("Help", "Macro Functions by Category").

Picture Box Control


The picture box is typically used to place other controls inside of it like the frame control.
The picture box is capable of displaying bitmaps, displaying bitmap buttons, and all the
features of the image control. However, the image control has better performance than the
picture box because it does not require a system resource known as a window. You should
use the image control (see “Image Control” on page 84) for displaying bitmaps and bitmap
buttons.

For a complete list of picture box control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Gauge Control
The gauge control is typically used to indicate the completion status of a process.

For a complete list of gauge control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

Slick-C Macro Programming Guide 83


Built-in Controls

Example:

// Create a form with a command button named ctlcancel, and


// gauge named ctlgauge1. Set the cancel and default
// properties of the command button to true.
//
#include "slick.sh"
static boolean gcancel;
_command test()
{
// Need to tell compiler ctlgauge1 is a control because
// the form1_wid.ctlgauge1 is too ambiguous.
_control ctlgauge1;

// Show the form modeless so there is no modal wait


form1_wid=show("form1");
// Disable all forms except form1_wid
disabled_wid_list=_enable_non_modal_forms(0,form1_wid);
gcancel=0;
for (i=1;i<=100;++i) {
// Read mouse, key, and all other events until none are left or
// until the variable gcancel becomes true
process_events(gcancel);
if (gcancel) {
break;
}
// Do work here. Replace the delay below with the operation
// you want to do. The delay makes this example look more real.
delay(10);
form1_wid.ctlgauge1.p_value=i;
}
// Enable all forms that were disabled.
_enable_non_modal_forms(1,0,disabled_wid_list);
form1_wid._delete_window();
}
defeventtab form1;
ctlcancel.lbutton_up()
{
gcancel=1;
}

Image Control
The image control performs a subset of the features of the picture box control. However, it
has better performance because an operating system resource known as a window is not
required. The image control is best used for creating bitmap buttons for button bars or tool
bars.

Adding a Bitmap Command Button or Check Box


Perform the following steps to add a bitmap button to a dialog box:

1. Create a new form for editing ("Macro", "New").

84 Slick-C Macro Programming Guide


Built-in Controls

2. Create an image control. Double click on the image control (Looks like slanted
rectangle) in the dialog editor.

3. Set the p_picture property to bbfind.bmp. Make sure you specify the full path
(c:\vslick\bitmaps UNIX: /usr/lib/vslick/bitmaps) is the default path used by
installation program).

4. Set the p_command property to gui_find. Notice that the down arrow of the
combo box displays all the editor commands.

5. Set the p_message property to Searches for a string you specify.

6. Set the p_style property to PSPIC_FLAT_BUTTON or PSPIC_BUTTON.

In step 3, you enter the "bbfind.bmp" bitmap as an example. The "bb" prefix indicates that
this is a bitmap that can be used by a toolbar. You can edit the "bbfind.bmp" file with paint
brush (pbrush.exe). Use "bbblank.bmp" as a template for creating your own bitmap
buttons.

Example:

// This example illustrates how to load your own picture like


// a toolbar button.
#include "slick.sh"
defeventtab form1;
ctlimage1.on_create()
{
index=_update_picture(-1,bitmap_path_search("bbfind.bmp"));
if (index<0) {
if (index==FILE_NOT_FOUND_RC) {
_message_box("Picture bbfind.bmp was not found");
} else {
_message_box(
"Error loading picture bbfind.bmp\n\n"get_message(index));
}
return("");
}
p_picture=index;
p_command="gui_find";
p_message="Searches for a string you specify";
p_style=PSPIC_FLAT_BUTTON;
}

Example:

// This example illustrate how to give the appearance of a button


// being pushed in. While you can do this by setting styles, here
// you can see how some other functions accomplish this task.
// For this example, create a form named form1 and an image control
// named ctlimage1.
#include "slick.sh"
defeventtab form1;
ctlimage1.on_create()
{

Slick-C Macro Programming Guide 85


Built-in Controls

index=_update_picture(-1,bitmap_path_search("bbfind.bmp"));
if (index<0) {
if (index==FILE_NOT_FOUND_RC) {
_message_box("Picture bbfind.bmp was not found");
} else {
_message_box(
"Error loading picture bbfind.bmp\n\n"get_message(index));
}
return("");
}
p_picture=index;
p_command="gui_find";
p_message="Searches for a string you specify";
p_style=PSPIC_BUTTON;
}
ctlimage1.lbutton_down()
{
// Reset the button counter so we don't get
// double and triple click events.
get_event('B');
mou_mode(1)
mou_capture();
done=0;
event=MOUSE_MOVE;
for (;;) {
switch (event) {
case MOUSE_MOVE:
mx=mou_last_x("m"); // "m" specifies mouse position in
// current scale mode
my=mou_last_y("m");
if (mx>=0 && my>=0 && mx<p_width && my<p_height) {
if (!p_value) {
// Show the button pushed in.
p_value=1;
}
} else {
if (p_value) {
// Show the button up.
p_value=0;
}
}
break;
case LBUTTON_UP:
case ESC:
p_value=0; // Restore the button state
done=1;
}
if (done) break;
event=get_event();
}
mou_mode(0);
mou_release();
say('out');
return("");
}

For a complete list of image control properties, methods, and events, use the menu item
("Help", "Macro Functions by Category").

86 Slick-C Macro Programming Guide


Adding Dialog Box Retrieval

Adding Dialog Box Retrieval


Dialog box retrieval is a mechanism which allows previous responses for check boxes, radio
buttons, text boxes, and combo boxes to be retrieved. Press F7 and F8 to retrieve the
previous or next response. For example, if you want to repeat your last Search and Replace
again, display the Replace dialog box ("Search", "Replace") and press Enter. The Replace
dialog box displays your last response including all check boxes. Try two search and replace
commands with this dialog box and then try pressing F7 or F8 when the Replace dialog box
is displayed. Your responses to dialog boxes are saved for your next session when you exit
the editor and auto restore is on ("Tools", "Configuration", "More Options...").

Example:

// This example illustrates how to add dialog box retrieval to your own
// dialog boxes. Create a form named "form1", a text box (any name), a
// check box (any name), and a command
// button named "ok".
#include "slick.sh"
defeventtab form1;
ctlok.on_create()
{
// Retrieve the previous response to this dialog box.
_retrieve_prev_form();
}
ctlok.lbutton_up()
{
_save_form_response();
p_active_form._delete_window(1);
}

Slick-C Macro Programming Guide 87


Menus

Menus
You may change or add menu items by using the Menu Editor dialog box ("Macro",
"Menus...", select a menu). To create a new menu, use the Open Menu dialog box ("Macro",
"Menus...") and press the New button. A quick way to bind a pop-up menu to a mouse click
is to use the Show button on the Open Menu dialog box while recording a macro. When you
are finished recording the macro, the Bind Command to Key dialog box is displayed which
allows you to bind your new macro to a mouse click.

Menu Macro Programming


This chapter describes macro programming details about menus. You do not need to read
this section unless you are attempting more advanced menu item enabling or you are writing
macros which manage menus. See online help on Menu Editor dialog box for information on
developing menus without macro programming.

Creating and Editing Menu Resources


Modified menus are stored in the state file "vslick.sta" (UNIX: "vslick.stu") The easiest way
to create or change a menu is to use the Open Menu dialog box ("Macro", "Menus..."). After
you have selected the menu, the Menu Editor dialog box is displayed which allows you to
easily edit a menu resource. Once the menu is created, you may use the show,
mou_show_menu, or _menu_show function to run the menu by displaying it as a pop-up.
The _menu_set method may be used to create a menu bar on a form. Another way to create
or change a menu is to define or modify a menu resource.

Defining a Menu Resource


Use the insert_object command to insert macro source code for a menu into the current
buffer. You can edit the resource properties and then run the macro to apply the resource
changes. You can ignore the message "No main entry point". Changing a menu resource
WILL NOT change any menu bars. Menu bars represent menu resources that have been
loaded. See _menu_load function in the online help for information on loading a menu
resource.

88 Slick-C Macro Programming Guide


Menus

A menu definition has the following format:

_menu menu_name {
submenu menu_item, help_command, help_message, categories
menu_item, command, categories, help_command, help_message
...
endsubmenu
submenu
...
endsubmenu
...
}

The items in italics have the following meaning:

menu_item Menu item name in double quotes. Use '&' to choose selection
character.
command Any editor command. Place cursor on Visual SlickEdit
command line and press '?' to list all editor commands.
help_command Command to be executed when F1 is pressed. Usually it is a
help or popup_imessage command.
categories Specifies zero or more help categories in double quotes.
Multiple help categories are separated with '|'.
help_message A single line message in double quotes displayed on message
line.

Sample Menu Definition:

_menu mymenu {
submenu "&File", "Help file menu", "Displays File drop-down menu","ncw"
"&New", "new", "", "help new", "Creates a new file to edit"
"&Open\tCtrl+O","gui_open","", "help gui_open", "Open a file"
endsubmenu
submenu "&Edit", "Help edit menu", "Displays Edit drop-down menu","ncw"
"Cu&t", "cut", "sel|nrdonly", "help cut", "Deletes the selection and copies it to the
clipboard"
}

Predefined Attributes For Auto-Enabling Commands


For convenience, Visual SlickEdit has some predefined enable/disable attributes which you
can specify for any command. You specify these attributes in the name_info of a command
definition. Auto-Enabling attributes affects the enable/disable state for a command placed in
a menu or in a toolbar.

Slick-C Macro Programming Guide 89


Menus

Example:

#include "slick.sh"
_command void top_of_buffer()
name_info(',' VSARG2_READ_ONLY| VSARG2_REQUIRES_EDITORCTL)
{
...
}

The above command will be disabled when there is no editor control to operate on.

Macro Callbacks for Enabling Commands


If the auto-enable attributes do not give you what you need, you can define a enable/disable
callback for your command. The name of the callback function you define is based on the
name of your command as shown below:

#include "slick.sh"
static boolean gSomeOtherState;
/*
This function gets called if your command is used in a menu _ or toolbar.
You must return a combination of the MF_ flags ORed together.

BEWARE: If an _OnUpdate callback causes a Slick-C run-time error, you


may not see the error. In addition, the timer used for toolbars,
Context Tagging(TM), AutoSave, and some other features may be
automatically terminated. Exit and restart the editor to restart
this timer. Use the "say" function to debug your _OnUpdate
callback
*/
int _OnUpdate_mycommand(CMDUI &cmdui,int target_wid,_str command)
{
//say('h1');
// Lets assume this command requires the target to be an
// editor control with a selection.
// IF the target is not an editor control
if ( !target_wid || !target_wid._isEditorCtl()) {
//say('disabled at h2');
return(MF_GRAYED);
}
//say('h3');
// IF the editor control does not have a selection
if (!target_wid.select_active2()) {
//say('disabled at h4');
return(MF_GRAYED);
}
//say('h5');
if (gSomeOtherState) {
//say('disabled at h6');
return(MF_GRAYED);
}
//say('enabled at h7')
return(MF_ENABLED);
}
_command void mycommand() name_info(','VSARG2_REQUIRES_EDITORCTL)
{

90 Slick-C Macro Programming Guide


Menus

// Some code here...


}
// This command effects the enable/disable of mycommand
_command void mycommand2(_str argument="0")
{
gSomeOtherState=(argument)?1:0;
// Indicate that the enable state of the toolbar buttons must be
// updated. The _tbSetRefreshBy function is very fast.
// Toolbars will be updated after the macro terminates and
// the user stops typing fast.
_tbSetRefreshBy(VSTBREFRESHBY_USER);
}

Putting a Menu Bar on a Form


The following sample code illustrates how to place a menu on a form as a menu bar:

#include "slick.sh"
// Create a form called form1 and set the border style to anything BUT
// BDS_DIALOG BOX. Windows does not allow forms with a dialog
// box style border to have menu bars.
defeventtab form1;
form1.on_load()
{
// Find index of Visual SlickEdit MDI menu resource
index=find_index(def_mdi_menu,oi2type(OI_MENU));
// Load this menu resource
menu_handle=p_active_form._menu_load(index);
// _set_menu will fail if the form has a dialog box style border.
// Put a menu bar on this form.
_menu_set(menu_handle);
// You DO NOT need to call _menu_destroy. This menu is destroyed
// when the form window is deleted.
}
form1.on_init_menu()
{
// Gray out all menu items which are not allowed when there
// no child windows.
_menu_set_state(p_menu_handle,"!ncw",MF_GRAYED,"C");
}

Displaying a Menu as a Pop-up


If the show or mou_show_menu function suits your needs, you should use one of them. The
following sample code illustrates how to display a menu as a pop-up:

#include "slick.sh"
defmain()
{
// Low-level code to display Visual SlickEdit menu bar as pop-up.
// Could just use show or mou_show_menu function.
index=find_index("_mdi_menu",oi2type(OI_MENU))
if (!index) {
message("Can't find _mdi_menu");
}
menu_handle=_menu_load(index,"P");
// Display this menu in the menu of the screen.

Slick-C Macro Programming Guide 91


Menus

x=_screen_width()/2;y=_screen_height()/2;
flags=VPM_CENTERALIGN|VPM_LEFTBUTTON;
_menu_show(menu_handle,flags,x,y);
_menu_destroy(menu_handle);
}

92 Slick-C Macro Programming Guide


Common Dialog Boxes

Common Dialog Boxes


The following are several important dialog box forms and functions you may want to use in
your own macros. See online help for examples and detailed information. Use the menu
item ("Help", "Search...") to get detailed online help for these items.

General purpose forms and dialog box functions:

_textbox_form General purpose form which displays a variable number of text


boxes or combo boxes.
_sellist_form General purpose form which displays a list box, an optional
combo box, and a variable number of command buttons.
_open_form General purpose form used to open and save files which does
not have the advanced controls.
_edit_form General purpose form used to open and save files which has the
advanced controls used for the ("File", "Open...") dialog box of
Visual SlickEdit.
_font_form General purpose form used to prompt for a font.
_choose_font Non-UNIX platforms only. General purpose dialog box built-in
to operating system used to prompt for a font.
_printer_setup Non-UNIX platforms only. General purpose dialog box built-in
to operating system used for printer setup.

There are a lot of commands which display dialog boxes. To find out what command a
particular menu item invokes, place your cursor on the menu item and press F1 to get help
on the command. If a key displays a dialog box, you can find out the command the key
executes by using the Bind Command to Key dialog box ("Tools", “Configuration”, "Key
Bindings...").

Slick-C Macro Programming Guide 93


String Functions Overview

String Functions Overview


The following are commonly used string functions. See online help on String Functions for
a complete list.

_str center(_str string,int width [,_str pad_ch])


Returns string padded evenly on left and right with spaces or a character you
choose with the optional argument pad_ch.
_str dec2hex(long number [,int base])
Returns number converted to base specified.
_str expand_tabs(_str string [,int start [,int count [,_str option]]])
Very similar to substr function except that this function supports tab characters
very well.
_str field(_str string,int width)
Returns string padded with trailing spaces to width characters
long hex2dec(_str number [,int base])
Returns number converted to base specified.
_str indent_string(int width)
If indent with tabs is on, a string of tabs of length width is returned. Otherwise, a
string of spaces of length width is returned.
boolean isalnum(_str ch)
Returns non-zero value if ch is a numeric or alphabetic character.
boolean isalpha(_str ch)
Returns non-zero value if ch is an alphabetic character.
boolean isdigit(_str ch)
Returns non-zero value if ch is a numeric character.
boolean isinteger(_str string)
Returns non-zero value if string is a valid int. If string is floating point number, 0
is returned.
boolean isnumber(_str string)
Returns non-zero value if string is a valid double (floating pointer number).
_str last_char(_str string)
Returns last character of string. If string is null, the space character is returned.
int lastpos(_str needle [,_str haystack [,int start [,_str options]]])
Returns the position (1..length(haystack)) of the last occurrence of needle in
haystack. If needle is not found, 0 is returned. Regular expressions are supported.
int length(_str string)
Returns the number of characters in string.
_str lowcase(_str string)
Returns string converted to lowercase.
_str number2onoff(_str number)
Returns "off" if number==0. Otherwise "on" is returned.
_str number2yesno(_str number)
Returns "N" if number==0. Otherwise "Y" is returned.

94 Visual SlickEdit v8 User Guide


String Functions Overview

parse expr with template


Breaks apart the expression expr given into variables that appear in template, and
much more.
boolean parseoption(_str &cmdline ,_str option_ch)
Strips "+" or "-" option from cmdline. Returns non-zero number if option_ch was
found.
int pos(_str needle [,_str haystack [,int start [,_str options]]])
Returns the position (1..length(haystack)) of the first occurrence of needle in
haystack. If needle is not found, 0 is returned. Regular expressions are supported.
boolean setonoff(_str &name,_str value)
Sets name to 1 or 0 corresponding to value="on" or value="off". Returns 0 if input
value is valid. Displays message if value is not "on" or "off".
boolean setyesno(int &name,_str value)
Sets name to 1 or 0 corresponding to value="Y","Yes" or value="N","No". Returns
0 if input value is valid. Displays message if value is not "Y" or "Yes", "N" or
"No".
_str stranslate(_str string, _str replace_string,_str search_string, _str search_options)
Returns string with all occurrences of search_string replaced with replace_string.
_str strieq(_str string1 ,_str string2)
Returns true if string1 matches string2 when case is ignored.
_str strip(_str string ,_str ltb [,_str strip_char])
Returns string stripped of leading and/or trailing strip_char.
_str strip_filename(_str filename, 'P'|'D'|'E'|'N')
Returns filename with part stripped. P=Path, D=Drive, E=Extension, N=Name.
_str strip_last_word(_str &line)
Returns the last space delimited word in line. The last word and trailing spaces are
deleted from line.
_str strip_options(_str cmdline ,_str &options)
Returns cmdline without words that start with the characters "-", "+", or "[".
options variable is set to stripped option words.
_str substr(_str string ,int start [,int len [,_str pad]])
Returns length characters of string beginning at start. By default, length defaults to
rest of string. If length is greater than length of string, the return string is padded
with blanks or pad character if specified.
_str translate(_str string [,_str output_table [,_str input_table [,_str pad]]])
Returns string with characters translated according to arguments.
_str upcase(_str string)
Returns string converted to uppercase.
int verify(_str string, _str reference [, "M"|"" [,int start]])
Returns the position (1..length(string)) of first character not matching or matching a
character in reference. 0 is returned on failure.
_str word(_str string,int Nth)
Returns the Nth space or tab delimited word in string. "" is returned if the Nth word
does not exist.

Visual SlickEdit v8 User Guide 95


String Functions Overview

Use the menu item ("Help", "Search...") to get detailed online help and examples for these
functions. For a list of string related functions, use the help item ("Help", "Macro Functions
by Category").

96 Visual SlickEdit v8 User Guide


Search Functions Overview

Search Functions Overview


Visual SlickEdit has two levels of search functions. The high level functions provide a few
extra features (user interfacing and multiple file searching) not provided by the lower level
built-in functions. For best speed, use the built-in functions. The built-in functions can be
used without affecting the high level search commands such as the find_next command. In
addition, the built-in functions are not affected by the global editor search options. For a list
of search related functions, use the help item ("Help", "Macro Functions by Category"). For
a complete list of search related functions, see online help on Search Functions.

Use the menu item ("Help", "Search...") to get detailed online help and examples for these
functions.

High Level Search Functions:

gui_find Displays Find dialog box and performs search using the find or
_mffind functions.
gui_replace Displays Replace dialog box and performs search using
gui_replace2 or _mfreplace functions.
gui_replace2 Performs a search and replace based on arguments given. This
function is very similar to the replace function, except that this
function uses a dialog box to prompt the user where to replace.
find_next Searches for next occurrence of search string used by any of
these high level search functions. This function is not affected
by previous searches done with low-level built-in functions.
find Performs search based on arguments given.
replace Performs a replace based on arguments given. The user is
prompted where to replace via the message line.
_mffind Performs a multiple file and/or buffer search based on the
arguments given.
_mfreplace Performs a multiple file and/or buffer search based on the
arguments given.

Lower Level Built-in Functions:

search Performs search, or search and replace, based on arguments


given. Does not support wrapping to top/bottom of file. When
performing a replace, the user is not prompted at all.
repeat_search Searches for the next occurrence of search string used by last
call to the search built-in.

Example:

// This example searches for lines which contain a particular search

Slick-C Macro Programming Guide 97


Search Functions Overview

// string and places the lines in another window and buffer.


defmain()
{
orig_wid=p_window_id;
// The +w option forces a new window to be created. The +t options
// force a new buffer to be created.
status=edit("+w +t");
if (status) {
_message_box("Unable to create temp window and buffer\n\n":+
get_message(status));
}
_delete_line(); // Delete the blank line
output_wid=p_window_id;

p_window_id=orig_wid;
top(); // Place the cursor at the top in column 1.
status=search("if","w@");// Case insensitive word search for "if"
// "@" specifies no string not found
// message.
for (;;) {
if (status) {
break;
}
get_line(line);
// Place the cursor at the end of the line so no more
// occurrences can be found on this line.
_end_line();
output_wid.insert_line(line);
status=repeat_search();
}
// Make the output window active so we can see the results
p_window_id=output_wid;
}

Example:

// This example is very similar to the example above except that the
// output data is placed in a view and buffer. The only advantage in
// using a view and buffer is that the output can be displayed
// in a list box without the user having to see a new window created.
#include "slick.sh"
defmain()
{
// Create a temporary view and buffer within the current window.
// Each window can store multiple cursor positions (views) to
// any buffer.
orig_view_id=_create_temp_view(temp_view_id);
if (orig_view_id=="") {
return("");
}

activate_view(orig_view_id);
top(); // Place the cursor at the top in column 1.
status=search("if","w"); // Case sensitive word search for if
for (;;) {
if (status) {
// clear the pending message caused by built-in search failing
clear_message();

98 Slick-C Macro Programming Guide


Search Functions Overview

break;
}
get_line(line);
// Place the cursor at the end of the line so no more occurrences
// can be found on this line.
_end_line();
activate_view(temp_view_id);
insert_line(line);
activate_view(orig_view_id);
status=repeat_search();
}

// Display the buffer in a list box.


// The _sellist_form dialog box will delete the temp view and buffer
// The original view must be activated before showing
// the _sellist_form or
// the dialog box will operate strangely
activate_view(orig_view_id);
result=show("_sellist_form -mdi -modal",
"Sample Selection List",
// Indicate next argument is view_id
SL_VIEWID|SL_SELECTCLINE,
temp_view_id,
"OK",
"",// Help item
"",// Use default font
"" // Call back function
);
if (result) {
message("Selection list cancelled");
} else {
message("Item selected is "result);
}
}

Slick-C Macro Programming Guide 99


Buffer Input/Output Functions

Buffer Input/Output Functions


The following are commonly used Input/Output Functions which operate on buffers and do
not require a selection:

.void _insert_text(_str string[, int Binary, _str NLChars])


Inserts string at cursor position
void _delete_text(int len [,"C"])
Delete len bytes starting from the cursor position.
_str _expand_tabsc(int start, int count [,"E"|"S"])
Returns data from current line starting at column (not byte position) start. count
columns of text are returned.
void get_line(_str &line)
Retrieves current line.
void replace_line(_str line)
Replaces current line.
void insert_line(_str line)
Inserts line after current line.
int delete_line()
Deletes the current line.
_str get_text([int count [,int seek_pos])
Gets a stream of text starting at cursor.
_str cur_word(int &start_col [,_str from_cursor,_str end_prev_word])
Gets the current word.
int _buf_transfer(int src_buf_id [,start_linenum [,end_linenum [,start_col [,end_col]]]]
)
Transfers data from src_buf_id to cursor.
void keyin(string)
Inserts string of characters as if typed from the keyboard. This function is SLOW
because it performs word wrap.

Use the menu item ("Help", "Search...") to get detailed online help and examples for these
functions.

Using selection functions is also an excellent way to transfer buffer data. For more
information, see “Selection Functions Overview” on page 101.

100 Visual SlickEdit v8 User Guide


Selection Functions Overview

Selection Functions Overview


Visual SlickEdit supports multiple selections. However, only one selection may be active or
visible. Selections are specified by handles. The _alloc_selection built-in returns a handle to
a selection. The function _free_selection frees a selection associated with the selection
handle given. Most selection functions accept a selection handle. A handle of '' specifies the
active selection or selection showing, which is always available. The _free_selection
function cannot free the active selection. To free the active selection, you must use the
_show_selection function first to make another selection the active selection. The actual
handle number of the active selection is returned by the expression
_duplicate_selection(""). For a list of selection related functions, use the help item ("Help",
"Macro Functions by Category").

Example:

// Duplicate the current line.


mark_id=_alloc_selection();
//
if (mark_id<0) {
message(get_message(mark_id));
return(rc);
}
_select_line(mark_id);
_copy_to_cursor(mark_id);
// This selection can be freed because it is not the active selection.
_free_selection(mark_id);

// This code copies selected text and keeps the resulting selection on
// the source text instead of the destination text.
if (_select_type()==""){
message(get_message(TEXT_NOT_SELECTED_RC));
return(1);
}
mark_id=_duplicate_selection() // Make a copy of the active
selection.
_copy_to_cursor();
// Save the selection id.
old_active_mark_id=
duplicate selection("");
// Must make another mark active before the old active mark can
// be freed.
show selection(mark_id); // Make copy of visible mark active
free selection(old_active_mark_id);

Writing Selection Filters


The module "markfilt.e" provides the procedure filter_selection for filtering selected text.
Define a global procedure that accepts a string and returns a string. Then pass the name of
the procedure to the filter_selection procedure.

Slick-C Macro Programming Guide 101


Selection Functions Overview

Example:

// This batch program converts the marked text into hexadecimal ASCII
// codes. Each hexadecimal ASCII code is separated by a comma. One
// possible use of this function could be to convert a binary font
// file into hexadecimal ASCII codes to be compiled into a C program.
#include "slick.sh"
defmain()
{
if (_select_type()=="" ) {
message(get_message(TEXT_NOT_SELECTED_RC));
return(TEXT_NOT_SELECTED_RC);
}
// Under scores must be converted to dashes.
return(filter_selection("hex-filt"));
}

_str hex_filt(string)
{
line="";
for(i =1;i<=length(string);++i) {
line=line:+dec2hex(_asc(substr(string,i,1))):+","
}
return(line);
}

102 Slick-C Macro Programming Guide


Unicode and SBCS/DBCS Macro Programming

Unicode and SBCS/DBCS Macro


Programming
If the Visual SlickEdit you are running does not support Unicode, you do not need to read
this section. Some OEMs do not start Visual SlickEdit in UTF-8 mode (Unicode support
mode).

When Visual SlickEdit is running in UTF-8 mode (by default, vs.exe for Windows runs in
this mode), buffers can contain either SBCS/DBCS data or UTF-8 data depending on how a
buffer is loaded. In order to make it easier for macros to support these two buffer data
formats, almost all macro functions accept and return UTF-8 strings. This allows most
macros to automatically work. Macros which use or set column positions often don’t work
correctly for both buffer data formats. The solution is to call “raw” functions.

Example:

// This won’t work if the current buffer is an SBCS/DBCS buffer,


// word is a UTF-8 string (which this example assumes), and word
// contains characters above 127.
p_col=p_col+length(word);
// This will work
p_col=p_col+_rawLength(word);
// This works too
word=_rawText(word);
p_col=p_col+length(word);

Example:

// This won’t work if the current buffer is an SBCS/DBCS buffer and


// The current line contains characters above 127.
get_line(line);
...
string=expand_tabs(line,p_col);
// This works
get_line_raw(line);
...
string=expand_tabs(line,p_col);
// This works too, but is less efficient if all operations on line
// can support raw data.
get_line(line);
...
string=expand_tabs(_rawText(line),p_col);

The _UTF8() macro function will tell you whether Visual SlickEdit is running in UTF-8
mode. The p_UTF8 property tells you whether the current buffer contains UTF-8 data. The
p_encoding property indicates what format the buffer will be saved in by default.

Slick-C Macro Programming Guide 103


Unicode and SBCS/DBCS Macro Programming

Like typical programming languages (Java, C++), Slick-C source files are code page
dependant. Strings are converted from the current code page to UTF-8. You only have to
worry about this if you enter characters above 127.

All macro functions and properties accept and return UTF-8 except the following:

The following Slick-C functions DO NOT accept or return UTF-8 data:

_default_option(VSOPTIONZ_SPECIAL_CHAR_XLAT_TAB)
All other options for this function are UTF-8.
All seek functions
goto_point(), _QROffset(), _GoToROffset, _nrseek(), point(), and seek()
For performance reasons all seeking is done on raw data. Since our tag database
stores seek positions, buffers need to be loaded in the same raw format so that seeks
works.
All _rawXXX() or XXX_raw() functions

(Unlike the C API) The Slick-C functions get_text(), and _expand_tabsc() return UTF-8 data.

The following Slick-C properties DO NOT accept or return UTF-8 data:

p_display_xlat

The following are Slick-C new raw functions:

_expand_tabsc_raw()
get_line_raw()
get_text_raw()
insert_line_raw()
_insert_text_raw()
replace_line_raw()
_rawLength()
_rawSubstr()
_rawText()

The following are Slick-C new that optional support raw data:

pos() – When p_rawpos appended to options argument.


lastpos() – When p_rawpos appended to options argument.
upcase() – When p_UTF8 property given as second argument.
lowcase()– When p_UTF8 property given as second argument.
parse - When p_rawpos appended to options of search argument.

104 Slick-C Macro Programming Guide


Unicode and SBCS/DBCS Macro Programming

The following are Slick-C new UTF-8 functions:

_MultiByteToUTF8()
_UTF8()
_UTF8Asc()
_UTF8Chr()
_UTF8ToMultiByte()

The following C API functions DO NOT accept or return UTF-8 data:

vsGetText(), vsGetRText(), vsExpandTabsC(), vsQSelectedTextLength(),


vsGetSelectedText()

These function always return raw data. Use the vsUTF8() function or check the
VSP_XLAT property to determine if you need to translate the buffer data. Since these
API functions assume that the maximum buffer length is the same as the read length, it
would be useless for these functions to return translated data.

All seek functions


vsQOffset, vsQROffset, vsGoToPoint, and vsGoToROffset

For performance reasons all seeking is done on raw data. Since our tag database stores
seek positions, buffers need to be loaded in the same raw format so that seeks works.

All vsXXXRaw() functions

Slick-C Macro Programming Guide 105


DLL Interface

DLL Interface
Visual SlickEdit has a DLL interface for Windows. We recommend using the Slick-C macro
language instead of the DLL interface except when you need to interface to another
program’s DLL, when you need better speed, or when the Slick-C macro language is missing
a function you need. Once a DLL function has been added, it can be called from a Slick-C
macro just like any other Slick-C function. In fact, DLL functions can be used for timer call
backs and anyplace a Slick-C function is used. To get started using the DLL interface, edit
the file "simple.c" in the <vslick>\samples\simple directory and read its comments for more
information. Currently, all VSAPI functions have the prefix "vs". Use the ("Help",
"Search") menu item and type "vs" for a list of VSAPI functions.

106 Slick-C Macro Programming Guide


Shelling Programs from a Slick-C Macro

Shelling Programs from a Slick-C Macro


To execute another program from a Slick-C macro you can use the shell built-in, the dos
command, or the execute built-in. The latter method is similar to executing a command on
Visual SlickEdit's command line, and allows you to create expressions which executes Slick-
C internal commands, Slick-C batch programs, or external programs. If you are only
interested in executing an external program, use the shell built-in or the dos command
described in the online help.

Example:

// Capture the output of Slick GREP and process the error messages.
dos("-e grep DEBUG *.c");
// Redirect the output of grep to a file.
shell("grep DEBUG *.c >junk");
// Run the DOS dir command and wait for a key to be pressed before
// closing command shell window.
shell("dir *.c >junk","w");
// Display the Calculator dialog box. Show is an internal command.
execute("show _calc_form");

Slick-C Macro Programming Guide 107


Hooking Exit and Other Events

Hooking Exit and Other Events


Invoking a Macro When Visual SlickEdit is Invoked
To invoke any macro command defined by _command or an external program when the
editor initializes, use the "-#" invocation option. For example, invoking the command "vs
makefile -#bottom_of_buffer" loads the file "makefile" and executes the bottom_of_buffer
command. To invoke a command with parameters, place the command and parameters
inside double quotes. Another method for getting macro code to execute without changing
any invocation options is to create a module with a definit entry point.

Invoking a Macro Before Visual SlickEdit Terminates


If you want a function to be invoked when the editor exits, create a macro procedure with a
name that has the prefix "_exit_". For example, the following procedure will automatically
get invoked when Visual SlickEdit exits:

_exit_cleanup_stuff()
{
messageNwait("Got here");
}

108 Slick-C Macro Programming Guide


Command Line Interfaces

Command Line Interfaces


This section describes how to write macros with command line interfaces.

Command Line Arguments


When a command is invoked from the command line, the expression arg(1) contains the rest
of the command line after the name with leading spaces removed. Alternatively, the
command can declare a named argument whose value is the same as arg(1). For example,
invoking the edit command "e file1 file2" calls the e command with "file1 file2" in arg(1).
The parse built-in is an excellent function for parsing a command line string (See online help
for more information on parse). When another macro calls a command, more than one
argument string may be passed. Calling the arg function with no parameters returns the
number of parameters the command or procedure was called with.

Example:

#include "slick.sh"
// This command supports completion on a filename followed by an
// environment variable argument
_command test1() name_info(FILE_ARG" "ENV_ARG")
{
parse arg(1) with file_name env_name;
message("file_name="file_name" env_name="env_name);
}
// This command supports completion on a filename followed by an
// environment variable argument
_command test1(_str cmdline="") name_info(FILE_ARG" "ENV_ARG")
{
parse cmdline with file_name env_name;
message("file_name="file_name" env_name="env_name);
}

The string constant expression given to the name_info keyword is used for argument
completion, restricting when the command can be executed, and a few other options. See
"name_info Attributes" on page 222 for more information.

get_string Procedure
The get_string procedure reads a single argument from the user. See get_string procedure
in the online help for a complete description.

Example:

#include "slick.sh"
_command test2()
{
if (get_string(file_name,"Filename: ",FILE_ARG";Help message")) {

Slick-C Macro Programming Guide 109


Command Line Interfaces

return(1); // Cancel key pressed.


}
if (get_string(env_name,"Environment variable name: ",
ENV_ARG";Help message","PATH") ) {
return(1); // Cancel key pressed.
}
message("file_name="file_name" env_name="env_name);
}

Single Argument Prompting with Support for Prompt Style


The prompt procedure is an easy and efficient way to write a command which accepts one
command line argument, or prompts for the argument if it is not given. If the user presses
ESC while being prompted for the argument, execution will not continue. See prompt
procedure in the online help for a complete description.

Example:

// This command supports completion on an environment variable argument


#include "slick.sh"
_command test3() name_info(ENV_ARG)
{
// If the user selects to abort, the prompt procedure
// stops execution.
env_name=prompt(arg(1),"Environment variable name: ");
message("env_name="env_name);
}

110 Slick-C Macro Programming Guide


State File Caching

State File Caching


By default, Visual SlickEdit does not load a module, event, dialog box template, or picture
from "vslick.sta" (UNIX: "vslick.stu") until it is referenced. Using the definit primitive
forces a module to be loaded when the editor is invoked. The default state file cache is about
200K. You may set this size with the "-st" invocation option or with the General
Configuration dialog box ("Tools", "Configuration", "General...", select Virtual Memory
Tab). When the state file cache becomes full, the least recently used module, dialog box
template, event table, or picture is removed from memory to reduce the cache size.

You may have critical modules which you want permanently stored in memory. Place the
no_code_swapping key word somewhere in your module (usually the top) to force a module
to be loaded and permanently stored in memory when Visual SlickEdit is invoked; then,
should a critical disk failure occur reading the state file, Visual SlickEdit will not be crippled.
A few of Visual SlickEdit's modules which provide basic editing capabilities remain
permanently in memory.

Slick-C Macro Programming Guide 111


Error Handling and the RC Variable

Error Handling and the RC Variable


The rc variable is a predefined global (meaning accessible from all loaded modules) variable.
In the future, the Slick-C language will not need to use the rc global variable for error
handling. Most functions which set the rc variable also return the error code so you don't
have to use rc. The following functions require you to use the rc variable for error handling:
buf_match, and get_env.

By convention, functions which use integer error codes return negative error codes which
correspond to the error codes in "rc.sh". For these functions, 0 means success and positive
codes means the error code is not in "rc.sh".

Some functions display an error message on the Visual SlickEdit message line. Use the
clear_message function to clear the message.

Example:

// Cause a message
_deselect();_copy_to_cursor();
// Clear the message
clear_message();

112 Slick-C Macro Programming Guide


Typical Mistakes

Typical Mistakes
Common programming mistakes occur when writing Slick-C language programs. One
mistake is to use the rc variable in an IF statement when the rc variable has changed. The
following example illustrates the mistake:

// Don't write code like this.


search("xyz"); // rc is set to 0 if "xyz" is found.
mark=_alloc_selection();
if (rc) { // Was "xyz" found?
...

The above sequence of statements does NOT work because the _alloc_selection function
sets the rc variable. If you execute a statement before the IF statement, save the value of rc
in a temporary variable, as shown below:

// Write code like this.


// rc is set to 0 if "xyz" is found and status is assigned rc.
status=search("xyz");
mark=_alloc_selection();
if (status ) { // Was "xyz" found?
...

Another common programming mistake is to rely on rc for all error conditions. Most
functions do not set rc. It is better to assign the return value to a variable, as shown below:

// Don't write code like this.


search("xyz"); // RC is set to 0 if "xyz" is found.
if (rc) { // Was "xyz" found?
...

// Write above code like this.


// rc is set to 0 if "xyz" is found and status is assigned rc.
status=search("xyz");
if (status ) { // Was "xyz" found?
...

Slick-C Macro Programming Guide 113


Interpreter Error Handling

Interpreter Error Handling


The two primitives _suspend and _resume may be used to process errors which would
normally halt the interpreter.

The _suspend primitive pushes a new level of error handling. After a _suspend has been
executed, errors which halt the interpreter will set the variable rc to the error code and
resume execution at the first statement after _suspend. The _resume function restores the
interpreter stack and code position to the state it was in after the last _suspend was executed.
Be sure to execute _resume to restore the suspend/resume stack.

Example:

defmain()
{
status=_suspend();
if (status) {
if (status<0) {
_message_box(get_message(status));
return(status);
}
return(0);
}
i=arg(1)+1; /* Handle invalid number argument */
message("i="i);
rc=1; // rc is the return value of the _suspend function
resume();
}

114 Slick-C Macro Programming Guide


Event Names

Event Names
Event names are used as arguments to the def primitive. Event names are also used when
comparing events returned by the get_event or test_event built-in functions or when
defining an event handler function.

An event name is a string literal of length one or more. An event name string of length one
specifies an ASCII character. To keep the macro source compatible, some event names do not
have to be enclosed in quotes as long as the “_” character is used instead of the “-” character.
The acceptable event constants are listed below:

ASCII characters
\0..\255 Backslash is used for non-displayable keys. You may also quote
displayable characters such as "a" or "4". The keys \1..\29 are also
represented by the keys "C-A", "C-B".."C-Z", "C-[","C-\\","C-]", "C-^",
and "C-_". The ASCII keys \129..\255 are the same key binding as \128.

Function keys
"F1", "F2"..."F12"

Extended keys
"ENTER", "TAB", "ESC", "BACKSPACE", "PAD_STAR", "PAD_PLUS",
"PAD_MINUS", "HOME", "END", "LEFT", "RIGHT", "UP", "DOWN", "PAD_5",
"PGUP", "PGDN", "DEL", "INS", "PAD_SLASH"

Mouse events
"LBUTTON-DOWN", "LBUTTON-DOUBLE-CLICK", "LBUTTON-TRIPLE-
CLICK", "RBUTTON-DOWN", "RBUTTON-DOUBLE-CLICK", "RBUTTON-
TRIPLE-CLICK", "MBUTTON-DOWN", "MBUTTON-DOUBLE-CLICK",
"MBUTTON-TRIPLE-CLICK", "LBUTTON-UP", "RBUTTON-UP", "MBUTTON-
UP"

ON events
"ON-CHANGE", "ON-CHANGE2", "ON-CLOSE", "ON-CREATE", "ON-CREATE2",
"ON-DESTROY", "ON-DESTROY2", "ON-DROP-DOWN", "ON-GOT-FOCUS",
"ON-HSB-BOTTOM", "ON-HSB-LINE-DOWN", "ON-HSB-LINE-UP", "ON-HSB-
PAGE-DOWN", "ON-HSB-PAGE-UP", "ON-HSB-THUMB-POS", "ON-HSB-
THUMB-TRACK", "ON-HSB-TOP", "ON-LOAD", "ON-LOAD-FOCUS", "ON-
RESIZE", "ON-SCROLL", "ON-SCROLL-LOCK", "ON-SPIN-DOWN", "ON-SPIN-
UP", "ON-VSB-BOTTOM", "ON-VSB-LINE-DOWN", "ON-VSB-LINE-UP", "ON-
VSB-PAGE-DOWN", "ON-VSB-PAGE-UP", "ON-VSB-THUMB-POS", "ON-VSB-
THUMB-TRACK", "ON-VSB-TOP"

Slick-C Macro Programming Guide 115


Event Names

Ctrl/Shift/Alt combinations
"A-<Extended key>", "C-<Extended key>", "S-<Extended key>", "S-C-<Extended key>"
For example, "A-ENTER", or "A-TAB" or "S-C-END"
"A-<Function key>", "C-<Function key>", "S-<Function key>"
For example, "A-F1".
"A-<Mouse event>", "C-<Mouse event>", "S-<Mouse event>"
For example, "A-LBUTTON-DOWN"
"C-S-<Extended key>", "C-<Extended key>", "S-<Extended key>"
For example, "A-ENTER" or "A-TAB"
"A-<ASCII character 0..128>"
Note that "A-a" is a different key than "A-A" which requires Alt and Shift keys to
be pressed. Also note that "A-"\1 is equivalent to "A-C-A".
"C-A", "C-B"..."C-Z", "C-[", "C-\\", "C-]", "C=^", "C-_", "C-,", "C-."
The keys \1..\29 are also represented by these keys.
"C-S-A,"C-S-B"... "C-S-Z", "C-S-1", "C-S-2"..."C-S-0"
"C-A-A".."C-A-Z"
Note that "A-"\1 is equivelent to "A-C-A".

Miscellaneous keys
"C-A-ENTER", "C-A-TAB", "C-A-ESC", "C-A-BACKSPACE"
"C-PRTSC", "C-CTRL", "A-ALT"

Miscellaneous events
"ON-SELECT"

Here are examples of uses for key names in the Slick-C language:

def "A-x"=safe_exit; // Note that "A-a" is different than "A-A" which


// requires the Alt and Shift keys to be pressed.
def "A-?"=help;

def "C-X" "b"=list_buffers;

def \0 - \255= nothing;

ctlcombo1.on_change()
{
}
ctlcombo1."c-s-a"()// Define event handler for Ctrl+Shift+A
{
}
ctlcombo1."a"-"z", "A-"Z"()// Define event handler for characters A-Z
// upper and lowercase
{
}

116 Slick-C Macro Programming Guide


Event Names

void p()
{
for (;;) {
key=get_event();
if (key:==name2event("ESC") break;
if (key:==name2event("UP")) {
...
} else if (key:==name2event("DOWN") ) {
...
}
}
}

Slick-C Macro Programming Guide 117


Differences Between Slick-C and C++

Differences Between Slick-C and C++


Structures
• Space for structure member variables is allocated when you access the member.

• Structure data is not continuous. This is obvious for string, array, and hash table
member variables which contain variable size data. However, even other types are
sometimes stored elsewhere. In the future, after a few changes are made, the way
Slick-C lays out memory will be documented.

• There is not a sizeof function which tells you the size of a structure in bytes.

Arrays
• Space for array elements is allocated when you index into the array.

• You can't use pointer variables to traverse array elements.

• You can't limit the number of elements that the array may contain.

• Specifying an array variable without the [] operator does not return a pointer to the
first element. Instead it refers to the entire array. This allows you to copy one array
to another or define a function which returns a copy of an array.

• There is not a sizeof function which tells you the size of the array in bytes. There is
a _length method which tells you the number of elements in the array.

Example:

struct PHONERECORD {
_str name;
_str PhoneNumber;
};

defmain()
{
PHONERECORD list[]; // No size limit is allowed here.

//Allocate space for 0 index and name member


list[0].name="Joe";
// Allocate space for PhoneNumber member.
list[0].PhoneNumber="555-1234";

PHONERECORD list2[];
list2=list; // Copy the entire array into list2

t=list2; // Now copy the entire array into a container variable.

118 Slick-C Macro Programming Guide


Differences Between Slick-C and C++

Hash Tables
Slick-C provides a :[] hash table operator which is similar to the array operator [] except that
you index hash tables with a string type.

Assignment Statement
Assignment statements in Slick-C are not as shallow as C++. Array, hash table and structure
types are recursively traversed. Pointers are not traversed.

Example:

struct {
int a[];
} s1,s2;
s1.a[0]=1;
s2=s1; // Copy stucture and all elements of array.

Comparison Operator
The == and != operators support comparing container types, arrays, hash tables and
structures. Complex types are traversed recursively like the assignment statement. Strings
within an array, hash table or struct must match exactly (spaces matter).

Preprocessing
Preprocessing expressions may use string and floating point expressions.

switch Statement
The switch statement supports string expressions in addition to integer expressions.

Labeled Loops
break and continue statements take an optional label parameter so you can break a specific
loop (like Java).

Example:

outerlabel:
for (;;) {
for (;;) {
if (...) break outerlabel;
if (...) continue outerlabel;
}
}

Slick-C Macro Programming Guide 119


Differences Between Slick-C and C++

Variable Argument Functions


An arg function allows you to define functions which accept a variable number of
arguments. The arg function may be used on the left side of an assignment statement.

defmain()
{
p("Param1",2,x);
}
void p()
{
messageNwait("Called with "arg()" arguments");
for (i=1;i<=arg();++i) {
messageNwait("arg("i")="arg(i));
}
//All undeclared variable parameters are passed by reference.
//so when a variable is passed, we can change the contents of
//the callers variable.
arg(3)="New value for x";
}

Built-in Graphics Primitives


You can define dialog box resources and menu resources. There are primitives for defining
event handlers for dialog boxes and declaring control types. This allows the Slick-C linker to
detect a reference to a control which does not exist on a dialog box before you execute your
code.

Clipboard Inheritance
Clipboard Inheritance provides inheritance specifically for dialog boxes. This feature allows
you to copy parts of existing dialog boxes to the clipboard, paste them elsewhere, and the
original code still runs. New code can be attached to the new controls without affecting the
original controls. New code can be added to the original controls to affect both instances of
the controls (inheritance). Creating inheritance for parts of dialog boxes is very natural
because the Slick-C language has been designed for this feature.

End of Statement. Semicolon


Currently Slick-C assumes end of line is a semicolon except under a few conditions.
Expressions may extend across line boundaries if the line ends in a binary operator or if the
line ends with a backslash. In addition, expressions in parentheses may extend across line
boundaries. In the future, Slick-C will enforce strict semicolons to conform with C++.

Type Checking
For the most part, type checking in Slick-C is identical to C++ except for the following:

• The typeless type is compatible with ALL other types.

• String constants are automatically converted to numeric types where necessary.

120 Slick-C Macro Programming Guide


Differences Between Slick-C and C++

• Integer types are automatically converted to string types.

• Functions do not require prototypes. However, when a prototype is given, strict


type checking is enforced like you would expect. A #pragma option to require
prototypes will eventually be added.

Capability Not Supported by Slick-C


• You cannnot define your own classes, methods, or inheritance. The important
class, public, private, and new keywords are not supported yet. Like Java, we
have decided that classes in Slick-C will not require a delete to free objects.

• Only one syntax is currently supported for making a call with a pointer to a function
variable. The pfn(p1,p2,...) syntax is not supported. This limitation is necessary for
container variables because the compiler does not know the type of the variable.
However, support will be added for the other syntax for typed pointers to functions.

• char and short types are not available.

• Template classes are not supported. Container variables are sometimes a more
powerful mechanism for accomplishing much of what is done with template
classes. However, users will likely want the speed and additional type checking of
template classes and many programmers are already used to template classes.

• Function overloading is not supported.

• enum is not supported.

• Currently Slick-C only supports the less ambiguous C style type casting. Support
for the new C++ type casting syntax TypeName(expression) may be added in the
future. The argument is between having an elegant less ambiguous grammar or
conforming to C++ so there is nothing new to learn. If you have an opinion on this
topic, let us know.

• Because Slick-C does not allow low level manipulation of memory, you can't do
things like type cast an "int *" to a "long *".

• There are no character constants defined using single quote characters. Slick-C
currently allows the use of single quotes to define strings. Single quoted strings are
much more readable for filenames or regular expressions which require the use of
backslashes. This syntax may be changed in the future so that single quotes may be
used for character constants.

• goto is not supported. (Slick-C supports labeled loops.)

Slick-C Macro Programming Guide 121


Windows Structure

Windows Structure
This section describes the internal data structure the editor uses to keep track of windows,
buffer positions (views), and buffer data. You need not read this unless you wish to write a
Slick-C macro which manipulates windows, views, and buffers.

The picture below represents invoking Visual SlickEdit with two files loaded (buffers b2 and
b3) and two windows (w1 and w2) viewing those files.

The extra window w0 is a hidden window used to allow quick switching to system buffers
such as ".command" and ".killed". To reduce the size of the drawing we have not given the
buffers names. Visual SlickEdit has one hidden window which cannot be displayed. If you
to attempt to leave the hidden window active, another window will be made active when the
editor refreshes the screen. Since window w1 is active, you currently see window w1 of
buffer b2. You might be able to see window w2 of buffer b3. If the window w1 does not
overlap window w2.

Visual SlickEdit maintains a ring of buffers and a ring of windows, where each window MAY
contain a ring of views. However, by convention, all windows except the hidden window
contain ONE view. Some macros temporarily create extra views in other windows, but they
delete them before they terminate. The built-ins _next_buffer and _prev_buffer activate
the next and previous buffers. _next_window and _prev_window move around the window
ring. _next_view and _prev_view move around the active view ring. The built-in function
load_files inserts views, windows, and/or buffers. _delete_buffer removes the active buffer
from the buffer ring and activates the previous non-hidden buffer. _quit_view removes the

122 Slick-C Macro Programming Guide


Windows Structure

active view from the active windows view ring. The previous view becomes the new active
view. When _quit_view is executed and only one view exists in the active window, the
window is removed and the previous window becomes active. You cannot delete the hidden
window.

A view holds the information necessary for the editor to remember your location and scroll
position in a buffer. A view also contains a window id and a buffer id. Activating a view
with the activate_view built-in activates the window and buffer specified by the view as well
as selecting the cursor location/scroll position.

Each buffer maintains a non-active view. When a buffer is activated by one of the built-ins
_next_buffer, _prev_buffer, _delete_buffer or load_files (assuming you do not use an
option which overrides this) the active view information is saved in the active buffer's non-
active view, and the new buffer’s non-active view information is copied into the active view.

Below is a description of the contents of each structure.

Some window properties are:

p_window_x, p_window_y Top left coordinates of window.


p_window_height, p_window_width Height and width of window.
p_tile_id Indicates which windows are part of a tile
window group and whether a window is
zoomed. Windows of a tiled window group
have the same tile_id. A zoomed window
has a negative tile_id.
p_x The top left x position of window.
p_y The top left y position of window.
p_height Window height.
p_width Window width.
p_view_id Pointer to active view.
p_next Window id of next window.
(_next_window)
p_prev Window id of previous window.
(_prev_window)
p_child Window id of child window.

Some view properties are:

block,line within block Accessible via point and goto_point.


p_line Line number of current line.
p_col Column position within current line. 1..2
billion
p_left_edge Column scroll position.
p_cursor_x Text cursor x position.
p_cursor_y Text cursor y position.

Slick-C Macro Programming Guide 123


Windows Structure

p_window_id Window id.


p_buf_id Buffer id.

Some buffer properties are:

p_buf_name Name of buffer.


p_buf_flags Indicates whether a buffer is hidden and may
specify other buffer options. See online help
on "internal-variables".
p_Noflines Number of lines in file.
p_modify Non zero indicates buffer has been modified.
p_margins String containing left, right, and new
paragraph margins ( 1..2 billion).
p_tabs String containing up to 2 billion tab stops.
p_mode_name Name of current mode.

124 Slick-C Macro Programming Guide


Converting SlickEdit 2.3/2.4 Macros and Configuration

Converting SlickEdit 2.3/2.4 Macros and


Configuration
Perform the following steps to convert your SlickEdit configuration changes to Visual
SlickEdit:

1. Install Visual SlickEdit into a different directory than SlickEdit as described below.

2. Run the list_source command from the Configuration menu in SlickEdit to list the
macro source for changes you have made. This will create a file called "userdefs.e"
(UNIX: "unixdefs.e").

3. Windows: Copy the "userdefs.e" file to your local configuration directory


(determined by the VSLICKCONFIG environment variable if you have one) or to
the macros directory (defaults to "c:\vslick\macros") and change its name to
"vusrdefs.e".

UNIX: Copy the "unixdefs.e" file to your local configuration directory "$HOME/
.vslick" and change its name to "vunxdefs.e".

4. Run Visual SlickEdit and type cleanup on the command line. All options that are
still present in SlickEdit will be converted.

5. Save the resulting file created by the “cleanup” command and type vusrdefs on the
command line to apply the changes to Visual SlickEdit.

To convert a macro source file you have written, perform the following steps:

1. Install Visual SlickEdit into a different directory than SlickEdit as described below
if you have not already done so.

2. Windows: Copy the macro source files you want to convert to your local
configuration directory (determined by the VSLICKCONFIG environment
variable if you have one) or to the macros directory (defaults to "c:\vslick\macros").

UNIX: Copy the macro source files you want to convert to your local
configuration directory "$HOME/.vslick".

3. Run Visual SlickEdit.

4. Edit the macro source file in the Visual SlickEdit directory you want to convert.

5. Type tconvert on the command line.

Slick-C Macro Programming Guide 125


Converting SlickEdit 2.3/2.4 Macros and Configuration

The converter can convert about 95% of your macro source. Typical conversion
problems are documented in the text file "convert.doc" which is located in the
configuration directory (defaults to "c:\vslick" or "/usr/lib/vslick" for UNIX).

126 Slick-C Macro Programming Guide


Index

Index Adding 58
case 33
casting types 28
Symbols Check Box control 75
Clipboard Inheritance(R) 64
Closing a dialog box 58
#pragma 44
Combo Box control 75
_control 45, 69
Command Button control 74
_delete_window 59, 61
Commands
_inherit 48
defining 36
_resume built-in 114
Concatenation 14, 18
const 15
A Constants
numeric 14
Active form 69
Active object 69 D
Adding completion to command 38
Aligning Controls 53
Declaring (See defining) 13
AND operator 17
def 46
Anonymous Unions 24
Default Arguments 35
arg built-in 35
defeventtab 47
Argument Declarations 34
defeventtab primitive 46
Array length method 25
Defining
constants 15
B event tables 48
functions 34
Batch macro 10 keys 46
bigfloat 20 procedures 34
bigint 20 definit 49
bigstring 20 defload 49
Bitmaps defmain 41
Adding to image control 85 Dialog Box Retrieval 87
Adding to list box 79 Dialog Boxes
Bitwise Common 93
and 17 Dialog editor 52
complement 16 Dialog Editor Properties dialog box 55
or 17 Directory List Box control 82
xor 17 Drive List control 81
boolean 20, 30
break 32 E

C Editor Control 74
Environment variables
Cancel button VSLICKINCLUDE 45
VSLICKPATH 45

Visual SlickEdit v8 Installation Guide 127


Index

VST 45 L
Event driven dialog box 9
Event driven dialog boxes 48
Label control 72
Event tables 46
List Box control 78
Executing programs from macro 107
load command 47
Loading macros 12
F Loops 31

false 20 M
File List Box control 81
filter_selection procedure 101
Macro
Filtering marked text 101
prompting 109
Find Slick-C Error menu item 51
Selection filters 101
find_error command 51
Macro converting
find_proc command 51
From SlickEdit 2.3 125
Floating point numbers 14
Mark_id 101
For 31
Mathematical Operators 16
Frame control 74
Menu
Function Pointers 27
Changing or Adding 88
Menu Macro Programming 88
G Methods 70
Modal and modeless dialog boxes 62
Gauge control 83 Moving Controls 54
get_string procedure 109 Multiple Instances 69

H N

Hex character code 14 name_info Attributes 38


hexadecimal numbers 14 no_code_swapping 111
Hscroll Bar control 81 NOT operator 16
null 25
Numeric constants 14
I

Image control 84
O
Including macro header files 45
Inheritance 48, 64, 67 Object Instances 69
initializing OK button
macro modules 49 Adding 58
Instances 69 operator 24
int 20 Operators 16
OR operator 17

128 Visual SlickEdit v8 Installation Guide


Index

P String literals 13
struct 21
suspend built-in 114
p_active_form 69
p_window_id 69
Picture Box control 83 T
Pictures
Adding to image control 85 Text Box control 73
Adding to list box 79 true 20
Pointer Variables 26 Type Casting 28
Preprocessing 43 typeless 20, 29
Product Support 2 typeless variable declaration 19
prompt procedure 110 TypeName 20
Prompting
from macros 109
Properties dialog box 55
U
prototypes 40
Unary operators 16
union 23
R

Radio Button Control 74


V
rc variable 112
return statement 34, 36 var 36
Run-time error finding 51 Vscroll Bar control 80
vslick.sta 111
vstw.exe program 12
S

Selecting Controls 53
W
Setting Properties 53
Shelling from macro 107 wid_expression 69
Sizing Controls 54
SlickEdit 2.3 X
Converting macros 125
Spin control 72
xcom command 42
static 19

Visual SlickEdit v8 Installation Guide 129


Index

130 Visual SlickEdit v8 Installation Guide


Reader’s Comments

Reader’s Comments
Thank you for using Visual SlickEdit! SlickEdit Inc. invites you to give us your comments
and suggestions for improving Visual SlickEdit and this Slick-C Macro Programming Guide.
Please take a moment to complete this Reader’s Comments sheet. SlickEdit values your input
and will consider your suggestions for future product releases.

Please rate the Slick-C Macro Programming Guide on the following items:

Very
Excellent Good Fair Poor
Good

Ease of finding information.


Completeness of information.
Accuracy of information.

Please list your suggestions for improvements to the Slick-C Macro Programming Guide:

Please list your suggestions for improvements and/or enhancements to the Visual SlickEdit:

Please fax this sheet or email the information to:


SlickEdit Inc.
Attn: Director of Product Management & Marketing
Fax +1 919.473.0080
marketing@slickedit.com

Thank you for your comments.

Slick-C Macro Programming Guide 131

You might also like