Multi-Edit's Top Bar Image - Click here to Return to the Home Page spacer image for website layout News regarding our IDE -click this image- Products of MESI Page -click this image- Support Avenues, Forums, Emails etc. -click this image- Purchase Online -click this image- Resources, Downloads, Zips for Mult-Edit -click this image- Company NFO -click this image- Website Sitemap -click this image-

- Written and documented by David Deley



Introduction to CMac Chapter 3: Caveats

There are a few differences between CMAC and other programming languages you may be familiar with, like C. These are small things you often end up learning the hard way, by experience. I mention these early on so you'll be aware of them. I also encourage others to append other caveats they've learned.


1. EXPRESSION EVALUATION IS STRICTLY LEFT-TO-RIGHT
CMAC doesn't have operator precedence as you may be used to in other languages. Expression evaluation is strictly left-to-right. For example, the following code doesn't work as expected:
Code:
">if (x >= y-z)
You have to add parenthesis:
Code:
if (x >= (y-z))



2. SINGLE QUOTED STRINGS vs. DOUBLE QUOTED STRINGS
Double quoted strings interpret the backslash \ character as a special character.
Code:
"\a" = 0x07 bell
"\b" = 0x08 backspace
"\f" = 0x0C form feed
"\n" = 0x0A newline
"\r" = 0x0D carriage return
"\t" = tab or space (see below*)
"\v" = 0x0B vertical tab
"\\" = 0x5C backslash
"\"" = 0x22 double quote
"\'" = 0x27 single quote
"\xHH" or "\XHH" = 0xHH where HH is a hexadecimal number
str Example = "First line\nSecond line\nThird line";

* "\t" will enter a 0x09 horizontal tab character if "Tab Expand" is set to "Tabs" under TOOLS -> CUSTOMIZE... -> Editing, or it will enter a 0x20 space character if "Tab Expand" is set to "Spaces".

Two double quotes together inside a double quoted string make a double quote:
Code:
"He said, ""Goodbye!"" and then left."

same as:
Code:
"He said, \"Goodbye!\" and then left."
Result:
Quote:
He said, "Goodbye!" and then left.

Single quoted strings interpret the vertical bar | character as a special character. A vertical bar followed by a number will insert that character value. A few examples:
Code:
'|12'  = form feed
'|10'  = newline
'|13'  = carriage return
'|124' = "|" vertical bar
'||'   = "|" vertical bar
'|65'  = 'A'
'|90'  = 'Z'
'|97'  = 'a'
'|122' = 'z'
str Example = 'First line|10Second line|10Third line';

Two single quotes together inside a single quoted string make a single quote:
Code:
'He said, ''Goodbye!'' and then left.'

Result:
Quote:
He said, 'Goodbye!' and then left.

3. MACROS MUST BE EITHER PROTOTYPED OR DEFINED BEFORE THEY ARE CALLED BY OTHER MACROS.
For example, the following will work because macro "mysub" is defined before macro "test" which calls it.
Code:
void mysub()
{
 ...
}

void test()
{
  mysub();
}

The other way is to prototype macro "mysub" at the beginning of the file. The following will work even though macro "mysub" is defined below macro "test" which calls it:
Code:
macro_file mycmac;
prototype mycmac {
  void mysub();
}

void test()
{
  mysub();
}

void mysub()
{
 ...
}

4. WINDOW ID vs. WINDOW NUMBER
There's a difference between a window number and a window ID. A window number is a number between 1 - 127 (assuming that's the highest number of windows we can have. The limit might be 255.) A window ID is something different. It's a very large number. Some system functions ask for a window ID while other system functions ask for a window number. 'TranslateWindowID' converts a window ID to a window number. NOTE: A window's number may change as windows are added and deleted.

A window's ID will not change. I therefore recommend you always work with window ID's and use 'TranslateWindowID' to get the window number when you need it. Window numbers are useful when you want to cycle through all existing windows.

It turns out that the Switch_Window system function has an undocumented feature. The documentation says it accepts a window number to switch to. But it is also smart enough to also accept a window ID. A window number is a number between 1 and 127 (or maybe 255, I'm not sure what the upper limit is). On the other hand a window ID has the lower 16 bits set to zero, so in hex a window ID looks like 0xnnnn0000. Thus it is easy to tell a window number from a window ID. Note this is undocumented so you should always use a window number with Switch_Window.

 

5. STRINGS ARE 254 CHARACTERS UNLESS YOU SPECIFY A LENGTH
If you do this:
Code:
str MyString;

then your string MyString is only 254 characters long (that is, the string will hold 254 characters and no more). If you need a longer string you have to specify the length.
Code:
str MyString[350];

MAX_LINE_LENGTH is a system constant (currently 16383) you can use to specify the longest possible string:
Code:
str MyString[MAX_LINE_LENGTH];

 

6. EXPLICIT STRINGS IN CMAC CODE
The longest explicit string in CMAC code you can specify is 253 characters. Any longer and bad things happen!
Code:
 str MyString[500];
MyString = "<no more than 253 characters between quotes>";

 

7. GLOBAL VARIABLES
If you set a global integer variable to zero (0) the global variable will disappear.
If you set a global string variable to "" (zero length string) the global variable will disappear.

This does not cause a problem, because if you reference a non-existant global integer you will get zero (0), and if you reference a non-existant global string you will get "" (zero length string).

 

GLOBAL ALIASES
Example:
Code:
global {
  int Decimal_Places     "!CALC_DECIMAL_PLACES";
  str Disp_Str           "!CALC_DISP_STR";
}

Here Disp_Str is your global alias you can use like a local variable, and !CALC_DISP_STR is the global variable created. (Some CMAC functions require a local variable and will not accept a global alias. You may equate a local variable to the global alias and then use your local variable.)
Code:
str ds;
ds = Disp_Str;
int x = svl(ds);  //Then something like this will work.


If instead you were to just declare
Code:
global {
  int Decimal_Places
  str Disp_Str
}

then the global variables created are the same as the alias names.

Global variables with names not preceded by a ' ! ', '@', or '~' are restored at the beginning of each editing session if the restore feature is enabled. (This is often not necessary or wanted, which is why so many global variable names start with '!' or '@'.)

 

8. DlgAddCtrl and ctrlid
Do not use -1 for ctrlid for any control which actually does something (e.g. PushButton). Multi-Edit 9.10 doesn't generate good ctrlid values when you use -1, so make up a unique ctrlid number for each control or the control won't work. Use -1 only for static elements, such as static text, bitmaps, or icons. Also do not use any of the following numbers as they have special meaning:


32767 - dlg_WCmd_Init
998 - ? (cased with 1)
2 - User aborted dialog (by Xing out or pressing Escape key)
1 - User pressed Return key (with no default button or focus button)

Do not use a number > 60,000 (this is the mistake Multi-Edit 9.10 makes when you use -1). To prevent conflicts with future versions of Multi-Edit, I suggest using numbers below 30,000. So ctrlid numbers in the range [1000 - 30,000] should be OK. (See Introduction to CMAC. 12: Dialogs {currently under construction}).