Introduction to CMac: 03. 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
if (x >= y-z)
You have to add parenthesis:
if (x >= (y-z))
2. SINGLE QUOTED STRINGS vs. DOUBLE QUOTED STRINGS
"\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:
"He said, ""Goodbye!"" and then left."
same as:
"He said, \"Goodbye!\" and then left."
Result:
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:
'|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:
'He said, ''Goodbye!'' and then left.'
Result:
He said, 'Goodbye!' and then left.
3. MACROS MUST BE EITHER PROTOTYPED OR DEFINED BEFORE THEY ARE CALLED BY OTHER MACROS.
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:
macro_file mycmac; prototype mycmac { void mysub(); } void test() { mysub(); } void mysub() { ... }
4. WINDOW ID vs. WINDOW NUMBER
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
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.
str MyString[350];
MAX_LINE_LENGTH is a system constant (currently 16383) you can use to specify the longest possible string:
str MyString[MAX_LINE_LENGTH];
6. EXPLICIT STRINGS IN CMac CODE
str MyString[500]; MyString = "<no more than 253 characters between quotes>";
7. GLOBAL VARIABLES
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-existent global string you will get ”” (zero length string).
8. GLOBAL ALIASES
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.)
str ds; ds = Disp_Str; int x = svl(ds); //Then something like this will work.
If instead you were to just declare
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 '@'.)
9. DlgAddCtrl and ctrlid
- 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).